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 #if FF_API_AVFORMAT_IO_CLOSE
870  oc->io_close = s->io_close;
872 #endif
873  oc->io_close2 = s->io_close2;
874  oc->strict_std_compliance = s->strict_std_compliance;
875  av_dict_copy(&oc->metadata, s->metadata, 0);
876 
877  if (vs->vtt_oformat) {
879  if (ret < 0)
880  return ret;
881  vtt_oc = vs->vtt_avf;
882  av_dict_copy(&vtt_oc->metadata, s->metadata, 0);
883  }
884 
885  for (i = 0; i < vs->nb_streams; i++) {
886  AVStream *st;
887  AVFormatContext *loc;
889  loc = vtt_oc;
890  else
891  loc = oc;
892 
893  if (!(st = avformat_new_stream(loc, NULL)))
894  return AVERROR(ENOMEM);
896  if (!oc->oformat->codec_tag ||
900  } else {
901  st->codecpar->codec_tag = 0;
902  }
903 
905  st->time_base = vs->streams[i]->time_base;
906  av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0);
907  st->id = vs->streams[i]->id;
908  }
909 
910  vs->start_pos = 0;
911  vs->new_start = 1;
912 
913  if (hls->segment_type == SEGMENT_TYPE_FMP4 && hls->max_seg_size > 0) {
914  if (hls->http_persistent > 0) {
915  //TODO: Support fragment fmp4 for http persistent in HLS muxer.
916  av_log(s, AV_LOG_WARNING, "http persistent mode is currently unsupported for fragment mp4 in the HLS muxer.\n");
917  }
918  if (hls->max_seg_size > 0) {
919  av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n");
920  return AVERROR_PATCHWELCOME;
921  }
922  }
923 
924  if ((ret = avio_open_dyn_buf(&oc->pb)) < 0)
925  return ret;
926 
927  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
928  set_http_options(s, &options, hls);
929  if (byterange_mode) {
930  ret = hlsenc_io_open(s, &vs->out, vs->basename, &options);
931  } else {
933  }
935  }
936  if (ret < 0) {
937  av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename);
938  return ret;
939  }
940 
942  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
943  av_dict_set(&options, "fflags", "-autobsf", 0);
944  av_dict_set(&options, "movflags", "+frag_custom+dash+delay_moov", AV_DICT_APPEND);
945  } else {
946  /* We only require one PAT/PMT per segment. */
947  char period[21];
948  snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1);
951  }
953  remaining_options = av_dict_count(options);
955  if (ret < 0)
956  return ret;
957  if (remaining_options) {
958  av_log(s, AV_LOG_ERROR, "Some of the provided format options are not recognized\n");
959  return AVERROR(EINVAL);
960  }
961  avio_flush(oc->pb);
962  return 0;
963 }
964 
965 static HLSSegment *find_segment_by_filename(HLSSegment *segment, const char *filename)
966 {
967  while (segment) {
968  if (!av_strcasecmp(segment->filename,filename))
969  return segment;
970  segment = segment->next;
971  }
972  return (HLSSegment *) NULL;
973 }
974 
976  VariantStream *vs, HLSSegment *en,
977  double duration, int64_t pos, int64_t size)
978 {
981  char * new_url = av_strdup(vs->current_segment_final_filename_fmt);
982  if (!new_url) {
983  return AVERROR(ENOMEM);
984  }
985  ff_format_set_url(vs->avf, new_url);
987  char *filename = NULL;
988  if (replace_int_data_in_filename(&filename, vs->avf->url, 's', pos + size) < 1) {
989  av_log(hls, AV_LOG_ERROR,
990  "Invalid second level segment filename template '%s', "
991  "you can try to remove second_level_segment_size flag\n",
992  vs->avf->url);
993  av_freep(&filename);
994  return AVERROR(EINVAL);
995  }
996  ff_format_set_url(vs->avf, filename);
997  }
999  char *filename = NULL;
1000  if (replace_int_data_in_filename(&filename, vs->avf->url,
1001  't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) {
1002  av_log(hls, AV_LOG_ERROR,
1003  "Invalid second level segment filename template '%s', "
1004  "you can try to remove second_level_segment_time flag\n",
1005  vs->avf->url);
1006  av_freep(&filename);
1007  return AVERROR(EINVAL);
1008  }
1009  ff_format_set_url(vs->avf, filename);
1010  }
1011  }
1012  return 0;
1013 }
1014 
1016 {
1017  int ret = 0;
1018 
1020  av_log(hls, AV_LOG_ERROR,
1021  "second_level_segment_duration hls_flag requires strftime to be true\n");
1022  ret = AVERROR(EINVAL);
1023  }
1024  if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
1025  av_log(hls, AV_LOG_ERROR,
1026  "second_level_segment_size hls_flag requires strfime to be true\n");
1027  ret = AVERROR(EINVAL);
1028  }
1030  av_log(hls, AV_LOG_ERROR,
1031  "second_level_segment_index hls_flag requires strftime to be true\n");
1032  ret = AVERROR(EINVAL);
1033  }
1034 
1035  return ret;
1036 }
1037 
1039 {
1040  const char *proto = avio_find_protocol_name(vs->basename);
1041  int segment_renaming_ok = proto && !strcmp(proto, "file");
1042  int ret = 0;
1043 
1044  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) && !segment_renaming_ok) {
1045  av_log(hls, AV_LOG_ERROR,
1046  "second_level_segment_duration hls_flag works only with file protocol segment names\n");
1047  ret = AVERROR(EINVAL);
1048  }
1049  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) && !segment_renaming_ok) {
1050  av_log(hls, AV_LOG_ERROR,
1051  "second_level_segment_size hls_flag works only with file protocol segment names\n");
1052  ret = AVERROR(EINVAL);
1053  }
1054 
1055  return ret;
1056 }
1057 
1058 static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename) {
1060  strlen(vs->current_segment_final_filename_fmt)) {
1061  ff_rename(old_filename, vs->avf->url, hls);
1062  }
1063 }
1064 
1066 {
1067  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) {
1068  char *filename = NULL;
1069  if (replace_int_data_in_filename(&filename,
1070  oc->url, 'd', vs->sequence) < 1) {
1071  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1072  "you can try to remove second_level_segment_index flag\n",
1073  oc->url);
1074  av_freep(&filename);
1075  return AVERROR(EINVAL);
1076  }
1077  ff_format_set_url(oc, filename);
1078  }
1082  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
1083  char *filename = NULL;
1084  if (replace_int_data_in_filename(&filename, oc->url, 's', 0) < 1) {
1085  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1086  "you can try to remove second_level_segment_size flag\n",
1087  oc->url);
1088  av_freep(&filename);
1089  return AVERROR(EINVAL);
1090  }
1091  ff_format_set_url(oc, filename);
1092  }
1093  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) {
1094  char *filename = NULL;
1095  if (replace_int_data_in_filename(&filename, oc->url, 't', 0) < 1) {
1096  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1097  "you can try to remove second_level_segment_time flag\n",
1098  oc->url);
1099  av_freep(&filename);
1100  return AVERROR(EINVAL);
1101  }
1102  ff_format_set_url(oc, filename);
1103  }
1104  }
1105  return 0;
1106 }
1107 
1108 /* Create a new segment and append it to the segment list */
1110  VariantStream *vs, double duration, int64_t pos,
1111  int64_t size)
1112 {
1113  HLSSegment *en = av_malloc(sizeof(*en));
1114  const char *filename;
1115  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1116  int ret;
1117 
1118  if (!en)
1119  return AVERROR(ENOMEM);
1120 
1121  en->var_stream_idx = vs->var_stream_idx;
1122  ret = sls_flags_filename_process(s, hls, vs, en, duration, pos, size);
1123  if (ret < 0) {
1124  av_freep(&en);
1125  return ret;
1126  }
1127 
1128  filename = av_basename(vs->avf->url);
1129 
1130  if (hls->use_localtime_mkdir) {
1131  filename = vs->avf->url;
1132  }
1133  if ((find_segment_by_filename(vs->segments, filename) || find_segment_by_filename(vs->old_segments, filename))
1134  && !byterange_mode) {
1135  av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename);
1136  }
1137  av_strlcpy(en->filename, filename, sizeof(en->filename));
1138 
1139  if (vs->has_subtitle)
1140  av_strlcpy(en->sub_filename, av_basename(vs->vtt_avf->url), sizeof(en->sub_filename));
1141  else
1142  en->sub_filename[0] = '\0';
1143 
1144  en->duration = duration;
1145  en->pos = pos;
1146  en->size = size;
1147  en->keyframe_pos = vs->video_keyframe_pos;
1149  en->next = NULL;
1150  en->discont = 0;
1151  en->discont_program_date_time = 0;
1152 
1153  if (vs->discontinuity) {
1154  en->discont = 1;
1155  vs->discontinuity = 0;
1156  }
1157 
1158  if (hls->key_info_file || hls->encrypt) {
1159  av_strlcpy(en->key_uri, vs->key_uri, sizeof(en->key_uri));
1160  av_strlcpy(en->iv_string, vs->iv_string, sizeof(en->iv_string));
1161  }
1162 
1163  if (!vs->segments)
1164  vs->segments = en;
1165  else
1166  vs->last_segment->next = en;
1167 
1168  vs->last_segment = en;
1169 
1170  // EVENT or VOD playlists imply sliding window cannot be used
1171  if (hls->pl_type != PLAYLIST_TYPE_NONE)
1172  hls->max_nb_segments = 0;
1173 
1174  if (hls->max_nb_segments && vs->nb_entries >= hls->max_nb_segments) {
1175  en = vs->segments;
1177  vs->initial_prog_date_time += en->duration;
1178  vs->segments = en->next;
1179  if (en && hls->flags & HLS_DELETE_SEGMENTS &&
1180  !(hls->flags & HLS_SINGLE_FILE)) {
1181  en->next = vs->old_segments;
1182  vs->old_segments = en;
1183  if ((ret = hls_delete_old_segments(s, hls, vs)) < 0)
1184  return ret;
1185  } else
1186  av_freep(&en);
1187  } else
1188  vs->nb_entries++;
1189 
1190  if (hls->max_seg_size > 0) {
1191  return 0;
1192  }
1193  vs->sequence++;
1194 
1195  return 0;
1196 }
1197 
1198 static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
1199 {
1200  HLSContext *hls = s->priv_data;
1201  AVIOContext *in;
1202  int ret = 0, is_segment = 0;
1203  int64_t new_start_pos;
1204  char line[MAX_URL_SIZE];
1205  const char *ptr;
1206  const char *end;
1207  double discont_program_date_time = 0;
1208 
1209  if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
1210  &s->interrupt_callback, NULL,
1211  s->protocol_whitelist, s->protocol_blacklist)) < 0)
1212  return ret;
1213 
1214  ff_get_chomp_line(in, line, sizeof(line));
1215  if (strcmp(line, "#EXTM3U")) {
1217  goto fail;
1218  }
1219 
1220  vs->discontinuity = 0;
1221  while (!avio_feof(in)) {
1222  ff_get_chomp_line(in, line, sizeof(line));
1223  if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
1224  int64_t tmp_sequence = strtoll(ptr, NULL, 10);
1225  if (tmp_sequence < vs->sequence)
1226  av_log(hls, AV_LOG_VERBOSE,
1227  "Found playlist sequence number was smaller """
1228  "than specified start sequence number: %"PRId64" < %"PRId64", "
1229  "omitting\n", tmp_sequence, hls->start_sequence);
1230  else {
1231  av_log(hls, AV_LOG_DEBUG, "Found playlist sequence number: %"PRId64"\n", tmp_sequence);
1232  vs->sequence = tmp_sequence;
1233  }
1234  } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
1235  is_segment = 1;
1236  vs->discontinuity = 1;
1237  } else if (av_strstart(line, "#EXTINF:", &ptr)) {
1238  is_segment = 1;
1239  vs->duration = atof(ptr);
1240  } else if (av_stristart(line, "#EXT-X-KEY:", &ptr)) {
1241  ptr = av_stristr(line, "URI=\"");
1242  if (ptr) {
1243  ptr += strlen("URI=\"");
1244  end = av_stristr(ptr, ",");
1245  if (end) {
1246  av_strlcpy(vs->key_uri, ptr, end - ptr);
1247  } else {
1248  av_strlcpy(vs->key_uri, ptr, sizeof(vs->key_uri));
1249  }
1250  }
1251 
1252  ptr = av_stristr(line, "IV=0x");
1253  if (ptr) {
1254  ptr += strlen("IV=0x");
1255  end = av_stristr(ptr, ",");
1256  if (end) {
1257  av_strlcpy(vs->iv_string, ptr, end - ptr);
1258  } else {
1259  av_strlcpy(vs->iv_string, ptr, sizeof(vs->iv_string));
1260  }
1261  }
1262  } else if (av_strstart(line, "#EXT-X-PROGRAM-DATE-TIME:", &ptr)) {
1263  struct tm program_date_time;
1264  int y,M,d,h,m,s;
1265  double ms;
1266  if (sscanf(ptr, "%d-%d-%dT%d:%d:%d.%lf", &y, &M, &d, &h, &m, &s, &ms) != 7) {
1268  goto fail;
1269  }
1270 
1271  program_date_time.tm_year = y - 1900;
1272  program_date_time.tm_mon = M - 1;
1273  program_date_time.tm_mday = d;
1274  program_date_time.tm_hour = h;
1275  program_date_time.tm_min = m;
1276  program_date_time.tm_sec = s;
1277  program_date_time.tm_isdst = -1;
1278 
1279  discont_program_date_time = mktime(&program_date_time);
1280  discont_program_date_time += (double)(ms / 1000);
1281  } else if (av_strstart(line, "#", NULL)) {
1282  continue;
1283  } else if (line[0]) {
1284  if (is_segment) {
1285  char *new_file = av_strdup(line);
1286  if (!new_file) {
1287  ret = AVERROR(ENOMEM);
1288  goto fail;
1289  }
1290  ff_format_set_url(vs->avf, new_file);
1291  is_segment = 0;
1292  new_start_pos = avio_tell(vs->avf->pb);
1293  vs->size = new_start_pos - vs->start_pos;
1294  ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size);
1295  if (discont_program_date_time) {
1296  vs->last_segment->discont_program_date_time = discont_program_date_time;
1297  discont_program_date_time += vs->duration;
1298  }
1299  if (ret < 0)
1300  goto fail;
1301  vs->start_pos = new_start_pos;
1302  }
1303  }
1304  }
1305 
1306 fail:
1307  avio_close(in);
1308  return ret;
1309 }
1310 
1312 {
1313  HLSSegment *en;
1314 
1315  while (p) {
1316  en = p;
1317  p = p->next;
1318  av_freep(&en);
1319  }
1320 }
1321 
1323 {
1324  size_t len = strlen(oc->url);
1325  char *final_filename = av_strdup(oc->url);
1326  int ret;
1327 
1328  if (!final_filename)
1329  return AVERROR(ENOMEM);
1330  final_filename[len-4] = '\0';
1331  ret = ff_rename(oc->url, final_filename, s);
1332  oc->url[len-4] = '\0';
1333  av_freep(&final_filename);
1334  return ret;
1335 }
1336 
1337 static const char* get_relative_url(const char *master_url, const char *media_url)
1338 {
1339  const char *p = strrchr(master_url, '/');
1340  size_t base_len = 0;
1341 
1342  if (!p) p = strrchr(master_url, '\\');
1343 
1344  if (p) {
1345  base_len = p - master_url;
1346  if (av_strncasecmp(master_url, media_url, base_len)) {
1347  av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n");
1348  return NULL;
1349  }
1350  } else {
1351  return media_url;
1352  }
1353 
1354  return media_url + base_len + 1;
1355 }
1356 
1357 static int64_t get_stream_bit_rate(AVStream *stream)
1358 {
1362  );
1363 
1364  if (stream->codecpar->bit_rate)
1365  return stream->codecpar->bit_rate;
1366  else if (sd) {
1367  AVCPBProperties *props = (AVCPBProperties*)sd->data;
1368  return props->max_bitrate;
1369  }
1370 
1371  return 0;
1372 }
1373 
1375  VariantStream * const input_vs)
1376 {
1377  HLSContext *hls = s->priv_data;
1378  VariantStream *vs, *temp_vs;
1379  AVStream *vid_st, *aud_st;
1381  unsigned int i, j;
1382  int ret, bandwidth;
1383  const char *m3u8_rel_name = NULL;
1384  const char *vtt_m3u8_rel_name = NULL;
1385  const char *ccgroup;
1386  const char *sgroup = NULL;
1387  ClosedCaptionsStream *ccs;
1388  const char *proto = avio_find_protocol_name(hls->master_m3u8_url);
1389  int is_file_proto = proto && !strcmp(proto, "file");
1390  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || hls->master_publish_rate);
1391  char temp_filename[MAX_URL_SIZE];
1392 
1393  input_vs->m3u8_created = 1;
1394  if (!hls->master_m3u8_created) {
1395  /* For the first time, wait until all the media playlists are created */
1396  for (i = 0; i < hls->nb_varstreams; i++)
1397  if (!hls->var_streams[i].m3u8_created)
1398  return 0;
1399  } else {
1400  /* Keep publishing the master playlist at the configured rate */
1401  if (&hls->var_streams[0] != input_vs || !hls->master_publish_rate ||
1402  input_vs->number % hls->master_publish_rate)
1403  return 0;
1404  }
1405 
1406  set_http_options(s, &options, hls);
1407  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", hls->master_m3u8_url);
1408  ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options);
1410  if (ret < 0) {
1411  av_log(s, AV_LOG_ERROR, "Failed to open master play list file '%s'\n",
1412  temp_filename);
1413  goto fail;
1414  }
1415 
1417 
1418  for (i = 0; i < hls->nb_ccstreams; i++) {
1419  ccs = &(hls->cc_streams[i]);
1420  avio_printf(hls->m3u8_out, "#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS");
1421  avio_printf(hls->m3u8_out, ",GROUP-ID=\"%s\"", ccs->ccgroup);
1422  avio_printf(hls->m3u8_out, ",NAME=\"%s\"", ccs->instreamid);
1423  if (ccs->language)
1424  avio_printf(hls->m3u8_out, ",LANGUAGE=\"%s\"", ccs->language);
1425  avio_printf(hls->m3u8_out, ",INSTREAM-ID=\"%s\"\n", ccs->instreamid);
1426  }
1427 
1428  /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/
1429  for (i = 0; i < hls->nb_varstreams; i++) {
1430  vs = &(hls->var_streams[i]);
1431 
1432  if (vs->has_video || vs->has_subtitle || !vs->agroup)
1433  continue;
1434 
1435  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1436  if (!m3u8_rel_name) {
1437  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1438  goto fail;
1439  }
1440 
1441  ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1);
1442  }
1443 
1444  /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/
1445  for (i = 0; i < hls->nb_varstreams; i++) {
1446  vs = &(hls->var_streams[i]);
1447 
1448  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1449  if (!m3u8_rel_name) {
1450  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1451  goto fail;
1452  }
1453 
1454  vid_st = NULL;
1455  aud_st = NULL;
1456  for (j = 0; j < vs->nb_streams; j++) {
1458  vid_st = vs->streams[j];
1459  else if (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
1460  aud_st = vs->streams[j];
1461  }
1462 
1463  if (!vid_st && !aud_st) {
1464  av_log(s, AV_LOG_WARNING, "Media stream not found\n");
1465  continue;
1466  }
1467 
1468  /**
1469  * Traverse through the list of audio only rendition streams and find
1470  * the rendition which has highest bitrate in the same audio group
1471  */
1472  if (vs->agroup) {
1473  for (j = 0; j < hls->nb_varstreams; j++) {
1474  temp_vs = &(hls->var_streams[j]);
1475  if (!temp_vs->has_video && !temp_vs->has_subtitle &&
1476  temp_vs->agroup &&
1477  !av_strcasecmp(temp_vs->agroup, vs->agroup)) {
1478  if (!aud_st)
1479  aud_st = temp_vs->streams[0];
1480  if (temp_vs->streams[0]->codecpar->bit_rate >
1481  aud_st->codecpar->bit_rate)
1482  aud_st = temp_vs->streams[0];
1483  }
1484  }
1485  }
1486 
1487  bandwidth = 0;
1488  if (vid_st)
1489  bandwidth += get_stream_bit_rate(vid_st);
1490  if (aud_st)
1491  bandwidth += get_stream_bit_rate(aud_st);
1492  bandwidth += bandwidth / 10;
1493 
1494  ccgroup = NULL;
1495  if (vid_st && vs->ccgroup) {
1496  /* check if this group name is available in the cc map string */
1497  for (j = 0; j < hls->nb_ccstreams; j++) {
1498  ccs = &(hls->cc_streams[j]);
1499  if (!av_strcasecmp(ccs->ccgroup, vs->ccgroup)) {
1500  ccgroup = vs->ccgroup;
1501  break;
1502  }
1503  }
1504  if (j == hls->nb_ccstreams)
1505  av_log(s, AV_LOG_WARNING, "mapping ccgroup %s not found\n",
1506  vs->ccgroup);
1507  }
1508 
1509  if (vid_st && vs->sgroup) {
1510  sgroup = vs->sgroup;
1511  vtt_m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->vtt_m3u8_name);
1512  if (!vtt_m3u8_rel_name) {
1513  av_log(s, AV_LOG_WARNING, "Unable to find relative subtitle URL\n");
1514  break;
1515  }
1516 
1517  ff_hls_write_subtitle_rendition(hls->m3u8_out, sgroup, vtt_m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1);
1518  }
1519 
1520  if (!hls->has_default_key || !hls->has_video_m3u8) {
1521  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name,
1522  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1523  } else {
1524  if (vid_st) {
1525  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name,
1526  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1527  }
1528  }
1529  }
1530 fail:
1531  if (ret >=0)
1532  hls->master_m3u8_created = 1;
1533  hlsenc_io_close(s, &hls->m3u8_out, temp_filename);
1534  if (use_temp_file)
1535  ff_rename(temp_filename, hls->master_m3u8_url, s);
1536 
1537  return ret;
1538 }
1539 
1540 static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
1541 {
1542  HLSContext *hls = s->priv_data;
1543  HLSSegment *en;
1544  int target_duration = 0;
1545  int ret = 0;
1546  char temp_filename[MAX_URL_SIZE];
1547  char temp_vtt_filename[MAX_URL_SIZE];
1548  int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries);
1549  const char *proto = avio_find_protocol_name(vs->m3u8_name);
1550  int is_file_proto = proto && !strcmp(proto, "file");
1551  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || !(hls->pl_type == PLAYLIST_TYPE_VOD));
1552  static unsigned warned_non_file;
1553  char *key_uri = NULL;
1554  char *iv_string = NULL;
1556  double prog_date_time = vs->initial_prog_date_time;
1557  double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? &prog_date_time : NULL;
1558  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1559 
1560  hls->version = 2;
1561  if (!(hls->flags & HLS_ROUND_DURATIONS)) {
1562  hls->version = 3;
1563  }
1564 
1565  if (byterange_mode) {
1566  hls->version = 4;
1567  sequence = 0;
1568  }
1569 
1570  if (hls->flags & HLS_I_FRAMES_ONLY) {
1571  hls->version = 4;
1572  }
1573 
1574  if (hls->flags & HLS_INDEPENDENT_SEGMENTS) {
1575  hls->version = 6;
1576  }
1577 
1578  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1579  hls->version = 7;
1580  }
1581 
1582  if (!is_file_proto && (hls->flags & HLS_TEMP_FILE) && !warned_non_file++)
1583  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
1584 
1585  set_http_options(s, &options, hls);
1586  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", vs->m3u8_name);
1587  if ((ret = hlsenc_io_open(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename, &options)) < 0) {
1588  if (hls->ignore_io_errors)
1589  ret = 0;
1590  goto fail;
1591  }
1592 
1593  for (en = vs->segments; en; en = en->next) {
1594  if (target_duration <= en->duration)
1595  target_duration = lrint(en->duration);
1596  }
1597 
1598  vs->discontinuity_set = 0;
1599  ff_hls_write_playlist_header(byterange_mode ? hls->m3u8_out : vs->out, hls->version, hls->allowcache,
1600  target_duration, sequence, hls->pl_type, hls->flags & HLS_I_FRAMES_ONLY);
1601 
1602  if ((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0) {
1603  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-DISCONTINUITY\n");
1604  vs->discontinuity_set = 1;
1605  }
1606  if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
1607  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
1608  }
1609  for (en = vs->segments; en; en = en->next) {
1610  if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) ||
1611  av_strcasecmp(en->iv_string, iv_string))) {
1612  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri);
1613  if (*en->iv_string)
1614  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, ",IV=0x%s", en->iv_string);
1615  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "\n");
1616  key_uri = en->key_uri;
1617  iv_string = en->iv_string;
1618  }
1619 
1620  if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) {
1621  ff_hls_write_init_file(byterange_mode ? hls->m3u8_out : vs->out, (hls->flags & HLS_SINGLE_FILE) ? en->filename : vs->fmp4_init_filename,
1622  hls->flags & HLS_SINGLE_FILE, vs->init_range_length, 0);
1623  }
1624 
1625  ret = ff_hls_write_file_entry(byterange_mode ? hls->m3u8_out : vs->out, en->discont, byterange_mode,
1626  en->duration, hls->flags & HLS_ROUND_DURATIONS,
1627  en->size, en->pos, hls->baseurl,
1628  en->filename,
1629  en->discont_program_date_time ? &en->discont_program_date_time : prog_date_time_p,
1631  if (en->discont_program_date_time)
1633  if (ret < 0) {
1634  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1635  }
1636  }
1637 
1638  if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
1639  ff_hls_write_end_list(byterange_mode ? hls->m3u8_out : vs->out);
1640 
1641  if (vs->vtt_m3u8_name) {
1642  snprintf(temp_vtt_filename, sizeof(temp_vtt_filename), use_temp_file ? "%s.tmp" : "%s", vs->vtt_m3u8_name);
1643  if ((ret = hlsenc_io_open(s, &hls->sub_m3u8_out, temp_vtt_filename, &options)) < 0) {
1644  if (hls->ignore_io_errors)
1645  ret = 0;
1646  goto fail;
1647  }
1649  target_duration, sequence, PLAYLIST_TYPE_NONE, 0);
1650  for (en = vs->segments; en; en = en->next) {
1651  ret = ff_hls_write_file_entry(hls->sub_m3u8_out, 0, byterange_mode,
1652  en->duration, 0, en->size, en->pos,
1653  hls->baseurl, en->sub_filename, NULL, 0, 0, 0);
1654  if (ret < 0) {
1655  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1656  }
1657  }
1658 
1659  if (last)
1661 
1662  }
1663 
1664 fail:
1666  ret = hlsenc_io_close(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename);
1667  if (ret < 0) {
1668  return ret;
1669  }
1671  if (use_temp_file) {
1672  ff_rename(temp_filename, vs->m3u8_name, s);
1673  if (vs->vtt_m3u8_name)
1674  ff_rename(temp_vtt_filename, vs->vtt_m3u8_name, s);
1675  }
1676  if (ret >= 0 && hls->master_pl_name)
1677  if (create_master_playlist(s, vs) < 0)
1678  av_log(s, AV_LOG_WARNING, "Master playlist creation failed\n");
1679 
1680  return ret;
1681 }
1682 
1684 {
1685  HLSContext *c = s->priv_data;
1686  AVFormatContext *oc = vs->avf;
1687  AVFormatContext *vtt_oc = vs->vtt_avf;
1689  const char *proto = NULL;
1690  int use_temp_file = 0;
1691  char iv_string[KEYSIZE*2 + 1];
1692  int err = 0;
1693 
1694  if (c->flags & HLS_SINGLE_FILE) {
1695  char *new_name = av_strdup(vs->basename);
1696  if (!new_name)
1697  return AVERROR(ENOMEM);
1698  ff_format_set_url(oc, new_name);
1699  if (vs->vtt_basename) {
1700  new_name = av_strdup(vs->vtt_basename);
1701  if (!new_name)
1702  return AVERROR(ENOMEM);
1703  ff_format_set_url(vtt_oc, new_name);
1704  }
1705  } else if (c->max_seg_size > 0) {
1706  char *filename = NULL;
1707  if (replace_int_data_in_filename(&filename,
1708  vs->basename, 'd', vs->sequence) < 1) {
1709  av_freep(&filename);
1710  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -strftime 1 with it\n", vs->basename);
1711  return AVERROR(EINVAL);
1712  }
1713  ff_format_set_url(oc, filename);
1714  } else {
1715  if (c->use_localtime) {
1716  int r;
1717  char *expanded = NULL;
1718 
1719  r = strftime_expand(vs->basename, &expanded);
1720  if (r < 0) {
1721  av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
1722  return r;
1723  }
1724  ff_format_set_url(oc, expanded);
1725 
1726  err = sls_flag_use_localtime_filename(oc, c, vs);
1727  if (err < 0) {
1728  return AVERROR(ENOMEM);
1729  }
1730 
1731  if (c->use_localtime_mkdir) {
1732  const char *dir;
1733  char *fn_copy = av_strdup(oc->url);
1734  if (!fn_copy)
1735  return AVERROR(ENOMEM);
1736  dir = av_dirname(fn_copy);
1737  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1738  av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
1739  av_freep(&fn_copy);
1740  return AVERROR(errno);
1741  }
1742  av_freep(&fn_copy);
1743  }
1744  } else {
1745  char *filename = NULL;
1746  if (replace_int_data_in_filename(&filename,
1747  vs->basename, 'd', vs->sequence) < 1) {
1748  av_freep(&filename);
1749  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -strftime 1 with it\n", vs->basename);
1750  return AVERROR(EINVAL);
1751  }
1752  ff_format_set_url(oc, filename);
1753  }
1754  if (vs->vtt_basename) {
1755  char *filename = NULL;
1756  if (replace_int_data_in_filename(&filename,
1757  vs->vtt_basename, 'd', vs->sequence) < 1) {
1758  av_freep(&filename);
1759  av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename);
1760  return AVERROR(EINVAL);
1761  }
1762  ff_format_set_url(vtt_oc, filename);
1763  }
1764  }
1765 
1766  proto = avio_find_protocol_name(oc->url);
1767  use_temp_file = proto && !strcmp(proto, "file") && (c->flags & HLS_TEMP_FILE);
1768 
1769  if (use_temp_file) {
1770  char *new_name = av_asprintf("%s.tmp", oc->url);
1771  if (!new_name)
1772  return AVERROR(ENOMEM);
1773  ff_format_set_url(oc, new_name);
1774  }
1775 
1776  if (c->key_info_file || c->encrypt) {
1777  if (c->segment_type == SEGMENT_TYPE_FMP4) {
1778  av_log(s, AV_LOG_ERROR, "Encrypted fmp4 not yet supported\n");
1779  return AVERROR_PATCHWELCOME;
1780  }
1781 
1782  if (c->key_info_file && c->encrypt) {
1783  av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file and -hls_enc,"
1784  " ignoring -hls_enc\n");
1785  }
1786 
1787  if (!vs->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) {
1788  if (c->key_info_file) {
1789  if ((err = hls_encryption_start(s, vs)) < 0)
1790  goto fail;
1791  } else {
1792  if (!c->encrypt_started) {
1793  if ((err = do_encrypt(s, vs)) < 0)
1794  goto fail;
1795  c->encrypt_started = 1;
1796  }
1797  av_strlcpy(vs->key_uri, c->key_uri, sizeof(vs->key_uri));
1798  av_strlcpy(vs->key_string, c->key_string, sizeof(vs->key_string));
1799  av_strlcpy(vs->iv_string, c->iv_string, sizeof(vs->iv_string));
1800  }
1801  vs->encrypt_started = 1;
1802  }
1803  err = av_strlcpy(iv_string, vs->iv_string, sizeof(iv_string));
1804  if (!err) {
1805  snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, vs->sequence);
1806  memset(vs->iv_string, 0, sizeof(vs->iv_string));
1807  memcpy(vs->iv_string, iv_string, sizeof(iv_string));
1808  }
1809  }
1810  if (c->segment_type != SEGMENT_TYPE_FMP4) {
1811  if (oc->oformat->priv_class && oc->priv_data) {
1812  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
1813  }
1814  if (c->flags & HLS_SINGLE_FILE) {
1815  if (c->key_info_file || c->encrypt) {
1816  av_dict_set(&options, "encryption_key", vs->key_string, 0);
1817  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
1818 
1819  /* Write temp file with cryption content */
1820  av_freep(&vs->basename_tmp);
1821  vs->basename_tmp = av_asprintf("crypto:%s.tmp", oc->url);
1822 
1823  /* append temp file content into single file */
1824  av_freep(&vs->basename);
1825  vs->basename = av_asprintf("%s", oc->url);
1826  } else {
1827  vs->basename_tmp = vs->basename;
1828  }
1830  if (!vs->out_single_file)
1831  if ((err = hlsenc_io_open(s, &vs->out_single_file, vs->basename, &options)) < 0) {
1832  if (c->ignore_io_errors)
1833  err = 0;
1834  goto fail;
1835  }
1836 
1837  if ((err = hlsenc_io_open(s, &vs->out, vs->basename_tmp, &options)) < 0) {
1838  if (c->ignore_io_errors)
1839  err = 0;
1840  goto fail;
1841  }
1842 
1843  }
1844  }
1845  if (vs->vtt_basename) {
1847  if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < 0) {
1848  if (c->ignore_io_errors)
1849  err = 0;
1850  goto fail;
1851  }
1852  }
1854 
1855  if (vs->vtt_basename) {
1856  err = avformat_write_header(vtt_oc,NULL);
1857  if (err < 0)
1858  return err;
1859  }
1860 
1861  return 0;
1862 fail:
1864 
1865  return err;
1866 }
1867 
1869 {
1870  char b[21];
1871  time_t t = time(NULL);
1872  struct tm *p, tmbuf;
1873  HLSContext *hls = s->priv_data;
1874 
1875  p = localtime_r(&t, &tmbuf);
1876  // no %s support when strftime returned error or left format string unchanged
1877  // also no %s support on MSVC, which invokes the invalid parameter handler on unsupported format strings, instead of returning an error
1878  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1879  return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.m4s" : "-%s.m4s";
1880  }
1881  return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.ts" : "-%s.ts";
1882 }
1883 
1884 static int append_postfix(char *name, int name_buf_len, int i)
1885 {
1886  char *p;
1887  char extension[10] = {'\0'};
1888 
1889  p = strrchr(name, '.');
1890  if (p) {
1891  av_strlcpy(extension, p, sizeof(extension));
1892  *p = '\0';
1893  }
1894 
1895  snprintf(name + strlen(name), name_buf_len - strlen(name), POSTFIX_PATTERN, i);
1896 
1897  if (strlen(extension))
1898  av_strlcat(name, extension, name_buf_len);
1899 
1900  return 0;
1901 }
1902 
1903 static int validate_name(int nb_vs, const char *fn)
1904 {
1905  const char *filename, *subdir_name;
1906  char *fn_dup = NULL;
1907  int ret = 0;
1908 
1909  if (!fn)
1910  return AVERROR(EINVAL);
1911 
1912  fn_dup = av_strdup(fn);
1913  if (!fn_dup)
1914  return AVERROR(ENOMEM);
1915  filename = av_basename(fn);
1916  subdir_name = av_dirname(fn_dup);
1917 
1918  if (nb_vs > 1 && !av_stristr(filename, "%v") && !av_stristr(subdir_name, "%v")) {
1919  av_log(NULL, AV_LOG_ERROR, "More than 1 variant streams are present, %%v is expected "
1920  "either in the filename or in the sub-directory name of file %s\n", fn);
1921  ret = AVERROR(EINVAL);
1922  goto fail;
1923  }
1924 
1925  if (av_stristr(filename, "%v") && av_stristr(subdir_name, "%v")) {
1926  av_log(NULL, AV_LOG_ERROR, "%%v is expected either in the filename or "
1927  "in the sub-directory name of file %s, but only in one of them\n", fn);
1928  ret = AVERROR(EINVAL);
1929  goto fail;
1930  }
1931 
1932 fail:
1933  av_freep(&fn_dup);
1934  return ret;
1935 }
1936 
1937 static int format_name(const char *buf, char **s, int index, const char *varname)
1938 {
1939  const char *proto, *dir;
1940  char *orig_buf_dup = NULL, *mod_buf_dup = NULL;
1941  int ret = 0;
1942 
1943  orig_buf_dup = av_strdup(buf);
1944  if (!orig_buf_dup)
1945  return AVERROR(ENOMEM);
1946 
1947  if (!av_stristr(buf, "%v")) {
1948  *s = orig_buf_dup;
1949  return 0;
1950  }
1951 
1952  if (!varname) {
1953  if (replace_int_data_in_filename(s, orig_buf_dup, 'v', index) < 1) {
1954  ret = AVERROR(EINVAL);
1955  goto fail;
1956  }
1957  } else {
1958  if (replace_str_data_in_filename(s, orig_buf_dup, 'v', varname) < 1) {
1959  ret = AVERROR(EINVAL);
1960  goto fail;
1961  }
1962  }
1963 
1964  proto = avio_find_protocol_name(orig_buf_dup);
1965  dir = av_dirname(orig_buf_dup);
1966 
1967  /* if %v is present in the file's directory, create sub-directory */
1968  if (av_stristr(dir, "%v") && proto && !strcmp(proto, "file")) {
1969  mod_buf_dup = av_strdup(*s);
1970  dir = av_dirname(mod_buf_dup);
1971  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1972  ret = AVERROR(errno);
1973  goto fail;
1974  }
1975  }
1976 
1977 fail:
1978  av_freep(&orig_buf_dup);
1979  av_freep(&mod_buf_dup);
1980  return ret;
1981 }
1982 
1984  enum AVMediaType codec_type,
1985  int64_t stream_id)
1986 {
1987  unsigned int stream_index, cnt;
1988  if (stream_id < 0 || stream_id > s->nb_streams - 1)
1989  return -1;
1990  cnt = 0;
1991  for (stream_index = 0; stream_index < s->nb_streams; stream_index++) {
1992  if (s->streams[stream_index]->codecpar->codec_type != codec_type)
1993  continue;
1994  if (cnt == stream_id)
1995  return stream_index;
1996  cnt++;
1997  }
1998  return -1;
1999 }
2000 
2002 {
2003  HLSContext *hls = s->priv_data;
2004  VariantStream *vs;
2005  int stream_index, i, j;
2006  enum AVMediaType codec_type;
2007  int nb_varstreams = 0, nb_streams;
2008  char *p, *q, *saveptr1, *saveptr2, *varstr, *keyval;
2009  const char *val;
2010 
2011  /**
2012  * Expected format for var_stream_map string is as below:
2013  * "a:0,v:0 a:1,v:1"
2014  * "a:0,agroup:a0,default:1,language:ENG a:1,agroup:a1,default:0 v:0,agroup:a0 v:1,agroup:a1"
2015  * This string specifies how to group the audio, video and subtitle streams
2016  * into different variant streams. The variant stream groups are separated
2017  * by space.
2018  *
2019  * a:, v:, s: are keys to specify audio, video and subtitle streams
2020  * respectively. Allowed values are 0 to 9 digits (limited just based on
2021  * practical usage)
2022  *
2023  * agroup: is key to specify audio group. A string can be given as value.
2024  * sgroup: is key to specify subtitle group. A string can be given as value.
2025  */
2026  p = av_strdup(hls->var_stream_map);
2027  if (!p)
2028  return AVERROR(ENOMEM);
2029 
2030  q = p;
2031  while (av_strtok(q, " \t", &saveptr1)) {
2032  q = NULL;
2033  nb_varstreams++;
2034  }
2035  av_freep(&p);
2036 
2037  hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * nb_varstreams);
2038  if (!hls->var_streams)
2039  return AVERROR(ENOMEM);
2040  hls->nb_varstreams = nb_varstreams;
2041 
2042  p = hls->var_stream_map;
2043  nb_varstreams = 0;
2044  while (varstr = av_strtok(p, " \t", &saveptr1)) {
2045  p = NULL;
2046 
2047  if (nb_varstreams < hls->nb_varstreams) {
2048  vs = &(hls->var_streams[nb_varstreams]);
2049  vs->var_stream_idx = nb_varstreams;
2050  vs->is_default = 0;
2051  nb_varstreams++;
2052  } else
2053  return AVERROR(EINVAL);
2054 
2055  q = varstr;
2056  while (1) {
2057  if (!av_strncasecmp(q, "a:", 2) || !av_strncasecmp(q, "v:", 2) ||
2058  !av_strncasecmp(q, "s:", 2))
2059  vs->nb_streams++;
2060  q = strchr(q, ',');
2061  if (!q)
2062  break;
2063  q++;
2064  }
2065  vs->streams = av_mallocz(sizeof(AVStream *) * vs->nb_streams);
2066  if (!vs->streams)
2067  return AVERROR(ENOMEM);
2068 
2069  nb_streams = 0;
2070  while (keyval = av_strtok(varstr, ",", &saveptr2)) {
2071  int64_t num;
2072  char *end;
2073  varstr = NULL;
2074  if (av_strstart(keyval, "language:", &val)) {
2075  vs->language = val;
2076  continue;
2077  } else if (av_strstart(keyval, "default:", &val)) {
2078  vs->is_default = (!av_strncasecmp(val, "YES", strlen("YES")) ||
2079  (!av_strncasecmp(val, "1", strlen("1"))));
2080  hls->has_default_key = 1;
2081  continue;
2082  } else if (av_strstart(keyval, "name:", &val)) {
2083  vs->varname = val;
2084  continue;
2085  } else if (av_strstart(keyval, "agroup:", &val)) {
2086  vs->agroup = val;
2087  continue;
2088  } else if (av_strstart(keyval, "sgroup:", &val)) {
2089  vs->sgroup = val;
2090  continue;
2091  } else if (av_strstart(keyval, "ccgroup:", &val)) {
2092  vs->ccgroup = val;
2093  continue;
2094  } else if (av_strstart(keyval, "v:", &val)) {
2096  hls->has_video_m3u8 = 1;
2097  } else if (av_strstart(keyval, "a:", &val)) {
2099  } else if (av_strstart(keyval, "s:", &val)) {
2101  } else {
2102  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2103  return AVERROR(EINVAL);
2104  }
2105 
2106  num = strtoll(val, &end, 10);
2107  if (!av_isdigit(*val) || *end != '\0') {
2108  av_log(s, AV_LOG_ERROR, "Invalid stream number: '%s'\n", val);
2109  return AVERROR(EINVAL);
2110  }
2111  stream_index = get_nth_codec_stream_index(s, codec_type, num);
2112 
2113  if (stream_index >= 0 && nb_streams < vs->nb_streams) {
2114  for (i = 0; nb_streams > 0 && i < nb_streams; i++) {
2115  if (vs->streams[i] == s->streams[stream_index]) {
2116  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once inside "
2117  "variant definition #%d\n", nb_varstreams - 1);
2118  return AVERROR(EINVAL);
2119  }
2120  }
2121  for (j = 0; nb_varstreams > 1 && j < nb_varstreams - 1; j++) {
2122  for (i = 0; i < hls->var_streams[j].nb_streams; i++) {
2123  if (hls->var_streams[j].streams[i] == s->streams[stream_index]) {
2124  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once "
2125  "in two different variant definitions #%d and #%d\n",
2126  j, nb_varstreams - 1);
2127  return AVERROR(EINVAL);
2128  }
2129  }
2130  }
2131  vs->streams[nb_streams++] = s->streams[stream_index];
2132  } else {
2133  av_log(s, AV_LOG_ERROR, "Unable to map stream at %s\n", keyval);
2134  return AVERROR(EINVAL);
2135  }
2136  }
2137  }
2138  av_log(s, AV_LOG_DEBUG, "Number of variant streams %d\n",
2139  hls->nb_varstreams);
2140 
2141  return 0;
2142 }
2143 
2145 {
2146  HLSContext *hls = s->priv_data;
2147  int nb_ccstreams = 0;
2148  char *p, *q, *ccstr, *keyval;
2149  char *saveptr1 = NULL, *saveptr2 = NULL;
2150  const char *val;
2151  ClosedCaptionsStream *ccs;
2152 
2153  p = av_strdup(hls->cc_stream_map);
2154  if(!p)
2155  return AVERROR(ENOMEM);
2156 
2157  q = p;
2158  while (av_strtok(q, " \t", &saveptr1)) {
2159  q = NULL;
2160  nb_ccstreams++;
2161  }
2162  av_freep(&p);
2163 
2164  hls->cc_streams = av_mallocz(sizeof(*hls->cc_streams) * nb_ccstreams);
2165  if (!hls->cc_streams)
2166  return AVERROR(ENOMEM);
2167  hls->nb_ccstreams = nb_ccstreams;
2168 
2169  p = hls->cc_stream_map;
2170  nb_ccstreams = 0;
2171  while (ccstr = av_strtok(p, " \t", &saveptr1)) {
2172  p = NULL;
2173 
2174  if (nb_ccstreams < hls->nb_ccstreams)
2175  ccs = &(hls->cc_streams[nb_ccstreams++]);
2176  else
2177  return AVERROR(EINVAL);
2178 
2179  while (keyval = av_strtok(ccstr, ",", &saveptr2)) {
2180  ccstr = NULL;
2181 
2182  if (av_strstart(keyval, "ccgroup:", &val)) {
2183  ccs->ccgroup = val;
2184  } else if (av_strstart(keyval, "instreamid:", &val)) {
2185  ccs->instreamid = val;
2186  } else if (av_strstart(keyval, "language:", &val)) {
2187  ccs->language = val;
2188  } else {
2189  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2190  return AVERROR(EINVAL);
2191  }
2192  }
2193 
2194  if (!ccs->ccgroup || !ccs->instreamid) {
2195  av_log(s, AV_LOG_ERROR, "Insufficient parameters in cc stream map string\n");
2196  return AVERROR(EINVAL);
2197  }
2198 
2199  if (av_strstart(ccs->instreamid, "CC", &val)) {
2200  if (atoi(val) < 1 || atoi(val) > 4) {
2201  av_log(s, AV_LOG_ERROR, "Invalid instream ID CC index %d in %s, range 1-4\n",
2202  atoi(val), ccs->instreamid);
2203  return AVERROR(EINVAL);
2204  }
2205  } else if (av_strstart(ccs->instreamid, "SERVICE", &val)) {
2206  if (atoi(val) < 1 || atoi(val) > 63) {
2207  av_log(s, AV_LOG_ERROR, "Invalid instream ID SERVICE index %d in %s, range 1-63 \n",
2208  atoi(val), ccs->instreamid);
2209  return AVERROR(EINVAL);
2210  }
2211  } else {
2212  av_log(s, AV_LOG_ERROR, "Invalid instream ID %s, supported are CCn or SERVICEn\n",
2213  ccs->instreamid);
2214  return AVERROR(EINVAL);
2215  }
2216  }
2217 
2218  return 0;
2219 }
2220 
2222 {
2223  HLSContext *hls = s->priv_data;
2224  unsigned int i;
2225  int ret = 0;
2226 
2227  if (hls->cc_stream_map) {
2229  if (ret < 0)
2230  return ret;
2231  }
2232 
2233  if (hls->var_stream_map) {
2235  } else {
2236  //By default, a single variant stream with all the codec streams is created
2237  hls->var_streams = av_mallocz(sizeof(*hls->var_streams));
2238  if (!hls->var_streams)
2239  return AVERROR(ENOMEM);
2240  hls->nb_varstreams = 1;
2241 
2242  hls->var_streams[0].var_stream_idx = 0;
2243  hls->var_streams[0].nb_streams = s->nb_streams;
2244  hls->var_streams[0].streams = av_mallocz(sizeof(AVStream *) *
2245  hls->var_streams[0].nb_streams);
2246  if (!hls->var_streams[0].streams)
2247  return AVERROR(ENOMEM);
2248 
2249  //by default, the first available ccgroup is mapped to the variant stream
2250  if (hls->nb_ccstreams)
2251  hls->var_streams[0].ccgroup = hls->cc_streams[0].ccgroup;
2252 
2253  for (i = 0; i < s->nb_streams; i++)
2254  hls->var_streams[0].streams[i] = s->streams[i];
2255  }
2256  return 0;
2257 }
2258 
2260 {
2261  HLSContext *hls = s->priv_data;
2262  const char *dir;
2263  char *fn1= NULL, *fn2 = NULL;
2264  int ret = 0;
2265 
2266  fn1 = av_strdup(s->url);
2267  if (!fn1)
2268  return AVERROR(ENOMEM);
2269  dir = av_dirname(fn1);
2270 
2271  /**
2272  * if output file's directory has %v, variants are created in sub-directories
2273  * then master is created at the sub-directories level
2274  */
2275  if (dir && av_stristr(av_basename(dir), "%v")) {
2276  fn2 = av_strdup(dir);
2277  if (!fn2) {
2278  ret = AVERROR(ENOMEM);
2279  goto fail;
2280  }
2281  dir = av_dirname(fn2);
2282  }
2283 
2284  if (dir && strcmp(dir, "."))
2286  else
2288 
2289  if (!hls->master_m3u8_url) {
2290  ret = AVERROR(ENOMEM);
2291  goto fail;
2292  }
2293 
2294 fail:
2295  av_freep(&fn1);
2296  av_freep(&fn2);
2297 
2298  return ret;
2299 }
2300 
2302 {
2303  HLSContext *hls = s->priv_data;
2304  int ret, i, j;
2305  VariantStream *vs = NULL;
2306 
2307  for (i = 0; i < hls->nb_varstreams; i++) {
2308  int subtitle_streams = 0;
2309  vs = &hls->var_streams[i];
2310 
2312  if (ret < 0)
2313  return ret;
2314  //av_assert0(s->nb_streams == hls->avf->nb_streams);
2315  for (j = 0; j < vs->nb_streams; j++) {
2316  AVStream *inner_st;
2317  AVStream *outer_st = vs->streams[j];
2318 
2319  if (hls->max_seg_size > 0) {
2320  if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
2321  (outer_st->codecpar->bit_rate > hls->max_seg_size)) {
2322  av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, "
2323  "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.",
2324  outer_st->codecpar->bit_rate, hls->max_seg_size);
2325  }
2326  }
2327 
2328  if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
2329  inner_st = vs->avf->streams[j - subtitle_streams];
2330  else if (vs->vtt_avf) {
2331  inner_st = vs->vtt_avf->streams[0];
2332  subtitle_streams++;
2333  } else {
2334  /* We have a subtitle stream, when the user does not want one */
2335  inner_st = NULL;
2336  continue;
2337  }
2338  avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
2339  if (outer_st->codecpar->codec_id == AV_CODEC_ID_HEVC &&
2340  outer_st->codecpar->codec_tag != MKTAG('h','v','c','1')) {
2341  av_log(s, AV_LOG_WARNING, "Stream HEVC is not hvc1, you should use tag:v hvc1 to set it.\n");
2342  }
2343  write_codec_attr(outer_st, vs);
2344 
2345  }
2346  /* Update the Codec Attr string for the mapped audio groups */
2347  if (vs->has_video && vs->agroup) {
2348  for (j = 0; j < hls->nb_varstreams; j++) {
2349  VariantStream *vs_agroup = &(hls->var_streams[j]);
2350  if (!vs_agroup->has_video && !vs_agroup->has_subtitle &&
2351  vs_agroup->agroup &&
2352  !av_strcasecmp(vs_agroup->agroup, vs->agroup)) {
2353  write_codec_attr(vs_agroup->streams[0], vs);
2354  }
2355  }
2356  }
2357  }
2358 
2359  return ret;
2360 }
2361 
2363 {
2364  HLSContext *hls = s->priv_data;
2366  int ret = 0;
2367 
2368  set_http_options(s, &options, hls);
2371  if (ret < 0)
2372  return ret;
2374  hlsenc_io_close(s, &vs->out, hls->fmp4_init_filename);
2375 
2376  return ret;
2377 }
2378 
2380 {
2381  int ret = 0;
2382  int64_t read_byte = 0;
2383  int64_t total_size = 0;
2384  char *filename = NULL;
2385  char buf[BUFSIZE];
2386  AVFormatContext *oc = vs->avf;
2387 
2388  hlsenc_io_close(s, &vs->out, vs->basename_tmp);
2389  filename = av_asprintf("%s.tmp", oc->url);
2390  ret = s->io_open(s, &vs->out, filename, AVIO_FLAG_READ, NULL);
2391  if (ret < 0) {
2392  av_free(filename);
2393  return ret;
2394  }
2395 
2396  do {
2397  read_byte = avio_read(vs->out, buf, BUFSIZE);
2398  if (read_byte > 0) {
2399  avio_write(vs->out_single_file, buf, read_byte);
2400  total_size += read_byte;
2401  ret = total_size;
2402  }
2403  } while (read_byte > 0);
2404 
2405  hlsenc_io_close(s, &vs->out, filename);
2406  av_free(filename);
2407 
2408  return ret;
2409 }
2411 {
2412  HLSContext *hls = s->priv_data;
2413  AVFormatContext *oc = NULL;
2414  AVStream *st = s->streams[pkt->stream_index];
2415  int64_t end_pts = 0;
2416  int is_ref_pkt = 1;
2417  int ret = 0, can_split = 1, i, j;
2418  int stream_index = 0;
2419  int subtitle_streams = 0;
2420  int range_length = 0;
2421  const char *proto = NULL;
2422  int use_temp_file = 0;
2423  VariantStream *vs = NULL;
2424  char *old_filename = NULL;
2425 
2426  for (i = 0; i < hls->nb_varstreams; i++) {
2427  vs = &hls->var_streams[i];
2428  for (j = 0; j < vs->nb_streams; j++) {
2430  subtitle_streams++;
2431  }
2432  if (vs->streams[j] == st) {
2434  oc = vs->vtt_avf;
2435  stream_index = 0;
2436  } else {
2437  oc = vs->avf;
2438  stream_index = j - subtitle_streams;
2439  }
2440  break;
2441  }
2442  }
2443 
2444  if (oc)
2445  break;
2446  }
2447 
2448  if (!oc) {
2449  av_log(s, AV_LOG_ERROR, "Unable to find mapping variant stream\n");
2450  return AVERROR(ENOMEM);
2451  }
2452 
2453  end_pts = hls->recording_time * vs->number;
2454 
2455  if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
2456  /* reset end_pts, hls->recording_time at end of the init hls list */
2457  int64_t init_list_dur = hls->init_time * vs->nb_entries;
2458  int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries) * hls->time;
2459  hls->recording_time = hls->time;
2460  end_pts = init_list_dur + after_init_list_dur ;
2461  }
2462 
2463  if (vs->start_pts == AV_NOPTS_VALUE) {
2464  vs->start_pts = pkt->pts;
2466  vs->start_pts_from_audio = 1;
2467  }
2469  vs->start_pts = pkt->pts;
2470  vs->start_pts_from_audio = 0;
2471  }
2472 
2473  if (vs->has_video) {
2474  can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
2475  ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME));
2476  is_ref_pkt = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->stream_index == vs->reference_stream_index);
2477  }
2478  if (pkt->pts == AV_NOPTS_VALUE)
2479  is_ref_pkt = can_split = 0;
2480 
2481  if (is_ref_pkt) {
2482  if (vs->end_pts == AV_NOPTS_VALUE)
2483  vs->end_pts = pkt->pts;
2484  if (vs->new_start) {
2485  vs->new_start = 0;
2486  vs->duration = (double)(pkt->pts - vs->end_pts)
2487  * st->time_base.num / st->time_base.den;
2488  vs->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2489  } else {
2490  if (pkt->duration) {
2491  vs->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2492  } else {
2493  av_log(s, AV_LOG_WARNING, "Stream %d packet with pts %" PRId64 " has duration 0. The segment duration may not be precise.\n",
2494  pkt->stream_index, pkt->pts);
2495  vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2496  }
2497  }
2498  }
2499 
2500  can_split = can_split && (pkt->pts - vs->end_pts > 0);
2501  if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base,
2502  end_pts, AV_TIME_BASE_Q) >= 0) {
2503  int64_t new_start_pos;
2504  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2505 
2506  av_write_frame(oc, NULL); /* Flush any buffered data */
2507  new_start_pos = avio_tell(oc->pb);
2508  vs->size = new_start_pos - vs->start_pos;
2509  avio_flush(oc->pb);
2510  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2511  if (!vs->init_range_length) {
2512  range_length = avio_close_dyn_buf(oc->pb, &vs->init_buffer);
2513  if (range_length <= 0)
2514  return AVERROR(EINVAL);
2515  avio_write(vs->out, vs->init_buffer, range_length);
2516  if (!hls->resend_init_file)
2517  av_freep(&vs->init_buffer);
2518  vs->init_range_length = range_length;
2519  avio_open_dyn_buf(&oc->pb);
2520  vs->packets_written = 0;
2521  vs->start_pos = range_length;
2522  if (!byterange_mode) {
2524  }
2525  }
2526  }
2527  if (!byterange_mode) {
2528  if (vs->vtt_avf) {
2529  hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url);
2530  }
2531  }
2532 
2533  if (hls->flags & HLS_SINGLE_FILE) {
2534  ret = flush_dynbuf(vs, &range_length);
2535  av_freep(&vs->temp_buffer);
2536  if (ret < 0) {
2537  return ret;
2538  }
2539  vs->size = range_length;
2540  if (hls->key_info_file || hls->encrypt)
2541  vs->size = append_single_file(s, vs);
2542  } else {
2543  if (oc->url[0]) {
2544  proto = avio_find_protocol_name(oc->url);
2545  use_temp_file = proto && !strcmp(proto, "file")
2546  && (hls->flags & HLS_TEMP_FILE);
2547  }
2548 
2549  if ((hls->max_seg_size > 0 && (vs->size + vs->start_pos >= hls->max_seg_size)) || !byterange_mode) {
2551  char *filename = NULL;
2552  if (hls->key_info_file || hls->encrypt) {
2553  av_dict_set(&options, "encryption_key", vs->key_string, 0);
2554  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2555  filename = av_asprintf("crypto:%s", oc->url);
2556  } else {
2557  filename = av_asprintf("%s", oc->url);
2558  }
2559  if (!filename) {
2561  return AVERROR(ENOMEM);
2562  }
2563 
2564  // look to rename the asset name
2565  if (use_temp_file)
2566  av_dict_set(&options, "mpegts_flags", "resend_headers", 0);
2567 
2568  set_http_options(s, &options, hls);
2569 
2570  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2571  if (ret < 0) {
2573  "Failed to open file '%s'\n", filename);
2574  av_freep(&filename);
2576  return hls->ignore_io_errors ? 0 : ret;
2577  }
2578  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2579  write_styp(vs->out);
2580  }
2581  ret = flush_dynbuf(vs, &range_length);
2582  if (ret < 0) {
2583  av_freep(&filename);
2585  return ret;
2586  }
2587  ret = hlsenc_io_close(s, &vs->out, filename);
2588  if (ret < 0) {
2589  av_log(s, AV_LOG_WARNING, "upload segment failed,"
2590  " will retry with a new http session.\n");
2591  ff_format_io_close(s, &vs->out);
2592  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2593  reflush_dynbuf(vs, &range_length);
2594  ret = hlsenc_io_close(s, &vs->out, filename);
2595  }
2597  av_freep(&vs->temp_buffer);
2598  av_freep(&filename);
2599  }
2600 
2601  if (use_temp_file)
2602  hls_rename_temp_file(s, oc);
2603  }
2604 
2605  old_filename = av_strdup(oc->url);
2606  if (!old_filename) {
2607  return AVERROR(ENOMEM);
2608  }
2609 
2610  if (vs->start_pos || hls->segment_type != SEGMENT_TYPE_FMP4) {
2611  double cur_duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2612  ret = hls_append_segment(s, hls, vs, cur_duration, vs->start_pos, vs->size);
2613  vs->end_pts = pkt->pts;
2614  vs->duration = 0;
2615  if (ret < 0) {
2616  av_freep(&old_filename);
2617  return ret;
2618  }
2619  }
2620 
2621  // if we're building a VOD playlist, skip writing the manifest multiple times, and just wait until the end
2622  if (hls->pl_type != PLAYLIST_TYPE_VOD) {
2623  if ((ret = hls_window(s, 0, vs)) < 0) {
2624  av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2625  ff_format_io_close(s, &vs->out);
2626  if ((ret = hls_window(s, 0, vs)) < 0) {
2627  av_freep(&old_filename);
2628  return ret;
2629  }
2630  }
2631  }
2632 
2633  if (hls->resend_init_file && hls->segment_type == SEGMENT_TYPE_FMP4) {
2634  ret = hls_init_file_resend(s, vs);
2635  if (ret < 0) {
2636  av_freep(&old_filename);
2637  return ret;
2638  }
2639  }
2640 
2641  if (hls->flags & HLS_SINGLE_FILE) {
2642  vs->start_pos += vs->size;
2643  if (hls->key_info_file || hls->encrypt)
2644  ret = hls_start(s, vs);
2645  if (hls->segment_type == SEGMENT_TYPE_MPEGTS && oc->oformat->priv_class && oc->priv_data) {
2646  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
2647  }
2648  } else if (hls->max_seg_size > 0) {
2649  if (vs->size + vs->start_pos >= hls->max_seg_size) {
2650  vs->sequence++;
2651  sls_flag_file_rename(hls, vs, old_filename);
2652  ret = hls_start(s, vs);
2653  vs->start_pos = 0;
2654  /* When split segment by byte, the duration is short than hls_time,
2655  * so it is not enough one segment duration as hls_time, */
2656  } else {
2657  vs->start_pos = new_start_pos;
2658  }
2659  } else {
2660  vs->start_pos = new_start_pos;
2661  sls_flag_file_rename(hls, vs, old_filename);
2662  ret = hls_start(s, vs);
2663  }
2664  vs->number++;
2665  av_freep(&old_filename);
2666 
2667  if (ret < 0) {
2668  return ret;
2669  }
2670  }
2671 
2672  vs->packets_written++;
2673  if (oc->pb) {
2674  ret = ff_write_chained(oc, stream_index, pkt, s, 0);
2675  vs->video_keyframe_size += pkt->size;
2677  vs->video_keyframe_size = avio_tell(oc->pb);
2678  } else {
2679  vs->video_keyframe_pos = avio_tell(vs->out);
2680  }
2681  if (hls->ignore_io_errors)
2682  ret = 0;
2683  }
2684 
2685  return ret;
2686 }
2687 
2689 {
2690  HLSContext *hls = s->priv_data;
2691  int i = 0;
2692  VariantStream *vs = NULL;
2693 
2694  for (i = 0; i < hls->nb_varstreams; i++) {
2695  vs = &hls->var_streams[i];
2696 
2697  av_freep(&vs->basename);
2700  av_freep(&vs->vtt_basename);
2701  av_freep(&vs->vtt_m3u8_name);
2702 
2705  if (hls->resend_init_file)
2706  av_freep(&vs->init_buffer);
2709  av_freep(&vs->m3u8_name);
2710  av_freep(&vs->streams);
2711  }
2712 
2713  ff_format_io_close(s, &hls->m3u8_out);
2716  av_freep(&hls->key_basename);
2717  av_freep(&hls->var_streams);
2718  av_freep(&hls->cc_streams);
2719  av_freep(&hls->master_m3u8_url);
2720 }
2721 
2723 {
2724  HLSContext *hls = s->priv_data;
2725  AVFormatContext *oc = NULL;
2726  AVFormatContext *vtt_oc = NULL;
2727  char *old_filename = NULL;
2728  const char *proto = NULL;
2729  int use_temp_file = 0;
2730  int i;
2731  int ret = 0;
2732  VariantStream *vs = NULL;
2734  int range_length, byterange_mode;
2735 
2736  for (i = 0; i < hls->nb_varstreams; i++) {
2737  char *filename = NULL;
2738  vs = &hls->var_streams[i];
2739  oc = vs->avf;
2740  vtt_oc = vs->vtt_avf;
2741  old_filename = av_strdup(oc->url);
2742  use_temp_file = 0;
2743 
2744  if (!old_filename) {
2745  return AVERROR(ENOMEM);
2746  }
2747  if (hls->key_info_file || hls->encrypt) {
2748  av_dict_set(&options, "encryption_key", vs->key_string, 0);
2749  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2750  filename = av_asprintf("crypto:%s", oc->url);
2751  } else {
2752  filename = av_asprintf("%s", oc->url);
2753  }
2754  if (!filename) {
2755  av_freep(&old_filename);
2756  return AVERROR(ENOMEM);
2757  }
2758 
2759  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2760  int range_length = 0;
2761  if (!vs->init_range_length) {
2762  uint8_t *buffer = NULL;
2763  av_write_frame(oc, NULL); /* Flush any buffered data */
2764 
2765  range_length = avio_close_dyn_buf(oc->pb, &buffer);
2766  avio_write(vs->out, buffer, range_length);
2767  av_freep(&buffer);
2768  vs->init_range_length = range_length;
2769  avio_open_dyn_buf(&oc->pb);
2770  vs->packets_written = 0;
2771  vs->start_pos = range_length;
2772  byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2773  if (!byterange_mode) {
2774  ff_format_io_close(s, &vs->out);
2776  }
2777  }
2778  }
2779  if (!(hls->flags & HLS_SINGLE_FILE)) {
2780  set_http_options(s, &options, hls);
2781  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2782  if (ret < 0) {
2783  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2784  goto failed;
2785  }
2786  if (hls->segment_type == SEGMENT_TYPE_FMP4)
2787  write_styp(vs->out);
2788  }
2789  ret = flush_dynbuf(vs, &range_length);
2790  if (ret < 0)
2791  goto failed;
2792 
2793  vs->size = range_length;
2794  ret = hlsenc_io_close(s, &vs->out, filename);
2795  if (ret < 0) {
2796  av_log(s, AV_LOG_WARNING, "upload segment failed, will retry with a new http session.\n");
2797  ff_format_io_close(s, &vs->out);
2798  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2799  if (ret < 0) {
2800  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2801  goto failed;
2802  }
2803  reflush_dynbuf(vs, &range_length);
2804  ret = hlsenc_io_close(s, &vs->out, filename);
2805  if (ret < 0)
2806  av_log(s, AV_LOG_WARNING, "Failed to upload file '%s' at the end.\n", oc->url);
2807  }
2808  if (hls->flags & HLS_SINGLE_FILE) {
2809  if (hls->key_info_file || hls->encrypt) {
2810  vs->size = append_single_file(s, vs);
2811  }
2813  }
2814 failed:
2815  av_freep(&vs->temp_buffer);
2817  av_freep(&filename);
2818  av_write_trailer(oc);
2819  if (oc->url[0]) {
2820  proto = avio_find_protocol_name(oc->url);
2821  use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & HLS_TEMP_FILE);
2822  }
2823 
2824  // rename that segment from .tmp to the real one
2825  if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) {
2826  hls_rename_temp_file(s, oc);
2827  av_freep(&old_filename);
2828  old_filename = av_strdup(oc->url);
2829 
2830  if (!old_filename) {
2831  return AVERROR(ENOMEM);
2832  }
2833  }
2834 
2835  /* after av_write_trailer, then duration + 1 duration per packet */
2836  hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size);
2837 
2838  sls_flag_file_rename(hls, vs, old_filename);
2839 
2840  if (vtt_oc) {
2841  if (vtt_oc->pb)
2842  av_write_trailer(vtt_oc);
2843  vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos;
2844  ff_format_io_close(s, &vtt_oc->pb);
2845  }
2846  ret = hls_window(s, 1, vs);
2847  if (ret < 0) {
2848  av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2849  ff_format_io_close(s, &vs->out);
2850  hls_window(s, 1, vs);
2851  }
2852  ffio_free_dyn_buf(&oc->pb);
2853 
2854  av_free(old_filename);
2855  }
2856 
2857  return 0;
2858 }
2859 
2860 
2862 {
2863  int ret = 0;
2864  int i = 0;
2865  int j = 0;
2866  HLSContext *hls = s->priv_data;
2867  const char *pattern;
2868  VariantStream *vs = NULL;
2869  const char *vtt_pattern = hls->flags & HLS_SINGLE_FILE ? ".vtt" : "%d.vtt";
2870  char *p = NULL;
2871  int http_base_proto = ff_is_http_proto(s->url);
2872  int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;
2873  double initial_program_date_time = av_gettime() / 1000000.0;
2874 
2875  if (hls->use_localtime) {
2877  } else {
2878  pattern = hls->segment_type == SEGMENT_TYPE_FMP4 ? "%d.m4s" : "%d.ts";
2879  if (hls->flags & HLS_SINGLE_FILE)
2880  pattern += 2;
2881  }
2882 
2883  hls->has_default_key = 0;
2884  hls->has_video_m3u8 = 0;
2886  if (ret < 0) {
2887  av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",
2888  ret);
2889  return ret;
2890  }
2891 
2892  if (!hls->method && http_base_proto) {
2893  av_log(hls, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n");
2894  }
2895 
2896  ret = validate_name(hls->nb_varstreams, s->url);
2897  if (ret < 0)
2898  return ret;
2899 
2900  if (hls->segment_filename) {
2902  if (ret < 0)
2903  return ret;
2904  }
2905 
2906  if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {
2908  if (ret < 0)
2909  return ret;
2910  }
2911 
2912  if (hls->subtitle_filename) {
2914  if (ret < 0)
2915  return ret;
2916  }
2917 
2918  if (hls->master_pl_name) {
2920  if (ret < 0) {
2921  av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",
2922  ret);
2923  return ret;
2924  }
2925  }
2926 
2930  time_t t = time(NULL);
2932  hls->start_sequence = av_gettime();
2934  hls->start_sequence = (int64_t)t;
2936  char b[15];
2937  struct tm *p, tmbuf;
2938  if (!(p = localtime_r(&t, &tmbuf)))
2939  return AVERROR(errno);
2940  if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
2941  return AVERROR(ENOMEM);
2942  hls->start_sequence = strtoll(b, NULL, 10);
2943  }
2944  av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
2945  }
2946 
2947  hls->recording_time = hls->init_time && hls->max_nb_segments > 0 ? hls->init_time : hls->time;
2948 
2949  if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) {
2950  // Independent segments cannot be guaranteed when splitting by time
2953  "'split_by_time' and 'independent_segments' cannot be "
2954  "enabled together. Disabling 'independent_segments' flag\n");
2955  }
2956 
2957  for (i = 0; i < hls->nb_varstreams; i++) {
2958  vs = &hls->var_streams[i];
2959 
2960  ret = format_name(s->url, &vs->m3u8_name, i, vs->varname);
2961  if (ret < 0)
2962  return ret;
2963 
2964  vs->sequence = hls->start_sequence;
2965  vs->start_pts = AV_NOPTS_VALUE;
2966  vs->end_pts = AV_NOPTS_VALUE;
2967  vs->current_segment_final_filename_fmt[0] = '\0';
2968  vs->initial_prog_date_time = initial_program_date_time;
2969 
2970  for (j = 0; j < vs->nb_streams; j++) {
2972  /* Get one video stream to reference for split segments
2973  * so use the first video stream index. */
2974  if ((vs->has_video == 1) && (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) {
2975  vs->reference_stream_index = vs->streams[j]->index;
2976  }
2978  }
2979 
2980  if (vs->has_video > 1)
2981  av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n");
2982  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2983  vs->oformat = av_guess_format("mp4", NULL, NULL);
2984  } else {
2985  vs->oformat = av_guess_format("mpegts", NULL, NULL);
2986  }
2987  if (!vs->oformat)
2988  return AVERROR_MUXER_NOT_FOUND;
2989 
2990  if (hls->segment_filename) {
2991  ret = format_name(hls->segment_filename, &vs->basename, i, vs->varname);
2992  if (ret < 0)
2993  return ret;
2994  } else {
2995  p = strrchr(vs->m3u8_name, '.');
2996  if (p)
2997  *p = '\0';
2998 
2999  vs->basename = av_asprintf("%s%s", vs->m3u8_name, pattern);
3000  if (!vs->basename)
3001  return AVERROR(ENOMEM);
3002 
3003  if (p)
3004  *p = '.';
3005  }
3006 
3007  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
3008  if (hls->nb_varstreams > 1)
3009  fmp4_init_filename_len += strlen(POSTFIX_PATTERN);
3010  if (hls->flags & HLS_SINGLE_FILE) {
3012  if (!vs->fmp4_init_filename)
3013  return AVERROR(ENOMEM);
3014  } else {
3015  vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);
3016  if (!vs->fmp4_init_filename)
3017  return AVERROR(ENOMEM);
3019  fmp4_init_filename_len);
3020  if (hls->nb_varstreams > 1) {
3021  if (av_stristr(vs->fmp4_init_filename, "%v")) {
3024  &vs->fmp4_init_filename, i, vs->varname);
3025  } else {
3026  ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i);
3027  }
3028  if (ret < 0)
3029  return ret;
3030  }
3031 
3032  if (hls->use_localtime) {
3033  int r;
3034  char *expanded = NULL;
3035 
3036  r = strftime_expand(vs->fmp4_init_filename, &expanded);
3037  if (r < 0) {
3038  av_log(s, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
3039  return r;
3040  }
3042  vs->fmp4_init_filename = expanded;
3043  }
3044 
3045  p = strrchr(vs->m3u8_name, '/');
3046  if (p) {
3047  char tmp = *(++p);
3048  *p = '\0';
3049  vs->base_output_dirname = av_asprintf("%s%s", vs->m3u8_name,
3050  vs->fmp4_init_filename);
3051  *p = tmp;
3052  } else {
3054  }
3055  if (!vs->base_output_dirname)
3056  return AVERROR(ENOMEM);
3057  }
3058  }
3059 
3061  if (ret < 0)
3062  return ret;
3063 
3064  if (vs->has_subtitle) {
3065  vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
3066  if (!vs->vtt_oformat)
3067  return AVERROR_MUXER_NOT_FOUND;
3068 
3069  p = strrchr(vs->m3u8_name, '.');
3070  if (p)
3071  *p = '\0';
3072 
3073  vs->vtt_basename = av_asprintf("%s%s", vs->m3u8_name, vtt_pattern);
3074  if (!vs->vtt_basename)
3075  return AVERROR(ENOMEM);
3076 
3077  if (hls->subtitle_filename) {
3079  if (ret < 0)
3080  return ret;
3081  } else {
3082  vs->vtt_m3u8_name = av_asprintf("%s_vtt.m3u8", vs->m3u8_name);
3083  if (!vs->vtt_m3u8_name)
3084  return AVERROR(ENOMEM);
3085  }
3086  if (p)
3087  *p = '.';
3088  }
3089 
3090  if ((ret = hls_mux_init(s, vs)) < 0)
3091  return ret;
3092 
3093  if (hls->flags & HLS_APPEND_LIST) {
3094  parse_playlist(s, vs->m3u8_name, vs);
3095  vs->discontinuity = 1;
3096  if (hls->init_time > 0) {
3097  av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
3098  " hls_init_time value will have no effect\n");
3099  hls->init_time = 0;
3100  hls->recording_time = hls->time;
3101  }
3102  }
3103 
3104  if ((ret = hls_start(s, vs)) < 0)
3105  return ret;
3106  vs->number++;
3107  }
3108 
3109  return ret;
3110 }
3111 
3112 #define OFFSET(x) offsetof(HLSContext, x)
3113 #define E AV_OPT_FLAG_ENCODING_PARAM
3114 static const AVOption options[] = {
3115  {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
3116  {"hls_time", "set segment length", OFFSET(time), AV_OPT_TYPE_DURATION, {.i64 = 2000000}, 0, INT64_MAX, E},
3117  {"hls_init_time", "set segment length at init list", OFFSET(init_time), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E},
3118  {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E},
3119  {"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},
3120  {"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},
3121  {"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},
3122  {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3123  {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3124  {"hls_segment_options","set segments files format options of hls", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
3125  {"hls_segment_size", "maximum size per segment file, (in bytes)", OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
3126  {"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},
3127  {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
3128  {"hls_enc_key", "hex-coded 16 byte key to encrypt the segments", OFFSET(key), AV_OPT_TYPE_STRING, .flags = E},
3129  {"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},
3130  {"hls_enc_iv", "hex-coded 16 byte initialization vector", OFFSET(iv), AV_OPT_TYPE_STRING, .flags = E},
3131  {"hls_subtitle_path", "set path of hls subtitles", OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3132  {"hls_segment_type", "set hls segment files type", OFFSET(segment_type), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, SEGMENT_TYPE_FMP4, E, "segment_type"},
3133  {"mpegts", "make segment file to mpegts files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, UINT_MAX, E, "segment_type"},
3134  {"fmp4", "make segment file to fragment mp4 files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_FMP4 }, 0, UINT_MAX, E, "segment_type"},
3135  {"hls_fmp4_init_filename", "set fragment mp4 file init filename", OFFSET(fmp4_init_filename), AV_OPT_TYPE_STRING, {.str = "init.mp4"}, 0, 0, E},
3136  {"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 },
3137  {"hls_flags", "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "flags"},
3138  {"single_file", "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX, E, "flags"},
3139  {"temp_file", "write segment and playlist to temporary file and rename when complete", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_TEMP_FILE }, 0, UINT_MAX, E, "flags"},
3140  {"delete_segments", "delete segment files that are no longer part of the playlist", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DELETE_SEGMENTS }, 0, UINT_MAX, E, "flags"},
3141  {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, "flags"},
3142  {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, "flags"},
3143  {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, "flags"},
3144  {"split_by_time", "split the hls segment by time which user set by hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX, E, "flags"},
3145  {"append_list", "append the new segments into old hls segment list", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX, E, "flags"},
3146  {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX, E, "flags"},
3147  {"second_level_segment_index", "include segment index in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_INDEX }, 0, UINT_MAX, E, "flags"},
3148  {"second_level_segment_duration", "include segment duration in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_DURATION }, 0, UINT_MAX, E, "flags"},
3149  {"second_level_segment_size", "include segment size in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_SIZE }, 0, UINT_MAX, E, "flags"},
3150  {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX, E, "flags"},
3151  {"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, "flags"},
3152  {"iframes_only", "add EXT-X-I-FRAMES-ONLY, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_I_FRAMES_ONLY }, 0, UINT_MAX, E, "flags"},
3153  {"strftime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3154  {"strftime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3155  {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, "pl_type" },
3156  {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, "pl_type" },
3157  {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, "pl_type" },
3158  {"method", "set the HTTP method(default: PUT)", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3159  {"hls_start_number_source", "set source of first number in sequence", OFFSET(start_sequence_source_type), AV_OPT_TYPE_INT, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, 0, HLS_START_SEQUENCE_LAST-1, E, "start_sequence_source_type" },
3160  {"generic", "start_number value (default)", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
3161  {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
3162  {"epoch_us", "microseconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
3163  {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
3164  {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3165  {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3166  {"cc_stream_map", "Closed captions stream map string", OFFSET(cc_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3167  {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3168  {"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},
3169  {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3170  {"timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
3171  {"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 },
3172  {"headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
3173  { NULL },
3174 };
3175 
3176 static const AVClass hls_class = {
3177  .class_name = "hls muxer",
3178  .item_name = av_default_item_name,
3179  .option = options,
3180  .version = LIBAVUTIL_VERSION_INT,
3181 };
3182 
3183 
3185  .p.name = "hls",
3186  .p.long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
3187  .p.extensions = "m3u8",
3188  .p.audio_codec = AV_CODEC_ID_AAC,
3189  .p.video_codec = AV_CODEC_ID_H264,
3190  .p.subtitle_codec = AV_CODEC_ID_WEBVTT,
3191 #if FF_API_ALLOW_FLUSH
3192  .p.flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_NODIMENSIONS,
3193 #else
3195 #endif
3196  .p.priv_class = &hls_class,
3197  .flags_internal = FF_FMT_ALLOW_FLUSH,
3198  .priv_data_size = sizeof(HLSContext),
3199  .init = hls_init,
3203  .deinit = hls_deinit,
3204 };
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:833
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:73
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:2301
av_codec_get_id
enum AVCodecID av_codec_get_id(const struct AVCodecTag *const *tags, unsigned int tag)
Get the AVCodecID for the given codec tag tag.
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:69
get_relative_url
static const char * get_relative_url(const char *master_url, const char *media_url)
Definition: hlsenc.c:1337
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:965
append_postfix
static int append_postfix(char *name, int name_buf_len, int i)
Definition: hlsenc.c:1884
level
uint8_t level
Definition: svq3.c:204
AV_CODEC_ID_AC3
@ AV_CODEC_ID_AC3
Definition: codec_id.h:445
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:1065
HLS_TEMP_FILE
@ HLS_TEMP_FILE
Definition: hlsenc.c:106
AVOutputFormat::name
const char * name
Definition: avformat.h:511
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:484
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:128
avio_close
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:1271
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:190
hls_init_file_resend
static int hls_init_file_resend(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:2362
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:1183
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:342
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:1411
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:251
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:239
fn
#define fn(a)
Definition: adynamicequalizer_template.c:61
AV_DICT_APPEND
#define AV_DICT_APPEND
If the entry already exists, append to it.
Definition: dict.h:82
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
ffio_open_whitelist
int ffio_open_whitelist(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist)
Definition: aviobuf.c:1244
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:509
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:456
hls_write_trailer
static int hls_write_trailer(struct AVFormatContext *s)
Definition: hlsenc.c:2722
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:1983
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:3113
os_support.h
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:546
update_variant_stream_info
static int update_variant_stream_info(AVFormatContext *s)
Definition: hlsenc.c:2221
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:1038
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:1381
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:761
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:99
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:138
ff_hls_muxer
const FFOutputFormat ff_hls_muxer
Definition: hlsenc.c:3184
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:975
hls_start
static int hls_start(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:1683
hls_delete_file
static int hls_delete_file(HLSContext *hls, AVFormatContext *avf, char *path, const char *proto)
Definition: hlsenc.c:578
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:513
ff_hls_write_audio_rendition
void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, const char *filename, const char *language, int name_id, int is_default)
Definition: hlsplaylist.c:40
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:487
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:443
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:674
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:1058
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:1552
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:1343
get_stream_bit_rate
static int64_t get_stream_bit_rate(AVStream *stream)
Definition: hlsenc.c:1357
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:55
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:1507
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:1903
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:442
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
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:365
hls_deinit
static void hls_deinit(AVFormatContext *s)
Definition: hlsenc.c:2688
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:226
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:637
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:343
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:328
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:536
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:1620
VariantStream::key_string
char key_string[KEYSIZE *2+1]
Definition: hlsenc.c:171
key
const char * key
Definition: hwcontext_opencl.c:174
AVCodecParameters::nb_coded_side_data
int nb_coded_side_data
Amount of entries in coded_side_data.
Definition: codec_par.h:228
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:477
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:270
AV_CODEC_ID_WEBVTT
@ AV_CODEC_ID_WEBVTT
Definition: codec_id.h:568
AVFormatContext
Format I/O context.
Definition: avformat.h:1115
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:864
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:880
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:232
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
ffurl_shutdown
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:660
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1157
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:921
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
AVOutputFormat::priv_class
const AVClass * priv_class
AVClass for the private context.
Definition: avformat.h:539
av_write_frame
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:1223
HLSContext::vtt_format_options
AVDictionary * vtt_format_options
Definition: hlsenc.c:232
PLAYLIST_TYPE_NB
@ PLAYLIST_TYPE_NB
Definition: hlsplaylist.h:35
SegmentType
SegmentType
Definition: hlsenc.c:112
AVCodecParameters::level
int level
Definition: codec_par.h:116
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:650
AV_CODEC_ID_EAC3
@ AV_CODEC_ID_EAC3
Definition: codec_id.h:482
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:444
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:1109
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:166
VariantStream::ccgroup
const char * ccgroup
Definition: hlsenc.c:183
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:1322
AVMediaType
AVMediaType
Definition: avutil.h:199
AVPacket::size
int size
Definition: packet.h:492
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:1374
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:1198
ffio_geturlcontext
struct URLContext * ffio_geturlcontext(AVIOContext *s)
Return the URLContext associated with the AVIOContext.
Definition: aviobuf.c:1028
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:115
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:469
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:843
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:123
HLSSegment::discont_program_date_time
double discont_program_date_time
Definition: hlsenc.c:90
AVStream::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:919
parse_variant_stream_mapstring
static int parse_variant_stream_mapstring(AVFormatContext *s)
Definition: hlsenc.c:2001
hls_init
static int hls_init(AVFormatContext *s)
Definition: hlsenc.c:2861
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:248
avio_wb32
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:412
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:497
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:225
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:3112
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:1198
hls_write_packet
static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: hlsenc.c:2410
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:1291
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
URLContext
Definition: url.h:37
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:479
AVOutputFormat
Definition: avformat.h:510
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:484
avio_internal.h
round
static av_always_inline av_const double round(double x)
Definition: libm.h:444
AVERROR_MUXER_NOT_FOUND
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:62
HLSContext::key_string
char key_string[KEYSIZE *2+1]
Definition: hlsenc.c: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:3114
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:1227
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:816
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:2115
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:223
write_packet
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
Definition: ffmpeg_mux.c:61
HLSContext::fmp4_init_filename
char * fmp4_init_filename
Definition: hlsenc.c:205
fn2
#define fn2(a, b)
Definition: adynamicequalizer_template.c:60
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:1580
AVStream::id
int id
Format-specific stream ID.
Definition: avformat.h:853
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:841
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:133
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:278
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:1134
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
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:847
random_seed.h
format_name
static int format_name(const char *buf, char **s, int index, const char *varname)
Definition: hlsenc.c:1937
MAX_URL_SIZE
#define MAX_URL_SIZE
Definition: internal.h:30
get_default_pattern_localtime_fmt
static const char * get_default_pattern_localtime_fmt(AVFormatContext *s)
Definition: hlsenc.c:1868
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:70
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
headers
FFmpeg currently uses a custom build this text attempts to document some of its obscure features and options Makefile the full command issued by make and its output will be shown on the screen DBG Preprocess x86 external assembler files to a dbg asm file in the object which then gets compiled Helps in developing those assembler files DESTDIR Destination directory for the install useful to prepare packages or install FFmpeg in cross environments GEN Set to ‘1’ to generate the missing or mismatched references Makefile builds all the libraries and the executables fate Run the fate test note that you must have installed it fate list List all fate regression test targets install Install headers
Definition: build_system.txt:34
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:102
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:659
update_master_pl_info
static int update_master_pl_info(AVFormatContext *s)
Definition: hlsenc.c:2259
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:1674
sls_flag_check_duration_size_index
static int sls_flag_check_duration_size_index(HLSContext *hls)
Definition: hlsenc.c:1015
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:493
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
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:72
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:169
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:636
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:79
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:468
hls_free_segments
static void hls_free_segments(HLSSegment *p)
Definition: hlsenc.c:1311
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
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:239
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:1726
append_single_file
static int64_t append_single_file(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:2379
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:468
d
d
Definition: ffmpeg_filter.c:368
AV_OPT_TYPE_FLAGS
@ AV_OPT_TYPE_FLAGS
Definition: opt.h:224
HLSContext::init_time
int64_t init_time
Definition: hlsenc.c:199
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
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:84
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:1540
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
h
h
Definition: vp9dsp_template.c:2038
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:346
HLSContext::key_uri
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c: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:1016
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:234
snprintf
#define snprintf
Definition: snprintf.h:34
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1143
ff_format_set_url
void ff_format_set_url(AVFormatContext *s, char *url)
Set AVFormatContext url field to the provided pointer.
Definition: avformat.c:836
parse_cc_stream_mapstring
static int parse_cc_stream_mapstring(AVFormatContext *s)
Definition: hlsenc.c:2144
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:358
hls_class
static const AVClass hls_class
Definition: hlsenc.c:3176
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:393
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:1390