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