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