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