FFmpeg
hlsenc.c
Go to the documentation of this file.
1 /*
2  * Apple HTTP Live Streaming segmenter
3  * Copyright (c) 2012, Luca Barbato
4  * Copyright (c) 2017 Akamai Technologies, Inc.
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "config.h"
24 #include "config_components.h"
25 #include <stdint.h>
26 #include <time.h>
27 #if HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 
31 #include "libavutil/avassert.h"
32 #include "libavutil/mathematics.h"
33 #include "libavutil/avstring.h"
34 #include "libavutil/bprint.h"
35 #include "libavutil/intreadwrite.h"
36 #include "libavutil/mem.h"
37 #include "libavutil/opt.h"
38 #include "libavutil/log.h"
39 #include "libavutil/random_seed.h"
40 #include "libavutil/time.h"
42 
43 #include "libavcodec/defs.h"
44 
45 #include "avformat.h"
46 #include "avio_internal.h"
47 #include "avc.h"
48 #if CONFIG_HTTP_PROTOCOL
49 #include "http.h"
50 #endif
51 #include "hlsplaylist.h"
52 #include "internal.h"
53 #include "nal.h"
54 #include "mux.h"
55 #include "os_support.h"
56 #include "url.h"
57 
58 typedef enum {
65 
66 typedef enum {
70 
71 #define KEYSIZE 16
72 #define LINE_BUFFER_SIZE MAX_URL_SIZE
73 #define HLS_MICROSECOND_UNIT 1000000
74 #define BUFSIZE (16 * 1024)
75 #define POSTFIX_PATTERN "_%d"
76 
77 typedef struct HLSSegment {
80  double duration; /* in seconds */
81  int discont;
86  unsigned var_stream_idx;
87 
89  char iv_string[KEYSIZE*2 + 1];
90 
91  struct HLSSegment *next;
93 } HLSSegment;
94 
95 typedef enum HLSFlags {
96  // Generate a single media file and use byte ranges in the playlist.
97  HLS_SINGLE_FILE = (1 << 0),
98  HLS_DELETE_SEGMENTS = (1 << 1),
99  HLS_ROUND_DURATIONS = (1 << 2),
100  HLS_DISCONT_START = (1 << 3),
101  HLS_OMIT_ENDLIST = (1 << 4),
102  HLS_SPLIT_BY_TIME = (1 << 5),
103  HLS_APPEND_LIST = (1 << 6),
105  HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in segment filenames when use_localtime e.g.: %%03d
106  HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration (microsec) in segment filenames when use_localtime e.g.: %%09t
107  HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) in segment filenames when use_localtime e.g.: %%014s
108  HLS_TEMP_FILE = (1 << 11),
109  HLS_PERIODIC_REKEY = (1 << 12),
111  HLS_I_FRAMES_ONLY = (1 << 14),
112 } HLSFlags;
113 
114 typedef enum {
117 } SegmentType;
118 
119 typedef struct VariantStream {
120  unsigned var_stream_idx;
121  unsigned number;
129  uint8_t *temp_buffer;
130  uint8_t *init_buffer;
131 
134 
139  double dpp; // duration per packet
145  double duration; // last segment duration computed so far, in seconds
146  int64_t start_pos; // last segment starting position
147  int64_t size; // last segment size
152 
157 
161 
163  char *basename;
166  char *m3u8_name;
167 
169  char current_segment_final_filename_fmt[MAX_URL_SIZE]; // when renaming segments
170 
173 
175 
178  char key_string[KEYSIZE*2 + 1];
179  char iv_string[KEYSIZE*2 + 1];
180 
182  char codec_attr[128];
184  unsigned int nb_streams;
185  int m3u8_created; /* status of media play-list creation */
186  int is_default; /* default status of audio group */
187  const char *language; /* audio language name */
188  const char *agroup; /* audio group name */
189  const char *sgroup; /* subtitle group name */
190  const char *ccgroup; /* closed caption group name */
191  const char *varname; /* variant name */
192  const char *subtitle_varname; /* subtitle variant name */
193 } VariantStream;
194 
195 typedef struct ClosedCaptionsStream {
196  const char *ccgroup; /* closed caption group name */
197  const char *instreamid; /* closed captions INSTREAM-ID */
198  const char *language; /* closed captions language */
200 
201 typedef struct HLSContext {
202  const AVClass *class; // Class for private options.
204  uint32_t start_sequence_source_type; // enum StartSequenceSourceType
205 
206  int64_t time; // Set by a private option.
207  int64_t init_time; // Set by a private option.
208  int max_nb_segments; // Set by a private option.
209  int hls_delete_threshold; // Set by a private option.
210  uint32_t flags; // enum HLSFlags
211  uint32_t pl_type; // enum PlaylistType
215  int resend_init_file; ///< resend init file into disk after refresh m3u8
216 
217  int use_localtime; ///< flag to expand filename with localtime
218  int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename
221  int64_t max_seg_size; // every segment file max size
222 
223  char *baseurl;
227 
228  int encrypt;
229  char *key;
230  char *key_url;
231  char *iv;
234 
238  char key_string[KEYSIZE*2 + 1];
239  char iv_string[KEYSIZE*2 + 1];
241 
242  char *method;
243  char *user_agent;
244 
246  unsigned int nb_varstreams;
248  unsigned int nb_ccstreams;
249 
250  int master_m3u8_created; /* status of master play-list creation */
251  char *master_m3u8_url; /* URL of the master m3u8 file */
252  int version; /* HLS version */
253  char *var_stream_map; /* user specified variant stream map string */
254  char *cc_stream_map; /* user specified closed caption streams map string */
256  unsigned int master_publish_rate;
257  int http_persistent;
263  char *headers;
264  int has_default_key; /* has DEFAULT field of var_stream_map */
265  int has_video_m3u8; /* has video stream m3u8 list */
266 } HLSContext;
267 
268 static int strftime_expand(const char *fmt, char **dest)
269 {
270  int r = 1;
271  time_t now0;
272  struct tm *tm, tmpbuf;
273  char *buf;
274 
275  buf = av_mallocz(MAX_URL_SIZE);
276  if (!buf)
277  return AVERROR(ENOMEM);
278 
279  time(&now0);
280  tm = localtime_r(&now0, &tmpbuf);
281  r = strftime(buf, MAX_URL_SIZE, fmt, tm);
282  if (!r) {
283  av_free(buf);
284  return AVERROR(EINVAL);
285  }
286  *dest = buf;
287 
288  return r;
289 }
290 
291 static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, const char *filename,
293 {
294  HLSContext *hls = s->priv_data;
295  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
296  int err = AVERROR_MUXER_NOT_FOUND;
297  if (!*pb || !http_base_proto || !hls->http_persistent) {
298  err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
299 #if CONFIG_HTTP_PROTOCOL
300  } else {
301  URLContext *http_url_context = ffio_geturlcontext(*pb);
302  av_assert0(http_url_context);
303  err = ff_http_do_new_request(http_url_context, filename);
304  if (err < 0)
305  ff_format_io_close(s, pb);
306 
307 #endif
308  }
309  return err;
310 }
311 
312 static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
313 {
314  HLSContext *hls = s->priv_data;
315  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
316  int ret = 0;
317  if (!*pb)
318  return ret;
319  if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) {
320  ff_format_io_close(s, pb);
321 #if CONFIG_HTTP_PROTOCOL
322  } else {
323  URLContext *http_url_context = ffio_geturlcontext(*pb);
324  av_assert0(http_url_context);
325  avio_flush(*pb);
326  ret = ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
327 #endif
328  }
329  return ret;
330 }
331 
333 {
334  int http_base_proto = ff_is_http_proto(s->url);
335 
336  if (c->method) {
337  av_dict_set(options, "method", c->method, 0);
338  } else if (http_base_proto) {
339  av_dict_set(options, "method", "PUT", 0);
340  }
341  if (c->user_agent)
342  av_dict_set(options, "user_agent", c->user_agent, 0);
343  if (c->http_persistent)
344  av_dict_set_int(options, "multiple_requests", 1, 0);
345  if (c->timeout >= 0)
346  av_dict_set_int(options, "timeout", c->timeout, 0);
347  if (c->headers)
348  av_dict_set(options, "headers", c->headers, 0);
349 }
350 
352 {
353  int codec_strlen = strlen(vs->codec_attr);
354  char attr[32];
355 
357  return;
359  return;
360 
361  if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
362  uint8_t *data = st->codecpar->extradata;
363  if (data) {
364  const uint8_t *p;
365 
366  if (AV_RB32(data) == 0x01 && (data[4] & 0x1F) == 7)
367  p = &data[5];
368  else if (AV_RB24(data) == 0x01 && (data[3] & 0x1F) == 7)
369  p = &data[4];
370  else if (data[0] == 0x01) /* avcC */
371  p = &data[1];
372  else
373  goto fail;
374  snprintf(attr, sizeof(attr),
375  "avc1.%02x%02x%02x", p[0], p[1], p[2]);
376  } else {
377  goto fail;
378  }
379  } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
380  uint8_t *data = st->codecpar->extradata;
382  int level = AV_LEVEL_UNKNOWN;
383 
384  if (st->codecpar->profile != AV_PROFILE_UNKNOWN)
385  profile = st->codecpar->profile;
386  if (st->codecpar->level != AV_LEVEL_UNKNOWN)
387  level = st->codecpar->level;
388 
389  /* check the boundary of data which from current position is small than extradata_size */
390  while (data && (data - st->codecpar->extradata + 19) < st->codecpar->extradata_size) {
391  /* get HEVC SPS NAL and seek to profile_tier_level */
392  if (!(data[0] | data[1] | data[2]) && data[3] == 1 && ((data[4] & 0x7E) == 0x42)) {
393  uint8_t *rbsp_buf;
394  int remain_size = 0;
395  int rbsp_size = 0;
396  /* skip start code + nalu header */
397  data += 6;
398  /* process by reference General NAL unit syntax */
399  remain_size = st->codecpar->extradata_size - (data - st->codecpar->extradata);
400  rbsp_buf = ff_nal_unit_extract_rbsp(data, remain_size, &rbsp_size, 0);
401  if (!rbsp_buf)
402  return;
403  if (rbsp_size < 13) {
404  av_freep(&rbsp_buf);
405  break;
406  }
407  /* skip sps_video_parameter_set_id u(4),
408  * sps_max_sub_layers_minus1 u(3),
409  * and sps_temporal_id_nesting_flag u(1) */
410  profile = rbsp_buf[1] & 0x1f;
411  /* skip 8 + 8 + 32 + 4 + 43 + 1 bit */
412  level = rbsp_buf[12];
413  av_freep(&rbsp_buf);
414  break;
415  }
416  data++;
417  }
418  if (st->codecpar->codec_tag == MKTAG('h','v','c','1') &&
420  level != AV_LEVEL_UNKNOWN) {
421  snprintf(attr, sizeof(attr), "%s.%d.4.L%d.B01", av_fourcc2str(st->codecpar->codec_tag), profile, level);
422  } else
423  goto fail;
424  } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) {
425  snprintf(attr, sizeof(attr), "mp4a.40.33");
426  } else if (st->codecpar->codec_id == AV_CODEC_ID_MP3) {
427  snprintf(attr, sizeof(attr), "mp4a.40.34");
428  } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
429  if (st->codecpar->profile != AV_PROFILE_UNKNOWN)
430  snprintf(attr, sizeof(attr), "mp4a.40.%d", st->codecpar->profile+1);
431  else
432  // This is for backward compatibility with the previous implementation.
433  snprintf(attr, sizeof(attr), "mp4a.40.2");
434  } else if (st->codecpar->codec_id == AV_CODEC_ID_AC3) {
435  snprintf(attr, sizeof(attr), "ac-3");
436  } else if (st->codecpar->codec_id == AV_CODEC_ID_EAC3) {
437  snprintf(attr, sizeof(attr), "ec-3");
438  } else {
439  goto fail;
440  }
441  // Don't write the same attribute multiple times
442  if (!av_stristr(vs->codec_attr, attr)) {
443  snprintf(vs->codec_attr + codec_strlen,
444  sizeof(vs->codec_attr) - codec_strlen,
445  "%s%s", codec_strlen ? "," : "", attr);
446  }
447  return;
448 
449 fail:
450  vs->codec_attr[0] = '\0';
452  return;
453 }
454 
455 static int replace_str_data_in_filename(char **s, const char *filename, char placeholder, const char *datastring)
456 {
457  const char *p;
458  char c;
459  int addchar_count;
460  int found_count = 0;
461  AVBPrint buf;
462  int ret;
463 
465 
466  p = filename;
467  for (;;) {
468  c = *p;
469  if (c == '\0')
470  break;
471  if (c == '%' && *(p+1) == '%') // %%
472  addchar_count = 2;
473  else if (c == '%' && *(p+1) == placeholder) {
474  av_bprintf(&buf, "%s", datastring);
475  p += 2;
476  addchar_count = 0;
477  found_count ++;
478  } else
479  addchar_count = 1;
480 
481  if (addchar_count > 0) {
482  av_bprint_append_data(&buf, p, addchar_count);
483  p += addchar_count;
484  }
485  }
486  if (!av_bprint_is_complete(&buf)) {
487  av_bprint_finalize(&buf, NULL);
488  return AVERROR(ENOMEM);
489  }
490  if ((ret = av_bprint_finalize(&buf, s)) < 0)
491  return ret;
492  return found_count;
493 }
494 
495 static int replace_int_data_in_filename(char **s, const char *filename, char placeholder, int64_t number)
496 {
497  const char *p;
498  char c;
499  int nd, addchar_count;
500  int found_count = 0;
501  AVBPrint buf;
502  int ret;
503 
505 
506  p = filename;
507  for (;;) {
508  c = *p;
509  if (c == '\0')
510  break;
511  if (c == '%' && *(p+1) == '%') // %%
512  addchar_count = 2;
513  else if (c == '%' && (av_isdigit(*(p+1)) || *(p+1) == placeholder)) {
514  nd = 0;
515  addchar_count = 1;
516  while (av_isdigit(*(p + addchar_count))) {
517  nd = nd * 10 + *(p + addchar_count) - '0';
518  addchar_count++;
519  }
520 
521  if (*(p + addchar_count) == placeholder) {
522  av_bprintf(&buf, "%0*"PRId64, (number < 0) ? nd : nd++, number);
523  p += (addchar_count + 1);
524  addchar_count = 0;
525  found_count++;
526  }
527 
528  } else
529  addchar_count = 1;
530 
531  av_bprint_append_data(&buf, p, addchar_count);
532  p += addchar_count;
533  }
534  if (!av_bprint_is_complete(&buf)) {
535  av_bprint_finalize(&buf, NULL);
536  return AVERROR(ENOMEM);
537  }
538  if ((ret = av_bprint_finalize(&buf, s)) < 0)
539  return ret;
540  return found_count;
541 }
542 
543 static void write_styp(AVIOContext *pb)
544 {
545  avio_wb32(pb, 24);
546  ffio_wfourcc(pb, "styp");
547  ffio_wfourcc(pb, "msdh");
548  avio_wb32(pb, 0); /* minor */
549  ffio_wfourcc(pb, "msdh");
550  ffio_wfourcc(pb, "msix");
551 }
552 
553 static int flush_dynbuf(VariantStream *vs, int *range_length)
554 {
555  AVFormatContext *ctx = vs->avf;
556 
557  if (!ctx->pb) {
558  return AVERROR(EINVAL);
559  }
560 
561  // flush
563 
564  // write out to file
565  *range_length = avio_close_dyn_buf(ctx->pb, &vs->temp_buffer);
566  ctx->pb = NULL;
567  avio_write(vs->out, vs->temp_buffer, *range_length);
568  avio_flush(vs->out);
569 
570  // re-open buffer
571  return avio_open_dyn_buf(&ctx->pb);
572 }
573 
574 static void reflush_dynbuf(VariantStream *vs, int *range_length)
575 {
576  // re-open buffer
577  avio_write(vs->out, vs->temp_buffer, *range_length);
578 }
579 
581  char *path, const char *proto)
582 {
583  if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
584  AVDictionary *opt = NULL;
585  int ret;
586 
587  set_http_options(avf, &opt, hls);
588  av_dict_set(&opt, "method", "DELETE", 0);
589 
590  ret = hlsenc_io_open(avf, &hls->http_delete, path, &opt);
591  av_dict_free(&opt);
592  if (ret < 0)
593  return hls->ignore_io_errors ? 1 : ret;
594 
595  //Nothing to write
596  hlsenc_io_close(avf, &hls->http_delete, path);
597  } else if (unlink(path) < 0) {
598  av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
599  path, strerror(errno));
600  }
601  return 0;
602 }
603 
605  VariantStream *vs)
606 {
607 
608  HLSSegment *segment, *previous_segment = NULL;
609  float playlist_duration = 0.0f;
610  int ret = 0;
611  int segment_cnt = 0;
612  AVBPrint path;
613  const char *dirname = NULL;
614  char *dirname_r = NULL;
615  char *dirname_repl = NULL;
616  const char *vtt_dirname = NULL;
617  char *vtt_dirname_r = NULL;
618  const char *proto = NULL;
619 
621 
622  segment = vs->segments;
623  while (segment) {
624  playlist_duration += segment->duration;
625  segment = segment->next;
626  }
627 
628  segment = vs->old_segments;
629  segment_cnt = 0;
630  while (segment) {
631  playlist_duration -= segment->duration;
632  previous_segment = segment;
633  segment = previous_segment->next;
634  segment_cnt++;
635  if (playlist_duration <= -previous_segment->duration) {
636  previous_segment->next = NULL;
637  break;
638  }
639  if (segment_cnt >= hls->hls_delete_threshold) {
640  previous_segment->next = NULL;
641  break;
642  }
643  }
644 
645  if (segment && !hls->use_localtime_mkdir) {
646  dirname_r = hls->segment_filename ? av_strdup(hls->segment_filename): av_strdup(vs->avf->url);
647  dirname = av_dirname(dirname_r);
648  }
649 
650  /* if %v is present in the file's directory
651  * all segment belongs to the same variant, so do it only once before the loop*/
652  if (dirname && av_stristr(dirname, "%v")) {
653  if (!vs->varname) {
654  if (replace_int_data_in_filename(&dirname_repl, dirname, 'v', segment->var_stream_idx) < 1) {
655  ret = AVERROR(EINVAL);
656  goto fail;
657  }
658  } else {
659  if (replace_str_data_in_filename(&dirname_repl, dirname, 'v', vs->varname) < 1) {
660  ret = AVERROR(EINVAL);
661  goto fail;
662  }
663  }
664 
665  dirname = dirname_repl;
666  }
667 
668  while (segment) {
669  av_log(hls, AV_LOG_DEBUG, "deleting old segment %s\n",
670  segment->filename);
671  if (!hls->use_localtime_mkdir) // segment->filename contains basename only
672  av_bprintf(&path, "%s/", dirname);
673  av_bprintf(&path, "%s", segment->filename);
674 
675  if (!av_bprint_is_complete(&path)) {
676  ret = AVERROR(ENOMEM);
677  goto fail;
678  }
679 
680  proto = avio_find_protocol_name(s->url);
681  if (ret = hls_delete_file(hls, s, path.str, proto))
682  goto fail;
683 
684  if ((segment->sub_filename[0] != '\0')) {
685  vtt_dirname_r = av_strdup(vs->vtt_avf->url);
686  vtt_dirname = av_dirname(vtt_dirname_r);
687 
688  av_bprint_clear(&path);
689  av_bprintf(&path, "%s/%s", vtt_dirname, segment->sub_filename);
690  av_freep(&vtt_dirname_r);
691 
692  if (!av_bprint_is_complete(&path)) {
693  ret = AVERROR(ENOMEM);
694  goto fail;
695  }
696 
697  if (ret = hls_delete_file(hls, s, path.str, proto))
698  goto fail;
699  }
700  av_bprint_clear(&path);
701  previous_segment = segment;
702  segment = previous_segment->next;
703  av_freep(&previous_segment);
704  }
705 
706 fail:
707  av_bprint_finalize(&path, NULL);
708  av_freep(&dirname_r);
709  av_freep(&dirname_repl);
710 
711  return ret;
712 }
713 
715 {
716  HLSContext *hls = s->priv_data;
717  int ret;
718  int len;
719  AVIOContext *pb;
720  uint8_t key[KEYSIZE];
721  char * key_basename_source = (hls->master_m3u8_url) ? hls->master_m3u8_url : s->url;
722 
723  len = strlen(key_basename_source) + 4 + 1;
724  hls->key_basename = av_mallocz(len);
725  if (!hls->key_basename)
726  return AVERROR(ENOMEM);
727 
728  av_strlcpy(hls->key_basename, key_basename_source, len);
729  av_strlcat(hls->key_basename, ".key", len);
730 
731  if (hls->key_url) {
732  av_strlcpy(hls->key_file, hls->key_url, sizeof(hls->key_file));
733  av_strlcpy(hls->key_uri, hls->key_url, sizeof(hls->key_uri));
734  } else {
735  av_strlcpy(hls->key_file, hls->key_basename, sizeof(hls->key_file));
736  av_strlcpy(hls->key_uri, hls->key_basename, sizeof(hls->key_uri));
737  }
738 
739  if (!*hls->iv_string) {
740  uint8_t iv[16] = { 0 };
741  char buf[33];
742 
743  if (!hls->iv) {
744  AV_WB64(iv + 8, vs->sequence);
745  } else {
746  memcpy(iv, hls->iv, sizeof(iv));
747  }
748  ff_data_to_hex(buf, iv, sizeof(iv), 0);
749  memcpy(hls->iv_string, buf, sizeof(hls->iv_string));
750  }
751 
752  if (!*hls->key_uri) {
753  av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
754  return AVERROR(EINVAL);
755  }
756 
757  if (!*hls->key_file) {
758  av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
759  return AVERROR(EINVAL);
760  }
761 
762  if (!*hls->key_string) {
764  if (!hls->key) {
765  if ((ret = av_random_bytes(key, sizeof(key))) < 0) {
766  av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n");
767  return ret;
768  }
769  } else {
770  memcpy(key, hls->key, sizeof(key));
771  }
772 
773  ff_data_to_hex(hls->key_string, key, sizeof(key), 0);
774  set_http_options(s, &options, hls);
775  ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_WRITE, &options);
777  if (ret < 0)
778  return ret;
779  avio_seek(pb, 0, SEEK_CUR);
780  avio_write(pb, key, KEYSIZE);
781  avio_close(pb);
782  }
783  return 0;
784 }
785 
786 
788 {
789  HLSContext *hls = s->priv_data;
790  int ret;
791  AVIOContext *pb;
792  uint8_t key[KEYSIZE];
794 
795  set_http_options(s, &options, hls);
796  ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, &options);
798  if (ret < 0) {
799  av_log(hls, AV_LOG_ERROR,
800  "error opening key info file %s\n", hls->key_info_file);
801  return ret;
802  }
803 
804  ff_get_line(pb, vs->key_uri, sizeof(vs->key_uri));
805  vs->key_uri[strcspn(vs->key_uri, "\r\n")] = '\0';
806 
807  ff_get_line(pb, vs->key_file, sizeof(vs->key_file));
808  vs->key_file[strcspn(vs->key_file, "\r\n")] = '\0';
809 
810  ff_get_line(pb, vs->iv_string, sizeof(vs->iv_string));
811  vs->iv_string[strcspn(vs->iv_string, "\r\n")] = '\0';
812 
813  ff_format_io_close(s, &pb);
814 
815  if (!*vs->key_uri) {
816  av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
817  return AVERROR(EINVAL);
818  }
819 
820  if (!*vs->key_file) {
821  av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
822  return AVERROR(EINVAL);
823  }
824 
825  set_http_options(s, &options, hls);
826  ret = s->io_open(s, &pb, vs->key_file, AVIO_FLAG_READ, &options);
828  if (ret < 0) {
829  av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", vs->key_file);
830  return ret;
831  }
832 
833  ret = avio_read(pb, key, sizeof(key));
834  ff_format_io_close(s, &pb);
835  if (ret != sizeof(key)) {
836  av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", vs->key_file);
837  if (ret >= 0 || ret == AVERROR_EOF)
838  ret = AVERROR(EINVAL);
839  return ret;
840  }
841  ff_data_to_hex(vs->key_string, key, sizeof(key), 0);
842 
843  return 0;
844 }
845 
847 {
849  HLSContext *hls = s->priv_data;
850  AVFormatContext *oc;
851  AVFormatContext *vtt_oc = NULL;
852  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
853  int remaining_options;
854  int i, ret;
855 
857  if (ret < 0)
858  return ret;
859  oc = vs->avf;
860 
861  oc->url = av_strdup("");
862  if (!oc->url)
863  return AVERROR(ENOMEM);
864 
865  oc->interrupt_callback = s->interrupt_callback;
866  oc->max_delay = s->max_delay;
867  oc->opaque = s->opaque;
868  oc->io_open = s->io_open;
869  oc->io_close2 = s->io_close2;
870  oc->strict_std_compliance = s->strict_std_compliance;
871  av_dict_copy(&oc->metadata, s->metadata, 0);
872 
873  if (vs->vtt_oformat) {
875  if (ret < 0)
876  return ret;
877  vtt_oc = vs->vtt_avf;
878  av_dict_copy(&vtt_oc->metadata, s->metadata, 0);
879  }
880 
881  for (i = 0; i < vs->nb_streams; i++) {
882  AVStream *st;
883  AVFormatContext *loc;
885  loc = vtt_oc;
886  else
887  loc = oc;
888 
889  if (!(st = avformat_new_stream(loc, NULL)))
890  return AVERROR(ENOMEM);
892  if (ret < 0)
893  return ret;
894  if (!oc->oformat->codec_tag ||
898  } else {
899  st->codecpar->codec_tag = 0;
900  }
901 
903  st->time_base = vs->streams[i]->time_base;
904  av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0);
905  st->id = vs->streams[i]->id;
906  }
907 
908  vs->start_pos = 0;
909  vs->new_start = 1;
910 
911  if (hls->segment_type == SEGMENT_TYPE_FMP4 && hls->max_seg_size > 0) {
912  if (hls->http_persistent > 0) {
913  //TODO: Support fragment fmp4 for http persistent in HLS muxer.
914  av_log(s, AV_LOG_WARNING, "http persistent mode is currently unsupported for fragment mp4 in the HLS muxer.\n");
915  }
916  if (hls->max_seg_size > 0) {
917  av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n");
918  return AVERROR_PATCHWELCOME;
919  }
920  }
921 
922  if ((ret = avio_open_dyn_buf(&oc->pb)) < 0)
923  return ret;
924 
925  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
926  set_http_options(s, &options, hls);
927  if (byterange_mode) {
928  ret = hlsenc_io_open(s, &vs->out, vs->basename, &options);
929  } else {
931  }
933  }
934  if (ret < 0) {
935  av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename);
936  return ret;
937  }
938 
940  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
941  av_dict_set(&options, "fflags", "-autobsf", 0);
942  av_dict_set(&options, "movflags", "+frag_custom+dash+delay_moov", AV_DICT_APPEND);
943  } else {
944  /* We only require one PAT/PMT per segment. */
945  char period[21];
946  snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1);
949  }
951  remaining_options = av_dict_count(options);
953  if (ret < 0)
954  return ret;
955  if (remaining_options) {
956  av_log(s, AV_LOG_ERROR, "Some of the provided format options are not recognized\n");
957  return AVERROR(EINVAL);
958  }
959  avio_flush(oc->pb);
960  return 0;
961 }
962 
963 static HLSSegment *find_segment_by_filename(HLSSegment *segment, const char *filename)
964 {
965  while (segment) {
966  if (!av_strcasecmp(segment->filename,filename))
967  return segment;
968  segment = segment->next;
969  }
970  return (HLSSegment *) NULL;
971 }
972 
974  VariantStream *vs, HLSSegment *en,
975  double duration, int64_t pos, int64_t size)
976 {
979  char * new_url = av_strdup(vs->current_segment_final_filename_fmt);
980  if (!new_url) {
981  return AVERROR(ENOMEM);
982  }
983  ff_format_set_url(vs->avf, new_url);
985  char *filename = NULL;
986  if (replace_int_data_in_filename(&filename, vs->avf->url, 's', pos + size) < 1) {
987  av_log(hls, AV_LOG_ERROR,
988  "Invalid second level segment filename template '%s', "
989  "you can try to remove second_level_segment_size flag\n",
990  vs->avf->url);
991  av_freep(&filename);
992  return AVERROR(EINVAL);
993  }
994  ff_format_set_url(vs->avf, filename);
995  }
997  char *filename = NULL;
998  if (replace_int_data_in_filename(&filename, vs->avf->url,
999  't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) {
1000  av_log(hls, AV_LOG_ERROR,
1001  "Invalid second level segment filename template '%s', "
1002  "you can try to remove second_level_segment_duration flag\n",
1003  vs->avf->url);
1004  av_freep(&filename);
1005  return AVERROR(EINVAL);
1006  }
1007  ff_format_set_url(vs->avf, filename);
1008  }
1009  }
1010  return 0;
1011 }
1012 
1014 {
1015  int ret = 0;
1016 
1018  av_log(hls, AV_LOG_ERROR,
1019  "second_level_segment_duration hls_flag requires strftime to be true\n");
1020  ret = AVERROR(EINVAL);
1021  }
1022  if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
1023  av_log(hls, AV_LOG_ERROR,
1024  "second_level_segment_size hls_flag requires strfime to be true\n");
1025  ret = AVERROR(EINVAL);
1026  }
1028  av_log(hls, AV_LOG_ERROR,
1029  "second_level_segment_index hls_flag requires strftime to be true\n");
1030  ret = AVERROR(EINVAL);
1031  }
1032 
1033  return ret;
1034 }
1035 
1037 {
1038  const char *proto = avio_find_protocol_name(vs->basename);
1039  int segment_renaming_ok = proto && !strcmp(proto, "file");
1040  int ret = 0;
1041 
1042  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) && !segment_renaming_ok) {
1043  av_log(hls, AV_LOG_ERROR,
1044  "second_level_segment_duration hls_flag works only with file protocol segment names\n");
1045  ret = AVERROR(EINVAL);
1046  }
1047  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) && !segment_renaming_ok) {
1048  av_log(hls, AV_LOG_ERROR,
1049  "second_level_segment_size hls_flag works only with file protocol segment names\n");
1050  ret = AVERROR(EINVAL);
1051  }
1052 
1053  return ret;
1054 }
1055 
1056 static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename) {
1058  strlen(vs->current_segment_final_filename_fmt)) {
1059  ff_rename(old_filename, vs->avf->url, hls);
1060  }
1061 }
1062 
1064 {
1065  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) {
1066  char *filename = NULL;
1067  if (replace_int_data_in_filename(&filename,
1068  oc->url, 'd', vs->sequence) < 1) {
1069  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1070  "you can try to remove second_level_segment_index flag\n",
1071  oc->url);
1072  av_freep(&filename);
1073  return AVERROR(EINVAL);
1074  }
1075  ff_format_set_url(oc, filename);
1076  }
1080  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
1081  char *filename = NULL;
1082  if (replace_int_data_in_filename(&filename, oc->url, 's', 0) < 1) {
1083  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1084  "you can try to remove second_level_segment_size flag\n",
1085  oc->url);
1086  av_freep(&filename);
1087  return AVERROR(EINVAL);
1088  }
1089  ff_format_set_url(oc, filename);
1090  }
1091  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) {
1092  char *filename = NULL;
1093  if (replace_int_data_in_filename(&filename, oc->url, 't', 0) < 1) {
1094  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1095  "you can try to remove second_level_segment_duration flag\n",
1096  oc->url);
1097  av_freep(&filename);
1098  return AVERROR(EINVAL);
1099  }
1100  ff_format_set_url(oc, filename);
1101  }
1102  }
1103  return 0;
1104 }
1105 
1106 /* Create a new segment and append it to the segment list */
1108  VariantStream *vs, double duration, int64_t pos,
1109  int64_t size)
1110 {
1111  HLSSegment *en = av_malloc(sizeof(*en));
1112  const char *filename;
1113  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1114  int ret;
1115 
1116  if (!en)
1117  return AVERROR(ENOMEM);
1118 
1119  vs->total_size += size;
1120  vs->total_duration += duration;
1121  if (duration > 0.5) {
1122  // Don't include the final, possibly very short segment in the
1123  // calculation of the max bitrate.
1124  int cur_bitrate = (int)(8 * size / duration);
1125  if (cur_bitrate > vs->max_bitrate)
1126  vs->max_bitrate = cur_bitrate;
1127  }
1128  if (vs->total_duration > 0)
1129  vs->avg_bitrate = (int)(8 * vs->total_size / vs->total_duration);
1130 
1131  en->var_stream_idx = vs->var_stream_idx;
1132  ret = sls_flags_filename_process(s, hls, vs, en, duration, pos, size);
1133  if (ret < 0) {
1134  av_freep(&en);
1135  return ret;
1136  }
1137 
1138  filename = av_basename(vs->avf->url);
1139 
1140  if (hls->use_localtime_mkdir) {
1141  filename = vs->avf->url;
1142  }
1143  if ((find_segment_by_filename(vs->segments, filename) || find_segment_by_filename(vs->old_segments, filename))
1144  && !byterange_mode) {
1145  av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename);
1146  }
1147  av_strlcpy(en->filename, filename, sizeof(en->filename));
1148 
1149  if (vs->has_subtitle)
1150  av_strlcpy(en->sub_filename, av_basename(vs->vtt_avf->url), sizeof(en->sub_filename));
1151  else
1152  en->sub_filename[0] = '\0';
1153 
1154  en->duration = duration;
1155  en->pos = pos;
1156  en->size = size;
1157  en->keyframe_pos = vs->video_keyframe_pos;
1159  en->next = NULL;
1160  en->discont = 0;
1161  en->discont_program_date_time = 0;
1162 
1163  if (vs->discontinuity) {
1164  en->discont = 1;
1165  vs->discontinuity = 0;
1166  }
1167 
1168  if (hls->key_info_file || hls->encrypt) {
1169  av_strlcpy(en->key_uri, vs->key_uri, sizeof(en->key_uri));
1170  av_strlcpy(en->iv_string, vs->iv_string, sizeof(en->iv_string));
1171  }
1172 
1173  if (!vs->segments)
1174  vs->segments = en;
1175  else
1176  vs->last_segment->next = en;
1177 
1178  vs->last_segment = en;
1179 
1180  // EVENT or VOD playlists imply sliding window cannot be used
1181  if (hls->pl_type != PLAYLIST_TYPE_NONE)
1182  hls->max_nb_segments = 0;
1183 
1184  if (hls->max_nb_segments && vs->nb_entries >= hls->max_nb_segments) {
1185  en = vs->segments;
1187  vs->initial_prog_date_time += en->duration;
1188  vs->segments = en->next;
1189  if (en && hls->flags & HLS_DELETE_SEGMENTS &&
1190  !(hls->flags & HLS_SINGLE_FILE)) {
1191  en->next = vs->old_segments;
1192  vs->old_segments = en;
1193  if ((ret = hls_delete_old_segments(s, hls, vs)) < 0)
1194  return ret;
1195  } else
1196  av_freep(&en);
1197  } else
1198  vs->nb_entries++;
1199 
1200  if (hls->max_seg_size > 0) {
1201  return 0;
1202  }
1203  vs->sequence++;
1204 
1205  return 0;
1206 }
1207 
1208 static int extract_segment_number(const char *filename) {
1209  const char *dot = strrchr(filename, '.');
1210  const char *num_start = dot - 1;
1211 
1212  while (num_start > filename && *num_start >= '0' && *num_start <= '9') {
1213  num_start--;
1214  }
1215 
1216  num_start++;
1217 
1218  if (num_start == dot)
1219  return -1;
1220 
1221  return atoi(num_start);
1222 }
1223 
1224 static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
1225 {
1226  HLSContext *hls = s->priv_data;
1227  AVIOContext *in;
1228  int ret = 0, is_segment = 0;
1229  int64_t new_start_pos;
1230  char line[MAX_URL_SIZE];
1231  const char *ptr;
1232  const char *end;
1233  double discont_program_date_time = 0;
1234 
1235  if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
1236  &s->interrupt_callback, NULL,
1237  s->protocol_whitelist, s->protocol_blacklist)) < 0)
1238  return ret;
1239 
1240  ff_get_chomp_line(in, line, sizeof(line));
1241  if (strcmp(line, "#EXTM3U")) {
1243  goto fail;
1244  }
1245 
1246  vs->discontinuity = 0;
1247  while (!avio_feof(in)) {
1248  ff_get_chomp_line(in, line, sizeof(line));
1249  if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
1250  int64_t tmp_sequence = strtoll(ptr, NULL, 10);
1251  if (tmp_sequence < vs->sequence)
1252  av_log(hls, AV_LOG_VERBOSE,
1253  "Found playlist sequence number was smaller """
1254  "than specified start sequence number: %"PRId64" < %"PRId64", "
1255  "omitting\n", tmp_sequence, hls->start_sequence);
1256  else {
1257  av_log(hls, AV_LOG_DEBUG, "Found playlist sequence number: %"PRId64"\n", tmp_sequence);
1258  vs->sequence = tmp_sequence;
1259  }
1260  } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
1261  is_segment = 1;
1262  vs->discontinuity = 1;
1263  } else if (av_strstart(line, "#EXTINF:", &ptr)) {
1264  is_segment = 1;
1265  vs->duration = atof(ptr);
1266  } else if (av_stristart(line, "#EXT-X-KEY:", &ptr)) {
1267  ptr = av_stristr(line, "URI=\"");
1268  if (ptr) {
1269  ptr += strlen("URI=\"");
1270  end = av_stristr(ptr, ",");
1271  if (end) {
1272  av_strlcpy(vs->key_uri, ptr, end - ptr);
1273  } else {
1274  av_strlcpy(vs->key_uri, ptr, sizeof(vs->key_uri));
1275  }
1276  }
1277 
1278  ptr = av_stristr(line, "IV=0x");
1279  if (ptr) {
1280  ptr += strlen("IV=0x");
1281  end = av_stristr(ptr, ",");
1282  if (end) {
1283  av_strlcpy(vs->iv_string, ptr, end - ptr);
1284  } else {
1285  av_strlcpy(vs->iv_string, ptr, sizeof(vs->iv_string));
1286  }
1287  }
1288  } else if (av_strstart(line, "#EXT-X-PROGRAM-DATE-TIME:", &ptr)) {
1289  struct tm program_date_time;
1290  int y,M,d,h,m,s;
1291  double ms;
1292  if (sscanf(ptr, "%d-%d-%dT%d:%d:%d.%lf", &y, &M, &d, &h, &m, &s, &ms) != 7) {
1294  goto fail;
1295  }
1296 
1297  program_date_time.tm_year = y - 1900;
1298  program_date_time.tm_mon = M - 1;
1299  program_date_time.tm_mday = d;
1300  program_date_time.tm_hour = h;
1301  program_date_time.tm_min = m;
1302  program_date_time.tm_sec = s;
1303  program_date_time.tm_isdst = -1;
1304 
1305  discont_program_date_time = mktime(&program_date_time);
1306  discont_program_date_time += (double)(ms / 1000);
1307  } else if (av_strstart(line, "#", NULL)) {
1308  continue;
1309  } else if (line[0]) {
1310  if (is_segment) {
1311  char *new_file = av_strdup(line);
1312  if (!new_file) {
1313  ret = AVERROR(ENOMEM);
1314  goto fail;
1315  }
1316  ff_format_set_url(vs->avf, new_file);
1317 
1318  if (vs->has_subtitle) {
1319  int vtt_index = extract_segment_number(line);
1320  const char *vtt_basename = av_basename(vs->vtt_basename);
1321  int len = strlen(vtt_basename) + 11;
1322  char *vtt_file = av_mallocz(len);
1323  if (!vtt_file) {
1324  ret = AVERROR(ENOMEM);
1325  goto fail;
1326  }
1327  snprintf(vtt_file, len, vtt_basename, vtt_index);
1328  ff_format_set_url(vs->vtt_avf, vtt_file);
1329  }
1330 
1331  is_segment = 0;
1332  new_start_pos = avio_tell(vs->avf->pb);
1333  vs->size = new_start_pos - vs->start_pos;
1334  ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size);
1335  if (discont_program_date_time) {
1336  vs->last_segment->discont_program_date_time = discont_program_date_time;
1337  discont_program_date_time += vs->duration;
1338  }
1339  if (ret < 0)
1340  goto fail;
1341  vs->start_pos = new_start_pos;
1342  }
1343  }
1344  }
1345 
1346 fail:
1347  avio_close(in);
1348  return ret;
1349 }
1350 
1352 {
1353  HLSSegment *en;
1354 
1355  while (p) {
1356  en = p;
1357  p = p->next;
1358  av_freep(&en);
1359  }
1360 }
1361 
1363 {
1364  size_t len = strlen(oc->url);
1365  char *final_filename = av_strdup(oc->url);
1366  int ret;
1367 
1368  if (!final_filename)
1369  return AVERROR(ENOMEM);
1370  final_filename[len-4] = '\0';
1371  ret = ff_rename(oc->url, final_filename, s);
1372  oc->url[len-4] = '\0';
1373  av_freep(&final_filename);
1374  return ret;
1375 }
1376 
1377 static const char* get_relative_url(const char *master_url, const char *media_url)
1378 {
1379  const char *p = strrchr(master_url, '/');
1380  size_t base_len = 0;
1381 
1382  if (!p) p = strrchr(master_url, '\\');
1383 
1384  if (p) {
1385  base_len = p - master_url;
1386  if (av_strncasecmp(master_url, media_url, base_len)) {
1387  av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n");
1388  return NULL;
1389  }
1390  } else {
1391  return media_url;
1392  }
1393 
1394  return media_url + base_len + 1;
1395 }
1396 
1398 {
1402  );
1403 
1404  if (stream->codecpar->bit_rate)
1405  return stream->codecpar->bit_rate;
1406  else if (sd) {
1407  AVCPBProperties *props = (AVCPBProperties*)sd->data;
1408  return props->max_bitrate;
1409  }
1410 
1411  return 0;
1412 }
1413 
1415  VariantStream * const input_vs,
1416  int final)
1417 {
1418  HLSContext *hls = s->priv_data;
1419  VariantStream *vs, *temp_vs;
1420  AVStream *vid_st, *aud_st;
1422  unsigned int i, j;
1423  int ret, bandwidth, avg_bandwidth;
1424  const char *m3u8_rel_name = NULL;
1425  const char *vtt_m3u8_rel_name = NULL;
1426  const char *ccgroup;
1427  const char *sgroup = NULL;
1428  ClosedCaptionsStream *ccs;
1429  const char *proto = avio_find_protocol_name(hls->master_m3u8_url);
1430  int is_file_proto = proto && !strcmp(proto, "file");
1431  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || hls->master_publish_rate);
1432  char temp_filename[MAX_URL_SIZE];
1433  int nb_channels;
1434 
1435  input_vs->m3u8_created = 1;
1436  if (!hls->master_m3u8_created) {
1437  /* For the first time, wait until all the media playlists are created */
1438  for (i = 0; i < hls->nb_varstreams; i++)
1439  if (!hls->var_streams[i].m3u8_created)
1440  return 0;
1441  } else {
1442  /* Keep publishing the master playlist at the configured rate */
1443  if ((&hls->var_streams[0] != input_vs || !hls->master_publish_rate ||
1444  input_vs->number % hls->master_publish_rate) && !final)
1445  return 0;
1446  }
1447 
1448  set_http_options(s, &options, hls);
1449  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", hls->master_m3u8_url);
1450  ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options);
1452  if (ret < 0) {
1453  av_log(s, AV_LOG_ERROR, "Failed to open master play list file '%s'\n",
1454  temp_filename);
1455  goto fail;
1456  }
1457 
1459 
1460  for (i = 0; i < hls->nb_ccstreams; i++) {
1461  ccs = &(hls->cc_streams[i]);
1462  avio_printf(hls->m3u8_out, "#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS");
1463  avio_printf(hls->m3u8_out, ",GROUP-ID=\"%s\"", ccs->ccgroup);
1464  avio_printf(hls->m3u8_out, ",NAME=\"%s\"", ccs->instreamid);
1465  if (ccs->language)
1466  avio_printf(hls->m3u8_out, ",LANGUAGE=\"%s\"", ccs->language);
1467  avio_printf(hls->m3u8_out, ",INSTREAM-ID=\"%s\"\n", ccs->instreamid);
1468  }
1469 
1470  /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/
1471  for (i = 0; i < hls->nb_varstreams; i++) {
1472  vs = &(hls->var_streams[i]);
1473 
1474  if (vs->has_video || vs->has_subtitle || !vs->agroup)
1475  continue;
1476 
1477  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1478  if (!m3u8_rel_name) {
1479  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1480  goto fail;
1481  }
1482  nb_channels = 0;
1483  for (j = 0; j < vs->nb_streams; j++)
1485  if (vs->streams[j]->codecpar->ch_layout.nb_channels > nb_channels)
1486  nb_channels = vs->streams[j]->codecpar->ch_layout.nb_channels;
1487 
1488  ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1, nb_channels);
1489  }
1490 
1491  /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/
1492  for (i = 0; i < hls->nb_varstreams; i++) {
1493  vs = &(hls->var_streams[i]);
1494 
1495  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1496  if (!m3u8_rel_name) {
1497  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1498  goto fail;
1499  }
1500 
1501  vid_st = NULL;
1502  aud_st = NULL;
1503  for (j = 0; j < vs->nb_streams; j++) {
1505  vid_st = vs->streams[j];
1506  else if (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
1507  aud_st = vs->streams[j];
1508  }
1509 
1510  if (!vid_st && !aud_st) {
1511  av_log(s, AV_LOG_WARNING, "Media stream not found\n");
1512  continue;
1513  }
1514 
1515  /**
1516  * Traverse through the list of audio only rendition streams and find
1517  * the rendition which has highest bitrate in the same audio group
1518  */
1519  if (vs->agroup) {
1520  for (j = 0; j < hls->nb_varstreams; j++) {
1521  temp_vs = &(hls->var_streams[j]);
1522  if (!temp_vs->has_video && !temp_vs->has_subtitle &&
1523  temp_vs->agroup &&
1524  !av_strcasecmp(temp_vs->agroup, vs->agroup)) {
1525  if (!aud_st)
1526  aud_st = temp_vs->streams[0];
1527  if (temp_vs->streams[0]->codecpar->bit_rate >
1528  aud_st->codecpar->bit_rate)
1529  aud_st = temp_vs->streams[0];
1530  }
1531  }
1532  }
1533 
1534  if (final) {
1535  bandwidth = vs->max_bitrate;
1536  avg_bandwidth = vs->avg_bitrate;
1537  } else {
1538  bandwidth = 0;
1539  if (vid_st)
1540  bandwidth += get_stream_bit_rate(vid_st);
1541  if (aud_st)
1542  bandwidth += get_stream_bit_rate(aud_st);
1543  bandwidth += bandwidth / 10;
1544  }
1545 
1546  ccgroup = NULL;
1547  if (vid_st && vs->ccgroup) {
1548  /* check if this group name is available in the cc map string */
1549  for (j = 0; j < hls->nb_ccstreams; j++) {
1550  ccs = &(hls->cc_streams[j]);
1551  if (!av_strcasecmp(ccs->ccgroup, vs->ccgroup)) {
1552  ccgroup = vs->ccgroup;
1553  break;
1554  }
1555  }
1556  if (j == hls->nb_ccstreams)
1557  av_log(s, AV_LOG_WARNING, "mapping ccgroup %s not found\n",
1558  vs->ccgroup);
1559  }
1560 
1561  if (vid_st && vs->sgroup) {
1562  sgroup = vs->sgroup;
1563  vtt_m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->vtt_m3u8_name);
1564  if (!vtt_m3u8_rel_name) {
1565  av_log(s, AV_LOG_WARNING, "Unable to find relative subtitle URL\n");
1566  break;
1567  }
1568 
1569  ff_hls_write_subtitle_rendition(hls->m3u8_out, sgroup, vtt_m3u8_rel_name, vs->language,
1570  vs->subtitle_varname, i, hls->has_default_key ? vs->is_default : 1);
1571  }
1572 
1573  if (!hls->has_default_key || !hls->has_video_m3u8) {
1574  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, avg_bandwidth, m3u8_rel_name,
1575  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1576  } else {
1577  if (vid_st) {
1578  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, avg_bandwidth, m3u8_rel_name,
1579  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1580  }
1581  }
1582  }
1583 fail:
1584  if (ret >=0)
1585  hls->master_m3u8_created = 1;
1586  hlsenc_io_close(s, &hls->m3u8_out, temp_filename);
1587  if (use_temp_file)
1588  ff_rename(temp_filename, hls->master_m3u8_url, s);
1589 
1590  return ret;
1591 }
1592 
1593 static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
1594 {
1595  HLSContext *hls = s->priv_data;
1596  HLSSegment *en;
1597  int target_duration = 0;
1598  int ret = 0;
1599  char temp_filename[MAX_URL_SIZE];
1600  char temp_vtt_filename[MAX_URL_SIZE];
1601  int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries);
1602  const char *proto = avio_find_protocol_name(vs->m3u8_name);
1603  int is_file_proto = proto && !strcmp(proto, "file");
1604  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || !(hls->pl_type == PLAYLIST_TYPE_VOD));
1605  static unsigned warned_non_file;
1606  char *key_uri = NULL;
1607  char *iv_string = NULL;
1609  double prog_date_time = vs->initial_prog_date_time;
1610  double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? &prog_date_time : NULL;
1611  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1612 
1613  hls->version = 2;
1614  if (!(hls->flags & HLS_ROUND_DURATIONS)) {
1615  hls->version = 3;
1616  }
1617 
1618  if (byterange_mode) {
1619  hls->version = 4;
1620  sequence = 0;
1621  }
1622 
1623  if (hls->flags & HLS_I_FRAMES_ONLY) {
1624  hls->version = 4;
1625  }
1626 
1627  if (hls->flags & HLS_INDEPENDENT_SEGMENTS) {
1628  hls->version = 6;
1629  }
1630 
1631  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1632  hls->version = 7;
1633  }
1634 
1635  if (!is_file_proto && (hls->flags & HLS_TEMP_FILE) && !warned_non_file++)
1636  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
1637 
1638  set_http_options(s, &options, hls);
1639  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", vs->m3u8_name);
1640  ret = hlsenc_io_open(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename, &options);
1642  if (ret < 0) {
1643  goto fail;
1644  }
1645 
1646  for (en = vs->segments; en; en = en->next) {
1647  if (target_duration <= en->duration)
1648  target_duration = lrint(en->duration);
1649  }
1650 
1651  vs->discontinuity_set = 0;
1652  ff_hls_write_playlist_header(byterange_mode ? hls->m3u8_out : vs->out, hls->version, hls->allowcache,
1653  target_duration, sequence, hls->pl_type, hls->flags & HLS_I_FRAMES_ONLY);
1654 
1655  if ((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0) {
1656  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-DISCONTINUITY\n");
1657  vs->discontinuity_set = 1;
1658  }
1659  if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
1660  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
1661  }
1662  for (en = vs->segments; en; en = en->next) {
1663  if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) ||
1664  av_strcasecmp(en->iv_string, iv_string))) {
1665  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri);
1666  if (*en->iv_string)
1667  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, ",IV=0x%s", en->iv_string);
1668  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "\n");
1669  key_uri = en->key_uri;
1670  iv_string = en->iv_string;
1671  }
1672 
1673  if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) {
1674  ff_hls_write_init_file(byterange_mode ? hls->m3u8_out : vs->out, (hls->flags & HLS_SINGLE_FILE) ? en->filename : vs->fmp4_init_filename,
1675  hls->flags & HLS_SINGLE_FILE, vs->init_range_length, 0);
1676  }
1677 
1678  ret = ff_hls_write_file_entry(byterange_mode ? hls->m3u8_out : vs->out, en->discont, byterange_mode,
1679  en->duration, hls->flags & HLS_ROUND_DURATIONS,
1680  en->size, en->pos, hls->baseurl,
1681  en->filename,
1682  en->discont_program_date_time ? &en->discont_program_date_time : prog_date_time_p,
1684  if (en->discont_program_date_time)
1686  if (ret < 0) {
1687  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1688  }
1689  }
1690 
1691  if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
1692  ff_hls_write_end_list(byterange_mode ? hls->m3u8_out : vs->out);
1693 
1694  if (vs->vtt_m3u8_name) {
1695  set_http_options(vs->vtt_avf, &options, hls);
1696  snprintf(temp_vtt_filename, sizeof(temp_vtt_filename), use_temp_file ? "%s.tmp" : "%s", vs->vtt_m3u8_name);
1697  ret = hlsenc_io_open(s, &hls->sub_m3u8_out, temp_vtt_filename, &options);
1699  if (ret < 0) {
1700  goto fail;
1701  }
1703  target_duration, sequence, PLAYLIST_TYPE_NONE, 0);
1704  for (en = vs->segments; en; en = en->next) {
1705  ret = ff_hls_write_file_entry(hls->sub_m3u8_out, en->discont, byterange_mode,
1706  en->duration, 0, en->size, en->pos,
1707  hls->baseurl, en->sub_filename, NULL, 0, 0, 0);
1708  if (ret < 0) {
1709  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1710  }
1711  }
1712 
1713  if (last && !(hls->flags & HLS_OMIT_ENDLIST))
1715 
1716  }
1717 
1718 fail:
1720  ret = hlsenc_io_close(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename);
1721  if (ret < 0) {
1722  return ret;
1723  }
1725  if (use_temp_file) {
1726  ff_rename(temp_filename, vs->m3u8_name, s);
1727  if (vs->vtt_m3u8_name)
1728  ff_rename(temp_vtt_filename, vs->vtt_m3u8_name, s);
1729  }
1730  if (ret >= 0 && hls->master_pl_name)
1731  if (create_master_playlist(s, vs, last) < 0)
1732  av_log(s, AV_LOG_WARNING, "Master playlist creation failed\n");
1733 
1734  return ret;
1735 }
1736 
1738 {
1739  HLSContext *c = s->priv_data;
1740  AVFormatContext *oc = vs->avf;
1741  AVFormatContext *vtt_oc = vs->vtt_avf;
1743  const char *proto = NULL;
1744  int use_temp_file = 0;
1745  char iv_string[KEYSIZE*2 + 1];
1746  int err = 0;
1747 
1748  if (c->flags & HLS_SINGLE_FILE) {
1749  char *new_name = av_strdup(vs->basename);
1750  if (!new_name)
1751  return AVERROR(ENOMEM);
1752  ff_format_set_url(oc, new_name);
1753  if (vs->vtt_basename) {
1754  new_name = av_strdup(vs->vtt_basename);
1755  if (!new_name)
1756  return AVERROR(ENOMEM);
1757  ff_format_set_url(vtt_oc, new_name);
1758  }
1759  } else if (c->max_seg_size > 0) {
1760  char *filename = NULL;
1761  if (replace_int_data_in_filename(&filename,
1762  vs->basename, 'd', vs->sequence) < 1) {
1763  av_freep(&filename);
1764  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -strftime 1 with it\n", vs->basename);
1765  return AVERROR(EINVAL);
1766  }
1767  ff_format_set_url(oc, filename);
1768  } else {
1769  if (c->use_localtime) {
1770  int r;
1771  char *expanded = NULL;
1772 
1773  r = strftime_expand(vs->basename, &expanded);
1774  if (r < 0) {
1775  av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
1776  return r;
1777  }
1778  ff_format_set_url(oc, expanded);
1779 
1780  err = sls_flag_use_localtime_filename(oc, c, vs);
1781  if (err < 0) {
1782  return AVERROR(ENOMEM);
1783  }
1784 
1785  if (c->use_localtime_mkdir) {
1786  const char *dir;
1787  char *fn_copy = av_strdup(oc->url);
1788  if (!fn_copy)
1789  return AVERROR(ENOMEM);
1790  dir = av_dirname(fn_copy);
1791  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1792  av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
1793  av_freep(&fn_copy);
1794  return AVERROR(errno);
1795  }
1796  av_freep(&fn_copy);
1797  }
1798  } else {
1799  char *filename = NULL;
1800  if (replace_int_data_in_filename(&filename,
1801  vs->basename, 'd', vs->sequence) < 1) {
1802  av_freep(&filename);
1803  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -strftime 1 with it\n", vs->basename);
1804  return AVERROR(EINVAL);
1805  }
1806  ff_format_set_url(oc, filename);
1807  }
1808  if (vs->vtt_basename) {
1809  char *filename = NULL;
1810  if (replace_int_data_in_filename(&filename,
1811  vs->vtt_basename, 'd', vs->sequence) < 1) {
1812  av_freep(&filename);
1813  av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename);
1814  return AVERROR(EINVAL);
1815  }
1816  ff_format_set_url(vtt_oc, filename);
1817  }
1818  }
1819 
1820  proto = avio_find_protocol_name(oc->url);
1821  use_temp_file = proto && !strcmp(proto, "file") && (c->flags & HLS_TEMP_FILE);
1822 
1823  if (use_temp_file) {
1824  char *new_name = av_asprintf("%s.tmp", oc->url);
1825  if (!new_name)
1826  return AVERROR(ENOMEM);
1827  ff_format_set_url(oc, new_name);
1828  }
1829 
1830  if (c->key_info_file || c->encrypt) {
1831  if (c->segment_type == SEGMENT_TYPE_FMP4) {
1832  av_log(s, AV_LOG_ERROR, "Encrypted fmp4 not yet supported\n");
1833  return AVERROR_PATCHWELCOME;
1834  }
1835 
1836  if (c->key_info_file && c->encrypt) {
1837  av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file and -hls_enc,"
1838  " ignoring -hls_enc\n");
1839  }
1840 
1841  if (!vs->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) {
1842  if (c->key_info_file) {
1843  if ((err = hls_encryption_start(s, vs)) < 0)
1844  goto fail;
1845  } else {
1846  if (!c->encrypt_started) {
1847  if ((err = do_encrypt(s, vs)) < 0)
1848  goto fail;
1849  c->encrypt_started = 1;
1850  }
1851  av_strlcpy(vs->key_uri, c->key_uri, sizeof(vs->key_uri));
1852  av_strlcpy(vs->key_string, c->key_string, sizeof(vs->key_string));
1853  av_strlcpy(vs->iv_string, c->iv_string, sizeof(vs->iv_string));
1854  }
1855  vs->encrypt_started = 1;
1856  }
1857  err = av_strlcpy(iv_string, vs->iv_string, sizeof(iv_string));
1858  if (!err) {
1859  snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, vs->sequence);
1860  memset(vs->iv_string, 0, sizeof(vs->iv_string));
1861  memcpy(vs->iv_string, iv_string, sizeof(iv_string));
1862  }
1863  }
1864  if (c->segment_type != SEGMENT_TYPE_FMP4) {
1865  if (oc->oformat->priv_class && oc->priv_data) {
1866  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
1867  }
1868  if (c->flags & HLS_SINGLE_FILE) {
1869  if (c->key_info_file || c->encrypt) {
1870  av_dict_set(&options, "encryption_key", vs->key_string, 0);
1871  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
1872 
1873  /* Write temp file with cryption content */
1874  av_freep(&vs->basename_tmp);
1875  vs->basename_tmp = av_asprintf("crypto:%s.tmp", oc->url);
1876 
1877  /* append temp file content into single file */
1878  av_freep(&vs->basename);
1879  vs->basename = av_asprintf("%s", oc->url);
1880  } else {
1881  vs->basename_tmp = vs->basename;
1882  }
1884  if (!vs->out_single_file)
1885  if ((err = hlsenc_io_open(s, &vs->out_single_file, vs->basename, &options)) < 0) {
1886  if (c->ignore_io_errors)
1887  err = 0;
1888  goto fail;
1889  }
1890 
1891  if ((err = hlsenc_io_open(s, &vs->out, vs->basename_tmp, &options)) < 0) {
1892  if (c->ignore_io_errors)
1893  err = 0;
1894  goto fail;
1895  }
1896 
1897  }
1898  }
1899  if (vs->vtt_basename) {
1901  if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < 0) {
1902  if (c->ignore_io_errors)
1903  err = 0;
1904  goto fail;
1905  }
1906  }
1908 
1909  if (vs->vtt_basename) {
1910  err = avformat_write_header(vtt_oc,NULL);
1911  if (err < 0)
1912  return err;
1913  }
1914 
1915  return 0;
1916 fail:
1918 
1919  return err;
1920 }
1921 
1923 {
1924  HLSContext *hls = s->priv_data;
1925 #if HAVE_LIBC_MSVCRT
1926  // no %s support on MSVC, which invokes the invalid parameter handler
1927  // on unsupported format strings, instead of returning an error
1928  int strftime_s_supported = 0;
1929 #else
1930  char b[21];
1931  time_t t = time(NULL);
1932  struct tm tmbuf, *p = localtime_r(&t, &tmbuf);
1933  // no %s support when strftime returned error or left format string unchanged
1934  int strftime_s_supported = strftime(b, sizeof(b), "%s", p) && strcmp(b, "%s");
1935 #endif
1936 
1937  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1938  return strftime_s_supported ? "-%s.m4s" : "-%Y%m%d%H%M%S.m4s";
1939  }
1940  return strftime_s_supported ? "-%s.ts" : "-%Y%m%d%H%M%S.ts";
1941 }
1942 
1943 static int append_postfix(char *name, int name_buf_len, int i)
1944 {
1945  char *p;
1946  char extension[10] = {'\0'};
1947 
1948  p = strrchr(name, '.');
1949  if (p) {
1950  av_strlcpy(extension, p, sizeof(extension));
1951  *p = '\0';
1952  }
1953 
1954  snprintf(name + strlen(name), name_buf_len - strlen(name), POSTFIX_PATTERN, i);
1955 
1956  if (strlen(extension))
1957  av_strlcat(name, extension, name_buf_len);
1958 
1959  return 0;
1960 }
1961 
1962 static int validate_name(int nb_vs, const char *fn)
1963 {
1964  const char *filename, *subdir_name;
1965  char *fn_dup = NULL;
1966  int ret = 0;
1967 
1968  if (!fn)
1969  return AVERROR(EINVAL);
1970 
1971  fn_dup = av_strdup(fn);
1972  if (!fn_dup)
1973  return AVERROR(ENOMEM);
1974  filename = av_basename(fn);
1975  subdir_name = av_dirname(fn_dup);
1976 
1977  if (nb_vs > 1 && !av_stristr(filename, "%v") && !av_stristr(subdir_name, "%v")) {
1978  av_log(NULL, AV_LOG_ERROR, "More than 1 variant streams are present, %%v is expected "
1979  "either in the filename or in the sub-directory name of file %s\n", fn);
1980  ret = AVERROR(EINVAL);
1981  goto fail;
1982  }
1983 
1984  if (av_stristr(filename, "%v") && av_stristr(subdir_name, "%v")) {
1985  av_log(NULL, AV_LOG_ERROR, "%%v is expected either in the filename or "
1986  "in the sub-directory name of file %s, but only in one of them\n", fn);
1987  ret = AVERROR(EINVAL);
1988  goto fail;
1989  }
1990 
1991 fail:
1992  av_freep(&fn_dup);
1993  return ret;
1994 }
1995 
1996 static int format_name(const char *buf, char **s, int index, const char *varname)
1997 {
1998  const char *proto, *dir;
1999  char *orig_buf_dup = NULL, *mod_buf_dup = NULL;
2000  int ret = 0;
2001 
2002  orig_buf_dup = av_strdup(buf);
2003  if (!orig_buf_dup)
2004  return AVERROR(ENOMEM);
2005 
2006  if (!av_stristr(buf, "%v")) {
2007  *s = orig_buf_dup;
2008  return 0;
2009  }
2010 
2011  if (!varname) {
2012  if (replace_int_data_in_filename(s, orig_buf_dup, 'v', index) < 1) {
2013  ret = AVERROR(EINVAL);
2014  goto fail;
2015  }
2016  } else {
2017  if (replace_str_data_in_filename(s, orig_buf_dup, 'v', varname) < 1) {
2018  ret = AVERROR(EINVAL);
2019  goto fail;
2020  }
2021  }
2022 
2023  proto = avio_find_protocol_name(orig_buf_dup);
2024  dir = av_dirname(orig_buf_dup);
2025 
2026  /* if %v is present in the file's directory, create sub-directory */
2027  if (av_stristr(dir, "%v") && proto && !strcmp(proto, "file")) {
2028  mod_buf_dup = av_strdup(*s);
2029  dir = av_dirname(mod_buf_dup);
2030  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
2031  ret = AVERROR(errno);
2032  goto fail;
2033  }
2034  }
2035 
2036 fail:
2037  av_freep(&orig_buf_dup);
2038  av_freep(&mod_buf_dup);
2039  return ret;
2040 }
2041 
2043  enum AVMediaType codec_type,
2044  int64_t stream_id)
2045 {
2046  unsigned int stream_index, cnt;
2047  if (stream_id < 0 || stream_id > s->nb_streams - 1)
2048  return -1;
2049  cnt = 0;
2050  for (stream_index = 0; stream_index < s->nb_streams; stream_index++) {
2051  if (s->streams[stream_index]->codecpar->codec_type != codec_type)
2052  continue;
2053  if (cnt == stream_id)
2054  return stream_index;
2055  cnt++;
2056  }
2057  return -1;
2058 }
2059 
2061 {
2062  HLSContext *hls = s->priv_data;
2063  VariantStream *vs;
2064  int stream_index, i, j;
2065  enum AVMediaType codec_type;
2066  int nb_varstreams = 0, nb_streams;
2067  char *p, *q, *saveptr1, *saveptr2, *varstr, *keyval;
2068  const char *val;
2069 
2070  /**
2071  * Expected format for var_stream_map string is as below:
2072  * "a:0,v:0 a:1,v:1"
2073  * "a:0,agroup:a0,default:1,language:ENG a:1,agroup:a1,default:0 v:0,agroup:a0 v:1,agroup:a1"
2074  * This string specifies how to group the audio, video and subtitle streams
2075  * into different variant streams. The variant stream groups are separated
2076  * by space.
2077  *
2078  * a:, v:, s: are keys to specify audio, video and subtitle streams
2079  * respectively. Allowed values are 0 to 9 digits (limited just based on
2080  * practical usage)
2081  *
2082  * agroup: is key to specify audio group. A string can be given as value.
2083  * sgroup: is key to specify subtitle group. A string can be given as value.
2084  */
2085  p = av_strdup(hls->var_stream_map);
2086  if (!p)
2087  return AVERROR(ENOMEM);
2088 
2089  q = p;
2090  while (av_strtok(q, " \t", &saveptr1)) {
2091  q = NULL;
2092  nb_varstreams++;
2093  }
2094  av_freep(&p);
2095 
2096  hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * nb_varstreams);
2097  if (!hls->var_streams)
2098  return AVERROR(ENOMEM);
2099  hls->nb_varstreams = nb_varstreams;
2100 
2101  p = hls->var_stream_map;
2102  nb_varstreams = 0;
2103  while (varstr = av_strtok(p, " \t", &saveptr1)) {
2104  p = NULL;
2105 
2106  if (nb_varstreams < hls->nb_varstreams) {
2107  vs = &(hls->var_streams[nb_varstreams]);
2108  vs->var_stream_idx = nb_varstreams;
2109  vs->is_default = 0;
2110  nb_varstreams++;
2111  } else
2112  return AVERROR(EINVAL);
2113 
2114  q = varstr;
2115  while (1) {
2116  if (!av_strncasecmp(q, "a:", 2) || !av_strncasecmp(q, "v:", 2) ||
2117  !av_strncasecmp(q, "s:", 2))
2118  vs->nb_streams++;
2119  q = strchr(q, ',');
2120  if (!q)
2121  break;
2122  q++;
2123  }
2124  vs->streams = av_mallocz(sizeof(AVStream *) * vs->nb_streams);
2125  if (!vs->streams)
2126  return AVERROR(ENOMEM);
2127 
2128  nb_streams = 0;
2129  while (keyval = av_strtok(varstr, ",", &saveptr2)) {
2130  int64_t num;
2131  char *end;
2132  varstr = NULL;
2133  if (av_strstart(keyval, "language:", &val)) {
2134  vs->language = val;
2135  continue;
2136  } else if (av_strstart(keyval, "default:", &val)) {
2137  vs->is_default = (!av_strncasecmp(val, "YES", strlen("YES")) ||
2138  (!av_strncasecmp(val, "1", strlen("1"))));
2139  hls->has_default_key = 1;
2140  continue;
2141  } else if (av_strstart(keyval, "name:", &val)) {
2142  vs->varname = val;
2143  continue;
2144  } else if (av_strstart(keyval, "sname:", &val)) {
2145  vs->subtitle_varname = val;
2146  continue;
2147  } else if (av_strstart(keyval, "agroup:", &val)) {
2148  vs->agroup = val;
2149  continue;
2150  } else if (av_strstart(keyval, "sgroup:", &val)) {
2151  vs->sgroup = val;
2152  continue;
2153  } else if (av_strstart(keyval, "ccgroup:", &val)) {
2154  vs->ccgroup = val;
2155  continue;
2156  } else if (av_strstart(keyval, "v:", &val)) {
2158  hls->has_video_m3u8 = 1;
2159  } else if (av_strstart(keyval, "a:", &val)) {
2161  } else if (av_strstart(keyval, "s:", &val)) {
2163  } else {
2164  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2165  return AVERROR(EINVAL);
2166  }
2167 
2168  num = strtoll(val, &end, 10);
2169  if (!av_isdigit(*val) || *end != '\0') {
2170  av_log(s, AV_LOG_ERROR, "Invalid stream number: '%s'\n", val);
2171  return AVERROR(EINVAL);
2172  }
2173  stream_index = get_nth_codec_stream_index(s, codec_type, num);
2174 
2175  if (stream_index >= 0 && nb_streams < vs->nb_streams) {
2176  for (i = 0; nb_streams > 0 && i < nb_streams; i++) {
2177  if (vs->streams[i] == s->streams[stream_index]) {
2178  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once inside "
2179  "variant definition #%d\n", nb_varstreams - 1);
2180  return AVERROR(EINVAL);
2181  }
2182  }
2183  for (j = 0; nb_varstreams > 1 && j < nb_varstreams - 1; j++) {
2184  for (i = 0; i < hls->var_streams[j].nb_streams; i++) {
2185  if (hls->var_streams[j].streams[i] == s->streams[stream_index]) {
2186  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once "
2187  "in two different variant definitions #%d and #%d\n",
2188  j, nb_varstreams - 1);
2189  return AVERROR(EINVAL);
2190  }
2191  }
2192  }
2193  vs->streams[nb_streams++] = s->streams[stream_index];
2194  } else {
2195  av_log(s, AV_LOG_ERROR, "Unable to map stream at %s\n", keyval);
2196  return AVERROR(EINVAL);
2197  }
2198  }
2199  }
2200  av_log(s, AV_LOG_DEBUG, "Number of variant streams %d\n",
2201  hls->nb_varstreams);
2202 
2203  return 0;
2204 }
2205 
2207 {
2208  HLSContext *hls = s->priv_data;
2209  int nb_ccstreams = 0;
2210  char *p, *q, *ccstr, *keyval;
2211  char *saveptr1 = NULL, *saveptr2 = NULL;
2212  const char *val;
2213  ClosedCaptionsStream *ccs;
2214 
2215  p = av_strdup(hls->cc_stream_map);
2216  if(!p)
2217  return AVERROR(ENOMEM);
2218 
2219  q = p;
2220  while (av_strtok(q, " \t", &saveptr1)) {
2221  q = NULL;
2222  nb_ccstreams++;
2223  }
2224  av_freep(&p);
2225 
2226  hls->cc_streams = av_mallocz(sizeof(*hls->cc_streams) * nb_ccstreams);
2227  if (!hls->cc_streams)
2228  return AVERROR(ENOMEM);
2229  hls->nb_ccstreams = nb_ccstreams;
2230 
2231  p = hls->cc_stream_map;
2232  nb_ccstreams = 0;
2233  while (ccstr = av_strtok(p, " \t", &saveptr1)) {
2234  p = NULL;
2235 
2236  if (nb_ccstreams < hls->nb_ccstreams)
2237  ccs = &(hls->cc_streams[nb_ccstreams++]);
2238  else
2239  return AVERROR(EINVAL);
2240 
2241  while (keyval = av_strtok(ccstr, ",", &saveptr2)) {
2242  ccstr = NULL;
2243 
2244  if (av_strstart(keyval, "ccgroup:", &val)) {
2245  ccs->ccgroup = val;
2246  } else if (av_strstart(keyval, "instreamid:", &val)) {
2247  ccs->instreamid = val;
2248  } else if (av_strstart(keyval, "language:", &val)) {
2249  ccs->language = val;
2250  } else {
2251  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2252  return AVERROR(EINVAL);
2253  }
2254  }
2255 
2256  if (!ccs->ccgroup || !ccs->instreamid) {
2257  av_log(s, AV_LOG_ERROR, "Insufficient parameters in cc stream map string\n");
2258  return AVERROR(EINVAL);
2259  }
2260 
2261  if (av_strstart(ccs->instreamid, "CC", &val)) {
2262  if (atoi(val) < 1 || atoi(val) > 4) {
2263  av_log(s, AV_LOG_ERROR, "Invalid instream ID CC index %d in %s, range 1-4\n",
2264  atoi(val), ccs->instreamid);
2265  return AVERROR(EINVAL);
2266  }
2267  } else if (av_strstart(ccs->instreamid, "SERVICE", &val)) {
2268  if (atoi(val) < 1 || atoi(val) > 63) {
2269  av_log(s, AV_LOG_ERROR, "Invalid instream ID SERVICE index %d in %s, range 1-63 \n",
2270  atoi(val), ccs->instreamid);
2271  return AVERROR(EINVAL);
2272  }
2273  } else {
2274  av_log(s, AV_LOG_ERROR, "Invalid instream ID %s, supported are CCn or SERVICEn\n",
2275  ccs->instreamid);
2276  return AVERROR(EINVAL);
2277  }
2278  }
2279 
2280  return 0;
2281 }
2282 
2284 {
2285  HLSContext *hls = s->priv_data;
2286  unsigned int i;
2287  int ret = 0;
2288 
2289  if (hls->cc_stream_map) {
2291  if (ret < 0)
2292  return ret;
2293  }
2294 
2295  if (hls->var_stream_map) {
2297  } else {
2298  //By default, a single variant stream with all the codec streams is created
2299  hls->var_streams = av_mallocz(sizeof(*hls->var_streams));
2300  if (!hls->var_streams)
2301  return AVERROR(ENOMEM);
2302  hls->nb_varstreams = 1;
2303 
2304  hls->var_streams[0].var_stream_idx = 0;
2305  hls->var_streams[0].nb_streams = s->nb_streams;
2306  hls->var_streams[0].streams = av_mallocz(sizeof(AVStream *) *
2307  hls->var_streams[0].nb_streams);
2308  if (!hls->var_streams[0].streams)
2309  return AVERROR(ENOMEM);
2310 
2311  //by default, the first available ccgroup is mapped to the variant stream
2312  if (hls->nb_ccstreams)
2313  hls->var_streams[0].ccgroup = hls->cc_streams[0].ccgroup;
2314 
2315  for (i = 0; i < s->nb_streams; i++)
2316  hls->var_streams[0].streams[i] = s->streams[i];
2317  }
2318  return 0;
2319 }
2320 
2322 {
2323  HLSContext *hls = s->priv_data;
2324  const char *dir;
2325  char *fn1= NULL, *fn2 = NULL;
2326  int ret = 0;
2327 
2328  fn1 = av_strdup(s->url);
2329  if (!fn1)
2330  return AVERROR(ENOMEM);
2331  dir = av_dirname(fn1);
2332 
2333  /**
2334  * if output file's directory has %v, variants are created in sub-directories
2335  * then master is created at the sub-directories level
2336  */
2337  if (dir && av_stristr(av_basename(dir), "%v")) {
2338  fn2 = av_strdup(dir);
2339  if (!fn2) {
2340  ret = AVERROR(ENOMEM);
2341  goto fail;
2342  }
2343  dir = av_dirname(fn2);
2344  }
2345 
2346  if (dir && strcmp(dir, "."))
2348  else
2350 
2351  if (!hls->master_m3u8_url) {
2352  ret = AVERROR(ENOMEM);
2353  goto fail;
2354  }
2355 
2356 fail:
2357  av_freep(&fn1);
2358  av_freep(&fn2);
2359 
2360  return ret;
2361 }
2362 
2364 {
2365  HLSContext *hls = s->priv_data;
2366  int ret, i, j;
2367  VariantStream *vs = NULL;
2368 
2369  for (i = 0; i < hls->nb_varstreams; i++) {
2370  int subtitle_streams = 0;
2371  vs = &hls->var_streams[i];
2372 
2374  if (ret < 0)
2375  return ret;
2376  //av_assert0(s->nb_streams == hls->avf->nb_streams);
2377  for (j = 0; j < vs->nb_streams; j++) {
2378  AVStream *inner_st;
2379  AVStream *outer_st = vs->streams[j];
2380 
2381  if (hls->max_seg_size > 0) {
2382  if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
2383  (outer_st->codecpar->bit_rate > hls->max_seg_size)) {
2384  av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, "
2385  "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.",
2386  outer_st->codecpar->bit_rate, hls->max_seg_size);
2387  }
2388  }
2389 
2390  if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
2391  inner_st = vs->avf->streams[j - subtitle_streams];
2392  else if (vs->vtt_avf) {
2393  inner_st = vs->vtt_avf->streams[0];
2394  subtitle_streams++;
2395  } else {
2396  /* We have a subtitle stream, when the user does not want one */
2397  inner_st = NULL;
2398  continue;
2399  }
2400  avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
2401  if (outer_st->codecpar->codec_id == AV_CODEC_ID_HEVC &&
2402  outer_st->codecpar->codec_tag != MKTAG('h','v','c','1')) {
2403  av_log(s, AV_LOG_WARNING, "Stream HEVC is not hvc1, you should use tag:v hvc1 to set it.\n");
2404  }
2405  write_codec_attr(outer_st, vs);
2406 
2407  }
2408  /* Update the Codec Attr string for the mapped audio groups */
2409  if (vs->has_video && vs->agroup) {
2410  for (j = 0; j < hls->nb_varstreams; j++) {
2411  VariantStream *vs_agroup = &(hls->var_streams[j]);
2412  if (!vs_agroup->has_video && !vs_agroup->has_subtitle &&
2413  vs_agroup->agroup &&
2414  !av_strcasecmp(vs_agroup->agroup, vs->agroup)) {
2415  write_codec_attr(vs_agroup->streams[0], vs);
2416  }
2417  }
2418  }
2419  }
2420 
2421  return 0;
2422 }
2423 
2425 {
2426  HLSContext *hls = s->priv_data;
2428  int ret = 0;
2429 
2430  set_http_options(s, &options, hls);
2433  if (ret < 0)
2434  return ret;
2436  hlsenc_io_close(s, &vs->out, hls->fmp4_init_filename);
2437 
2438  return ret;
2439 }
2440 
2442 {
2443  int64_t ret = 0;
2444  int64_t read_byte = 0;
2445  int64_t total_size = 0;
2446  char *filename = NULL;
2447  char buf[BUFSIZE];
2448  AVFormatContext *oc = vs->avf;
2449 
2450  hlsenc_io_close(s, &vs->out, vs->basename_tmp);
2451  filename = av_asprintf("%s.tmp", oc->url);
2452  ret = s->io_open(s, &vs->out, filename, AVIO_FLAG_READ, NULL);
2453  if (ret < 0) {
2454  av_free(filename);
2455  return ret;
2456  }
2457 
2458  do {
2459  read_byte = avio_read(vs->out, buf, BUFSIZE);
2460  if (read_byte > 0) {
2461  avio_write(vs->out_single_file, buf, read_byte);
2462  total_size += read_byte;
2463  ret = total_size;
2464  }
2465  } while (read_byte > 0);
2466 
2467  hlsenc_io_close(s, &vs->out, filename);
2468  av_free(filename);
2469 
2470  return ret;
2471 }
2473 {
2474  HLSContext *hls = s->priv_data;
2475  AVFormatContext *oc = NULL;
2476  AVStream *st = s->streams[pkt->stream_index];
2477  int64_t end_pts = 0;
2478  int is_ref_pkt = 1;
2479  int ret = 0, can_split = 1, i, j;
2480  int stream_index = 0;
2481  int range_length = 0;
2482  const char *proto = NULL;
2483  int use_temp_file = 0;
2484  VariantStream *vs = NULL;
2485  char *old_filename = NULL;
2486 
2487  for (i = 0; i < hls->nb_varstreams; i++) {
2488  int subtitle_streams = 0;
2489  vs = &hls->var_streams[i];
2490  for (j = 0; j < vs->nb_streams; j++) {
2492  subtitle_streams++;
2493  }
2494  if (vs->streams[j] == st) {
2496  oc = vs->vtt_avf;
2497  stream_index = 0;
2498  } else {
2499  oc = vs->avf;
2500  stream_index = j - subtitle_streams;
2501  }
2502  break;
2503  }
2504  }
2505 
2506  if (oc)
2507  break;
2508  }
2509 
2510  if (!oc) {
2511  av_log(s, AV_LOG_ERROR, "Unable to find mapping variant stream\n");
2512  return AVERROR(ENOMEM);
2513  }
2514 
2515  end_pts = hls->recording_time * vs->number;
2516 
2517  if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
2518  /* reset end_pts, hls->recording_time at end of the init hls list */
2519  int64_t init_list_dur = hls->init_time * vs->nb_entries;
2520  int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries) * hls->time;
2521  hls->recording_time = hls->time;
2522  end_pts = init_list_dur + after_init_list_dur ;
2523  }
2524 
2525  if (vs->start_pts == AV_NOPTS_VALUE) {
2526  vs->start_pts = pkt->pts;
2528  vs->start_pts_from_audio = 1;
2529  }
2531  vs->start_pts = pkt->pts;
2532  vs->start_pts_from_audio = 0;
2533  }
2534 
2535  if (vs->has_video) {
2537  ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME));
2538  is_ref_pkt = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->stream_index == vs->reference_stream_index);
2539  }
2540  if (pkt->pts == AV_NOPTS_VALUE)
2541  is_ref_pkt = can_split = 0;
2542 
2543  if (is_ref_pkt) {
2544  if (vs->end_pts == AV_NOPTS_VALUE)
2545  vs->end_pts = pkt->pts;
2546  if (vs->new_start) {
2547  vs->new_start = 0;
2548  vs->duration = (double)(pkt->pts - vs->end_pts)
2549  * st->time_base.num / st->time_base.den;
2550  vs->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2551  } else {
2552  if (pkt->duration) {
2553  vs->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2554  } else {
2555  av_log(s, AV_LOG_WARNING, "Stream %d packet with pts %" PRId64 " has duration 0. The segment duration may not be precise.\n",
2556  pkt->stream_index, pkt->pts);
2557  vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2558  }
2559  }
2560  }
2561 
2562  can_split = can_split && (pkt->pts - vs->end_pts > 0);
2563  if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base,
2564  end_pts, AV_TIME_BASE_Q) >= 0) {
2565  int64_t new_start_pos;
2566  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2567  double cur_duration;
2568 
2569  av_write_frame(oc, NULL); /* Flush any buffered data */
2570  new_start_pos = avio_tell(oc->pb);
2571  vs->size = new_start_pos - vs->start_pos;
2572  avio_flush(oc->pb);
2573  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2574  if (!vs->init_range_length) {
2575  range_length = avio_close_dyn_buf(oc->pb, &vs->init_buffer);
2576  if (range_length <= 0)
2577  return AVERROR(EINVAL);
2578  avio_write(vs->out, vs->init_buffer, range_length);
2579  if (!hls->resend_init_file)
2580  av_freep(&vs->init_buffer);
2581  vs->init_range_length = range_length;
2582  avio_open_dyn_buf(&oc->pb);
2583  vs->packets_written = 0;
2584  vs->start_pos = range_length;
2585  if (!byterange_mode) {
2587  }
2588  }
2589  }
2590  if (!byterange_mode) {
2591  if (vs->vtt_avf) {
2592  hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url);
2593  }
2594  }
2595 
2596  if (hls->flags & HLS_SINGLE_FILE) {
2597  ret = flush_dynbuf(vs, &range_length);
2598  av_freep(&vs->temp_buffer);
2599  if (ret < 0) {
2600  return ret;
2601  }
2602  vs->size = range_length;
2603  if (hls->key_info_file || hls->encrypt)
2604  vs->size = append_single_file(s, vs);
2605  } else {
2606  if (oc->url[0]) {
2607  proto = avio_find_protocol_name(oc->url);
2608  use_temp_file = proto && !strcmp(proto, "file")
2609  && (hls->flags & HLS_TEMP_FILE);
2610  }
2611 
2612  if ((hls->max_seg_size > 0 && (vs->size + vs->start_pos >= hls->max_seg_size)) || !byterange_mode) {
2614  char *filename = NULL;
2615  if (hls->key_info_file || hls->encrypt) {
2616  av_dict_set(&options, "encryption_key", vs->key_string, 0);
2617  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2618  filename = av_asprintf("crypto:%s", oc->url);
2619  } else {
2620  filename = av_asprintf("%s", oc->url);
2621  }
2622  if (!filename) {
2624  return AVERROR(ENOMEM);
2625  }
2626 
2627  // look to rename the asset name
2628  if (use_temp_file)
2629  av_dict_set(&options, "mpegts_flags", "resend_headers", 0);
2630 
2631  set_http_options(s, &options, hls);
2632 
2633  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2634  if (ret < 0) {
2636  "Failed to open file '%s'\n", filename);
2637  av_freep(&filename);
2639  return hls->ignore_io_errors ? 0 : ret;
2640  }
2641  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2642  write_styp(vs->out);
2643  }
2644  ret = flush_dynbuf(vs, &range_length);
2645  if (ret < 0) {
2646  av_freep(&filename);
2648  return ret;
2649  }
2650  vs->size = range_length;
2651  ret = hlsenc_io_close(s, &vs->out, filename);
2652  if (ret < 0) {
2653  av_log(s, AV_LOG_WARNING, "upload segment failed,"
2654  " will retry with a new http session.\n");
2655  ff_format_io_close(s, &vs->out);
2656  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2657  if (ret >= 0) {
2658  reflush_dynbuf(vs, &range_length);
2659  ret = hlsenc_io_close(s, &vs->out, filename);
2660  }
2661  }
2663  av_freep(&vs->temp_buffer);
2664  av_freep(&filename);
2665  }
2666 
2667  if (use_temp_file)
2668  hls_rename_temp_file(s, oc);
2669  }
2670 
2671  if (ret < 0)
2672  return ret;
2673 
2674  old_filename = av_strdup(oc->url);
2675  if (!old_filename) {
2676  return AVERROR(ENOMEM);
2677  }
2678 
2679  cur_duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2680  ret = hls_append_segment(s, hls, vs, cur_duration, vs->start_pos, vs->size);
2681  vs->end_pts = pkt->pts;
2682  vs->duration = 0;
2683  if (ret < 0) {
2684  av_freep(&old_filename);
2685  return ret;
2686  }
2687 
2688  // if we're building a VOD playlist, skip writing the manifest multiple times, and just wait until the end
2689  if (hls->pl_type != PLAYLIST_TYPE_VOD) {
2690  if ((ret = hls_window(s, 0, vs)) < 0) {
2691  av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2692  ff_format_io_close(s, &vs->out);
2693  if ((ret = hls_window(s, 0, vs)) < 0) {
2694  av_freep(&old_filename);
2695  return ret;
2696  }
2697  }
2698  }
2699 
2700  if (hls->resend_init_file && hls->segment_type == SEGMENT_TYPE_FMP4) {
2701  ret = hls_init_file_resend(s, vs);
2702  if (ret < 0) {
2703  av_freep(&old_filename);
2704  return ret;
2705  }
2706  }
2707 
2708  if (hls->flags & HLS_SINGLE_FILE) {
2709  vs->start_pos += vs->size;
2710  if (hls->key_info_file || hls->encrypt)
2711  ret = hls_start(s, vs);
2712  if (hls->segment_type == SEGMENT_TYPE_MPEGTS && oc->oformat->priv_class && oc->priv_data) {
2713  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
2714  }
2715  } else if (hls->max_seg_size > 0) {
2716  if (vs->size + vs->start_pos >= hls->max_seg_size) {
2717  vs->sequence++;
2718  sls_flag_file_rename(hls, vs, old_filename);
2719  ret = hls_start(s, vs);
2720  vs->start_pos = 0;
2721  /* When split segment by byte, the duration is short than hls_time,
2722  * so it is not enough one segment duration as hls_time, */
2723  } else {
2724  vs->start_pos = new_start_pos;
2725  }
2726  } else {
2727  vs->start_pos = 0;
2728  sls_flag_file_rename(hls, vs, old_filename);
2729  ret = hls_start(s, vs);
2730  }
2731  vs->number++;
2732  av_freep(&old_filename);
2733 
2734  if (ret < 0) {
2735  return ret;
2736  }
2737  }
2738 
2739  vs->packets_written++;
2740  if (oc->pb) {
2741  ret = ff_write_chained(oc, stream_index, pkt, s, 0);
2742  vs->video_keyframe_size += pkt->size;
2744  vs->video_keyframe_size = avio_tell(oc->pb);
2745  } else {
2746  vs->video_keyframe_pos = avio_tell(vs->out);
2747  }
2748  if (hls->ignore_io_errors)
2749  ret = 0;
2750  }
2751 
2752  return ret;
2753 }
2754 
2756 {
2757  HLSContext *hls = s->priv_data;
2758  int i = 0;
2759  VariantStream *vs = NULL;
2760 
2761  for (i = 0; i < hls->nb_varstreams; i++) {
2762  vs = &hls->var_streams[i];
2763 
2764  av_freep(&vs->basename);
2767  av_freep(&vs->vtt_basename);
2768  av_freep(&vs->vtt_m3u8_name);
2769 
2772  if (hls->resend_init_file)
2773  av_freep(&vs->init_buffer);
2776  av_freep(&vs->m3u8_name);
2777  av_freep(&vs->streams);
2778  }
2779 
2780  ff_format_io_close(s, &hls->m3u8_out);
2783  av_freep(&hls->key_basename);
2784  av_freep(&hls->var_streams);
2785  av_freep(&hls->cc_streams);
2786  av_freep(&hls->master_m3u8_url);
2787 }
2788 
2790 {
2791  HLSContext *hls = s->priv_data;
2792  AVFormatContext *oc = NULL;
2793  AVFormatContext *vtt_oc = NULL;
2794  char *old_filename = NULL;
2795  const char *proto = NULL;
2796  int use_temp_file = 0;
2797  int i;
2798  int ret = 0;
2799  VariantStream *vs = NULL;
2801  int range_length, byterange_mode;
2802 
2803  for (i = 0; i < hls->nb_varstreams; i++) {
2804  char *filename = NULL;
2805  vs = &hls->var_streams[i];
2806  oc = vs->avf;
2807  vtt_oc = vs->vtt_avf;
2808  old_filename = av_strdup(oc->url);
2809  use_temp_file = 0;
2810 
2811  if (!old_filename) {
2812  return AVERROR(ENOMEM);
2813  }
2814  if (hls->key_info_file || hls->encrypt) {
2815  av_dict_set(&options, "encryption_key", vs->key_string, 0);
2816  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2817  filename = av_asprintf("crypto:%s", oc->url);
2818  } else {
2819  filename = av_asprintf("%s", oc->url);
2820  }
2821  if (!filename) {
2823  av_freep(&old_filename);
2824  return AVERROR(ENOMEM);
2825  }
2826 
2827  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2828  int range_length = 0;
2829  if (!vs->init_range_length) {
2830  uint8_t *buffer = NULL;
2831  av_write_frame(oc, NULL); /* Flush any buffered data */
2832 
2833  range_length = avio_close_dyn_buf(oc->pb, &buffer);
2834  avio_write(vs->out, buffer, range_length);
2835  av_freep(&buffer);
2836  vs->init_range_length = range_length;
2837  avio_open_dyn_buf(&oc->pb);
2838  vs->packets_written = 0;
2839  vs->start_pos = range_length;
2840  byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2841  if (!byterange_mode) {
2842  ff_format_io_close(s, &vs->out);
2844  }
2845  }
2846  }
2847  if (!(hls->flags & HLS_SINGLE_FILE)) {
2848  set_http_options(s, &options, hls);
2849  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2850  if (ret < 0) {
2851  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2852  goto failed;
2853  }
2854  if (hls->segment_type == SEGMENT_TYPE_FMP4)
2855  write_styp(vs->out);
2856  }
2857  ret = flush_dynbuf(vs, &range_length);
2858  if (ret < 0)
2859  goto failed;
2860 
2861  vs->size = range_length;
2862  ret = hlsenc_io_close(s, &vs->out, filename);
2863  if (ret < 0) {
2864  av_log(s, AV_LOG_WARNING, "upload segment failed, will retry with a new http session.\n");
2865  ff_format_io_close(s, &vs->out);
2866  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2867  if (ret < 0) {
2868  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2869  goto failed;
2870  }
2871  reflush_dynbuf(vs, &range_length);
2872  ret = hlsenc_io_close(s, &vs->out, filename);
2873  if (ret < 0)
2874  av_log(s, AV_LOG_WARNING, "Failed to upload file '%s' at the end.\n", oc->url);
2875  }
2876  if (hls->flags & HLS_SINGLE_FILE) {
2877  if (hls->key_info_file || hls->encrypt) {
2878  vs->size = append_single_file(s, vs);
2879  }
2881  }
2882 failed:
2883  av_freep(&vs->temp_buffer);
2885  av_freep(&filename);
2886  av_write_trailer(oc);
2887  if (oc->url[0]) {
2888  proto = avio_find_protocol_name(oc->url);
2889  use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & HLS_TEMP_FILE);
2890  }
2891 
2892  // rename that segment from .tmp to the real one
2893  if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) {
2894  hls_rename_temp_file(s, oc);
2895  av_freep(&old_filename);
2896  old_filename = av_strdup(oc->url);
2897 
2898  if (!old_filename) {
2899  return AVERROR(ENOMEM);
2900  }
2901  }
2902 
2903  /* after av_write_trailer, then duration + 1 duration per packet */
2904  hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size);
2905 
2906  sls_flag_file_rename(hls, vs, old_filename);
2907 
2908  if (vtt_oc) {
2909  if (vtt_oc->pb)
2910  av_write_trailer(vtt_oc);
2911  vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos;
2912  ff_format_io_close(s, &vtt_oc->pb);
2913  }
2914  ret = hls_window(s, 1, vs);
2915  if (ret < 0) {
2916  av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2917  ff_format_io_close(s, &vs->out);
2918  hls_window(s, 1, vs);
2919  }
2920  ffio_free_dyn_buf(&oc->pb);
2921 
2922  av_free(old_filename);
2923  }
2924 
2925  return 0;
2926 }
2927 
2928 
2930 {
2931  int ret = 0;
2932  int i = 0;
2933  int j = 0;
2934  HLSContext *hls = s->priv_data;
2935  const char *pattern;
2936  VariantStream *vs = NULL;
2937  const char *vtt_pattern = hls->flags & HLS_SINGLE_FILE ? ".vtt" : "%d.vtt";
2938  char *p = NULL;
2939  int http_base_proto = ff_is_http_proto(s->url);
2940  int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;
2941  double initial_program_date_time = av_gettime() / 1000000.0;
2942 
2943  if (hls->use_localtime) {
2945  } else {
2946  pattern = hls->segment_type == SEGMENT_TYPE_FMP4 ? "%d.m4s" : "%d.ts";
2947  if (hls->flags & HLS_SINGLE_FILE)
2948  pattern += 2;
2949  }
2950 
2951  hls->has_default_key = 0;
2952  hls->has_video_m3u8 = 0;
2954  if (ret < 0) {
2955  av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",
2956  ret);
2957  return ret;
2958  }
2959 
2960  if (!hls->method && http_base_proto) {
2961  av_log(hls, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n");
2962  }
2963 
2964  ret = validate_name(hls->nb_varstreams, s->url);
2965  if (ret < 0)
2966  return ret;
2967 
2968  if (hls->segment_filename) {
2970  if (ret < 0)
2971  return ret;
2972  }
2973 
2974  if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {
2976  if (ret < 0)
2977  return ret;
2978  }
2979 
2980  if (hls->subtitle_filename) {
2982  if (ret < 0)
2983  return ret;
2984  }
2985 
2986  if (hls->master_pl_name) {
2988  if (ret < 0) {
2989  av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",
2990  ret);
2991  return ret;
2992  }
2993  }
2994 
2998  time_t t = time(NULL);
3000  hls->start_sequence = av_gettime();
3002  hls->start_sequence = (int64_t)t;
3004  char b[15];
3005  struct tm *p, tmbuf;
3006  if (!(p = localtime_r(&t, &tmbuf)))
3007  return AVERROR(errno);
3008  if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
3009  return AVERROR(ENOMEM);
3010  hls->start_sequence = strtoll(b, NULL, 10);
3011  }
3012  av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
3013  }
3014 
3015  hls->recording_time = hls->init_time && hls->max_nb_segments > 0 ? hls->init_time : hls->time;
3016 
3017  if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) {
3018  // Independent segments cannot be guaranteed when splitting by time
3021  "'split_by_time' and 'independent_segments' cannot be "
3022  "enabled together. Disabling 'independent_segments' flag\n");
3023  }
3024 
3025  for (i = 0; i < hls->nb_varstreams; i++) {
3026  vs = &hls->var_streams[i];
3027 
3028  ret = format_name(s->url, &vs->m3u8_name, i, vs->varname);
3029  if (ret < 0)
3030  return ret;
3031 
3032  vs->sequence = hls->start_sequence;
3033  vs->start_pts = AV_NOPTS_VALUE;
3034  vs->end_pts = AV_NOPTS_VALUE;
3035  vs->current_segment_final_filename_fmt[0] = '\0';
3036  vs->initial_prog_date_time = initial_program_date_time;
3037 
3038  for (j = 0; j < vs->nb_streams; j++) {
3040  /* Get one video stream to reference for split segments
3041  * so use the first video stream index. */
3042  if ((vs->has_video == 1) && (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) {
3043  vs->reference_stream_index = vs->streams[j]->index;
3044  }
3046  }
3047 
3048  if (vs->has_video > 1)
3049  av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n");
3050  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
3051  vs->oformat = av_guess_format("mp4", NULL, NULL);
3052  } else {
3053  vs->oformat = av_guess_format("mpegts", NULL, NULL);
3054  }
3055  if (!vs->oformat)
3056  return AVERROR_MUXER_NOT_FOUND;
3057 
3058  if (hls->segment_filename) {
3059  ret = format_name(hls->segment_filename, &vs->basename, i, vs->varname);
3060  if (ret < 0)
3061  return ret;
3062  } else {
3063  p = strrchr(vs->m3u8_name, '.');
3064  if (p)
3065  *p = '\0';
3066 
3067  vs->basename = av_asprintf("%s%s", vs->m3u8_name, pattern);
3068  if (!vs->basename)
3069  return AVERROR(ENOMEM);
3070 
3071  if (p)
3072  *p = '.';
3073  }
3074 
3075  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
3076  if (hls->nb_varstreams > 1)
3077  fmp4_init_filename_len += strlen(POSTFIX_PATTERN);
3078  if (hls->flags & HLS_SINGLE_FILE) {
3080  if (!vs->fmp4_init_filename)
3081  return AVERROR(ENOMEM);
3082  } else {
3083  vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);
3084  if (!vs->fmp4_init_filename)
3085  return AVERROR(ENOMEM);
3087  fmp4_init_filename_len);
3088  if (hls->nb_varstreams > 1) {
3089  if (av_stristr(vs->fmp4_init_filename, "%v")) {
3092  &vs->fmp4_init_filename, i, vs->varname);
3093  } else {
3094  ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i);
3095  }
3096  if (ret < 0)
3097  return ret;
3098  }
3099 
3100  if (hls->use_localtime) {
3101  int r;
3102  char *expanded = NULL;
3103 
3104  r = strftime_expand(vs->fmp4_init_filename, &expanded);
3105  if (r < 0) {
3106  av_log(s, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
3107  return r;
3108  }
3110  vs->fmp4_init_filename = expanded;
3111  }
3112 
3113  p = strrchr(vs->m3u8_name, '/');
3114  if (p) {
3115  char tmp = *(++p);
3116  *p = '\0';
3117  vs->base_output_dirname = av_asprintf("%s%s", vs->m3u8_name,
3118  vs->fmp4_init_filename);
3119  *p = tmp;
3120  } else {
3122  }
3123  if (!vs->base_output_dirname)
3124  return AVERROR(ENOMEM);
3125  }
3126  }
3127 
3129  if (ret < 0)
3130  return ret;
3131 
3132  if (vs->has_subtitle) {
3133  vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
3134  if (!vs->vtt_oformat)
3135  return AVERROR_MUXER_NOT_FOUND;
3136 
3137  p = strrchr(vs->m3u8_name, '.');
3138  if (p)
3139  *p = '\0';
3140 
3141  vs->vtt_basename = av_asprintf("%s%s", vs->m3u8_name, vtt_pattern);
3142  if (!vs->vtt_basename)
3143  return AVERROR(ENOMEM);
3144 
3145  if (hls->subtitle_filename) {
3147  if (ret < 0)
3148  return ret;
3149  } else {
3150  vs->vtt_m3u8_name = av_asprintf("%s_vtt.m3u8", vs->m3u8_name);
3151  if (!vs->vtt_m3u8_name)
3152  return AVERROR(ENOMEM);
3153  }
3154  if (p)
3155  *p = '.';
3156  }
3157 
3158  if ((ret = hls_mux_init(s, vs)) < 0)
3159  return ret;
3160 
3161  if (hls->flags & HLS_APPEND_LIST) {
3162  parse_playlist(s, vs->m3u8_name, vs);
3163  vs->discontinuity = 1;
3164  if (hls->init_time > 0) {
3165  av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
3166  " hls_init_time value will have no effect\n");
3167  hls->init_time = 0;
3168  hls->recording_time = hls->time;
3169  }
3170  }
3171 
3172  if ((ret = hls_start(s, vs)) < 0)
3173  return ret;
3174  vs->number++;
3175  }
3176 
3177  return ret;
3178 }
3179 
3180 #define OFFSET(x) offsetof(HLSContext, x)
3181 #define E AV_OPT_FLAG_ENCODING_PARAM
3182 static const AVOption options[] = {
3183  {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
3184  {"hls_time", "set segment length", OFFSET(time), AV_OPT_TYPE_DURATION, {.i64 = 2000000}, 0, INT64_MAX, E},
3185  {"hls_init_time", "set segment length at init list", OFFSET(init_time), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E},
3186  {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E},
3187  {"hls_delete_threshold", "set number of unreferenced segments to keep before deleting", OFFSET(hls_delete_threshold), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, E},
3188  {"hls_vtt_options","set hls vtt list of options for the container format used for hls", OFFSET(vtt_format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3189  {"hls_allow_cache", "explicitly set whether the client MAY (1) or MUST NOT (0) cache media segments", OFFSET(allowcache), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, E},
3190  {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3191  {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3192  {"hls_segment_options","set segments files format options of hls", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
3193  {"hls_segment_size", "maximum size per segment file, (in bytes)", OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
3194  {"hls_key_info_file", "file with key URI and key file path", OFFSET(key_info_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3195  {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
3196  {"hls_enc_key", "hex-coded 16 byte key to encrypt the segments", OFFSET(key), AV_OPT_TYPE_STRING, .flags = E},
3197  {"hls_enc_key_url", "url to access the key to decrypt the segments", OFFSET(key_url), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3198  {"hls_enc_iv", "hex-coded 16 byte initialization vector", OFFSET(iv), AV_OPT_TYPE_STRING, .flags = E},
3199  {"hls_subtitle_path", "set path of hls subtitles", OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3200  {"hls_segment_type", "set hls segment files type", OFFSET(segment_type), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, SEGMENT_TYPE_FMP4, E, .unit = "segment_type"},
3201  {"mpegts", "make segment file to mpegts files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, UINT_MAX, E, .unit = "segment_type"},
3202  {"fmp4", "make segment file to fragment mp4 files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_FMP4 }, 0, UINT_MAX, E, .unit = "segment_type"},
3203  {"hls_fmp4_init_filename", "set fragment mp4 file init filename", OFFSET(fmp4_init_filename), AV_OPT_TYPE_STRING, {.str = "init.mp4"}, 0, 0, E},
3204  {"hls_fmp4_init_resend", "resend fragment mp4 init file after refresh m3u8 every time", OFFSET(resend_init_file), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3205  {"hls_flags", "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, .unit = "flags"},
3206  {"single_file", "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX, E, .unit = "flags"},
3207  {"temp_file", "write segment and playlist to temporary file and rename when complete", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_TEMP_FILE }, 0, UINT_MAX, E, .unit = "flags"},
3208  {"delete_segments", "delete segment files that are no longer part of the playlist", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DELETE_SEGMENTS }, 0, UINT_MAX, E, .unit = "flags"},
3209  {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, .unit = "flags"},
3210  {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, .unit = "flags"},
3211  {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, .unit = "flags"},
3212  {"split_by_time", "split the hls segment by time which user set by hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX, E, .unit = "flags"},
3213  {"append_list", "append the new segments into old hls segment list", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX, E, .unit = "flags"},
3214  {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX, E, .unit = "flags"},
3215  {"second_level_segment_index", "include segment index in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_INDEX }, 0, UINT_MAX, E, .unit = "flags"},
3216  {"second_level_segment_duration", "include segment duration in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_DURATION }, 0, UINT_MAX, E, .unit = "flags"},
3217  {"second_level_segment_size", "include segment size in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_SIZE }, 0, UINT_MAX, E, .unit = "flags"},
3218  {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX, E, .unit = "flags"},
3219  {"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, .unit = "flags"},
3220  {"iframes_only", "add EXT-X-I-FRAMES-ONLY, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_I_FRAMES_ONLY }, 0, UINT_MAX, E, .unit = "flags"},
3221  {"strftime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3222  {"strftime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3223  {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, .unit = "pl_type" },
3224  {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, .unit = "pl_type" },
3225  {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, .unit = "pl_type" },
3226  {"method", "set the HTTP method(default: PUT)", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3227  {"hls_start_number_source", "set source of first number in sequence", OFFSET(start_sequence_source_type), AV_OPT_TYPE_INT, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, 0, HLS_START_SEQUENCE_LAST-1, E, .unit = "start_sequence_source_type" },
3228  {"generic", "start_number value (default)", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3229  {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3230  {"epoch_us", "microseconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3231  {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3232  {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3233  {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3234  {"cc_stream_map", "Closed captions stream map string", OFFSET(cc_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3235  {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3236  {"master_pl_publish_rate", "Publish master play list every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E},
3237  {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3238  {"timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
3239  {"ignore_io_errors", "Ignore IO errors for stable long-duration runs with network output", OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
3240  {"headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
3241  { NULL },
3242 };
3243 
3244 static const AVClass hls_class = {
3245  .class_name = "hls muxer",
3246  .item_name = av_default_item_name,
3247  .option = options,
3248  .version = LIBAVUTIL_VERSION_INT,
3249 };
3250 
3251 
3253  .p.name = "hls",
3254  .p.long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
3255  .p.extensions = "m3u8",
3256  .p.audio_codec = AV_CODEC_ID_AAC,
3257  .p.video_codec = AV_CODEC_ID_H264,
3258  .p.subtitle_codec = AV_CODEC_ID_WEBVTT,
3259 #if FF_API_ALLOW_FLUSH
3260  .p.flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_NODIMENSIONS,
3261 #else
3263 #endif
3264  .p.priv_class = &hls_class,
3265  .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
3266  .priv_data_size = sizeof(HLSContext),
3267  .init = hls_init,
3271  .deinit = hls_deinit,
3272 };
M
#define M(a, b)
Definition: vp3dsp.c:48
ff_get_chomp_line
int ff_get_chomp_line(AVIOContext *s, char *buf, int maxlen)
Same as ff_get_line but strip the white-space characters in the text tail.
Definition: aviobuf.c:786
VariantStream::vtt_avf
AVFormatContext * vtt_avf
Definition: hlsenc.c:133
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
hls_write_header
static int hls_write_header(AVFormatContext *s)
Definition: hlsenc.c:2363
av_codec_get_id
enum AVCodecID av_codec_get_id(const struct AVCodecTag *const *tags, unsigned int tag)
Get the AVCodecID for the given codec tag tag.
ffio_open_whitelist
int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist)
Definition: avio.c:471
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:69
get_relative_url
static const char * get_relative_url(const char *master_url, const char *media_url)
Definition: hlsenc.c:1377
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
find_segment_by_filename
static HLSSegment * find_segment_by_filename(HLSSegment *segment, const char *filename)
Definition: hlsenc.c:963
append_postfix
static int append_postfix(char *name, int name_buf_len, int i)
Definition: hlsenc.c:1943
level
uint8_t level
Definition: svq3.c:205
AV_CODEC_ID_AC3
@ AV_CODEC_ID_AC3
Definition: codec_id.h:449
HLSContext::timeout
int64_t timeout
Definition: hlsenc.c:261
sls_flag_use_localtime_filename
static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c, VariantStream *vs)
Definition: hlsenc.c:1063
HLS_TEMP_FILE
@ HLS_TEMP_FILE
Definition: hlsenc.c:108
AVOutputFormat::name
const char * name
Definition: avformat.h:510
av_bprint_is_complete
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:218
r
const char * r
Definition: vf_curves.c:127
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
strftime_expand
static int strftime_expand(const char *fmt, char **dest)
Definition: hlsenc.c:268
VariantStream::has_subtitle
int has_subtitle
Definition: hlsenc.c:136
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:51
HLSContext::resend_init_file
int resend_init_file
resend init file into disk after refresh m3u8
Definition: hlsenc.c:215
HLSContext::hls_delete_threshold
int hls_delete_threshold
Definition: hlsenc.c:209
av_compare_ts
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
Definition: mathematics.c:147
AVFMT_NODIMENSIONS
#define AVFMT_NODIMENSIONS
Format does not need width/height.
Definition: avformat.h:483
VariantStream::codec_attr
char codec_attr[128]
Definition: hlsenc.c:182
ffio_wfourcc
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
Definition: avio_internal.h:124
HLSContext::key_file
char key_file[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:236
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
ff_hls_write_end_list
void ff_hls_write_end_list(AVIOContext *out)
Definition: hlsplaylist.c:201
hls_init_file_resend
static int hls_init_file_resend(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:2424
av_stristr
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
Definition: avstring.c:58
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
HLSSegment::filename
char filename[MAX_URL_SIZE]
Definition: hlsenc.c:78
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
av_dict_count
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition: dict.c:39
fn1
#define fn1(name, depth)
Definition: blend_modes.c:85
PLAYLIST_TYPE_VOD
@ PLAYLIST_TYPE_VOD
Definition: hlsplaylist.h:34
VariantStream::key_uri
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:177
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:264
int64_t
long long int64_t
Definition: coverity.c:34
VariantStream::init_range_length
int init_range_length
Definition: hlsenc.c:128
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:115
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:207
write_styp
static void write_styp(AVIOContext *pb)
Definition: hlsenc.c:543
VariantStream::var_stream_idx
unsigned var_stream_idx
Definition: hlsenc.c:120
HLSContext::cc_stream_map
char * cc_stream_map
Definition: hlsenc.c:254
PLAYLIST_TYPE_EVENT
@ PLAYLIST_TYPE_EVENT
Definition: hlsplaylist.h:33
HLS_APPEND_LIST
@ HLS_APPEND_LIST
Definition: hlsenc.c:103
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1368
deinit
static void deinit(AVFormatContext *s)
Definition: chromaprint.c:52
create_master_playlist
static int create_master_playlist(AVFormatContext *s, VariantStream *const input_vs, int final)
Definition: hlsenc.c:1414
AVPacketSideData
This structure stores auxiliary information for decoding, presenting, or otherwise processing the cod...
Definition: packet.h:390
HLS_SECOND_LEVEL_SEGMENT_INDEX
@ HLS_SECOND_LEVEL_SEGMENT_INDEX
Definition: hlsenc.c:105
HLS_DELETE_SEGMENTS
@ HLS_DELETE_SEGMENTS
Definition: hlsenc.c:98
AVFormatContext::strict_std_compliance
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1657
HLSContext::ignore_io_errors
int ignore_io_errors
Definition: hlsenc.c:262
KEYSIZE
#define KEYSIZE
Definition: hlsenc.c:71
HLS_MICROSECOND_UNIT
#define HLS_MICROSECOND_UNIT
Definition: hlsenc.c:73
ClosedCaptionsStream
Definition: hlsenc.c:195
AVOption
AVOption.
Definition: opt.h:429
HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH
@ HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH
Definition: hlsenc.c:62
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:149
HLS_INDEPENDENT_SEGMENTS
@ HLS_INDEPENDENT_SEGMENTS
Definition: hlsenc.c:110
HLS_OMIT_ENDLIST
@ HLS_OMIT_ENDLIST
Definition: hlsenc.c:101
HLSContext::iv
char * iv
Definition: hlsenc.c:231
VariantStream::iv_string
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:179
AV_OPT_TYPE_DURATION
@ AV_OPT_TYPE_DURATION
Underlying C type is int64_t.
Definition: opt.h:319
AV_DICT_APPEND
#define AV_DICT_APPEND
If the entry already exists, append to it.
Definition: dict.h:82
VariantStream::total_duration
double total_duration
Definition: hlsenc.c:154
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
VariantStream::start_pts
int64_t start_pts
Definition: hlsenc.c:140
HLSContext::nb_ccstreams
unsigned int nb_ccstreams
Definition: hlsenc.c:248
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:557
AVCodecParameters::codec_tag
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:59
PLAYLIST_TYPE_NONE
@ PLAYLIST_TYPE_NONE
Definition: hlsplaylist.h:32
mathematics.h
AVDictionary
Definition: dict.c:34
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
BUFSIZE
#define BUFSIZE
Definition: hlsenc.c:74
avformat_init_output
av_warn_unused_result int avformat_init_output(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and initialize the codec, but do not write the header.
Definition: mux.c:467
extract_segment_number
static int extract_segment_number(const char *filename)
Definition: hlsenc.c:1208
hls_write_trailer
static int hls_write_trailer(struct AVFormatContext *s)
Definition: hlsenc.c:2789
get_nth_codec_stream_index
static int get_nth_codec_stream_index(AVFormatContext *s, enum AVMediaType codec_type, int64_t stream_id)
Definition: hlsenc.c:2042
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:327
LINE_BUFFER_SIZE
#define LINE_BUFFER_SIZE
Definition: hlsenc.c:72
codec_type
enum AVMediaType codec_type
Definition: rtp.c:37
E
#define E
Definition: hlsenc.c:3181
os_support.h
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:594
update_variant_stream_info
static int update_variant_stream_info(AVFormatContext *s)
Definition: hlsenc.c:2283
av_basename
const char * av_basename(const char *path)
Thread safe basename.
Definition: avstring.c:252
AV_WB64
#define AV_WB64(p, v)
Definition: intreadwrite.h:429
FFOutputFormat::p
AVOutputFormat p
The public AVOutputFormat.
Definition: mux.h:65
hlsplaylist.h
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
HLSContext::allowcache
int allowcache
Definition: hlsenc.c:219
HLSContext::user_agent
char * user_agent
Definition: hlsenc.c:243
sls_flag_check_duration_size
static int sls_flag_check_duration_size(HLSContext *hls, VariantStream *vs)
Definition: hlsenc.c:1036
av_append_path_component
char * av_append_path_component(const char *path, const char *component)
Append path component to the existing path.
Definition: avstring.c:296
VariantStream::key_file
char key_file[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:176
HLSSegment::duration
double duration
Definition: hlsenc.c:80
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1573
do_encrypt
static int do_encrypt(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:714
HLSContext::use_localtime
int use_localtime
flag to expand filename with localtime
Definition: hlsenc.c:217
SEGMENT_TYPE_FMP4
@ SEGMENT_TYPE_FMP4
Definition: hlsenc.c:116
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: avformat.c:867
ff_hls_write_playlist_header
void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type, int iframe_mode)
Definition: hlsplaylist.c:110
segment::duration
int64_t duration
Definition: hls.c:78
fail
#define fail()
Definition: checkasm.h:193
ff_hls_muxer
const FFOutputFormat ff_hls_muxer
Definition: hlsenc.c:3252
sls_flags_filename_process
static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls, VariantStream *vs, HLSSegment *en, double duration, int64_t pos, int64_t size)
Definition: hlsenc.c:973
hls_start
static int hls_start(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:1737
hls_delete_file
static int hls_delete_file(HLSContext *hls, AVFormatContext *avf, char *path, const char *proto)
Definition: hlsenc.c:580
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:494
val
static double val(void *priv, double ch)
Definition: aeval.c:77
VariantStream::oformat
const AVOutputFormat * oformat
Definition: hlsenc.c:123
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:835
VariantStream::start_pts_from_audio
int start_pts_from_audio
Definition: hlsenc.c:138
AV_CODEC_ID_MP3
@ AV_CODEC_ID_MP3
preferred ID for decoding MPEG audio layer 1, 2 or 3
Definition: codec_id.h:447
ff_rename
int ff_rename(const char *url_src, const char *url_dst, void *logctx)
Wrap ffurl_move() and log if error happens.
Definition: avio.c:861
ff_data_to_hex
char * ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase)
Write hexadecimal string corresponding to given binary data.
Definition: utils.c:448
AVRational::num
int num
Numerator.
Definition: rational.h:59
HLS_PERIODIC_REKEY
@ HLS_PERIODIC_REKEY
Definition: hlsenc.c:109
av_dirname
const char * av_dirname(char *path)
Thread safe dirname.
Definition: avstring.c:275
sls_flag_file_rename
static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename)
Definition: hlsenc.c:1056
HLS_ROUND_DURATIONS
@ HLS_ROUND_DURATIONS
Definition: hlsenc.c:99
HLSContext::use_localtime_mkdir
int use_localtime_mkdir
flag to mkdir dirname in timebased filename
Definition: hlsenc.c:218
avio_close_dyn_buf
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1407
avassert.h
lrint
#define lrint
Definition: tablegen.h:53
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
AVFormatContext::metadata
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1535
get_stream_bit_rate
static int64_t get_stream_bit_rate(AVStream *stream)
Definition: hlsenc.c:1397
HLSSegment::keyframe_pos
int64_t keyframe_pos
Definition: hlsenc.c:84
HLSSegment::discont
int discont
Definition: hlsenc.c:81
AV_PROFILE_UNKNOWN
#define AV_PROFILE_UNKNOWN
Definition: defs.h:65
VariantStream::avg_bitrate
int64_t avg_bitrate
Definition: hlsenc.c:155
HLSContext::key_basename
char * key_basename
Definition: hlsenc.c:232
HLSContext::m3u8_out
AVIOContext * m3u8_out
Definition: hlsenc.c:258
duration
int64_t duration
Definition: movenc.c:65
avio_open_dyn_buf
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1362
HLSContext::encrypt_started
int encrypt_started
Definition: hlsenc.c:233
HLSSegment::next
struct HLSSegment * next
Definition: hlsenc.c:91
validate_name
static int validate_name(int nb_vs, const char *fn)
Definition: hlsenc.c:1962
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
HLSContext::method
char * method
Definition: hlsenc.c:242
set_http_options
static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c)
Definition: hlsenc.c:332
CODEC_ATTRIBUTE_WRITTEN
@ CODEC_ATTRIBUTE_WRITTEN
Definition: hlsenc.c:67
VariantStream::vtt_oformat
const AVOutputFormat * vtt_oformat
Definition: hlsenc.c:124
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
HLSContext::has_default_key
int has_default_key
Definition: hlsenc.c:264
AV_CODEC_ID_MP2
@ AV_CODEC_ID_MP2
Definition: codec_id.h:446
av_strtok
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition: avstring.c:178
flush_dynbuf
static int flush_dynbuf(VariantStream *vs, int *range_length)
Definition: hlsenc.c:553
hls_deinit
static void hls_deinit(AVFormatContext *s)
Definition: hlsenc.c:2755
HLS_SECOND_LEVEL_SEGMENT_SIZE
@ HLS_SECOND_LEVEL_SEGMENT_SIZE
Definition: hlsenc.c:107
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Underlying C type is int64_t.
Definition: opt.h:263
VariantStream::has_video
int has_video
Definition: hlsenc.c:135
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:618
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
AVPacketSideData::data
uint8_t * data
Definition: packet.h:391
VariantStream::language
const char * language
Definition: hlsenc.c:187
ctx
AVFormatContext * ctx
Definition: movenc.c:49
nb_streams
static int nb_streams
Definition: ffprobe.c:384
HLSContext::time
int64_t time
Definition: hlsenc.c:206
HLSContext::key_url
char * key_url
Definition: hlsenc.c:230
AVOutputFormat::codec_tag
const struct AVCodecTag *const * codec_tag
List of supported codec_id-codec_tag pairs, ordered by "better choice first".
Definition: avformat.h:535
av_stristart
int av_stristart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str independent of case.
Definition: avstring.c:47
AVFormatContext::opaque
void * opaque
User data.
Definition: avformat.h:1862
VariantStream::key_string
char key_string[KEYSIZE *2+1]
Definition: hlsenc.c:178
key
const char * key
Definition: hwcontext_opencl.c:189
AVCodecParameters::nb_coded_side_data
int nb_coded_side_data
Amount of entries in coded_side_data.
Definition: codec_par.h:86
AVCPBProperties
This structure describes the bitrate properties of an encoded bitstream.
Definition: defs.h:271
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
avformat_write_header
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: mux.c:488
VariantStream::attr_status
CodecAttributeStatus attr_status
Definition: hlsenc.c:183
VariantStream::video_lastpos
int64_t video_lastpos
Definition: hlsenc.c:142
VariantStream::reference_stream_index
int reference_stream_index
Definition: hlsenc.c:151
VariantStream::base_output_dirname
char * base_output_dirname
Definition: hlsenc.c:172
VariantStream::segments
HLSSegment * segments
Definition: hlsenc.c:158
write_codec_attr
static void write_codec_attr(AVStream *st, VariantStream *vs)
Definition: hlsenc.c:351
time_internal.h
ff_http_do_new_request
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition: http.c:476
avio_flush
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:223
AV_CODEC_ID_WEBVTT
@ AV_CODEC_ID_WEBVTT
Definition: codec_id.h:574
AVFormatContext
Format I/O context.
Definition: avformat.h:1300
VariantStream::video_keyframe_pos
int64_t video_keyframe_pos
Definition: hlsenc.c:143
internal.h
ff_hls_write_subtitle_rendition
void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup, const char *filename, const char *language, const char *sname, int name_id, int is_default)
Definition: hlsplaylist.c:58
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:771
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
replace_str_data_in_filename
static int replace_str_data_in_filename(char **s, const char *filename, char placeholder, const char *datastring)
Definition: hlsenc.c:455
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
reflush_dynbuf
static void reflush_dynbuf(VariantStream *vs, int *range_length)
Definition: hlsenc.c:574
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:787
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
StartSequenceSourceType
StartSequenceSourceType
Definition: hlsenc.c:58
VariantStream::m3u8_name
char * m3u8_name
Definition: hlsenc.c:166
write_trailer
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:101
VariantStream::new_start
int new_start
Definition: hlsenc.c:137
HLS_PROGRAM_DATE_TIME
@ HLS_PROGRAM_DATE_TIME
Definition: hlsenc.c:104
AV_LEVEL_UNKNOWN
#define AV_LEVEL_UNKNOWN
Definition: defs.h:198
VariantStream::subtitle_varname
const char * subtitle_varname
Definition: hlsenc.c:192
HLSSegment::sub_filename
char sub_filename[MAX_URL_SIZE]
Definition: hlsenc.c:79
ff_nal_unit_extract_rbsp
uint8_t * ff_nal_unit_extract_rbsp(const uint8_t *src, uint32_t src_len, uint32_t *dst_len, int header_len)
Definition: nal.c:160
HLSSegment::iv_string
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:89
period
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option keep it simple and lowercase description are in without period
Definition: writing_filters.txt:89
HLSSegment::key_uri
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:88
HLSContext::vtt_format_options_str
char * vtt_format_options_str
Definition: hlsenc.c:224
HLSContext::http_delete
AVIOContext * http_delete
Definition: hlsenc.c:260
AV_OPT_TYPE_DICT
@ AV_OPT_TYPE_DICT
Underlying C type is AVDictionary*.
Definition: opt.h:290
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
ffurl_shutdown
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:847
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1342
avc.h
HLS_START_SEQUENCE_LAST
@ HLS_START_SEQUENCE_LAST
Definition: hlsenc.c:63
hlsenc_io_open
static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, const char *filename, AVDictionary **options)
Definition: hlsenc.c:291
options
Definition: swscale.c:42
AVStream::metadata
AVDictionary * metadata
Definition: avformat.h:828
FFOutputFormat
Definition: mux.h:61
double
double
Definition: af_crystalizer.c:132
HLSSegment
Definition: hlsenc.c:77
AV_DICT_DONT_OVERWRITE
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition: dict.h:81
time.h
VariantStream::discontinuity_set
int discontinuity_set
Definition: hlsenc.c:149
ffio_geturlcontext
URLContext * ffio_geturlcontext(AVIOContext *s)
Return the URLContext associated with the AVIOContext.
Definition: avio.c:107
AVOutputFormat::priv_class
const AVClass * priv_class
AVClass for the private context.
Definition: avformat.h:538
av_write_frame
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:1236
HLSContext::vtt_format_options
AVDictionary * vtt_format_options
Definition: hlsenc.c:240
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
Audio only.
Definition: codec_par.h:180
PLAYLIST_TYPE_NB
@ PLAYLIST_TYPE_NB
Definition: hlsplaylist.h:35
SegmentType
SegmentType
Definition: hlsenc.c:114
AVCodecParameters::level
int level
Definition: codec_par.h:129
index
int index
Definition: gxfenc.c:90
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
HLS_START_SEQUENCE_AS_START_NUMBER
@ HLS_START_SEQUENCE_AS_START_NUMBER
Definition: hlsenc.c:59
HLSContext::key
char * key
Definition: hlsenc.c:229
VariantStream::old_segments
HLSSegment * old_segments
Definition: hlsenc.c:160
av_packet_side_data_get
const AVPacketSideData * av_packet_side_data_get(const AVPacketSideData *sd, int nb_sd, enum AVPacketSideDataType type)
Get side information from a side data array.
Definition: packet.c:656
AV_CODEC_ID_EAC3
@ AV_CODEC_ID_EAC3
Definition: codec_id.h:486
VariantStream::is_default
int is_default
Definition: hlsenc.c:186
AVCodecParameters::extradata_size
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:73
HLS_I_FRAMES_ONLY
@ HLS_I_FRAMES_ONLY
Definition: hlsenc.c:111
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:448
av_strncasecmp
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:217
VariantStream::initial_prog_date_time
double initial_prog_date_time
Definition: hlsenc.c:168
HLSContext::segment_filename
char * segment_filename
Definition: hlsenc.c:212
hls_append_segment
static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, VariantStream *vs, double duration, int64_t pos, int64_t size)
Definition: hlsenc.c:1107
ff_hls_write_stream_info
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, int avg_bandwidth, const char *filename, const char *agroup, const char *codecs, const char *ccgroup, const char *sgroup)
Definition: hlsplaylist.c:78
HLSFlags
HLSFlags
Definition: hlsenc.c:95
HLSContext::cc_streams
ClosedCaptionsStream * cc_streams
Definition: hlsenc.c:247
ff_hls_write_playlist_version
void ff_hls_write_playlist_version(AVIOContext *out, int version)
Definition: hlsplaylist.c:32
HLSContext::has_video_m3u8
int has_video_m3u8
Definition: hlsenc.c:265
VariantStream::init_buffer
uint8_t * init_buffer
Definition: hlsenc.c:130
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
VariantStream::ccgroup
const char * ccgroup
Definition: hlsenc.c:190
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:368
HLSSegment::keyframe_size
int64_t keyframe_size
Definition: hlsenc.c:85
hls_rename_temp_file
static int hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
Definition: hlsenc.c:1362
AVMediaType
AVMediaType
Definition: avutil.h:199
AVPacket::size
int size
Definition: packet.h:540
HLSContext::master_pl_name
char * master_pl_name
Definition: hlsenc.c:255
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
av_codec_get_tag
unsigned int av_codec_get_tag(const struct AVCodecTag *const *tags, enum AVCodecID id)
Get the codec tag for the given codec id id.
FF_OFMT_FLAG_ALLOW_FLUSH
#define FF_OFMT_FLAG_ALLOW_FLUSH
This flag indicates that the muxer stores data internally and supports flushing it.
Definition: mux.h:38
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:240
HLS_SPLIT_BY_TIME
@ HLS_SPLIT_BY_TIME
Definition: hlsenc.c:102
VariantStream::basename_tmp
char * basename_tmp
Definition: hlsenc.c:162
localtime_r
#define localtime_r
Definition: time_internal.h:46
HLSContext::start_sequence_source_type
uint32_t start_sequence_source_type
Definition: hlsenc.c:204
AVFormatContext::url
char * url
input or output URL.
Definition: avformat.h:1416
size
int size
Definition: twinvq_data.h:10344
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
HLSSegment::pos
int64_t pos
Definition: hlsenc.c:82
AV_RB32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:96
HLSContext::pl_type
uint32_t pl_type
Definition: hlsenc.c:211
AVCodecParameters::profile
int profile
Codec-specific bitstream restrictions that the stream conforms to.
Definition: codec_par.h:128
CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN
@ CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN
Definition: hlsenc.c:68
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:468
ff_is_http_proto
int ff_is_http_proto(const char *filename)
Utility function to check if the file uses http or https protocol.
Definition: utils.c:572
ff_format_io_close
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: avformat.c:958
ff_hls_write_init_file
void ff_hls_write_init_file(AVIOContext *out, const char *filename, int byterange_mode, int64_t size, int64_t pos)
Definition: hlsplaylist.c:134
HLSSegment::discont_program_date_time
double discont_program_date_time
Definition: hlsenc.c:92
fn
#define fn(a)
Definition: aap_template.c:37
AVStream::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:826
parse_variant_stream_mapstring
static int parse_variant_stream_mapstring(AVFormatContext *s)
Definition: hlsenc.c:2060
hls_init
static int hls_init(AVFormatContext *s)
Definition: hlsenc.c:2929
VariantStream::agroup
const char * agroup
Definition: hlsenc.c:188
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:201
avio_wb32
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:365
av_isdigit
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition: avstring.h:202
VariantStream::sequence
int64_t sequence
Definition: hlsenc.c:122
line
Definition: graph2dot.c:48
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:545
HLSContext::start_sequence
int64_t start_sequence
Definition: hlsenc.c:203
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:223
av_strstart
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:36
VariantStream::temp_buffer
uint8_t * temp_buffer
Definition: hlsenc.c:129
HLSContext::format_options
AVDictionary * format_options
Definition: hlsenc.c:226
OFFSET
#define OFFSET(x)
Definition: hlsenc.c:3180
HLS_DISCONT_START
@ HLS_DISCONT_START
Definition: hlsenc.c:100
VariantStream::video_keyframe_size
int64_t video_keyframe_size
Definition: hlsenc.c:144
VariantStream::basename
char * basename
Definition: hlsenc.c:163
HLS_START_SEQUENCE_AS_FORMATTED_DATETIME
@ HLS_START_SEQUENCE_AS_FORMATTED_DATETIME
Definition: hlsenc.c:61
parse_playlist
static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
Definition: hlsenc.c:1224
hls_write_packet
static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: hlsenc.c:2472
VariantStream::last_segment
HLSSegment * last_segment
Definition: hlsenc.c:159
av_write_trailer
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1298
AV_PKT_DATA_CPB_PROPERTIES
@ AV_PKT_DATA_CPB_PROPERTIES
This side data corresponds to the AVCPBProperties struct.
Definition: packet.h:142
VariantStream::m3u8_created
int m3u8_created
Definition: hlsenc.c:185
bprint.h
ff_hls_write_audio_rendition
void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, const char *filename, const char *language, int name_id, int is_default, int nb_channels)
Definition: hlsplaylist.c:40
URLContext
Definition: url.h:35
HLSContext::iv_string
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:239
log.h
AVFMT_GLOBALHEADER
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:478
AVOutputFormat
Definition: avformat.h:509
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:532
avio_internal.h
round
static av_always_inline av_const double round(double x)
Definition: libm.h:444
fn2
#define fn2(a, b)
Definition: aap_template.c:36
AVERROR_MUXER_NOT_FOUND
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:62
HLSContext::key_string
char key_string[KEYSIZE *2+1]
Definition: hlsenc.c:238
VariantStream::sgroup
const char * sgroup
Definition: hlsenc.c:189
HLSContext::max_nb_segments
int max_nb_segments
Definition: hlsenc.c:208
VariantStream::start_pos
int64_t start_pos
Definition: hlsenc.c:146
AVCPBProperties::max_bitrate
int64_t max_bitrate
Maximum bitrate of the stream, in bits per second.
Definition: defs.h:276
VariantStream::nb_streams
unsigned int nb_streams
Definition: hlsenc.c:184
HLSContext::sub_m3u8_out
AVIOContext * sub_m3u8_out
Definition: hlsenc.c:259
hls_encryption_start
static int hls_encryption_start(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:787
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:228
HLSContext
Definition: hls.c:205
options
static const AVOption options[]
Definition: hlsenc.c:3182
url.h
hlsenc_io_close
static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
Definition: hlsenc.c:312
av_random_bytes
int av_random_bytes(uint8_t *buf, size_t len)
Generate cryptographically secure random data, i.e.
Definition: random_seed.c:130
AVFormatContext::max_delay
int max_delay
Definition: avformat.h:1445
VariantStream::number
unsigned number
Definition: hlsenc.c:121
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
ff_get_line
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
Read a whole line of text from AVIOContext.
Definition: aviobuf.c:769
HLSSegment::var_stream_idx
unsigned var_stream_idx
Definition: hlsenc.c:86
len
int len
Definition: vorbis_enc_data.h:426
start_sequence
static const uint8_t start_sequence[]
Definition: rtpdec_h264.c:66
profile
int profile
Definition: mxfenc.c:2233
VariantStream::duration
double duration
Definition: hlsenc.c:145
VariantStream::streams
AVStream ** streams
Definition: hlsenc.c:181
AVCodecParameters::coded_side_data
AVPacketSideData * coded_side_data
Additional data associated with the entire stream.
Definition: codec_par.h:81
nal.h
write_packet
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
Definition: ffmpeg_mux.c:209
HLSContext::fmp4_init_filename
char * fmp4_init_filename
Definition: hlsenc.c:213
HLSContext::encrypt
int encrypt
Definition: hlsenc.c:228
VariantStream::max_bitrate
int64_t max_bitrate
Definition: hlsenc.c:156
HLSContext::http_persistent
int http_persistent
Definition: hls.c:227
HLS_SINGLE_FILE
@ HLS_SINGLE_FILE
Definition: hlsenc.c:97
ffio_free_dyn_buf
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1435
AVStream::id
int id
Format-specific stream ID.
Definition: avformat.h:760
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:748
VariantStream::out_single_file
AVIOContext * out_single_file
Definition: hlsenc.c:126
ff_hls_write_file_entry
int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, int byterange_mode, double duration, int round_duration, int64_t size, int64_t pos, const char *baseurl, const char *filename, double *prog_date_time, int64_t video_keyframe_size, int64_t video_keyframe_pos, int iframe_mode)
Definition: hlsplaylist.c:144
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:231
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:80
VariantStream::fmp4_init_filename
char * fmp4_init_filename
Definition: hlsenc.c:171
HLSContext::subtitle_filename
char * subtitle_filename
Definition: hlsenc.c:225
AVFormatContext::oformat
const struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1319
av_strlcat
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes,...
Definition: avstring.c:95
replace_int_data_in_filename
static int replace_int_data_in_filename(char **s, const char *filename, char placeholder, int64_t number)
Definition: hlsenc.c:495
hls_delete_old_segments
static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, VariantStream *vs)
Definition: hlsenc.c:604
pos
unsigned int pos
Definition: spdifenc.c:414
avformat.h
VariantStream::end_pts
int64_t end_pts
Definition: hlsenc.c:141
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:99
VariantStream::encrypt_started
int encrypt_started
Definition: hlsenc.c:174
VariantStream::discontinuity
int discontinuity
Definition: hlsenc.c:150
VariantStream::nb_entries
int nb_entries
Definition: hlsenc.c:148
SEGMENT_TYPE_MPEGTS
@ SEGMENT_TYPE_MPEGTS
Definition: hlsenc.c:115
avio_printf
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
VariantStream::current_segment_final_filename_fmt
char current_segment_final_filename_fmt[MAX_URL_SIZE]
Definition: hlsenc.c:169
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:754
can_split
static void can_split(const VVCLocalContext *lc, int x0, int y0, int cb_width, int cb_height, int mtt_depth, int depth_offset, int part_idx, VVCSplitMode last_split_mode, VVCTreeType tree_type, VVCModeType mode_type, VVCAllowedSplit *split)
Definition: ctu.c:523
random_seed.h
format_name
static int format_name(const char *buf, char **s, int index, const char *varname)
Definition: hlsenc.c:1996
MAX_URL_SIZE
#define MAX_URL_SIZE
Definition: internal.h:30
get_default_pattern_localtime_fmt
static const char * get_default_pattern_localtime_fmt(AVFormatContext *s)
Definition: hlsenc.c:1922
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
AVRational::den
int den
Denominator.
Definition: rational.h:60
VariantStream::packets_written
int packets_written
Definition: hlsenc.c:127
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
headers
FFmpeg currently uses a custom build this text attempts to document some of its obscure features and options Makefile the full command issued by make and its output will be shown on the screen DBG Preprocess x86 external assembler files to a dbg asm file in the object which then gets compiled Helps in developing those assembler files DESTDIR Destination directory for the install useful to prepare packages or install FFmpeg in cross environments GEN Set to ‘1’ to generate the missing or mismatched references Makefile builds all the libraries and the executables fate Run the fate test note that you must have installed it fate list List all fate regression test targets install Install headers
Definition: build_system.txt:34
defs.h
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:232
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: avformat.c:149
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:612
update_master_pl_info
static int update_master_pl_info(AVFormatContext *s)
Definition: hlsenc.c:2321
AVFormatContext::io_open
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
Definition: avformat.h:1903
sls_flag_check_duration_size_index
static int sls_flag_check_duration_size_index(HLSContext *hls)
Definition: hlsenc.c:1013
ClosedCaptionsStream::language
const char * language
Definition: hlsenc.c:198
VariantStream::vtt_m3u8_name
char * vtt_m3u8_name
Definition: hlsenc.c:165
HLSContext::baseurl
char * baseurl
Definition: hlsenc.c:223
AVPacket::stream_index
int stream_index
Definition: packet.h:541
CodecAttributeStatus
CodecAttributeStatus
Definition: hlsenc.c:66
segment
Definition: hls.c:77
HLSContext::key_info_file
char * key_info_file
Definition: hlsenc.c:235
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
av_dict_set_int
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition: dict.c:167
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:617
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
av_guess_format
const AVOutputFormat * av_guess_format(const char *short_name, const char *filename, const char *mime_type)
Return the output format in the list of registered output formats which best matches the provided par...
Definition: format.c:79
mem.h
VariantStream::out
AVIOContext * out
Definition: hlsenc.c:125
HLSContext::nb_varstreams
unsigned int nb_varstreams
Definition: hlsenc.c:246
HLSContext::master_m3u8_created
int master_m3u8_created
Definition: hlsenc.c:250
VariantStream::size
int64_t size
Definition: hlsenc.c:147
HLSContext::version
int version
Definition: hlsenc.c:252
ff_mkdir_p
int ff_mkdir_p(const char *path)
Automatically create sub-directories.
Definition: utils.c:414
HLSContext::var_streams
VariantStream * var_streams
Definition: hlsenc.c:245
VariantStream::dpp
double dpp
Definition: hlsenc.c:139
VariantStream::avf
AVFormatContext * avf
Definition: hlsenc.c:132
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
POSTFIX_PATTERN
#define POSTFIX_PATTERN
Definition: hlsenc.c:75
AVPacket
This structure stores compressed data.
Definition: packet.h:516
hls_free_segments
static void hls_free_segments(HLSSegment *p)
Definition: hlsenc.c:1351
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
HLSContext::flags
uint32_t flags
Definition: hlsenc.c:210
hls_mux_init
static int hls_mux_init(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:846
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:88
av_dict_copy
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:237
VariantStream::varname
const char * varname
Definition: hlsenc.c:191
AVFormatContext::io_close2
int(* io_close2)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1917
append_single_file
static int64_t append_single_file(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:2441
avio_find_protocol_name
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:657
AV_OPT_TYPE_FLAGS
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition: opt.h:255
HLSContext::init_time
int64_t init_time
Definition: hlsenc.c:207
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
avio_close
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: avio.c:616
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:85
AVCodecParameters::bit_rate
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:97
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
hls_window
static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
Definition: hlsenc.c:1593
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
h
h
Definition: vp9dsp_template.c:2070
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:348
HLSContext::key_uri
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:237
AV_RB24
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_RB24
Definition: bytestream.h:97
avformat_alloc_output_context2
int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
Definition: mux.c:95
AVStream::pts_wrap_bits
int pts_wrap_bits
Number of bits in timestamps.
Definition: avformat.h:923
http.h
HLS_SECOND_LEVEL_SEGMENT_DURATION
@ HLS_SECOND_LEVEL_SEGMENT_DURATION
Definition: hlsenc.c:106
av_bprint_append_data
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
Definition: bprint.c:163
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
snprintf
#define snprintf
Definition: snprintf.h:34
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1328
ff_format_set_url
void ff_format_set_url(AVFormatContext *s, char *url)
Set AVFormatContext url field to the provided pointer.
Definition: avformat.c:951
parse_cc_stream_mapstring
static int parse_cc_stream_mapstring(AVFormatContext *s)
Definition: hlsenc.c:2206
HLSContext::segment_type
int segment_type
Definition: hlsenc.c:214
HLSContext::master_m3u8_url
char * master_m3u8_url
Definition: hlsenc.c:251
HLSContext::recording_time
int64_t recording_time
Definition: hlsenc.c:220
HLSContext::max_seg_size
int64_t max_seg_size
Definition: hlsenc.c:221
HLSContext::master_publish_rate
unsigned int master_publish_rate
Definition: hlsenc.c:256
ClosedCaptionsStream::instreamid
const char * instreamid
Definition: hlsenc.c:197
HLSSegment::size
int64_t size
Definition: hlsenc.c:83
HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH
@ HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH
Definition: hlsenc.c:60
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: codec_par.c:106
VariantStream::vtt_basename
char * vtt_basename
Definition: hlsenc.c:164
ClosedCaptionsStream::ccgroup
const char * ccgroup
Definition: hlsenc.c:196
HLSContext::headers
char * headers
Definition: hlsenc.c:263
av_fourcc2str
#define av_fourcc2str(fourcc)
Definition: avutil.h:348
hls_class
static const AVClass hls_class
Definition: hlsenc.c:3244
VariantStream
Definition: hlsenc.c:119
VariantStream::total_size
int64_t total_size
Definition: hlsenc.c:153
avio_feof
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:346
HLSContext::var_stream_map
char * var_stream_map
Definition: hlsenc.c:253
mux.h
ff_write_chained
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src, int interleave)
Write a packet to another muxer than the one the user originally intended.
Definition: mux.c:1397