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