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