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