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