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