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