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