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