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