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