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