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 <float.h>
25 #include <stdint.h>
26 #if HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 
30 #if CONFIG_GCRYPT
31 #include <gcrypt.h>
32 #elif CONFIG_OPENSSL
33 #include <openssl/rand.h>
34 #endif
35 
36 #include "libavutil/avassert.h"
37 #include "libavutil/mathematics.h"
38 #include "libavutil/parseutils.h"
39 #include "libavutil/avstring.h"
40 #include "libavutil/intreadwrite.h"
41 #include "libavutil/random_seed.h"
42 #include "libavutil/opt.h"
43 #include "libavutil/log.h"
44 #include "libavutil/time.h"
46 
47 #include "avformat.h"
48 #include "avio_internal.h"
49 #if CONFIG_HTTP_PROTOCOL
50 #include "http.h"
51 #endif
52 #include "hlsplaylist.h"
53 #include "internal.h"
54 #include "os_support.h"
55 
56 typedef enum {
63 
64 typedef enum {
68 
69 #define KEYSIZE 16
70 #define LINE_BUFFER_SIZE MAX_URL_SIZE
71 #define HLS_MICROSECOND_UNIT 1000000
72 #define POSTFIX_PATTERN "_%d"
73 
74 typedef struct HLSSegment {
77  double duration; /* in seconds */
78  int discont;
79  int64_t pos;
80  int64_t size;
81  int64_t keyframe_pos;
82  int64_t keyframe_size;
83  unsigned var_stream_idx;
84 
86  char iv_string[KEYSIZE*2 + 1];
87 
88  struct HLSSegment *next;
89 } HLSSegment;
90 
91 typedef enum HLSFlags {
92  // Generate a single media file and use byte ranges in the playlist.
93  HLS_SINGLE_FILE = (1 << 0),
94  HLS_DELETE_SEGMENTS = (1 << 1),
95  HLS_ROUND_DURATIONS = (1 << 2),
96  HLS_DISCONT_START = (1 << 3),
97  HLS_OMIT_ENDLIST = (1 << 4),
98  HLS_SPLIT_BY_TIME = (1 << 5),
99  HLS_APPEND_LIST = (1 << 6),
101  HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in segment filenames when use_localtime e.g.: %%03d
102  HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration (microsec) in segment filenames when use_localtime e.g.: %%09t
103  HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) in segment filenames when use_localtime e.g.: %%014s
104  HLS_TEMP_FILE = (1 << 11),
105  HLS_PERIODIC_REKEY = (1 << 12),
107  HLS_I_FRAMES_ONLY = (1 << 14),
108 } HLSFlags;
109 
110 typedef enum {
113 } SegmentType;
114 
115 typedef struct VariantStream {
116  unsigned var_stream_idx;
117  unsigned number;
118  int64_t sequence;
126 
129 
134  double dpp; // duration per packet
135  int64_t start_pts;
136  int64_t end_pts;
137  int64_t video_lastpos;
140  double duration; // last segment duration computed so far, in seconds
141  int64_t start_pos; // last segment starting position
142  int64_t size; // last segment size
147 
151 
152  char *basename;
155  char *m3u8_name;
156 
158  char current_segment_final_filename_fmt[MAX_URL_SIZE]; // when renaming segments
159 
162 
164 
167  char key_string[KEYSIZE*2 + 1];
168  char iv_string[KEYSIZE*2 + 1];
169 
171  char codec_attr[128];
173  unsigned int nb_streams;
174  int m3u8_created; /* status of media play-list creation */
175  int is_default; /* default status of audio group */
176  const char *language; /* audio lauguage name */
177  const char *agroup; /* audio group name */
178  const char *sgroup; /* subtitle group name */
179  const char *ccgroup; /* closed caption group name */
180  const char *varname; /* variant name */
181 } VariantStream;
182 
183 typedef struct ClosedCaptionsStream {
184  const char *ccgroup; /* closed caption group name */
185  const char *instreamid; /* closed captions INSTREAM-ID */
186  const char *language; /* closed captions langauge */
188 
189 typedef struct HLSContext {
190  const AVClass *class; // Class for private options.
191  int64_t start_sequence;
192  uint32_t start_sequence_source_type; // enum StartSequenceSourceType
193 
194  float time; // Set by a private option.
195  float init_time; // Set by a private option.
196  int max_nb_segments; // Set by a private option.
197  int hls_delete_threshold; // Set by a private option.
198 #if FF_API_HLS_WRAP
199  int wrap; // Set by a private option.
200 #endif
201  uint32_t flags; // enum HLSFlags
202  uint32_t pl_type; // enum PlaylistType
206  int resend_init_file; ///< resend init file into disk after refresh m3u8
207 
208  int use_localtime; ///< flag to expand filename with localtime
209  int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename
211  int64_t recording_time;
212  int64_t max_seg_size; // every segment file max size
213 
214  char *baseurl;
218 
219  int encrypt;
220  char *key;
221  char *key_url;
222  char *iv;
225 
229  char key_string[KEYSIZE*2 + 1];
230  char iv_string[KEYSIZE*2 + 1];
232 
233  char *method;
234  char *user_agent;
235 
237  unsigned int nb_varstreams;
239  unsigned int nb_ccstreams;
240 
241  int master_m3u8_created; /* status of master play-list creation */
242  char *master_m3u8_url; /* URL of the master m3u8 file */
243  int version; /* HLS version */
244  char *var_stream_map; /* user specified variant stream map string */
245  char *cc_stream_map; /* user specified closed caption streams map string */
247  unsigned int master_publish_rate;
248  int http_persistent;
251  int64_t timeout;
253  char *headers;
254  int has_default_key; /* has DEFAULT field of var_stream_map */
255  int has_video_m3u8; /* has video stream m3u8 list */
256 } HLSContext;
257 
258 static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
260 {
261  HLSContext *hls = s->priv_data;
262  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
263  int err = AVERROR_MUXER_NOT_FOUND;
264  if (!*pb || !http_base_proto || !hls->http_persistent) {
265  err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
266 #if CONFIG_HTTP_PROTOCOL
267  } else {
268  URLContext *http_url_context = ffio_geturlcontext(*pb);
269  av_assert0(http_url_context);
270  err = ff_http_do_new_request(http_url_context, filename);
271  if (err < 0)
272  ff_format_io_close(s, pb);
273 
274 #endif
275  }
276  return err;
277 }
278 
279 static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
280 {
281  HLSContext *hls = s->priv_data;
282  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
283  int ret = 0;
284  if (!*pb)
285  return ret;
286  if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) {
287  ff_format_io_close(s, pb);
288 #if CONFIG_HTTP_PROTOCOL
289  } else {
290  URLContext *http_url_context = ffio_geturlcontext(*pb);
291  av_assert0(http_url_context);
292  avio_flush(*pb);
293  ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
294  ret = ff_http_get_shutdown_status(http_url_context);
295 #endif
296  }
297  return ret;
298 }
299 
301 {
302  int http_base_proto = ff_is_http_proto(s->url);
303 
304  if (c->method) {
305  av_dict_set(options, "method", c->method, 0);
306  } else if (http_base_proto) {
307  av_dict_set(options, "method", "PUT", 0);
308  }
309  if (c->user_agent)
310  av_dict_set(options, "user_agent", c->user_agent, 0);
311  if (c->http_persistent)
312  av_dict_set_int(options, "multiple_requests", 1, 0);
313  if (c->timeout >= 0)
314  av_dict_set_int(options, "timeout", c->timeout, 0);
315  if (c->headers)
316  av_dict_set(options, "headers", c->headers, 0);
317 }
318 
320 {
321  int codec_strlen = strlen(vs->codec_attr);
322  char attr[32];
323 
325  return;
327  return;
328 
329  if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
330  uint8_t *data = st->codecpar->extradata;
331  if (data && (data[0] | data[1] | data[2]) == 0 && data[3] == 1 && (data[4] & 0x1F) == 7) {
332  snprintf(attr, sizeof(attr),
333  "avc1.%02x%02x%02x", data[5], data[6], data[7]);
334  } else {
335  goto fail;
336  }
337  } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) {
338  snprintf(attr, sizeof(attr), "mp4a.40.33");
339  } else if (st->codecpar->codec_id == AV_CODEC_ID_MP3) {
340  snprintf(attr, sizeof(attr), "mp4a.40.34");
341  } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
342  /* TODO : For HE-AAC, HE-AACv2, the last digit needs to be set to 5 and 29 respectively */
343  snprintf(attr, sizeof(attr), "mp4a.40.2");
344  } else if (st->codecpar->codec_id == AV_CODEC_ID_AC3) {
345  snprintf(attr, sizeof(attr), "ac-3");
346  } else if (st->codecpar->codec_id == AV_CODEC_ID_EAC3) {
347  snprintf(attr, sizeof(attr), "ec-3");
348  } else {
349  goto fail;
350  }
351  // Don't write the same attribute multiple times
352  if (!av_stristr(vs->codec_attr, attr)) {
353  snprintf(vs->codec_attr + codec_strlen,
354  sizeof(vs->codec_attr) - codec_strlen,
355  "%s%s", codec_strlen ? "," : "", attr);
356  }
357  return;
358 
359 fail:
360  vs->codec_attr[0] = '\0';
362  return;
363 }
364 
365 static int replace_str_data_in_filename(char **s, const char *filename, char placeholder, const char *datastring)
366 {
367  const char *p;
368  char *new_filename;
369  char c;
370  int addchar_count;
371  int found_count = 0;
372  AVBPrint buf;
373 
375 
376  p = filename;
377  for (;;) {
378  c = *p;
379  if (c == '\0')
380  break;
381  if (c == '%' && *(p+1) == '%') // %%
382  addchar_count = 2;
383  else if (c == '%' && *(p+1) == placeholder) {
384  av_bprintf(&buf, "%s", datastring);
385  p += 2;
386  addchar_count = 0;
387  found_count ++;
388  } else
389  addchar_count = 1;
390 
391  if (addchar_count > 0) {
392  av_bprint_append_data(&buf, p, addchar_count);
393  p += addchar_count;
394  }
395  }
396  if (!av_bprint_is_complete(&buf)) {
397  av_bprint_finalize(&buf, NULL);
398  return -1;
399  }
400  if (av_bprint_finalize(&buf, &new_filename) < 0 || !new_filename)
401  return -1;
402  *s = new_filename;
403  return found_count;
404 }
405 
406 static int replace_int_data_in_filename(char **s, const char *filename, char placeholder, int64_t number)
407 {
408  const char *p;
409  char *new_filename;
410  char c;
411  int nd, addchar_count;
412  int found_count = 0;
413  AVBPrint buf;
414 
416 
417  p = filename;
418  for (;;) {
419  c = *p;
420  if (c == '\0')
421  break;
422  if (c == '%' && *(p+1) == '%') // %%
423  addchar_count = 2;
424  else if (c == '%' && (av_isdigit(*(p+1)) || *(p+1) == placeholder)) {
425  nd = 0;
426  addchar_count = 1;
427  while (av_isdigit(*(p + addchar_count))) {
428  nd = nd * 10 + *(p + addchar_count) - '0';
429  addchar_count++;
430  }
431 
432  if (*(p + addchar_count) == placeholder) {
433  av_bprintf(&buf, "%0*"PRId64, (number < 0) ? nd : nd++, number);
434  p += (addchar_count + 1);
435  addchar_count = 0;
436  found_count++;
437  }
438 
439  } else
440  addchar_count = 1;
441 
442  av_bprint_append_data(&buf, p, addchar_count);
443  p += addchar_count;
444  }
445  if (!av_bprint_is_complete(&buf)) {
446  av_bprint_finalize(&buf, NULL);
447  return -1;
448  }
449  if (av_bprint_finalize(&buf, &new_filename) < 0 || !new_filename)
450  return -1;
451  *s = new_filename;
452  return found_count;
453 }
454 
455 static void write_styp(AVIOContext *pb)
456 {
457  avio_wb32(pb, 24);
458  ffio_wfourcc(pb, "styp");
459  ffio_wfourcc(pb, "msdh");
460  avio_wb32(pb, 0); /* minor */
461  ffio_wfourcc(pb, "msdh");
462  ffio_wfourcc(pb, "msix");
463 }
464 
465 static int flush_dynbuf(VariantStream *vs, int *range_length)
466 {
467  AVFormatContext *ctx = vs->avf;
468 
469  if (!ctx->pb) {
470  return AVERROR(EINVAL);
471  }
472 
473  // flush
475 
476  // write out to file
477  *range_length = avio_close_dyn_buf(ctx->pb, &vs->temp_buffer);
478  ctx->pb = NULL;
479  avio_write(vs->out, vs->temp_buffer, *range_length);
480  avio_flush(vs->out);
481 
482  // re-open buffer
483  return avio_open_dyn_buf(&ctx->pb);
484 }
485 
486 static void reflush_dynbuf(VariantStream *vs, int *range_length)
487 {
488  // re-open buffer
489  avio_write(vs->out, vs->temp_buffer, *range_length);
490 }
491 
492 #if HAVE_DOS_PATHS
493 #define SEPARATOR '\\'
494 #else
495 #define SEPARATOR '/'
496 #endif
497 
499  const char *path, const char *proto)
500 {
501  if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
502  AVDictionary *opt = NULL;
503  AVIOContext *out = NULL;
504  int ret;
505  av_dict_set(&opt, "method", "DELETE", 0);
506  ret = avf->io_open(avf, &out, path, AVIO_FLAG_WRITE, &opt);
507  av_dict_free(&opt);
508  if (ret < 0)
509  return hls->ignore_io_errors ? 1 : ret;
510  ff_format_io_close(avf, &out);
511  } else if (unlink(path) < 0) {
512  av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
513  path, strerror(errno));
514  }
515  return 0;
516 }
517 
519  VariantStream *vs)
520 {
521 
522  HLSSegment *segment, *previous_segment = NULL;
523  float playlist_duration = 0.0f;
524  int ret = 0;
525  int segment_cnt = 0;
526  AVBPrint path;
527  const char *dirname = NULL;
528  char *dirname_r = NULL;
529  char *dirname_repl = NULL;
530  const char *vtt_dirname = NULL;
531  char *vtt_dirname_r = NULL;
532  const char *proto = NULL;
533 
535 
536  segment = vs->segments;
537  while (segment) {
538  playlist_duration += segment->duration;
539  segment = segment->next;
540  }
541 
542  segment = vs->old_segments;
543  segment_cnt = 0;
544  while (segment) {
545  playlist_duration -= segment->duration;
546  previous_segment = segment;
547  segment = previous_segment->next;
548  segment_cnt++;
549  if (playlist_duration <= -previous_segment->duration) {
550  previous_segment->next = NULL;
551  break;
552  }
553  if (segment_cnt >= hls->hls_delete_threshold) {
554  previous_segment->next = NULL;
555  break;
556  }
557  }
558 
559  if (segment && !hls->use_localtime_mkdir) {
560  dirname_r = hls->segment_filename ? av_strdup(hls->segment_filename): av_strdup(vs->avf->url);
561  dirname = av_dirname(dirname_r);
562  }
563 
564  /* if %v is present in the file's directory
565  * all segment belongs to the same variant, so do it only once before the loop*/
566  if (dirname && av_stristr(dirname, "%v")) {
567  if (!vs->varname) {
568  if (replace_int_data_in_filename(&dirname_repl, dirname, 'v', segment->var_stream_idx) < 1) {
569  ret = AVERROR(EINVAL);
570  goto fail;
571  }
572  } else {
573  if (replace_str_data_in_filename(&dirname_repl, dirname, 'v', vs->varname) < 1) {
574  ret = AVERROR(EINVAL);
575  goto fail;
576  }
577  }
578 
579  dirname = dirname_repl;
580  }
581 
582  while (segment) {
583  av_log(hls, AV_LOG_DEBUG, "deleting old segment %s\n",
584  segment->filename);
585  if (!hls->use_localtime_mkdir) // segment->filename contains basename only
586  av_bprintf(&path, "%s%c", dirname, SEPARATOR);
587  av_bprintf(&path, "%s", segment->filename);
588 
589  if (!av_bprint_is_complete(&path)) {
590  ret = AVERROR(ENOMEM);
591  goto fail;
592  }
593 
594  proto = avio_find_protocol_name(s->url);
595  if (ret = hls_delete_file(hls, vs->avf, path.str, proto))
596  goto fail;
597 
598  if ((segment->sub_filename[0] != '\0')) {
599  vtt_dirname_r = av_strdup(vs->vtt_avf->url);
600  vtt_dirname = av_dirname(vtt_dirname_r);
601 
602  av_bprint_clear(&path);
603  av_bprintf(&path, "%s%c%s", vtt_dirname, SEPARATOR,
604  segment->sub_filename);
605  av_freep(&vtt_dirname_r);
606 
607  if (!av_bprint_is_complete(&path)) {
608  ret = AVERROR(ENOMEM);
609  goto fail;
610  }
611 
612  if (ret = hls_delete_file(hls, vs->vtt_avf, path.str, proto))
613  goto fail;
614  }
615  av_bprint_clear(&path);
616  previous_segment = segment;
617  segment = previous_segment->next;
618  av_freep(&previous_segment);
619  }
620 
621 fail:
622  av_bprint_finalize(&path, NULL);
623  av_freep(&dirname_r);
624  av_freep(&dirname_repl);
625 
626  return ret;
627 }
628 
629 static int randomize(uint8_t *buf, int len)
630 {
631 #if CONFIG_GCRYPT
632  gcry_randomize(buf, len, GCRY_VERY_STRONG_RANDOM);
633  return 0;
634 #elif CONFIG_OPENSSL
635  if (RAND_bytes(buf, len))
636  return 0;
637 #else
638  return AVERROR(ENOSYS);
639 #endif
640  return AVERROR(EINVAL);
641 }
642 
644 {
645  HLSContext *hls = s->priv_data;
646  int ret;
647  int len;
648  AVIOContext *pb;
650  char * key_basename_source = (hls->master_m3u8_url) ? hls->master_m3u8_url : s->url;
651 
652  len = strlen(key_basename_source) + 4 + 1;
653  hls->key_basename = av_mallocz(len);
654  if (!hls->key_basename)
655  return AVERROR(ENOMEM);
656 
657  av_strlcpy(hls->key_basename, key_basename_source, len);
658  av_strlcat(hls->key_basename, ".key", len);
659 
660  if (hls->key_url) {
661  av_strlcpy(hls->key_file, hls->key_url, sizeof(hls->key_file));
662  av_strlcpy(hls->key_uri, hls->key_url, sizeof(hls->key_uri));
663  } else {
664  av_strlcpy(hls->key_file, hls->key_basename, sizeof(hls->key_file));
665  av_strlcpy(hls->key_uri, hls->key_basename, sizeof(hls->key_uri));
666  }
667 
668  if (!*hls->iv_string) {
669  uint8_t iv[16] = { 0 };
670  char buf[33];
671 
672  if (!hls->iv) {
673  AV_WB64(iv + 8, vs->sequence);
674  } else {
675  memcpy(iv, hls->iv, sizeof(iv));
676  }
677  ff_data_to_hex(buf, iv, sizeof(iv), 0);
678  buf[32] = '\0';
679  memcpy(hls->iv_string, buf, sizeof(hls->iv_string));
680  }
681 
682  if (!*hls->key_uri) {
683  av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
684  return AVERROR(EINVAL);
685  }
686 
687  if (!*hls->key_file) {
688  av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
689  return AVERROR(EINVAL);
690  }
691 
692  if (!*hls->key_string) {
694  if (!hls->key) {
695  if ((ret = randomize(key, sizeof(key))) < 0) {
696  av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n");
697  return ret;
698  }
699  } else {
700  memcpy(key, hls->key, sizeof(key));
701  }
702 
703  ff_data_to_hex(hls->key_string, key, sizeof(key), 0);
704  set_http_options(s, &options, hls);
705  ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_WRITE, &options);
707  if (ret < 0)
708  return ret;
709  avio_seek(pb, 0, SEEK_CUR);
710  avio_write(pb, key, KEYSIZE);
711  avio_close(pb);
712  }
713  return 0;
714 }
715 
716 
718 {
719  HLSContext *hls = s->priv_data;
720  int ret;
721  AVIOContext *pb;
724 
725  set_http_options(s, &options, hls);
726  ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, &options);
728  if (ret < 0) {
729  av_log(hls, AV_LOG_ERROR,
730  "error opening key info file %s\n", hls->key_info_file);
731  return ret;
732  }
733 
734  ff_get_line(pb, vs->key_uri, sizeof(vs->key_uri));
735  vs->key_uri[strcspn(vs->key_uri, "\r\n")] = '\0';
736 
737  ff_get_line(pb, vs->key_file, sizeof(vs->key_file));
738  vs->key_file[strcspn(vs->key_file, "\r\n")] = '\0';
739 
740  ff_get_line(pb, vs->iv_string, sizeof(vs->iv_string));
741  vs->iv_string[strcspn(vs->iv_string, "\r\n")] = '\0';
742 
743  ff_format_io_close(s, &pb);
744 
745  if (!*vs->key_uri) {
746  av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
747  return AVERROR(EINVAL);
748  }
749 
750  if (!*vs->key_file) {
751  av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
752  return AVERROR(EINVAL);
753  }
754 
755  set_http_options(s, &options, hls);
756  ret = s->io_open(s, &pb, vs->key_file, AVIO_FLAG_READ, &options);
758  if (ret < 0) {
759  av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", vs->key_file);
760  return ret;
761  }
762 
763  ret = avio_read(pb, key, sizeof(key));
764  ff_format_io_close(s, &pb);
765  if (ret != sizeof(key)) {
766  av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", vs->key_file);
767  if (ret >= 0 || ret == AVERROR_EOF)
768  ret = AVERROR(EINVAL);
769  return ret;
770  }
771  ff_data_to_hex(vs->key_string, key, sizeof(key), 0);
772 
773  return 0;
774 }
775 
777 {
779  HLSContext *hls = s->priv_data;
780  AVFormatContext *oc;
781  AVFormatContext *vtt_oc = NULL;
782  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
783  int remaining_options;
784  int i, ret;
785 
787  if (ret < 0)
788  return ret;
789  oc = vs->avf;
790 
791  oc->url = av_strdup("");
792  if (!oc->url)
793  return AVERROR(ENOMEM);
794 
795  oc->interrupt_callback = s->interrupt_callback;
796  oc->max_delay = s->max_delay;
797  oc->opaque = s->opaque;
798  oc->io_open = s->io_open;
799  oc->io_close = s->io_close;
800  oc->strict_std_compliance = s->strict_std_compliance;
801  av_dict_copy(&oc->metadata, s->metadata, 0);
802 
803  if (vs->vtt_oformat) {
805  if (ret < 0)
806  return ret;
807  vtt_oc = vs->vtt_avf;
808  av_dict_copy(&vtt_oc->metadata, s->metadata, 0);
809  }
810 
811  for (i = 0; i < vs->nb_streams; i++) {
812  AVStream *st;
813  AVFormatContext *loc;
815  loc = vtt_oc;
816  else
817  loc = oc;
818 
819  if (!(st = avformat_new_stream(loc, NULL)))
820  return AVERROR(ENOMEM);
822  if (!oc->oformat->codec_tag ||
826  } else {
827  st->codecpar->codec_tag = 0;
828  }
829 
831  st->time_base = vs->streams[i]->time_base;
832  av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0);
833  }
834 
835  vs->start_pos = 0;
836  vs->new_start = 1;
837 
838  if (hls->segment_type == SEGMENT_TYPE_FMP4 && hls->max_seg_size > 0) {
839  if (hls->http_persistent > 0) {
840  //TODO: Support fragment fmp4 for http persistent in HLS muxer.
841  av_log(s, AV_LOG_WARNING, "http persistent mode is currently unsupported for fragment mp4 in the HLS muxer.\n");
842  }
843  if (hls->max_seg_size > 0) {
844  av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n");
845  return AVERROR_PATCHWELCOME;
846  }
847  }
848 
849  if ((ret = avio_open_dyn_buf(&oc->pb)) < 0)
850  return ret;
851 
852  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
853  set_http_options(s, &options, hls);
854  if (byterange_mode) {
855  ret = hlsenc_io_open(s, &vs->out, vs->basename, &options);
856  } else {
858  }
860  }
861  if (ret < 0) {
862  av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename);
863  return ret;
864  }
865 
867  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
868  av_dict_set(&options, "fflags", "-autobsf", 0);
869  av_dict_set(&options, "movflags", "+frag_custom+dash+delay_moov", AV_DICT_APPEND);
870  } else {
871  /* We only require one PAT/PMT per segment. */
872  char period[21];
873  snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1);
876  }
878  remaining_options = av_dict_count(options);
880  if (ret < 0)
881  return ret;
882  if (remaining_options) {
883  av_log(s, AV_LOG_ERROR, "Some of the provided format options are not recognized\n");
884  return AVERROR(EINVAL);
885  }
886  avio_flush(oc->pb);
887  return 0;
888 }
889 
890 static HLSSegment *find_segment_by_filename(HLSSegment *segment, const char *filename)
891 {
892  while (segment) {
893  if (!av_strcasecmp(segment->filename,filename))
894  return segment;
895  segment = segment->next;
896  }
897  return (HLSSegment *) NULL;
898 }
899 
901  VariantStream *vs, HLSSegment *en,
902  double duration, int64_t pos, int64_t size)
903 {
906  char * new_url = av_strdup(vs->current_segment_final_filename_fmt);
907  if (!new_url) {
908  return AVERROR(ENOMEM);
909  }
910  ff_format_set_url(vs->avf, new_url);
912  char *filename = NULL;
913  if (replace_int_data_in_filename(&filename, vs->avf->url, 's', pos + size) < 1) {
914  av_log(hls, AV_LOG_ERROR,
915  "Invalid second level segment filename template '%s', "
916  "you can try to remove second_level_segment_size flag\n",
917  vs->avf->url);
918  av_freep(&filename);
919  return AVERROR(EINVAL);
920  }
921  ff_format_set_url(vs->avf, filename);
922  }
924  char *filename = NULL;
925  if (replace_int_data_in_filename(&filename, vs->avf->url,
926  't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) {
927  av_log(hls, AV_LOG_ERROR,
928  "Invalid second level segment filename template '%s', "
929  "you can try to remove second_level_segment_time flag\n",
930  vs->avf->url);
931  av_freep(&filename);
932  return AVERROR(EINVAL);
933  }
934  ff_format_set_url(vs->avf, filename);
935  }
936  }
937  return 0;
938 }
939 
941 {
942  int ret = 0;
943 
945  av_log(hls, AV_LOG_ERROR,
946  "second_level_segment_duration hls_flag requires strftime to be true\n");
947  ret = AVERROR(EINVAL);
948  }
950  av_log(hls, AV_LOG_ERROR,
951  "second_level_segment_size hls_flag requires strfime to be true\n");
952  ret = AVERROR(EINVAL);
953  }
955  av_log(hls, AV_LOG_ERROR,
956  "second_level_segment_index hls_flag requires strftime to be true\n");
957  ret = AVERROR(EINVAL);
958  }
959 
960  return ret;
961 }
962 
964 {
965  const char *proto = avio_find_protocol_name(vs->basename);
966  int segment_renaming_ok = proto && !strcmp(proto, "file");
967  int ret = 0;
968 
969  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) && !segment_renaming_ok) {
970  av_log(hls, AV_LOG_ERROR,
971  "second_level_segment_duration hls_flag works only with file protocol segment names\n");
972  ret = AVERROR(EINVAL);
973  }
974  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) && !segment_renaming_ok) {
975  av_log(hls, AV_LOG_ERROR,
976  "second_level_segment_size hls_flag works only with file protocol segment names\n");
977  ret = AVERROR(EINVAL);
978  }
979 
980  return ret;
981 }
982 
983 static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename) {
986  ff_rename(old_filename, vs->avf->url, hls);
987  }
988 }
989 
991 {
992  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) {
993  char *filename = NULL;
994  if (replace_int_data_in_filename(&filename,
995 #if FF_API_HLS_WRAP
996  oc->url, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) {
997 #else
998  oc->url, 'd', vs->sequence) < 1) {
999 #endif
1000  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1001  "you can try to remove second_level_segment_index flag\n",
1002  oc->url);
1003  av_freep(&filename);
1004  return AVERROR(EINVAL);
1005  }
1006  ff_format_set_url(oc, filename);
1007  }
1011  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
1012  char *filename = NULL;
1013  if (replace_int_data_in_filename(&filename, oc->url, 's', 0) < 1) {
1014  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1015  "you can try to remove second_level_segment_size flag\n",
1016  oc->url);
1017  av_freep(&filename);
1018  return AVERROR(EINVAL);
1019  }
1020  ff_format_set_url(oc, filename);
1021  }
1022  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) {
1023  char *filename = NULL;
1024  if (replace_int_data_in_filename(&filename, oc->url, 't', 0) < 1) {
1025  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1026  "you can try to remove second_level_segment_time flag\n",
1027  oc->url);
1028  av_freep(&filename);
1029  return AVERROR(EINVAL);
1030  }
1031  ff_format_set_url(oc, filename);
1032  }
1033  }
1034  return 0;
1035 }
1036 
1037 /* Create a new segment and append it to the segment list */
1039  VariantStream *vs, double duration, int64_t pos,
1040  int64_t size)
1041 {
1042  HLSSegment *en = av_malloc(sizeof(*en));
1043  const char *filename;
1044  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1045  int ret;
1046 
1047  if (!en)
1048  return AVERROR(ENOMEM);
1049 
1050  en->var_stream_idx = vs->var_stream_idx;
1051  ret = sls_flags_filename_process(s, hls, vs, en, duration, pos, size);
1052  if (ret < 0) {
1053  av_freep(&en);
1054  return ret;
1055  }
1056 
1057  filename = av_basename(vs->avf->url);
1058 
1059  if (hls->use_localtime_mkdir) {
1060  filename = vs->avf->url;
1061  }
1062  if ((find_segment_by_filename(vs->segments, filename) || find_segment_by_filename(vs->old_segments, filename))
1063  && !byterange_mode) {
1064  av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename);
1065  }
1066  av_strlcpy(en->filename, filename, sizeof(en->filename));
1067 
1068  if (vs->has_subtitle)
1069  av_strlcpy(en->sub_filename, av_basename(vs->vtt_avf->url), sizeof(en->sub_filename));
1070  else
1071  en->sub_filename[0] = '\0';
1072 
1073  en->duration = duration;
1074  en->pos = pos;
1075  en->size = size;
1076  en->keyframe_pos = vs->video_keyframe_pos;
1078  en->next = NULL;
1079  en->discont = 0;
1080 
1081  if (vs->discontinuity) {
1082  en->discont = 1;
1083  vs->discontinuity = 0;
1084  }
1085 
1086  if (hls->key_info_file || hls->encrypt) {
1087  av_strlcpy(en->key_uri, vs->key_uri, sizeof(en->key_uri));
1088  av_strlcpy(en->iv_string, vs->iv_string, sizeof(en->iv_string));
1089  }
1090 
1091  if (!vs->segments)
1092  vs->segments = en;
1093  else
1094  vs->last_segment->next = en;
1095 
1096  vs->last_segment = en;
1097 
1098  // EVENT or VOD playlists imply sliding window cannot be used
1099  if (hls->pl_type != PLAYLIST_TYPE_NONE)
1100  hls->max_nb_segments = 0;
1101 
1102  if (hls->max_nb_segments && vs->nb_entries >= hls->max_nb_segments) {
1103  en = vs->segments;
1104  vs->initial_prog_date_time += en->duration;
1105  vs->segments = en->next;
1106  if (en && hls->flags & HLS_DELETE_SEGMENTS &&
1107 #if FF_API_HLS_WRAP
1108  !(hls->flags & HLS_SINGLE_FILE || hls->wrap)) {
1109 #else
1110  !(hls->flags & HLS_SINGLE_FILE)) {
1111 #endif
1112  en->next = vs->old_segments;
1113  vs->old_segments = en;
1114  if ((ret = hls_delete_old_segments(s, hls, vs)) < 0)
1115  return ret;
1116  } else
1117  av_freep(&en);
1118  } else
1119  vs->nb_entries++;
1120 
1121  if (hls->max_seg_size > 0) {
1122  return 0;
1123  }
1124  vs->sequence++;
1125 
1126  return 0;
1127 }
1128 
1129 static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
1130 {
1131  HLSContext *hls = s->priv_data;
1132  AVIOContext *in;
1133  int ret = 0, is_segment = 0;
1134  int64_t new_start_pos;
1135  char line[MAX_URL_SIZE];
1136  const char *ptr;
1137  const char *end;
1138 
1139  if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
1140  &s->interrupt_callback, NULL,
1141  s->protocol_whitelist, s->protocol_blacklist)) < 0)
1142  return ret;
1143 
1144  ff_get_chomp_line(in, line, sizeof(line));
1145  if (strcmp(line, "#EXTM3U")) {
1147  goto fail;
1148  }
1149 
1150  vs->discontinuity = 0;
1151  while (!avio_feof(in)) {
1152  ff_get_chomp_line(in, line, sizeof(line));
1153  if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
1154  int64_t tmp_sequence = strtoll(ptr, NULL, 10);
1155  if (tmp_sequence < vs->sequence)
1156  av_log(hls, AV_LOG_VERBOSE,
1157  "Found playlist sequence number was smaller """
1158  "than specified start sequence number: %"PRId64" < %"PRId64", "
1159  "omitting\n", tmp_sequence, hls->start_sequence);
1160  else {
1161  av_log(hls, AV_LOG_DEBUG, "Found playlist sequence number: %"PRId64"\n", tmp_sequence);
1162  vs->sequence = tmp_sequence;
1163  }
1164  } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
1165  is_segment = 1;
1166  vs->discontinuity = 1;
1167  } else if (av_strstart(line, "#EXTINF:", &ptr)) {
1168  is_segment = 1;
1169  vs->duration = atof(ptr);
1170  } else if (av_stristart(line, "#EXT-X-KEY:", &ptr)) {
1171  ptr = av_stristr(line, "URI=\"");
1172  if (ptr) {
1173  ptr += strlen("URI=\"");
1174  end = av_stristr(ptr, ",");
1175  if (end) {
1176  av_strlcpy(vs->key_uri, ptr, end - ptr);
1177  } else {
1178  av_strlcpy(vs->key_uri, ptr, sizeof(vs->key_uri));
1179  }
1180  }
1181 
1182  ptr = av_stristr(line, "IV=0x");
1183  if (ptr) {
1184  ptr += strlen("IV=0x");
1185  end = av_stristr(ptr, ",");
1186  if (end) {
1187  av_strlcpy(vs->iv_string, ptr, end - ptr);
1188  } else {
1189  av_strlcpy(vs->iv_string, ptr, sizeof(vs->iv_string));
1190  }
1191  }
1192 
1193  } else if (av_strstart(line, "#", NULL)) {
1194  continue;
1195  } else if (line[0]) {
1196  if (is_segment) {
1197  char *new_file = av_strdup(line);
1198  if (!new_file) {
1199  ret = AVERROR(ENOMEM);
1200  goto fail;
1201  }
1202  ff_format_set_url(vs->avf, new_file);
1203  is_segment = 0;
1204  new_start_pos = avio_tell(vs->avf->pb);
1205  vs->size = new_start_pos - vs->start_pos;
1206  vs->initial_prog_date_time -= vs->duration; // this is a previously existing segment
1207  ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size);
1208  if (ret < 0)
1209  goto fail;
1210  vs->start_pos = new_start_pos;
1211  }
1212  }
1213  }
1214 
1215 fail:
1216  avio_close(in);
1217  return ret;
1218 }
1219 
1221 {
1222  HLSSegment *en;
1223 
1224  while (p) {
1225  en = p;
1226  p = p->next;
1227  av_freep(&en);
1228  }
1229 }
1230 
1232 {
1233  size_t len = strlen(oc->url);
1234  char *final_filename = av_strdup(oc->url);
1235  int ret;
1236 
1237  if (!final_filename)
1238  return AVERROR(ENOMEM);
1239  final_filename[len-4] = '\0';
1240  ret = ff_rename(oc->url, final_filename, s);
1241  oc->url[len-4] = '\0';
1242  av_freep(&final_filename);
1243  return ret;
1244 }
1245 
1246 static const char* get_relative_url(const char *master_url, const char *media_url)
1247 {
1248  const char *p = strrchr(master_url, '/');
1249  size_t base_len = 0;
1250 
1251  if (!p) p = strrchr(master_url, '\\');
1252 
1253  if (p) {
1254  base_len = p - master_url;
1255  if (av_strncasecmp(master_url, media_url, base_len)) {
1256  av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n");
1257  return NULL;
1258  }
1259  } else {
1260  return media_url;
1261  }
1262 
1263  return media_url + base_len + 1;
1264 }
1265 
1266 static int64_t get_stream_bit_rate(AVStream *stream)
1267 {
1269  stream,
1271  NULL
1272  );
1273 
1274  if (stream->codecpar->bit_rate)
1275  return stream->codecpar->bit_rate;
1276  else if (props)
1277  return props->max_bitrate;
1278 
1279  return 0;
1280 }
1281 
1283  VariantStream * const input_vs)
1284 {
1285  HLSContext *hls = s->priv_data;
1286  VariantStream *vs, *temp_vs;
1287  AVStream *vid_st, *aud_st;
1289  unsigned int i, j;
1290  int ret, bandwidth;
1291  const char *m3u8_rel_name = NULL;
1292  const char *vtt_m3u8_rel_name = NULL;
1293  const char *ccgroup;
1294  const char *sgroup = NULL;
1295  ClosedCaptionsStream *ccs;
1296  const char *proto = avio_find_protocol_name(hls->master_m3u8_url);
1297  int is_file_proto = proto && !strcmp(proto, "file");
1298  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || hls->master_publish_rate);
1299  char temp_filename[MAX_URL_SIZE];
1300 
1301  input_vs->m3u8_created = 1;
1302  if (!hls->master_m3u8_created) {
1303  /* For the first time, wait until all the media playlists are created */
1304  for (i = 0; i < hls->nb_varstreams; i++)
1305  if (!hls->var_streams[i].m3u8_created)
1306  return 0;
1307  } else {
1308  /* Keep publishing the master playlist at the configured rate */
1309  if (&hls->var_streams[0] != input_vs || !hls->master_publish_rate ||
1310  input_vs->number % hls->master_publish_rate)
1311  return 0;
1312  }
1313 
1314  set_http_options(s, &options, hls);
1315  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", hls->master_m3u8_url);
1316  ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options);
1318  if (ret < 0) {
1319  av_log(s, AV_LOG_ERROR, "Failed to open master play list file '%s'\n",
1320  temp_filename);
1321  goto fail;
1322  }
1323 
1325 
1326  for (i = 0; i < hls->nb_ccstreams; i++) {
1327  ccs = &(hls->cc_streams[i]);
1328  avio_printf(hls->m3u8_out, "#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS");
1329  avio_printf(hls->m3u8_out, ",GROUP-ID=\"%s\"", ccs->ccgroup);
1330  avio_printf(hls->m3u8_out, ",NAME=\"%s\"", ccs->instreamid);
1331  if (ccs->language)
1332  avio_printf(hls->m3u8_out, ",LANGUAGE=\"%s\"", ccs->language);
1333  avio_printf(hls->m3u8_out, ",INSTREAM-ID=\"%s\"\n", ccs->instreamid);
1334  }
1335 
1336  /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/
1337  for (i = 0; i < hls->nb_varstreams; i++) {
1338  vs = &(hls->var_streams[i]);
1339 
1340  if (vs->has_video || vs->has_subtitle || !vs->agroup)
1341  continue;
1342 
1343  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1344  if (!m3u8_rel_name) {
1345  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1346  goto fail;
1347  }
1348 
1349  ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1);
1350  }
1351 
1352  /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/
1353  for (i = 0; i < hls->nb_varstreams; i++) {
1354  vs = &(hls->var_streams[i]);
1355 
1356  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1357  if (!m3u8_rel_name) {
1358  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1359  goto fail;
1360  }
1361 
1362  vid_st = NULL;
1363  aud_st = NULL;
1364  for (j = 0; j < vs->nb_streams; j++) {
1366  vid_st = vs->streams[j];
1367  else if (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
1368  aud_st = vs->streams[j];
1369  }
1370 
1371  if (!vid_st && !aud_st) {
1372  av_log(s, AV_LOG_WARNING, "Media stream not found\n");
1373  continue;
1374  }
1375 
1376  /**
1377  * Traverse through the list of audio only rendition streams and find
1378  * the rendition which has highest bitrate in the same audio group
1379  */
1380  if (vs->agroup) {
1381  for (j = 0; j < hls->nb_varstreams; j++) {
1382  temp_vs = &(hls->var_streams[j]);
1383  if (!temp_vs->has_video && !temp_vs->has_subtitle &&
1384  temp_vs->agroup &&
1385  !av_strcasecmp(temp_vs->agroup, vs->agroup)) {
1386  if (!aud_st)
1387  aud_st = temp_vs->streams[0];
1388  if (temp_vs->streams[0]->codecpar->bit_rate >
1389  aud_st->codecpar->bit_rate)
1390  aud_st = temp_vs->streams[0];
1391  }
1392  }
1393  }
1394 
1395  bandwidth = 0;
1396  if (vid_st)
1397  bandwidth += get_stream_bit_rate(vid_st);
1398  if (aud_st)
1399  bandwidth += get_stream_bit_rate(aud_st);
1400  bandwidth += bandwidth / 10;
1401 
1402  ccgroup = NULL;
1403  if (vid_st && vs->ccgroup) {
1404  /* check if this group name is available in the cc map string */
1405  for (j = 0; j < hls->nb_ccstreams; j++) {
1406  ccs = &(hls->cc_streams[j]);
1407  if (!av_strcasecmp(ccs->ccgroup, vs->ccgroup)) {
1408  ccgroup = vs->ccgroup;
1409  break;
1410  }
1411  }
1412  if (j == hls->nb_ccstreams)
1413  av_log(s, AV_LOG_WARNING, "mapping ccgroup %s not found\n",
1414  vs->ccgroup);
1415  }
1416 
1417  if (vid_st && vs->sgroup) {
1418  sgroup = vs->sgroup;
1419  vtt_m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->vtt_m3u8_name);
1420  if (!vtt_m3u8_rel_name) {
1421  av_log(s, AV_LOG_WARNING, "Unable to find relative subtitle URL\n");
1422  break;
1423  }
1424 
1425  ff_hls_write_subtitle_rendition(hls->m3u8_out, sgroup, vtt_m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1);
1426  }
1427 
1428  if (!hls->has_default_key || !hls->has_video_m3u8) {
1429  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name,
1430  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1431  } else {
1432  if (vid_st) {
1433  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name,
1434  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1435  }
1436  }
1437  }
1438 fail:
1439  if (ret >=0)
1440  hls->master_m3u8_created = 1;
1441  hlsenc_io_close(s, &hls->m3u8_out, temp_filename);
1442  if (use_temp_file)
1443  ff_rename(temp_filename, hls->master_m3u8_url, s);
1444 
1445  return ret;
1446 }
1447 
1448 static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
1449 {
1450  HLSContext *hls = s->priv_data;
1451  HLSSegment *en;
1452  int target_duration = 0;
1453  int ret = 0;
1454  char temp_filename[MAX_URL_SIZE];
1455  char temp_vtt_filename[MAX_URL_SIZE];
1456  int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries);
1457  const char *proto = avio_find_protocol_name(vs->m3u8_name);
1458  int is_file_proto = proto && !strcmp(proto, "file");
1459  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || !(hls->pl_type == PLAYLIST_TYPE_VOD));
1460  static unsigned warned_non_file;
1461  char *key_uri = NULL;
1462  char *iv_string = NULL;
1464  double prog_date_time = vs->initial_prog_date_time;
1465  double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? &prog_date_time : NULL;
1466  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1467 
1468  hls->version = 3;
1469  if (byterange_mode) {
1470  hls->version = 4;
1471  sequence = 0;
1472  }
1473 
1474  if (hls->flags & HLS_INDEPENDENT_SEGMENTS) {
1475  hls->version = 6;
1476  }
1477 
1478  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1479  hls->version = 7;
1480  }
1481 
1482  if (!is_file_proto && (hls->flags & HLS_TEMP_FILE) && !warned_non_file++)
1483  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
1484 
1485  set_http_options(s, &options, hls);
1486  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", vs->m3u8_name);
1487  if ((ret = hlsenc_io_open(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename, &options)) < 0) {
1488  if (hls->ignore_io_errors)
1489  ret = 0;
1490  goto fail;
1491  }
1492 
1493  for (en = vs->segments; en; en = en->next) {
1494  if (target_duration <= en->duration)
1495  target_duration = lrint(en->duration);
1496  }
1497 
1498  vs->discontinuity_set = 0;
1499  ff_hls_write_playlist_header(byterange_mode ? hls->m3u8_out : vs->out, hls->version, hls->allowcache,
1500  target_duration, sequence, hls->pl_type, hls->flags & HLS_I_FRAMES_ONLY);
1501 
1502  if ((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0) {
1503  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-DISCONTINUITY\n");
1504  vs->discontinuity_set = 1;
1505  }
1506  if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
1507  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
1508  }
1509  for (en = vs->segments; en; en = en->next) {
1510  if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) ||
1511  av_strcasecmp(en->iv_string, iv_string))) {
1512  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri);
1513  if (*en->iv_string)
1514  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, ",IV=0x%s", en->iv_string);
1515  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "\n");
1516  key_uri = en->key_uri;
1517  iv_string = en->iv_string;
1518  }
1519 
1520  if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) {
1521  ff_hls_write_init_file(byterange_mode ? hls->m3u8_out : vs->out, (hls->flags & HLS_SINGLE_FILE) ? en->filename : vs->fmp4_init_filename,
1522  hls->flags & HLS_SINGLE_FILE, vs->init_range_length, 0);
1523  }
1524 
1525  ret = ff_hls_write_file_entry(byterange_mode ? hls->m3u8_out : vs->out, en->discont, byterange_mode,
1526  en->duration, hls->flags & HLS_ROUND_DURATIONS,
1527  en->size, en->pos, hls->baseurl,
1528  en->filename, prog_date_time_p, en->keyframe_size, en->keyframe_pos, hls->flags & HLS_I_FRAMES_ONLY);
1529  if (ret < 0) {
1530  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1531  }
1532  }
1533 
1534  if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
1535  ff_hls_write_end_list(byterange_mode ? hls->m3u8_out : vs->out);
1536 
1537  if (vs->vtt_m3u8_name) {
1538  snprintf(temp_vtt_filename, sizeof(temp_vtt_filename), use_temp_file ? "%s.tmp" : "%s", vs->vtt_m3u8_name);
1539  if ((ret = hlsenc_io_open(s, &hls->sub_m3u8_out, temp_vtt_filename, &options)) < 0) {
1540  if (hls->ignore_io_errors)
1541  ret = 0;
1542  goto fail;
1543  }
1545  target_duration, sequence, PLAYLIST_TYPE_NONE, 0);
1546  for (en = vs->segments; en; en = en->next) {
1547  ret = ff_hls_write_file_entry(hls->sub_m3u8_out, 0, byterange_mode,
1548  en->duration, 0, en->size, en->pos,
1549  hls->baseurl, en->sub_filename, NULL, 0, 0, 0);
1550  if (ret < 0) {
1551  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1552  }
1553  }
1554 
1555  if (last)
1557 
1558  }
1559 
1560 fail:
1562  ret = hlsenc_io_close(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename);
1563  if (ret < 0) {
1564  return ret;
1565  }
1567  if (use_temp_file) {
1568  ff_rename(temp_filename, vs->m3u8_name, s);
1569  if (vs->vtt_m3u8_name)
1570  ff_rename(temp_vtt_filename, vs->vtt_m3u8_name, s);
1571  }
1572  if (ret >= 0 && hls->master_pl_name)
1573  if (create_master_playlist(s, vs) < 0)
1574  av_log(s, AV_LOG_WARNING, "Master playlist creation failed\n");
1575 
1576  return ret;
1577 }
1578 
1580 {
1581  HLSContext *c = s->priv_data;
1582  AVFormatContext *oc = vs->avf;
1583  AVFormatContext *vtt_oc = vs->vtt_avf;
1585  const char *proto = NULL;
1586  int use_temp_file = 0;
1587  char iv_string[KEYSIZE*2 + 1];
1588  int err = 0;
1589 
1590  if (c->flags & HLS_SINGLE_FILE) {
1591  char *new_name = av_strdup(vs->basename);
1592  if (!new_name)
1593  return AVERROR(ENOMEM);
1594  ff_format_set_url(oc, new_name);
1595  if (vs->vtt_basename) {
1596  new_name = av_strdup(vs->vtt_basename);
1597  if (!new_name)
1598  return AVERROR(ENOMEM);
1599  ff_format_set_url(vtt_oc, new_name);
1600  }
1601  } else if (c->max_seg_size > 0) {
1602  char *filename = NULL;
1603  if (replace_int_data_in_filename(&filename,
1604 #if FF_API_HLS_WRAP
1605  vs->basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) {
1606 #else
1607  vs->basename, 'd', vs->sequence) < 1) {
1608 #endif
1609  av_freep(&filename);
1610  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -strftime 1 with it\n", vs->basename);
1611  return AVERROR(EINVAL);
1612  }
1613  ff_format_set_url(oc, filename);
1614  } else {
1615  if (c->use_localtime) {
1616  time_t now0;
1617  struct tm *tm, tmpbuf;
1618  int bufsize = strlen(vs->basename) + MAX_URL_SIZE;
1619  char *buf = av_mallocz(bufsize);
1620  if (!buf)
1621  return AVERROR(ENOMEM);
1622  time(&now0);
1623  tm = localtime_r(&now0, &tmpbuf);
1624  ff_format_set_url(oc, buf);
1625  if (!strftime(oc->url, bufsize, vs->basename, tm)) {
1626  av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
1627  return AVERROR(EINVAL);
1628  }
1629 
1630  err = sls_flag_use_localtime_filename(oc, c, vs);
1631  if (err < 0) {
1632  return AVERROR(ENOMEM);
1633  }
1634 
1635  if (c->use_localtime_mkdir) {
1636  const char *dir;
1637  char *fn_copy = av_strdup(oc->url);
1638  if (!fn_copy)
1639  return AVERROR(ENOMEM);
1640  dir = av_dirname(fn_copy);
1641  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1642  av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
1643  av_freep(&fn_copy);
1644  return AVERROR(errno);
1645  }
1646  av_freep(&fn_copy);
1647  }
1648  } else {
1649  char *filename = NULL;
1650  if (replace_int_data_in_filename(&filename,
1651 #if FF_API_HLS_WRAP
1652  vs->basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) {
1653 #else
1654  vs->basename, 'd', vs->sequence) < 1) {
1655 #endif
1656  av_freep(&filename);
1657  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -strftime 1 with it\n", vs->basename);
1658  return AVERROR(EINVAL);
1659  }
1660  ff_format_set_url(oc, filename);
1661  }
1662  if (vs->vtt_basename) {
1663  char *filename = NULL;
1664  if (replace_int_data_in_filename(&filename,
1665 #if FF_API_HLS_WRAP
1666  vs->vtt_basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) {
1667 #else
1668  vs->vtt_basename, 'd', vs->sequence) < 1) {
1669 #endif
1670  av_freep(&filename);
1671  av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename);
1672  return AVERROR(EINVAL);
1673  }
1674  ff_format_set_url(vtt_oc, filename);
1675  }
1676  }
1677 
1678  proto = avio_find_protocol_name(oc->url);
1679  use_temp_file = proto && !strcmp(proto, "file") && (c->flags & HLS_TEMP_FILE);
1680 
1681  if (use_temp_file) {
1682  char *new_name = av_asprintf("%s.tmp", oc->url);
1683  if (!new_name)
1684  return AVERROR(ENOMEM);
1685  ff_format_set_url(oc, new_name);
1686  }
1687 
1688  if (c->key_info_file || c->encrypt) {
1689  if (c->segment_type == SEGMENT_TYPE_FMP4) {
1690  av_log(s, AV_LOG_ERROR, "Encrypted fmp4 not yet supported\n");
1691  return AVERROR_PATCHWELCOME;
1692  }
1693 
1694  if (c->key_info_file && c->encrypt) {
1695  av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file and -hls_enc,"
1696  " ignoring -hls_enc\n");
1697  }
1698 
1699  if (!vs->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) {
1700  if (c->key_info_file) {
1701  if ((err = hls_encryption_start(s, vs)) < 0)
1702  goto fail;
1703  } else {
1704  if (!c->encrypt_started) {
1705  if ((err = do_encrypt(s, vs)) < 0)
1706  goto fail;
1707  c->encrypt_started = 1;
1708  }
1709  av_strlcpy(vs->key_uri, c->key_uri, sizeof(vs->key_uri));
1710  av_strlcpy(vs->key_string, c->key_string, sizeof(vs->key_string));
1711  av_strlcpy(vs->iv_string, c->iv_string, sizeof(vs->iv_string));
1712  }
1713  vs->encrypt_started = 1;
1714  }
1715  err = av_strlcpy(iv_string, vs->iv_string, sizeof(iv_string));
1716  if (!err) {
1717  snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, vs->sequence);
1718  memset(vs->iv_string, 0, sizeof(vs->iv_string));
1719  memcpy(vs->iv_string, iv_string, sizeof(iv_string));
1720  }
1721  }
1722  if (c->segment_type != SEGMENT_TYPE_FMP4) {
1723  if (oc->oformat->priv_class && oc->priv_data) {
1724  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
1725  }
1726  if (c->flags & HLS_SINGLE_FILE) {
1728  if ((err = hlsenc_io_open(s, &vs->out, oc->url, &options)) < 0) {
1729  if (c->ignore_io_errors)
1730  err = 0;
1731  goto fail;
1732  }
1733  }
1734  }
1735  if (vs->vtt_basename) {
1737  if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < 0) {
1738  if (c->ignore_io_errors)
1739  err = 0;
1740  goto fail;
1741  }
1742  }
1744 
1745  if (vs->vtt_basename) {
1746  err = avformat_write_header(vtt_oc,NULL);
1747  if (err < 0)
1748  return err;
1749  }
1750 
1751  return 0;
1752 fail:
1754 
1755  return err;
1756 }
1757 
1759 {
1760  char b[21];
1761  time_t t = time(NULL);
1762  struct tm *p, tmbuf;
1763  HLSContext *hls = s->priv_data;
1764 
1765  p = localtime_r(&t, &tmbuf);
1766  // no %s support when strftime returned error or left format string unchanged
1767  // also no %s support on MSVC, which invokes the invalid parameter handler on unsupported format strings, instead of returning an error
1768  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1769  return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.m4s" : "-%s.m4s";
1770  }
1771  return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.ts" : "-%s.ts";
1772 }
1773 
1774 static int append_postfix(char *name, int name_buf_len, int i)
1775 {
1776  char *p;
1777  char extension[10] = {'\0'};
1778 
1779  p = strrchr(name, '.');
1780  if (p) {
1781  av_strlcpy(extension, p, sizeof(extension));
1782  *p = '\0';
1783  }
1784 
1785  snprintf(name + strlen(name), name_buf_len - strlen(name), POSTFIX_PATTERN, i);
1786 
1787  if (strlen(extension))
1788  av_strlcat(name, extension, name_buf_len);
1789 
1790  return 0;
1791 }
1792 
1793 static int validate_name(int nb_vs, const char *fn)
1794 {
1795  const char *filename, *subdir_name;
1796  char *fn_dup = NULL;
1797  int ret = 0;
1798 
1799  if (!fn)
1800  return AVERROR(EINVAL);
1801 
1802  fn_dup = av_strdup(fn);
1803  if (!fn_dup)
1804  return AVERROR(ENOMEM);
1805  filename = av_basename(fn);
1806  subdir_name = av_dirname(fn_dup);
1807 
1808  if (nb_vs > 1 && !av_stristr(filename, "%v") && !av_stristr(subdir_name, "%v")) {
1809  av_log(NULL, AV_LOG_ERROR, "More than 1 variant streams are present, %%v is expected "
1810  "either in the filename or in the sub-directory name of file %s\n", fn);
1811  ret = AVERROR(EINVAL);
1812  goto fail;
1813  }
1814 
1815  if (av_stristr(filename, "%v") && av_stristr(subdir_name, "%v")) {
1816  av_log(NULL, AV_LOG_ERROR, "%%v is expected either in the filename or "
1817  "in the sub-directory name of file %s, but only in one of them\n", fn);
1818  ret = AVERROR(EINVAL);
1819  goto fail;
1820  }
1821 
1822 fail:
1823  av_freep(&fn_dup);
1824  return ret;
1825 }
1826 
1827 static int format_name(const char *buf, char **s, int index, const char *varname)
1828 {
1829  const char *proto, *dir;
1830  char *orig_buf_dup = NULL, *mod_buf_dup = NULL;
1831  int ret = 0;
1832 
1833  orig_buf_dup = av_strdup(buf);
1834  if (!orig_buf_dup)
1835  return AVERROR(ENOMEM);
1836 
1837  if (!av_stristr(buf, "%v")) {
1838  *s = orig_buf_dup;
1839  return 0;
1840  }
1841 
1842  if (!varname) {
1843  if (replace_int_data_in_filename(s, orig_buf_dup, 'v', index) < 1) {
1844  ret = AVERROR(EINVAL);
1845  goto fail;
1846  }
1847  } else {
1848  if (replace_str_data_in_filename(s, orig_buf_dup, 'v', varname) < 1) {
1849  ret = AVERROR(EINVAL);
1850  goto fail;
1851  }
1852  }
1853 
1854  proto = avio_find_protocol_name(orig_buf_dup);
1855  dir = av_dirname(orig_buf_dup);
1856 
1857  /* if %v is present in the file's directory, create sub-directory */
1858  if (av_stristr(dir, "%v") && proto && !strcmp(proto, "file")) {
1859  mod_buf_dup = av_strdup(*s);
1860  dir = av_dirname(mod_buf_dup);
1861  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1862  ret = AVERROR(errno);
1863  goto fail;
1864  }
1865  }
1866 
1867 fail:
1868  av_freep(&orig_buf_dup);
1869  av_freep(&mod_buf_dup);
1870  return ret;
1871 }
1872 
1874  enum AVMediaType codec_type,
1875  int64_t stream_id)
1876 {
1877  unsigned int stream_index, cnt;
1878  if (stream_id < 0 || stream_id > s->nb_streams - 1)
1879  return -1;
1880  cnt = 0;
1881  for (stream_index = 0; stream_index < s->nb_streams; stream_index++) {
1882  if (s->streams[stream_index]->codecpar->codec_type != codec_type)
1883  continue;
1884  if (cnt == stream_id)
1885  return stream_index;
1886  cnt++;
1887  }
1888  return -1;
1889 }
1890 
1892 {
1893  HLSContext *hls = s->priv_data;
1894  VariantStream *vs;
1895  int stream_index, i, j;
1896  enum AVMediaType codec_type;
1897  int nb_varstreams = 0, nb_streams;
1898  char *p, *q, *saveptr1, *saveptr2, *varstr, *keyval;
1899  const char *val;
1900 
1901  /**
1902  * Expected format for var_stream_map string is as below:
1903  * "a:0,v:0 a:1,v:1"
1904  * "a:0,agroup:a0,default:1,language:ENG a:1,agroup:a1,default:0 v:0,agroup:a0 v:1,agroup:a1"
1905  * This string specifies how to group the audio, video and subtitle streams
1906  * into different variant streams. The variant stream groups are separated
1907  * by space.
1908  *
1909  * a:, v:, s: are keys to specify audio, video and subtitle streams
1910  * respectively. Allowed values are 0 to 9 digits (limited just based on
1911  * practical usage)
1912  *
1913  * agroup: is key to specify audio group. A string can be given as value.
1914  * sgroup: is key to specify subtitle group. A string can be given as value.
1915  */
1916  p = av_strdup(hls->var_stream_map);
1917  if (!p)
1918  return AVERROR(ENOMEM);
1919 
1920  q = p;
1921  while (av_strtok(q, " \t", &saveptr1)) {
1922  q = NULL;
1923  nb_varstreams++;
1924  }
1925  av_freep(&p);
1926 
1927  hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * nb_varstreams);
1928  if (!hls->var_streams)
1929  return AVERROR(ENOMEM);
1930  hls->nb_varstreams = nb_varstreams;
1931 
1932  p = hls->var_stream_map;
1933  nb_varstreams = 0;
1934  while (varstr = av_strtok(p, " \t", &saveptr1)) {
1935  p = NULL;
1936 
1937  if (nb_varstreams < hls->nb_varstreams) {
1938  vs = &(hls->var_streams[nb_varstreams]);
1939  vs->var_stream_idx = nb_varstreams;
1940  vs->is_default = 0;
1941  nb_varstreams++;
1942  } else
1943  return AVERROR(EINVAL);
1944 
1945  q = varstr;
1946  while (1) {
1947  if (!av_strncasecmp(q, "a:", 2) || !av_strncasecmp(q, "v:", 2) ||
1948  !av_strncasecmp(q, "s:", 2))
1949  vs->nb_streams++;
1950  q = strchr(q, ',');
1951  if (!q)
1952  break;
1953  q++;
1954  }
1955  vs->streams = av_mallocz(sizeof(AVStream *) * vs->nb_streams);
1956  if (!vs->streams)
1957  return AVERROR(ENOMEM);
1958 
1959  nb_streams = 0;
1960  while (keyval = av_strtok(varstr, ",", &saveptr2)) {
1961  int64_t num;
1962  char *end;
1963  varstr = NULL;
1964  if (av_strstart(keyval, "language:", &val)) {
1965  vs->language = val;
1966  continue;
1967  } else if (av_strstart(keyval, "default:", &val)) {
1968  vs->is_default = (!av_strncasecmp(val, "YES", strlen("YES")) ||
1969  (!av_strncasecmp(val, "1", strlen("1"))));
1970  hls->has_default_key = 1;
1971  continue;
1972  } else if (av_strstart(keyval, "name:", &val)) {
1973  vs->varname = val;
1974  continue;
1975  } else if (av_strstart(keyval, "agroup:", &val)) {
1976  vs->agroup = val;
1977  continue;
1978  } else if (av_strstart(keyval, "sgroup:", &val)) {
1979  vs->sgroup = val;
1980  continue;
1981  } else if (av_strstart(keyval, "ccgroup:", &val)) {
1982  vs->ccgroup = val;
1983  continue;
1984  } else if (av_strstart(keyval, "v:", &val)) {
1986  hls->has_video_m3u8 = 1;
1987  } else if (av_strstart(keyval, "a:", &val)) {
1989  } else if (av_strstart(keyval, "s:", &val)) {
1991  } else {
1992  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
1993  return AVERROR(EINVAL);
1994  }
1995 
1996  num = strtoll(val, &end, 10);
1997  if (!av_isdigit(*val) || *end != '\0') {
1998  av_log(s, AV_LOG_ERROR, "Invalid stream number: '%s'\n", val);
1999  return AVERROR(EINVAL);
2000  }
2001  stream_index = get_nth_codec_stream_index(s, codec_type, num);
2002 
2003  if (stream_index >= 0 && nb_streams < vs->nb_streams) {
2004  for (i = 0; nb_streams > 0 && i < nb_streams; i++) {
2005  if (vs->streams[i] == s->streams[stream_index]) {
2006  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once inside "
2007  "variant definition #%d\n", nb_varstreams - 1);
2008  return AVERROR(EINVAL);
2009  }
2010  }
2011  for (j = 0; nb_varstreams > 1 && j < nb_varstreams - 1; j++) {
2012  for (i = 0; i < hls->var_streams[j].nb_streams; i++) {
2013  if (hls->var_streams[j].streams[i] == s->streams[stream_index]) {
2014  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once "
2015  "in two different variant definitions #%d and #%d\n",
2016  j, nb_varstreams - 1);
2017  return AVERROR(EINVAL);
2018  }
2019  }
2020  }
2021  vs->streams[nb_streams++] = s->streams[stream_index];
2022  } else {
2023  av_log(s, AV_LOG_ERROR, "Unable to map stream at %s\n", keyval);
2024  return AVERROR(EINVAL);
2025  }
2026  }
2027  }
2028  av_log(s, AV_LOG_DEBUG, "Number of variant streams %d\n",
2029  hls->nb_varstreams);
2030 
2031  return 0;
2032 }
2033 
2035 {
2036  HLSContext *hls = s->priv_data;
2037  int nb_ccstreams = 0;
2038  char *p, *q, *ccstr, *keyval;
2039  char *saveptr1 = NULL, *saveptr2 = NULL;
2040  const char *val;
2041  ClosedCaptionsStream *ccs;
2042 
2043  p = av_strdup(hls->cc_stream_map);
2044  if(!p)
2045  return AVERROR(ENOMEM);
2046 
2047  q = p;
2048  while (av_strtok(q, " \t", &saveptr1)) {
2049  q = NULL;
2050  nb_ccstreams++;
2051  }
2052  av_freep(&p);
2053 
2054  hls->cc_streams = av_mallocz(sizeof(*hls->cc_streams) * nb_ccstreams);
2055  if (!hls->cc_streams)
2056  return AVERROR(ENOMEM);
2057  hls->nb_ccstreams = nb_ccstreams;
2058 
2059  p = hls->cc_stream_map;
2060  nb_ccstreams = 0;
2061  while (ccstr = av_strtok(p, " \t", &saveptr1)) {
2062  p = NULL;
2063 
2064  if (nb_ccstreams < hls->nb_ccstreams)
2065  ccs = &(hls->cc_streams[nb_ccstreams++]);
2066  else
2067  return AVERROR(EINVAL);
2068 
2069  while (keyval = av_strtok(ccstr, ",", &saveptr2)) {
2070  ccstr = NULL;
2071 
2072  if (av_strstart(keyval, "ccgroup:", &val)) {
2073  ccs->ccgroup = val;
2074  } else if (av_strstart(keyval, "instreamid:", &val)) {
2075  ccs->instreamid = val;
2076  } else if (av_strstart(keyval, "language:", &val)) {
2077  ccs->language = val;
2078  } else {
2079  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2080  return AVERROR(EINVAL);
2081  }
2082  }
2083 
2084  if (!ccs->ccgroup || !ccs->instreamid) {
2085  av_log(s, AV_LOG_ERROR, "Insufficient parameters in cc stream map string\n");
2086  return AVERROR(EINVAL);
2087  }
2088 
2089  if (av_strstart(ccs->instreamid, "CC", &val)) {
2090  if (atoi(val) < 1 || atoi(val) > 4) {
2091  av_log(s, AV_LOG_ERROR, "Invalid instream ID CC index %d in %s, range 1-4\n",
2092  atoi(val), ccs->instreamid);
2093  return AVERROR(EINVAL);
2094  }
2095  } else if (av_strstart(ccs->instreamid, "SERVICE", &val)) {
2096  if (atoi(val) < 1 || atoi(val) > 63) {
2097  av_log(s, AV_LOG_ERROR, "Invalid instream ID SERVICE index %d in %s, range 1-63 \n",
2098  atoi(val), ccs->instreamid);
2099  return AVERROR(EINVAL);
2100  }
2101  } else {
2102  av_log(s, AV_LOG_ERROR, "Invalid instream ID %s, supported are CCn or SERVICEn\n",
2103  ccs->instreamid);
2104  return AVERROR(EINVAL);
2105  }
2106  }
2107 
2108  return 0;
2109 }
2110 
2112 {
2113  HLSContext *hls = s->priv_data;
2114  unsigned int i;
2115  int ret = 0;
2116 
2117  if (hls->cc_stream_map) {
2119  if (ret < 0)
2120  return ret;
2121  }
2122 
2123  if (hls->var_stream_map) {
2125  } else {
2126  //By default, a single variant stream with all the codec streams is created
2127  hls->var_streams = av_mallocz(sizeof(*hls->var_streams));
2128  if (!hls->var_streams)
2129  return AVERROR(ENOMEM);
2130  hls->nb_varstreams = 1;
2131 
2132  hls->var_streams[0].var_stream_idx = 0;
2133  hls->var_streams[0].nb_streams = s->nb_streams;
2134  hls->var_streams[0].streams = av_mallocz(sizeof(AVStream *) *
2135  hls->var_streams[0].nb_streams);
2136  if (!hls->var_streams[0].streams)
2137  return AVERROR(ENOMEM);
2138 
2139  //by default, the first available ccgroup is mapped to the variant stream
2140  if (hls->nb_ccstreams)
2141  hls->var_streams[0].ccgroup = hls->cc_streams[0].ccgroup;
2142 
2143  for (i = 0; i < s->nb_streams; i++)
2144  hls->var_streams[0].streams[i] = s->streams[i];
2145  }
2146  return 0;
2147 }
2148 
2150 {
2151  HLSContext *hls = s->priv_data;
2152  const char *dir;
2153  char *fn1= NULL, *fn2 = NULL;
2154  int ret = 0;
2155 
2156  fn1 = av_strdup(s->url);
2157  if (!fn1)
2158  return AVERROR(ENOMEM);
2159  dir = av_dirname(fn1);
2160 
2161  /**
2162  * if output file's directory has %v, variants are created in sub-directories
2163  * then master is created at the sub-directories level
2164  */
2165  if (dir && av_stristr(av_basename(dir), "%v")) {
2166  fn2 = av_strdup(dir);
2167  if (!fn2) {
2168  ret = AVERROR(ENOMEM);
2169  goto fail;
2170  }
2171  dir = av_dirname(fn2);
2172  }
2173 
2174  if (dir && strcmp(dir, "."))
2176  else
2178 
2179  if (!hls->master_m3u8_url) {
2180  ret = AVERROR(ENOMEM);
2181  goto fail;
2182  }
2183 
2184 fail:
2185  av_freep(&fn1);
2186  av_freep(&fn2);
2187 
2188  return ret;
2189 }
2190 
2192 {
2193  HLSContext *hls = s->priv_data;
2194  int ret, i, j;
2195  VariantStream *vs = NULL;
2196 
2197  for (i = 0; i < hls->nb_varstreams; i++) {
2198  vs = &hls->var_streams[i];
2199 
2201  if (ret < 0)
2202  return ret;
2203  //av_assert0(s->nb_streams == hls->avf->nb_streams);
2204  for (j = 0; j < vs->nb_streams; j++) {
2205  AVStream *inner_st;
2206  AVStream *outer_st = vs->streams[j];
2207 
2208  if (hls->max_seg_size > 0) {
2209  if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
2210  (outer_st->codecpar->bit_rate > hls->max_seg_size)) {
2211  av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, "
2212  "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.",
2213  outer_st->codecpar->bit_rate, hls->max_seg_size);
2214  }
2215  }
2216 
2217  if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
2218  inner_st = vs->avf->streams[j];
2219  else if (vs->vtt_avf)
2220  inner_st = vs->vtt_avf->streams[0];
2221  else {
2222  /* We have a subtitle stream, when the user does not want one */
2223  inner_st = NULL;
2224  continue;
2225  }
2226  avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
2227  write_codec_attr(outer_st, vs);
2228 
2229  }
2230  /* Update the Codec Attr string for the mapped audio groups */
2231  if (vs->has_video && vs->agroup) {
2232  for (j = 0; j < hls->nb_varstreams; j++) {
2233  VariantStream *vs_agroup = &(hls->var_streams[j]);
2234  if (!vs_agroup->has_video && !vs_agroup->has_subtitle &&
2235  vs_agroup->agroup &&
2236  !av_strcasecmp(vs_agroup->agroup, vs->agroup)) {
2237  write_codec_attr(vs_agroup->streams[0], vs);
2238  }
2239  }
2240  }
2241  }
2242 
2243  return ret;
2244 }
2245 
2247 {
2248  HLSContext *hls = s->priv_data;
2250  int ret = 0;
2251 
2252  set_http_options(s, &options, hls);
2255  if (ret < 0)
2256  return ret;
2258  hlsenc_io_close(s, &vs->out, hls->fmp4_init_filename);
2259 
2260  return ret;
2261 }
2262 
2264 {
2265  HLSContext *hls = s->priv_data;
2266  AVFormatContext *oc = NULL;
2267  AVStream *st = s->streams[pkt->stream_index];
2268  int64_t end_pts = 0;
2269  int is_ref_pkt = 1;
2270  int ret = 0, can_split = 1, i, j;
2271  int stream_index = 0;
2272  int range_length = 0;
2273  const char *proto = NULL;
2274  int use_temp_file = 0;
2275  VariantStream *vs = NULL;
2276  char *old_filename = NULL;
2277 
2278  for (i = 0; i < hls->nb_varstreams; i++) {
2279  vs = &hls->var_streams[i];
2280  for (j = 0; j < vs->nb_streams; j++) {
2281  if (vs->streams[j] == st) {
2283  oc = vs->vtt_avf;
2284  stream_index = 0;
2285  } else {
2286  oc = vs->avf;
2287  stream_index = j;
2288  }
2289  break;
2290  }
2291  }
2292 
2293  if (oc)
2294  break;
2295  }
2296 
2297  if (!oc) {
2298  av_log(s, AV_LOG_ERROR, "Unable to find mapping variant stream\n");
2299  return AVERROR(ENOMEM);
2300  }
2301 
2302  end_pts = hls->recording_time * vs->number;
2303 
2304  if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
2305  /* reset end_pts, hls->recording_time at end of the init hls list */
2306  int64_t init_list_dur = hls->init_time * vs->nb_entries * AV_TIME_BASE;
2307  int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries) * (hls->time * AV_TIME_BASE);
2308  hls->recording_time = hls->time * AV_TIME_BASE;
2309  end_pts = init_list_dur + after_init_list_dur ;
2310  }
2311 
2312  if (vs->start_pts == AV_NOPTS_VALUE) {
2313  vs->start_pts = pkt->pts;
2315  vs->start_pts_from_audio = 1;
2316  }
2318  vs->start_pts = pkt->pts;
2319  vs->start_pts_from_audio = 0;
2320  }
2321 
2322  if (vs->has_video) {
2323  can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
2324  ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME));
2325  is_ref_pkt = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->stream_index == vs->reference_stream_index);
2326  }
2327  if (pkt->pts == AV_NOPTS_VALUE)
2328  is_ref_pkt = can_split = 0;
2329 
2330  if (is_ref_pkt) {
2331  if (vs->end_pts == AV_NOPTS_VALUE)
2332  vs->end_pts = pkt->pts;
2333  if (vs->new_start) {
2334  vs->new_start = 0;
2335  vs->duration = (double)(pkt->pts - vs->end_pts)
2336  * st->time_base.num / st->time_base.den;
2337  vs->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2338  } else {
2339  if (pkt->duration) {
2340  vs->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2341  } else {
2342  av_log(s, AV_LOG_WARNING, "pkt->duration = 0, maybe the hls segment duration will not precise\n");
2343  vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2344  }
2345  }
2346 
2347  }
2348 
2349  if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base,
2350  end_pts, AV_TIME_BASE_Q) >= 0) {
2351  int64_t new_start_pos;
2352  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2353 
2354  av_write_frame(oc, NULL); /* Flush any buffered data */
2355  new_start_pos = avio_tell(oc->pb);
2356  vs->size = new_start_pos - vs->start_pos;
2357  avio_flush(oc->pb);
2358  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2359  if (!vs->init_range_length) {
2360  range_length = avio_close_dyn_buf(oc->pb, &vs->init_buffer);
2361  if (range_length <= 0)
2362  return AVERROR(EINVAL);
2363  avio_write(vs->out, vs->init_buffer, range_length);
2364  if (!hls->resend_init_file)
2365  av_freep(&vs->init_buffer);
2366  vs->init_range_length = range_length;
2367  avio_open_dyn_buf(&oc->pb);
2368  vs->packets_written = 0;
2369  vs->start_pos = range_length;
2370  if (!byterange_mode) {
2372  }
2373  }
2374  }
2375  if (!byterange_mode) {
2376  if (vs->vtt_avf) {
2377  hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url);
2378  }
2379  }
2380 
2381  if (hls->flags & HLS_SINGLE_FILE) {
2382  ret = flush_dynbuf(vs, &range_length);
2383  av_freep(&vs->temp_buffer);
2384  if (ret < 0) {
2385  return ret;
2386  }
2387  vs->size = range_length;
2388  } else {
2389  if (oc->url[0]) {
2390  proto = avio_find_protocol_name(oc->url);
2391  use_temp_file = proto && !strcmp(proto, "file")
2392  && (hls->flags & HLS_TEMP_FILE);
2393  }
2394 
2395  if ((hls->max_seg_size > 0 && (vs->size >= hls->max_seg_size)) || !byterange_mode) {
2397  char *filename = NULL;
2398  if (hls->key_info_file || hls->encrypt) {
2399  av_dict_set(&options, "encryption_key", vs->key_string, 0);
2400  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2401  filename = av_asprintf("crypto:%s", oc->url);
2402  } else {
2403  filename = av_asprintf("%s", oc->url);
2404  }
2405  if (!filename) {
2407  return AVERROR(ENOMEM);
2408  }
2409 
2410  // look to rename the asset name
2411  if (use_temp_file)
2412  av_dict_set(&options, "mpegts_flags", "resend_headers", 0);
2413 
2414  set_http_options(s, &options, hls);
2415 
2416  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2417  if (ret < 0) {
2419  "Failed to open file '%s'\n", filename);
2420  av_freep(&filename);
2422  return hls->ignore_io_errors ? 0 : ret;
2423  }
2424  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2425  write_styp(vs->out);
2426  }
2427  ret = flush_dynbuf(vs, &range_length);
2428  if (ret < 0) {
2429  av_freep(&filename);
2431  return ret;
2432  }
2433  ret = hlsenc_io_close(s, &vs->out, filename);
2434  if (ret < 0) {
2435  av_log(s, AV_LOG_WARNING, "upload segment failed,"
2436  " will retry with a new http session.\n");
2437  ff_format_io_close(s, &vs->out);
2438  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2439  reflush_dynbuf(vs, &range_length);
2440  ret = hlsenc_io_close(s, &vs->out, filename);
2441  }
2443  av_freep(&vs->temp_buffer);
2444  av_freep(&filename);
2445  }
2446 
2447  if (use_temp_file)
2448  hls_rename_temp_file(s, oc);
2449  }
2450 
2451  old_filename = av_strdup(oc->url);
2452  if (!old_filename) {
2453  return AVERROR(ENOMEM);
2454  }
2455 
2456  if (vs->start_pos || hls->segment_type != SEGMENT_TYPE_FMP4) {
2457  double cur_duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2458  ret = hls_append_segment(s, hls, vs, cur_duration, vs->start_pos, vs->size);
2459  vs->end_pts = pkt->pts;
2460  vs->duration = 0;
2461  if (ret < 0) {
2462  av_freep(&old_filename);
2463  return ret;
2464  }
2465  }
2466 
2467  // if we're building a VOD playlist, skip writing the manifest multiple times, and just wait until the end
2468  if (hls->pl_type != PLAYLIST_TYPE_VOD) {
2469  if ((ret = hls_window(s, 0, vs)) < 0) {
2470  av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2471  ff_format_io_close(s, &vs->out);
2472  if ((ret = hls_window(s, 0, vs)) < 0) {
2473  av_freep(&old_filename);
2474  return ret;
2475  }
2476  }
2477  }
2478 
2479  if (hls->resend_init_file && hls->segment_type == SEGMENT_TYPE_FMP4) {
2480  ret = hls_init_file_resend(s, vs);
2481  if (ret < 0) {
2482  av_freep(&old_filename);
2483  return ret;
2484  }
2485  }
2486 
2487  if (hls->flags & HLS_SINGLE_FILE) {
2488  vs->start_pos += vs->size;
2489  } else if (hls->max_seg_size > 0) {
2490  vs->start_pos = new_start_pos;
2491  if (vs->size >= hls->max_seg_size) {
2492  vs->sequence++;
2493  sls_flag_file_rename(hls, vs, old_filename);
2494  ret = hls_start(s, vs);
2495  vs->start_pos = 0;
2496  /* When split segment by byte, the duration is short than hls_time,
2497  * so it is not enough one segment duration as hls_time, */
2498  }
2499  } else {
2500  vs->start_pos = new_start_pos;
2501  sls_flag_file_rename(hls, vs, old_filename);
2502  ret = hls_start(s, vs);
2503  }
2504  vs->number++;
2505  av_freep(&old_filename);
2506 
2507  if (ret < 0) {
2508  return ret;
2509  }
2510 
2511  }
2512 
2513  vs->packets_written++;
2514  if (oc->pb) {
2515  ret = ff_write_chained(oc, stream_index, pkt, s, 0);
2516  vs->video_keyframe_size += pkt->size;
2518  vs->video_keyframe_size = avio_tell(oc->pb);
2519  } else {
2520  vs->video_keyframe_pos = avio_tell(vs->out);
2521  }
2522  if (hls->ignore_io_errors)
2523  ret = 0;
2524  }
2525 
2526  return ret;
2527 }
2528 
2530 {
2531  HLSContext *hls = s->priv_data;
2532  int i = 0;
2533  VariantStream *vs = NULL;
2534 
2535  for (i = 0; i < hls->nb_varstreams; i++) {
2536  vs = &hls->var_streams[i];
2537 
2538  av_freep(&vs->basename);
2541  av_freep(&vs->vtt_basename);
2542  av_freep(&vs->vtt_m3u8_name);
2543 
2546  if (hls->resend_init_file)
2547  av_freep(&vs->init_buffer);
2550  av_freep(&vs->m3u8_name);
2551  av_freep(&vs->streams);
2552  }
2553 
2554  ff_format_io_close(s, &hls->m3u8_out);
2556  av_freep(&hls->key_basename);
2557  av_freep(&hls->var_streams);
2558  av_freep(&hls->cc_streams);
2559  av_freep(&hls->master_m3u8_url);
2560 }
2561 
2563 {
2564  HLSContext *hls = s->priv_data;
2565  AVFormatContext *oc = NULL;
2566  AVFormatContext *vtt_oc = NULL;
2567  char *old_filename = NULL;
2568  const char *proto = NULL;
2569  int use_temp_file = 0;
2570  int i;
2571  int ret = 0;
2572  VariantStream *vs = NULL;
2574  int range_length, byterange_mode;
2575 
2576  for (i = 0; i < hls->nb_varstreams; i++) {
2577  char *filename = NULL;
2578  vs = &hls->var_streams[i];
2579  oc = vs->avf;
2580  vtt_oc = vs->vtt_avf;
2581  old_filename = av_strdup(oc->url);
2582  use_temp_file = 0;
2583 
2584  if (!old_filename) {
2585  return AVERROR(ENOMEM);
2586  }
2587  if (hls->key_info_file || hls->encrypt) {
2588  av_dict_set(&options, "encryption_key", vs->key_string, 0);
2589  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2590  filename = av_asprintf("crypto:%s", oc->url);
2591  } else {
2592  filename = av_asprintf("%s", oc->url);
2593  }
2594  if (!filename) {
2595  av_freep(&old_filename);
2596  return AVERROR(ENOMEM);
2597  }
2598 
2599  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2600  int range_length = 0;
2601  if (!vs->init_range_length) {
2602  uint8_t *buffer = NULL;
2603  av_write_frame(oc, NULL); /* Flush any buffered data */
2604 
2605  range_length = avio_close_dyn_buf(oc->pb, &buffer);
2606  avio_write(vs->out, buffer, range_length);
2607  av_freep(&buffer);
2608  vs->init_range_length = range_length;
2609  avio_open_dyn_buf(&oc->pb);
2610  vs->packets_written = 0;
2611  vs->start_pos = range_length;
2612  byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2613  if (!byterange_mode) {
2614  ff_format_io_close(s, &vs->out);
2616  }
2617  }
2618  }
2619  if (!(hls->flags & HLS_SINGLE_FILE)) {
2620  set_http_options(s, &options, hls);
2621  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2622  if (ret < 0) {
2623  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2624  goto failed;
2625  }
2626  if (hls->segment_type == SEGMENT_TYPE_FMP4)
2627  write_styp(vs->out);
2628  }
2629  ret = flush_dynbuf(vs, &range_length);
2630  if (ret < 0)
2631  goto failed;
2632 
2633  vs->size = range_length;
2634  hlsenc_io_close(s, &vs->out, filename);
2635  ret = hlsenc_io_close(s, &vs->out, filename);
2636  if (ret < 0) {
2637  av_log(s, AV_LOG_WARNING, "upload segment failed, will retry with a new http session.\n");
2638  ff_format_io_close(s, &vs->out);
2639  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2640  if (ret < 0) {
2641  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2642  goto failed;
2643  }
2644  reflush_dynbuf(vs, &range_length);
2645  ret = hlsenc_io_close(s, &vs->out, filename);
2646  if (ret < 0)
2647  av_log(s, AV_LOG_WARNING, "Failed to upload file '%s' at the end.\n", oc->url);
2648  }
2649 
2650 failed:
2651  av_freep(&vs->temp_buffer);
2653  av_freep(&filename);
2654  av_write_trailer(oc);
2655  if (oc->url[0]) {
2656  proto = avio_find_protocol_name(oc->url);
2657  use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & HLS_TEMP_FILE);
2658  }
2659 
2660  // rename that segment from .tmp to the real one
2661  if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) {
2662  hls_rename_temp_file(s, oc);
2663  av_freep(&old_filename);
2664  old_filename = av_strdup(oc->url);
2665 
2666  if (!old_filename) {
2667  return AVERROR(ENOMEM);
2668  }
2669  }
2670 
2671  /* after av_write_trailer, then duration + 1 duration per packet */
2672  hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size);
2673 
2674  sls_flag_file_rename(hls, vs, old_filename);
2675 
2676  if (vtt_oc) {
2677  if (vtt_oc->pb)
2678  av_write_trailer(vtt_oc);
2679  vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos;
2680  ff_format_io_close(s, &vtt_oc->pb);
2681  }
2682  ret = hls_window(s, 1, vs);
2683  if (ret < 0) {
2684  av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2685  ff_format_io_close(s, &vs->out);
2686  hls_window(s, 1, vs);
2687  }
2688  ffio_free_dyn_buf(&oc->pb);
2689 
2690  av_free(old_filename);
2691  }
2692 
2693  return 0;
2694 }
2695 
2696 
2698 {
2699  int ret = 0;
2700  int i = 0;
2701  int j = 0;
2702  HLSContext *hls = s->priv_data;
2703  const char *pattern;
2704  VariantStream *vs = NULL;
2705  const char *vtt_pattern = hls->flags & HLS_SINGLE_FILE ? ".vtt" : "%d.vtt";
2706  char *p = NULL;
2707  int http_base_proto = ff_is_http_proto(s->url);
2708  int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;
2709 
2710  if (hls->use_localtime) {
2712  } else {
2713  pattern = hls->segment_type == SEGMENT_TYPE_FMP4 ? "%d.m4s" : "%d.ts";
2714  if (hls->flags & HLS_SINGLE_FILE)
2715  pattern += 2;
2716  }
2717 
2718  hls->has_default_key = 0;
2719  hls->has_video_m3u8 = 0;
2721  if (ret < 0) {
2722  av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",
2723  ret);
2724  return ret;
2725  }
2726 
2727  if (!hls->method && http_base_proto) {
2728  av_log(hls, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n");
2729  }
2730 
2731  ret = validate_name(hls->nb_varstreams, s->url);
2732  if (ret < 0)
2733  return ret;
2734 
2735  if (hls->segment_filename) {
2737  if (ret < 0)
2738  return ret;
2739  }
2740 
2741  if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {
2743  if (ret < 0)
2744  return ret;
2745  }
2746 
2747  if (hls->subtitle_filename) {
2749  if (ret < 0)
2750  return ret;
2751  }
2752 
2753  if (hls->master_pl_name) {
2755  if (ret < 0) {
2756  av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",
2757  ret);
2758  return ret;
2759  }
2760  }
2761 
2765  time_t t = time(NULL);
2767  hls->start_sequence = av_gettime();
2769  hls->start_sequence = (int64_t)t;
2771  char b[15];
2772  struct tm *p, tmbuf;
2773  if (!(p = localtime_r(&t, &tmbuf)))
2774  return AVERROR(errno);
2775  if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
2776  return AVERROR(ENOMEM);
2777  hls->start_sequence = strtoll(b, NULL, 10);
2778  }
2779  av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
2780  }
2781 
2782  hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;
2783 
2784  if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) {
2785  // Independent segments cannot be guaranteed when splitting by time
2788  "'split_by_time' and 'independent_segments' cannot be "
2789  "enabled together. Disabling 'independent_segments' flag\n");
2790  }
2791 
2792  for (i = 0; i < hls->nb_varstreams; i++) {
2793  vs = &hls->var_streams[i];
2794 
2795  ret = format_name(s->url, &vs->m3u8_name, i, vs->varname);
2796  if (ret < 0)
2797  return ret;
2798 
2799  vs->sequence = hls->start_sequence;
2800  vs->start_pts = AV_NOPTS_VALUE;
2801  vs->end_pts = AV_NOPTS_VALUE;
2802  vs->current_segment_final_filename_fmt[0] = '\0';
2803 
2804  if (hls->flags & HLS_PROGRAM_DATE_TIME) {
2805  time_t now0;
2806  time(&now0);
2807  vs->initial_prog_date_time = now0;
2808  }
2809 
2810  for (j = 0; j < vs->nb_streams; j++) {
2812  /* Get one video stream to reference for split segments
2813  * so use the first video stream index. */
2814  if ((vs->has_video == 1) && (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) {
2815  vs->reference_stream_index = vs->streams[j]->index;
2816  }
2818  }
2819 
2820  if (vs->has_video > 1)
2821  av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n");
2822  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2823  vs->oformat = av_guess_format("mp4", NULL, NULL);
2824  } else {
2825  vs->oformat = av_guess_format("mpegts", NULL, NULL);
2826  }
2827  if (!vs->oformat)
2828  return AVERROR_MUXER_NOT_FOUND;
2829 
2830  if (hls->segment_filename) {
2831  ret = format_name(hls->segment_filename, &vs->basename, i, vs->varname);
2832  if (ret < 0)
2833  return ret;
2834  } else {
2835  p = strrchr(vs->m3u8_name, '.');
2836  if (p)
2837  *p = '\0';
2838 
2839  vs->basename = av_asprintf("%s%s", vs->m3u8_name, pattern);
2840  if (!vs->basename)
2841  return AVERROR(ENOMEM);
2842 
2843  if (p)
2844  *p = '.';
2845  }
2846 
2847  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2848  if (hls->nb_varstreams > 1)
2849  fmp4_init_filename_len += strlen(POSTFIX_PATTERN);
2850  if (hls->flags & HLS_SINGLE_FILE) {
2852  if (!vs->fmp4_init_filename)
2853  return AVERROR(ENOMEM);
2854  } else {
2855  vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);
2856  if (!vs->fmp4_init_filename)
2857  return AVERROR(ENOMEM);
2859  fmp4_init_filename_len);
2860  if (hls->nb_varstreams > 1) {
2861  if (av_stristr(vs->fmp4_init_filename, "%v")) {
2864  &vs->fmp4_init_filename, i, vs->varname);
2865  } else {
2866  ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i);
2867  }
2868  if (ret < 0)
2869  return ret;
2870  }
2871 
2872  p = strrchr(vs->m3u8_name, '/');
2873  if (p) {
2874  char tmp = *(++p);
2875  *p = '\0';
2876  vs->base_output_dirname = av_asprintf("%s%s", vs->m3u8_name,
2877  vs->fmp4_init_filename);
2878  *p = tmp;
2879  } else {
2881  }
2882  if (!vs->base_output_dirname)
2883  return AVERROR(ENOMEM);
2884  }
2885  }
2886 
2888  if (ret < 0)
2889  return ret;
2890 
2891  if (vs->has_subtitle) {
2892  vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
2893  if (!vs->vtt_oformat)
2894  return AVERROR_MUXER_NOT_FOUND;
2895 
2896  p = strrchr(vs->m3u8_name, '.');
2897  if (p)
2898  *p = '\0';
2899 
2900  vs->vtt_basename = av_asprintf("%s%s", vs->m3u8_name, vtt_pattern);
2901  if (!vs->vtt_basename)
2902  return AVERROR(ENOMEM);
2903 
2904  if (hls->subtitle_filename) {
2906  if (ret < 0)
2907  return ret;
2908  } else {
2909  vs->vtt_m3u8_name = av_asprintf("%s_vtt.m3u8", vs->m3u8_name);
2910  if (!vs->vtt_m3u8_name)
2911  return AVERROR(ENOMEM);
2912  }
2913  if (p)
2914  *p = '.';
2915  }
2916 
2917  if ((ret = hls_mux_init(s, vs)) < 0)
2918  return ret;
2919 
2920  if (hls->flags & HLS_APPEND_LIST) {
2921  parse_playlist(s, vs->m3u8_name, vs);
2922  vs->discontinuity = 1;
2923  if (hls->init_time > 0) {
2924  av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
2925  " hls_init_time value will have no effect\n");
2926  hls->init_time = 0;
2927  hls->recording_time = hls->time * AV_TIME_BASE;
2928  }
2929  }
2930 
2931  if ((ret = hls_start(s, vs)) < 0)
2932  return ret;
2933  vs->number++;
2934  }
2935 
2936  return ret;
2937 }
2938 
2939 #define OFFSET(x) offsetof(HLSContext, x)
2940 #define E AV_OPT_FLAG_ENCODING_PARAM
2941 static const AVOption options[] = {
2942  {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
2943  {"hls_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E},
2944  {"hls_init_time", "set segment length in seconds at init list", OFFSET(init_time), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0, FLT_MAX, E},
2945  {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E},
2946  {"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},
2947  {"hls_ts_options","set hls mpegts list of options for the container format used for hls", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
2948  {"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},
2949 #if FF_API_HLS_WRAP
2950  {"hls_wrap", "set number after which the index wraps (will be deprecated)", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
2951 #endif
2952  {"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},
2953  {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
2954  {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
2955  {"hls_segment_size", "maximum size per segment file, (in bytes)", OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
2956  {"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},
2957  {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
2958  {"hls_enc_key", "hex-coded 16 byte key to encrypt the segments", OFFSET(key), AV_OPT_TYPE_STRING, .flags = E},
2959  {"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},
2960  {"hls_enc_iv", "hex-coded 16 byte initialization vector", OFFSET(iv), AV_OPT_TYPE_STRING, .flags = E},
2961  {"hls_subtitle_path", "set path of hls subtitles", OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
2962  {"hls_segment_type", "set hls segment files type", OFFSET(segment_type), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, SEGMENT_TYPE_FMP4, E, "segment_type"},
2963  {"mpegts", "make segment file to mpegts files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, UINT_MAX, E, "segment_type"},
2964  {"fmp4", "make segment file to fragment mp4 files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_FMP4 }, 0, UINT_MAX, E, "segment_type"},
2965  {"hls_fmp4_init_filename", "set fragment mp4 file init filename", OFFSET(fmp4_init_filename), AV_OPT_TYPE_STRING, {.str = "init.mp4"}, 0, 0, E},
2966  {"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 },
2967  {"hls_flags", "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "flags"},
2968  {"single_file", "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX, E, "flags"},
2969  {"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, "flags"},
2970  {"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, "flags"},
2971  {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, "flags"},
2972  {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, "flags"},
2973  {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, "flags"},
2974  {"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, "flags"},
2975  {"append_list", "append the new segments into old hls segment list", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX, E, "flags"},
2976  {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX, E, "flags"},
2977  {"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, "flags"},
2978  {"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, "flags"},
2979  {"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, "flags"},
2980  {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX, E, "flags"},
2981  {"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, "flags"},
2982  {"iframes_only", "add EXT-X-I-FRAMES-ONLY, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_I_FRAMES_ONLY }, 0, UINT_MAX, E, "flags"},
2983 #if FF_API_HLS_USE_LOCALTIME
2984  {"use_localtime", "set filename expansion with strftime at segment creation(will be deprecated)", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
2985 #endif
2986  {"strftime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
2987 #if FF_API_HLS_USE_LOCALTIME
2988  {"use_localtime_mkdir", "create last directory component in strftime-generated filename(will be deprecated)", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
2989 #endif
2990  {"strftime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
2991  {"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, "pl_type" },
2992  {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, "pl_type" },
2993  {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, "pl_type" },
2994  {"method", "set the HTTP method(default: PUT)", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
2995  {"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, "start_sequence_source_type" },
2996  {"generic", "start_number value (default)", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
2997  {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
2998  {"epoch_us", "microseconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
2999  {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
3000  {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3001  {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3002  {"cc_stream_map", "Closed captions stream map string", OFFSET(cc_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3003  {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3004  {"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},
3005  {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3006  {"timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
3007  {"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 },
3008  {"headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
3009  { NULL },
3010 };
3011 
3012 static const AVClass hls_class = {
3013  .class_name = "hls muxer",
3014  .item_name = av_default_item_name,
3015  .option = options,
3016  .version = LIBAVUTIL_VERSION_INT,
3017 };
3018 
3019 
3021  .name = "hls",
3022  .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
3023  .extensions = "m3u8",
3024  .priv_data_size = sizeof(HLSContext),
3025  .audio_codec = AV_CODEC_ID_AAC,
3026  .video_codec = AV_CODEC_ID_H264,
3027  .subtitle_codec = AV_CODEC_ID_WEBVTT,
3029  .init = hls_init,
3033  .deinit = hls_deinit,
3034  .priv_class = &hls_class,
3035 };
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:803
VariantStream::vtt_avf
AVFormatContext * vtt_avf
Definition: hlsenc.c:128
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
hls_write_header
static int hls_write_header(AVFormatContext *s)
Definition: hlsenc.c:2191
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.
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
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:74
get_relative_url
static const char * get_relative_url(const char *master_url, const char *media_url)
Definition: hlsenc.c:1246
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:890
append_postfix
static int append_postfix(char *name, int name_buf_len, int i)
Definition: hlsenc.c:1774
AV_CODEC_ID_AC3
@ AV_CODEC_ID_AC3
Definition: codec_id.h:413
HLSContext::timeout
int64_t timeout
Definition: hlsenc.c:251
sls_flag_use_localtime_filename
static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c, VariantStream *vs)
Definition: hlsenc.c:990
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
HLS_TEMP_FILE
@ HLS_TEMP_FILE
Definition: hlsenc.c:104
AVOutputFormat::name
const char * name
Definition: avformat.h:491
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
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4526
VariantStream::has_subtitle
int has_subtitle
Definition: hlsenc.c:131
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
HLSContext::resend_init_file
int resend_init_file
resend init file into disk after refresh m3u8
Definition: hlsenc.c:206
HLSContext::hls_delete_threshold
int hls_delete_threshold
Definition: hlsenc.c:197
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:466
VariantStream::codec_attr
char codec_attr[128]
Definition: hlsenc.c:171
ffio_wfourcc
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
Definition: avio_internal.h:58
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
avio_close
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:1147
HLSContext::key_file
char key_file[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:227
out
FILE * out
Definition: movenc.c:54
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:189
hls_init_file_resend
static int hls_init_file_resend(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:2246
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:56
HLSSegment::filename
char filename[MAX_URL_SIZE]
Definition: hlsenc.c:75
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:55
av_dict_count
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition: dict.c:35
PLAYLIST_TYPE_VOD
@ PLAYLIST_TYPE_VOD
Definition: hlsplaylist.h:35
VariantStream::key_uri
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:166
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
VariantStream::init_range_length
int init_range_length
Definition: hlsenc.c:123
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
write_styp
static void write_styp(AVIOContext *pb)
Definition: hlsenc.c:455
VariantStream::var_stream_idx
unsigned var_stream_idx
Definition: hlsenc.c:116
HLSContext::cc_stream_map
char * cc_stream_map
Definition: hlsenc.c:245
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:92
PLAYLIST_TYPE_EVENT
@ PLAYLIST_TYPE_EVENT
Definition: hlsplaylist.h:34
HLS_APPEND_LIST
@ HLS_APPEND_LIST
Definition: hlsenc.c:99
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:26
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1403
HLS_SECOND_LEVEL_SEGMENT_INDEX
@ HLS_SECOND_LEVEL_SEGMENT_INDEX
Definition: hlsenc.c:101
HLS_DELETE_SEGMENTS
@ HLS_DELETE_SEGMENTS
Definition: hlsenc.c:94
AVFormatContext::strict_std_compliance
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1643
HLSContext::ignore_io_errors
int ignore_io_errors
Definition: hlsenc.c:252
KEYSIZE
#define KEYSIZE
Definition: hlsenc.c:69
HLS_MICROSECOND_UNIT
#define HLS_MICROSECOND_UNIT
Definition: hlsenc.c:71
ClosedCaptionsStream
Definition: hlsenc.c:183
AVOption
AVOption.
Definition: opt.h:246
HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH
@ HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH
Definition: hlsenc.c:60
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:91
HLS_INDEPENDENT_SEGMENTS
@ HLS_INDEPENDENT_SEGMENTS
Definition: hlsenc.c:106
HLS_OMIT_ENDLIST
@ HLS_OMIT_ENDLIST
Definition: hlsenc.c:97
HLSContext::iv
char * iv
Definition: hlsenc.c:222
VariantStream::iv_string
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:168
AV_OPT_TYPE_DURATION
@ AV_OPT_TYPE_DURATION
Definition: opt.h:237
AV_DICT_APPEND
#define AV_DICT_APPEND
If the entry already exists, append to it.
Definition: dict.h:77
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
ffio_open_whitelist
int ffio_open_whitelist(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist)
Definition: aviobuf.c:1120
VariantStream::start_pts
int64_t start_pts
Definition: hlsenc.c:135
float.h
HLSContext::nb_ccstreams
unsigned int nb_ccstreams
Definition: hlsenc.c:239
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:373
AVCodecParameters::codec_tag
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:64
PLAYLIST_TYPE_NONE
@ PLAYLIST_TYPE_NONE
Definition: hlsplaylist.h:33
mathematics.h
AVDictionary
Definition: dict.c:30
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:158
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:485
ff_hls_muxer
AVOutputFormat ff_hls_muxer
Definition: hlsenc.c:3020
hls_write_trailer
static int hls_write_trailer(struct AVFormatContext *s)
Definition: hlsenc.c:2562
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:1873
LINE_BUFFER_SIZE
#define LINE_BUFFER_SIZE
Definition: hlsenc.c:70
codec_type
enum AVMediaType codec_type
Definition: rtp.c:37
E
#define E
Definition: hlsenc.c:2940
os_support.h
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:388
update_variant_stream_info
static int update_variant_stream_info(AVFormatContext *s)
Definition: hlsenc.c:2111
av_basename
const char * av_basename(const char *path)
Thread safe basename.
Definition: avstring.c:258
AV_WB64
#define AV_WB64(p, v)
Definition: intreadwrite.h:433
hlsplaylist.h
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
ff_const59
#define ff_const59
The ff_const59 define is not part of the public API and will be removed without further warning.
Definition: avformat.h:535
HLSContext::allowcache
int allowcache
Definition: hlsenc.c:210
HLSContext::user_agent
char * user_agent
Definition: hlsenc.c:234
sls_flag_check_duration_size
static int sls_flag_check_duration_size(HLSContext *hls, VariantStream *vs)
Definition: hlsenc.c:963
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:302
VariantStream::key_file
char key_file[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:165
HLSSegment::duration
double duration
Definition: hlsenc.c:77
av_guess_format
ff_const59 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:51
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1613
do_encrypt
static int do_encrypt(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:643
HLSContext::use_localtime
int use_localtime
flag to expand filename with localtime
Definition: hlsenc.c:208
SEGMENT_TYPE_FMP4
@ SEGMENT_TYPE_FMP4
Definition: hlsenc.c:112
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:98
segment::duration
int64_t duration
Definition: hls.c:69
fail
#define fail()
Definition: checkasm.h:123
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:900
wrap
#define wrap(func)
Definition: neontest.h:65
hls_start
static int hls_start(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:1579
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
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)
Definition: hlsplaylist.c:39
VariantStream::vtt_oformat
ff_const59 AVOutputFormat * vtt_oformat
Definition: hlsenc.c:120
val
static double val(void *priv, double ch)
Definition: aeval.c:76
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:465
VariantStream::start_pts_from_audio
int start_pts_from_audio
Definition: hlsenc.c:133
AV_CODEC_ID_MP3
@ AV_CODEC_ID_MP3
preferred ID for decoding MPEG audio layer 1, 2 or 3
Definition: codec_id.h:411
fn
#define fn(a)
Definition: colorspacedsp_template.c:42
ff_rename
int ff_rename(const char *url_src, const char *url_dst, void *logctx)
Wrap avpriv_io_move and log if error happens.
Definition: avio.c:673
ff_data_to_hex
char * ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase)
Definition: utils.c:4899
AVRational::num
int num
Numerator.
Definition: rational.h:59
HLS_PERIODIC_REKEY
@ HLS_PERIODIC_REKEY
Definition: hlsenc.c:105
av_dirname
const char * av_dirname(char *path)
Thread safe dirname.
Definition: avstring.c:281
sls_flag_file_rename
static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename)
Definition: hlsenc.c:983
HLS_ROUND_DURATIONS
@ HLS_ROUND_DURATIONS
Definition: hlsenc.c:95
HLSContext::use_localtime_mkdir
int use_localtime_mkdir
flag to mkdir dirname in timebased filename
Definition: hlsenc.c:209
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:1401
avassert.h
lrint
#define lrint
Definition: tablegen.h:53
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVFormatContext::metadata
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1575
get_stream_bit_rate
static int64_t get_stream_bit_rate(AVStream *stream)
Definition: hlsenc.c:1266
HLSSegment::keyframe_pos
int64_t keyframe_pos
Definition: hlsenc.c:81
HLSSegment::discont
int discont
Definition: hlsenc.c:78
ff_hls_write_subtitle_rendition
void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup, const char *filename, const char *language, int name_id, int is_default)
Definition: hlsplaylist.c:54
HLSContext::key_basename
char * key_basename
Definition: hlsenc.c:223
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:1305
HLSContext::m3u8_out
AVIOContext * m3u8_out
Definition: hlsenc.c:249
duration
int64_t duration
Definition: movenc.c:63
avio_open_dyn_buf
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1356
HLSContext::encrypt_started
int encrypt_started
Definition: hlsenc.c:224
HLSSegment::next
struct HLSSegment * next
Definition: hlsenc.c:88
validate_name
static int validate_name(int nb_vs, const char *fn)
Definition: hlsenc.c:1793
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
HLSContext::method
char * method
Definition: hlsenc.c:233
set_http_options
static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c)
Definition: hlsenc.c:300
CODEC_ATTRIBUTE_WRITTEN
@ CODEC_ATTRIBUTE_WRITTEN
Definition: hlsenc.c:65
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
HLSContext::has_default_key
int has_default_key
Definition: hlsenc.c:254
AV_CODEC_ID_MP2
@ AV_CODEC_ID_MP2
Definition: codec_id.h:410
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:184
flush_dynbuf
static int flush_dynbuf(VariantStream *vs, int *range_length)
Definition: hlsenc.c:465
hls_deinit
static void hls_deinit(AVFormatContext *s)
Definition: hlsenc.c:2529
HLS_SECOND_LEVEL_SEGMENT_SIZE
@ HLS_SECOND_LEVEL_SEGMENT_SIZE
Definition: hlsenc.c:103
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Definition: opt.h:224
VariantStream::has_video
int has_video
Definition: hlsenc.c:130
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:675
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
VariantStream::language
const char * language
Definition: hlsenc.c:176
ctx
AVFormatContext * ctx
Definition: movenc.c:48
ff_is_http_proto
int ff_is_http_proto(char *filename)
Utility function to check if the file uses http or https protocol.
Definition: utils.c:5702
nb_streams
static int nb_streams
Definition: ffprobe.c:282
HLSContext::key_url
char * key_url
Definition: hlsenc.c:221
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:516
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:45
AVFormatContext::opaque
void * opaque
User data.
Definition: avformat.h:1841
VariantStream::key_string
char key_string[KEYSIZE *2+1]
Definition: hlsenc.c:167
key
const char * key
Definition: hwcontext_opencl.c:168
AVCPBProperties
This structure describes the bitrate properties of an encoded bitstream.
Definition: avcodec.h:448
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:76
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:505
VariantStream::attr_status
CodecAttributeStatus attr_status
Definition: hlsenc.c:172
VariantStream::video_lastpos
int64_t video_lastpos
Definition: hlsenc.c:137
VariantStream::reference_stream_index
int reference_stream_index
Definition: hlsenc.c:146
VariantStream::base_output_dirname
char * base_output_dirname
Definition: hlsenc.c:161
VariantStream::segments
HLSSegment * segments
Definition: hlsenc.c:148
write_codec_attr
static void write_codec_attr(AVStream *st, VariantStream *vs)
Definition: hlsenc.c:319
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:333
avio_flush
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:233
AV_CODEC_ID_WEBVTT
@ AV_CODEC_ID_WEBVTT
Definition: codec_id.h:527
AVFormatContext
Format I/O context.
Definition: avformat.h:1335
VariantStream::video_keyframe_pos
int64_t video_keyframe_pos
Definition: hlsenc.c:138
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1012
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:365
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
reflush_dynbuf
static void reflush_dynbuf(VariantStream *vs, int *range_length)
Definition: hlsenc.c:486
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:894
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
StartSequenceSourceType
StartSequenceSourceType
Definition: hlsenc.c:56
VariantStream::m3u8_name
char * m3u8_name
Definition: hlsenc.c:155
write_trailer
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:98
VariantStream::new_start
int new_start
Definition: hlsenc.c:132
HLS_PROGRAM_DATE_TIME
@ HLS_PROGRAM_DATE_TIME
Definition: hlsenc.c:100
HLSSegment::sub_filename
char sub_filename[MAX_URL_SIZE]
Definition: hlsenc.c:76
HLSSegment::iv_string
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:86
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:85
HLSContext::vtt_format_options_str
char * vtt_format_options_str
Definition: hlsenc.c:215
AV_OPT_TYPE_DICT
@ AV_OPT_TYPE_DICT
Definition: opt.h:230
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
ffurl_shutdown
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:659
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1377
parseutils.h
HLS_START_SEQUENCE_LAST
@ HLS_START_SEQUENCE_LAST
Definition: hlsenc.c:61
AVStream::metadata
AVDictionary * metadata
Definition: avformat.h:929
hls_delete_file
static int hls_delete_file(HLSContext *hls, AVFormatContext *avf, const char *path, const char *proto)
Definition: hlsenc.c:498
HLSSegment
Definition: hlsenc.c:74
AV_DICT_DONT_OVERWRITE
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition: dict.h:76
time.h
VariantStream::discontinuity_set
int discontinuity_set
Definition: hlsenc.c:144
AVOutputFormat::priv_class
const AVClass * priv_class
AVClass for the private context.
Definition: avformat.h:519
av_write_frame
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:1190
VariantStream::oformat
ff_const59 AVOutputFormat * oformat
Definition: hlsenc.c:119
HLSContext::vtt_format_options
AVDictionary * vtt_format_options
Definition: hlsenc.c:231
randomize
static int randomize(uint8_t *buf, int len)
Definition: hlsenc.c:629
PLAYLIST_TYPE_NB
@ PLAYLIST_TYPE_NB
Definition: hlsplaylist.h:36
SegmentType
SegmentType
Definition: hlsenc.c:110
index
int index
Definition: gxfenc.c:89
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
AVFormatContext::oformat
ff_const59 struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1354
HLS_START_SEQUENCE_AS_START_NUMBER
@ HLS_START_SEQUENCE_AS_START_NUMBER
Definition: hlsenc.c:57
HLSContext::key
char * key
Definition: hlsenc.c:220
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:185
VariantStream::old_segments
HLSSegment * old_segments
Definition: hlsenc.c:150
AV_CODEC_ID_EAC3
@ AV_CODEC_ID_EAC3
Definition: codec_id.h:450
VariantStream::is_default
int is_default
Definition: hlsenc.c:175
fn2
#define fn2(a, b, c)
Definition: colorspacedsp_template.c:41
HLS_I_FRAMES_ONLY
@ HLS_I_FRAMES_ONLY
Definition: hlsenc.c:107
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:412
av_strncasecmp
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:223
VariantStream::initial_prog_date_time
double initial_prog_date_time
Definition: hlsenc.c:157
HLSContext::segment_filename
char * segment_filename
Definition: hlsenc.c:203
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:1038
HLSFlags
HLSFlags
Definition: hlsenc.c:91
HLSContext::cc_streams
ClosedCaptionsStream * cc_streams
Definition: hlsenc.c:238
ff_hls_write_playlist_version
void ff_hls_write_playlist_version(AVIOContext *out, int version)
Definition: hlsplaylist.c:31
HLSContext::has_video_m3u8
int has_video_m3u8
Definition: hlsenc.c:255
VariantStream::init_buffer
uint8_t * init_buffer
Definition: hlsenc.c:125
AVIOContext
Bytestream IO Context.
Definition: avio.h:161
VariantStream::ccgroup
const char * ccgroup
Definition: hlsenc.c:179
HLSSegment::keyframe_size
int64_t keyframe_size
Definition: hlsenc.c:82
hls_rename_temp_file
static int hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
Definition: hlsenc.c:1231
AVMediaType
AVMediaType
Definition: avutil.h:199
AVPacket::size
int size
Definition: packet.h:356
HLSContext::master_pl_name
char * master_pl_name
Definition: hlsenc.c:246
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:188
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.
av_stream_get_side_data
uint8_t * av_stream_get_side_data(const AVStream *stream, enum AVPacketSideDataType type, int *size)
Get side information from stream.
Definition: utils.c:5508
HLS_SPLIT_BY_TIME
@ HLS_SPLIT_BY_TIME
Definition: hlsenc.c:98
create_master_playlist
static int create_master_playlist(AVFormatContext *s, VariantStream *const input_vs)
Definition: hlsenc.c:1282
localtime_r
#define localtime_r
Definition: time_internal.h:46
FFMAX
#define FFMAX(a, b)
Definition: common.h:94
HLSContext::start_sequence_source_type
uint32_t start_sequence_source_type
Definition: hlsenc.c:192
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4948
AVFormatContext::url
char * url
input or output URL.
Definition: avformat.h:1431
size
int size
Definition: twinvq_data.h:11134
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
HLSSegment::pos
int64_t pos
Definition: hlsenc.c:79
AVFMT_ALLOW_FLUSH
#define AVFMT_ALLOW_FLUSH
Format allows flushing.
Definition: avformat.h:471
HLSContext::pl_type
uint32_t pl_type
Definition: hlsenc.c:202
CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN
@ CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN
Definition: hlsenc.c:66
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:458
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:122
AVStream::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:927
parse_variant_stream_mapstring
static int parse_variant_stream_mapstring(AVFormatContext *s)
Definition: hlsenc.c:1891
hls_init
static int hls_init(AVFormatContext *s)
Definition: hlsenc.c:2697
VariantStream::agroup
const char * agroup
Definition: hlsenc.c:177
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:213
avio_wb32
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:375
av_isdigit
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition: avstring.h:206
VariantStream::sequence
int64_t sequence
Definition: hlsenc.c:118
AVCPBProperties::max_bitrate
int max_bitrate
Maximum bitrate of the stream, in bits per second.
Definition: avcodec.h:454
line
Definition: graph2dot.c:48
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:361
HLSContext::start_sequence
int64_t start_sequence
Definition: hlsenc.c:191
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:203
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:34
VariantStream::temp_buffer
uint8_t * temp_buffer
Definition: hlsenc.c:124
avformat_alloc_output_context2
int avformat_alloc_output_context2(AVFormatContext **ctx, ff_const59 AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
Definition: mux.c:135
HLSContext::format_options
AVDictionary * format_options
Definition: hlsenc.c:217
OFFSET
#define OFFSET(x)
Definition: hlsenc.c:2939
HLS_DISCONT_START
@ HLS_DISCONT_START
Definition: hlsenc.c:96
VariantStream::video_keyframe_size
int64_t video_keyframe_size
Definition: hlsenc.c:139
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:226
ff_http_get_shutdown_status
int ff_http_get_shutdown_status(URLContext *h)
Get the HTTP shutdown response status, be used after http_shutdown.
Definition: http.c:317
VariantStream::basename
char * basename
Definition: hlsenc.c:152
write_packet
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:702
HLS_START_SEQUENCE_AS_FORMATTED_DATETIME
@ HLS_START_SEQUENCE_AS_FORMATTED_DATETIME
Definition: hlsenc.c:59
parse_playlist
static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
Definition: hlsenc.c:1129
hls_write_packet
static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: hlsenc.c:2263
in
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
Definition: audio_convert.c:326
VariantStream::last_segment
HLSSegment * last_segment
Definition: hlsenc.c:149
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:1251
VariantStream::m3u8_created
int m3u8_created
Definition: hlsenc.c:174
URLContext
Definition: url.h:38
HLSContext::iv_string
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:230
log.h
AVFMT_GLOBALHEADER
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:461
AVOutputFormat
Definition: avformat.h:490
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:348
avio_internal.h
round
static av_always_inline av_const double round(double x)
Definition: libm.h:444
AVERROR_MUXER_NOT_FOUND
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:60
HLSContext::key_string
char key_string[KEYSIZE *2+1]
Definition: hlsenc.c:229
AV_TIME_BASE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
VariantStream::sgroup
const char * sgroup
Definition: hlsenc.c:178
HLSContext::max_nb_segments
int max_nb_segments
Definition: hlsenc.c:196
VariantStream::start_pos
int64_t start_pos
Definition: hlsenc.c:141
VariantStream::nb_streams
unsigned int nb_streams
Definition: hlsenc.c:173
HLSContext::sub_m3u8_out
AVIOContext * sub_m3u8_out
Definition: hlsenc.c:250
hls_encryption_start
static int hls_encryption_start(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:717
HLSContext
Definition: hls.c:192
options
static const AVOption options[]
Definition: hlsenc.c:2941
uint8_t
uint8_t
Definition: audio_convert.c:194
hlsenc_io_close
static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
Definition: hlsenc.c:279
AVFormatContext::max_delay
int max_delay
Definition: avformat.h:1460
VariantStream::number
unsigned number
Definition: hlsenc.c:117
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:237
ff_get_line
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
Read a whole line of text from AVIOContext.
Definition: aviobuf.c:786
HLSSegment::var_stream_idx
unsigned var_stream_idx
Definition: hlsenc.c:83
AV_PKT_DATA_CPB_PROPERTIES
@ AV_PKT_DATA_CPB_PROPERTIES
This side data corresponds to the AVCPBProperties struct.
Definition: packet.h:145
len
int len
Definition: vorbis_enc_data.h:452
start_sequence
static const uint8_t start_sequence[]
Definition: rtpdec_h264.c:65
VariantStream::duration
double duration
Definition: hlsenc.c:140
VariantStream::streams
AVStream ** streams
Definition: hlsenc.c:170
HLSContext::fmp4_init_filename
char * fmp4_init_filename
Definition: hlsenc.c:204
HLSContext::encrypt
int encrypt
Definition: hlsenc.c:219
HLSContext::http_persistent
int http_persistent
Definition: hls.c:212
HLS_SINGLE_FILE
@ HLS_SINGLE_FILE
Definition: hlsenc.c:93
ffio_free_dyn_buf
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1431
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:865
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:132
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:241
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:72
VariantStream::fmp4_init_filename
char * fmp4_init_filename
Definition: hlsenc.c:160
HLSContext::subtitle_filename
char * subtitle_filename
Definition: hlsenc.c:216
HLSContext::init_time
float init_time
Definition: hlsenc.c:195
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:93
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:406
hls_delete_old_segments
static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, VariantStream *vs)
Definition: hlsenc.c:518
pos
unsigned int pos
Definition: spdifenc.c:412
avformat.h
VariantStream::end_pts
int64_t end_pts
Definition: hlsenc.c:136
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
VariantStream::encrypt_started
int encrypt_started
Definition: hlsenc.c:163
ff_format_set_url
void ff_format_set_url(AVFormatContext *s, char *url)
Set AVFormatContext url field to the provided pointer.
Definition: utils.c:5855
VariantStream::discontinuity
int discontinuity
Definition: hlsenc.c:145
VariantStream::nb_entries
int nb_entries
Definition: hlsenc.c:143
SEGMENT_TYPE_MPEGTS
@ SEGMENT_TYPE_MPEGTS
Definition: hlsenc.c:111
HLSContext::time
float time
Definition: hlsenc.c:194
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:158
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2109
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:866
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
random_seed.h
format_name
static int format_name(const char *buf, char **s, int index, const char *varname)
Definition: hlsenc.c:1827
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:1758
SEPARATOR
#define SEPARATOR
Definition: hlsenc.c:495
pkt
static AVPacket pkt
Definition: demuxing_decoding.c:54
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:122
ff_hls_write_stream_info
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, const char *filename, const char *agroup, const char *codecs, const char *ccgroup, const char *sgroup)
Definition: hlsplaylist.c:69
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:223
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
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4455
hlsenc_io_open
static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, AVDictionary **options)
Definition: hlsenc.c:258
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:625
update_master_pl_info
static int update_master_pl_info(AVFormatContext *s)
Definition: hlsenc.c:2149
AVFormatContext::io_close
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1923
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:1917
sls_flag_check_duration_size_index
static int sls_flag_check_duration_size_index(HLSContext *hls)
Definition: hlsenc.c:940
ClosedCaptionsStream::language
const char * language
Definition: hlsenc.c:186
VariantStream::vtt_m3u8_name
char * vtt_m3u8_name
Definition: hlsenc.c:154
HLSContext::baseurl
char * baseurl
Definition: hlsenc.c:214
AVPacket::stream_index
int stream_index
Definition: packet.h:357
CodecAttributeStatus
CodecAttributeStatus
Definition: hlsenc.c:64
segment
Definition: hls.c:68
HLSContext::key_info_file
char * key_info_file
Definition: hlsenc.c:226
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:147
ff_format_io_close
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5695
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:674
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
VariantStream::out
AVIOContext * out
Definition: hlsenc.c:121
HLSContext::nb_varstreams
unsigned int nb_varstreams
Definition: hlsenc.c:237
HLSContext::master_m3u8_created
int master_m3u8_created
Definition: hlsenc.c:241
VariantStream::size
int64_t size
Definition: hlsenc.c:142
HLSContext::version
int version
Definition: hlsenc.c:243
ff_mkdir_p
int ff_mkdir_p(const char *path)
Automatically create sub-directories.
Definition: utils.c:4865
HLSContext::var_streams
VariantStream * var_streams
Definition: hlsenc.c:236
VariantStream::dpp
double dpp
Definition: hlsenc.c:134
VariantStream::avf
AVFormatContext * avf
Definition: hlsenc.c:127
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
POSTFIX_PATTERN
#define POSTFIX_PATTERN
Definition: hlsenc.c:72
AVPacket
This structure stores compressed data.
Definition: packet.h:332
hls_free_segments
static void hls_free_segments(HLSSegment *p)
Definition: hlsenc.c:1220
FF_API_HLS_WRAP
#define FF_API_HLS_WRAP
Definition: version.h:71
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:240
HLSContext::flags
uint32_t flags
Definition: hlsenc.c:201
hls_mux_init
static int hls_mux_init(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:776
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
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:70
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:217
VariantStream::varname
const char * varname
Definition: hlsenc.c:180
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:475
AV_OPT_TYPE_FLAGS
@ AV_OPT_TYPE_FLAGS
Definition: opt.h:222
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
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:83
AVCodecParameters::bit_rate
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:89
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
hls_window
static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
Definition: hlsenc.c:1448
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:227
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:346
HLSContext::key_uri
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:228
AVStream::pts_wrap_bits
int pts_wrap_bits
number of bits in pts (used for wrapping control)
Definition: avformat.h:1057
http.h
HLS_SECOND_LEVEL_SEGMENT_DURATION
@ HLS_SECOND_LEVEL_SEGMENT_DURATION
Definition: hlsenc.c:102
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:232
snprintf
#define snprintf
Definition: snprintf.h:34
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1363
parse_cc_stream_mapstring
static int parse_cc_stream_mapstring(AVFormatContext *s)
Definition: hlsenc.c:2034
ffio_geturlcontext
URLContext * ffio_geturlcontext(AVIOContext *s)
Return the URLContext associated with the AVIOContext.
Definition: aviobuf.c:971
HLSContext::segment_type
int segment_type
Definition: hlsenc.c:205
HLSContext::master_m3u8_url
char * master_m3u8_url
Definition: hlsenc.c:242
HLSContext::recording_time
int64_t recording_time
Definition: hlsenc.c:211
HLSContext::max_seg_size
int64_t max_seg_size
Definition: hlsenc.c:212
HLSContext::master_publish_rate
unsigned int master_publish_rate
Definition: hlsenc.c:247
ClosedCaptionsStream::instreamid
const char * instreamid
Definition: hlsenc.c:185
HLSSegment::size
int64_t size
Definition: hlsenc.c:80
HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH
@ HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH
Definition: hlsenc.c:58
VariantStream::vtt_basename
char * vtt_basename
Definition: hlsenc.c:153
ClosedCaptionsStream::ccgroup
const char * ccgroup
Definition: hlsenc.c:184
HLSContext::headers
char * headers
Definition: hlsenc.c:253
hls_class
static const AVClass hls_class
Definition: hlsenc.c:3012
VariantStream
Definition: hlsenc.c:115
avio_feof
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:356
HLSContext::var_stream_map
char * var_stream_map
Definition: hlsenc.c:244