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