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