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