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;
785  av_dict_copy(&oc->metadata, s->metadata, 0);
786 
787  if (vs->vtt_oformat) {
789  if (ret < 0)
790  return ret;
791  vtt_oc = vs->vtt_avf;
792  vtt_oc->oformat = vs->vtt_oformat;
793  av_dict_copy(&vtt_oc->metadata, s->metadata, 0);
794  }
795 
796  for (i = 0; i < vs->nb_streams; i++) {
797  AVStream *st;
798  AVFormatContext *loc;
800  loc = vtt_oc;
801  else
802  loc = oc;
803 
804  if (!(st = avformat_new_stream(loc, NULL)))
805  return AVERROR(ENOMEM);
807  if (!oc->oformat->codec_tag ||
811  } else {
812  st->codecpar->codec_tag = 0;
813  }
814 
816  st->time_base = vs->streams[i]->time_base;
817  av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0);
818  }
819 
820  vs->packets_written = 1;
821  vs->start_pos = 0;
822  vs->new_start = 1;
823 
824  if (hls->segment_type == SEGMENT_TYPE_FMP4 && hls->max_seg_size > 0) {
825  if (hls->http_persistent > 0) {
826  //TODO: Support fragment fmp4 for http persistent in HLS muxer.
827  av_log(s, AV_LOG_WARNING, "http persistent mode is currently unsupported for fragment mp4 in the HLS muxer.\n");
828  }
829  if (hls->max_seg_size > 0) {
830  av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n");
831  return AVERROR_PATCHWELCOME;
832  }
833  }
834 
835  vs->packets_written = 0;
836  vs->init_range_length = 0;
837  set_http_options(s, &options, hls);
838  if ((ret = avio_open_dyn_buf(&oc->pb)) < 0)
839  return ret;
840 
841  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
842  if (byterange_mode) {
843  ret = hlsenc_io_open(s, &vs->out, vs->basename, &options);
844  } else {
845  ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options);
846  }
847  }
848  av_dict_free(&options);
849  if (ret < 0) {
850  av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename);
851  return ret;
852  }
853 
854  if (hls->format_options_str) {
855  ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
856  if (ret < 0) {
857  av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n",
858  hls->format_options_str);
859  return ret;
860  }
861  }
862 
863  av_dict_copy(&options, hls->format_options, 0);
864  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
865  av_dict_set(&options, "fflags", "-autobsf", 0);
866  av_dict_set(&options, "movflags", "+frag_custom+dash+delay_moov", AV_DICT_APPEND);
867  ret = avformat_init_output(oc, &options);
868  if (ret < 0)
869  return ret;
870  if (av_dict_count(options)) {
871  av_log(s, AV_LOG_ERROR, "Some of the provided format options in '%s' are not recognized\n", hls->format_options_str);
872  av_dict_free(&options);
873  return AVERROR(EINVAL);
874  }
875  }
876  avio_flush(oc->pb);
877  av_dict_free(&options);
878  return 0;
879 }
880 
882 {
883  while (segment) {
884  if (!av_strcasecmp(segment->filename,filename))
885  return segment;
886  segment = segment->next;
887  }
888  return (HLSSegment *) NULL;
889 }
890 
892  VariantStream *vs, HLSSegment *en,
893  double duration, int64_t pos, int64_t size)
894 {
897  char * new_url = av_strdup(vs->current_segment_final_filename_fmt);
898  if (!new_url) {
899  return AVERROR(ENOMEM);
900  }
901  ff_format_set_url(vs->avf, new_url);
903  char *filename = NULL;
904  if (replace_int_data_in_filename(&filename, vs->avf->url, 's', pos + size) < 1) {
905  av_log(hls, AV_LOG_ERROR,
906  "Invalid second level segment filename template '%s', "
907  "you can try to remove second_level_segment_size flag\n",
908  vs->avf->url);
909  av_freep(&filename);
910  return AVERROR(EINVAL);
911  }
912  ff_format_set_url(vs->avf, filename);
913  }
915  char *filename = NULL;
916  if (replace_int_data_in_filename(&filename, vs->avf->url,
917  't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) {
918  av_log(hls, AV_LOG_ERROR,
919  "Invalid second level segment filename template '%s', "
920  "you can try to remove second_level_segment_time flag\n",
921  vs->avf->url);
922  av_freep(&filename);
923  return AVERROR(EINVAL);
924  }
925  ff_format_set_url(vs->avf, filename);
926  }
927  }
928  return 0;
929 }
930 
932 {
933  int ret = 0;
934 
936  av_log(hls, AV_LOG_ERROR,
937  "second_level_segment_duration hls_flag requires strftime to be true\n");
938  ret = AVERROR(EINVAL);
939  }
941  av_log(hls, AV_LOG_ERROR,
942  "second_level_segment_size hls_flag requires strfime to be true\n");
943  ret = AVERROR(EINVAL);
944  }
946  av_log(hls, AV_LOG_ERROR,
947  "second_level_segment_index hls_flag requires strftime to be true\n");
948  ret = AVERROR(EINVAL);
949  }
950 
951  return ret;
952 }
953 
955 {
956  const char *proto = avio_find_protocol_name(vs->basename);
957  int segment_renaming_ok = proto && !strcmp(proto, "file");
958  int ret = 0;
959 
960  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) && !segment_renaming_ok) {
961  av_log(hls, AV_LOG_ERROR,
962  "second_level_segment_duration hls_flag works only with file protocol segment names\n");
963  ret = AVERROR(EINVAL);
964  }
965  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) && !segment_renaming_ok) {
966  av_log(hls, AV_LOG_ERROR,
967  "second_level_segment_size hls_flag works only with file protocol segment names\n");
968  ret = AVERROR(EINVAL);
969  }
970 
971  return ret;
972 }
973 
974 static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename) {
977  ff_rename(old_filename, vs->avf->url, hls);
978  }
979 }
980 
982 {
984  char *filename = NULL;
985  if (replace_int_data_in_filename(&filename,
986 #if FF_API_HLS_WRAP
987  oc->url, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) {
988 #else
989  oc->url, 'd', vs->sequence) < 1) {
990 #endif
991  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
992  "you can try to remove second_level_segment_index flag\n",
993  oc->url);
994  av_freep(&filename);
995  return AVERROR(EINVAL);
996  }
997  ff_format_set_url(oc, filename);
998  }
1003  char *filename = NULL;
1004  if (replace_int_data_in_filename(&filename, oc->url, 's', 0) < 1) {
1005  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1006  "you can try to remove second_level_segment_size flag\n",
1007  oc->url);
1008  av_freep(&filename);
1009  return AVERROR(EINVAL);
1010  }
1011  ff_format_set_url(oc, filename);
1012  }
1014  char *filename = NULL;
1015  if (replace_int_data_in_filename(&filename, oc->url, 't', 0) < 1) {
1016  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1017  "you can try to remove second_level_segment_time flag\n",
1018  oc->url);
1019  av_freep(&filename);
1020  return AVERROR(EINVAL);
1021  }
1022  ff_format_set_url(oc, filename);
1023  }
1024  }
1025  return 0;
1026 }
1027 
1028 /* Create a new segment and append it to the segment list */
1030  VariantStream *vs, double duration, int64_t pos,
1031  int64_t size)
1032 {
1033  HLSSegment *en = av_malloc(sizeof(*en));
1034  const char *filename;
1035  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1036  int ret;
1037 
1038  if (!en)
1039  return AVERROR(ENOMEM);
1040 
1041  en->var_stream_idx = vs->var_stream_idx;
1042  ret = sls_flags_filename_process(s, hls, vs, en, duration, pos, size);
1043  if (ret < 0) {
1044  av_freep(&en);
1045  return ret;
1046  }
1047 
1048  filename = av_basename(vs->avf->url);
1049 
1050  if (hls->use_localtime_mkdir) {
1051  filename = vs->avf->url;
1052  }
1053  if ((find_segment_by_filename(vs->segments, filename) || find_segment_by_filename(vs->old_segments, filename))
1054  && !byterange_mode) {
1055  av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename);
1056  }
1057  av_strlcpy(en->filename, filename, sizeof(en->filename));
1058 
1059  if (vs->has_subtitle)
1060  av_strlcpy(en->sub_filename, av_basename(vs->vtt_avf->url), sizeof(en->sub_filename));
1061  else
1062  en->sub_filename[0] = '\0';
1063 
1064  en->duration = duration;
1065  en->pos = pos;
1066  en->size = size;
1067  en->keyframe_pos = vs->video_keyframe_pos;
1069  en->next = NULL;
1070  en->discont = 0;
1071 
1072  if (vs->discontinuity) {
1073  en->discont = 1;
1074  vs->discontinuity = 0;
1075  }
1076 
1077  if (hls->key_info_file || hls->encrypt) {
1078  av_strlcpy(en->key_uri, hls->key_uri, sizeof(en->key_uri));
1079  av_strlcpy(en->iv_string, hls->iv_string, sizeof(en->iv_string));
1080  }
1081 
1082  if (!vs->segments)
1083  vs->segments = en;
1084  else
1085  vs->last_segment->next = en;
1086 
1087  vs->last_segment = en;
1088 
1089  // EVENT or VOD playlists imply sliding window cannot be used
1090  if (hls->pl_type != PLAYLIST_TYPE_NONE)
1091  hls->max_nb_segments = 0;
1092 
1093  if (hls->max_nb_segments && vs->nb_entries >= hls->max_nb_segments) {
1094  en = vs->segments;
1095  vs->initial_prog_date_time += en->duration;
1096  vs->segments = en->next;
1097  if (en && hls->flags & HLS_DELETE_SEGMENTS &&
1098 #if FF_API_HLS_WRAP
1099  !(hls->flags & HLS_SINGLE_FILE || hls->wrap)) {
1100 #else
1101  !(hls->flags & HLS_SINGLE_FILE)) {
1102 #endif
1103  en->next = vs->old_segments;
1104  vs->old_segments = en;
1105  if ((ret = hls_delete_old_segments(s, hls, vs)) < 0)
1106  return ret;
1107  } else
1108  av_freep(&en);
1109  } else
1110  vs->nb_entries++;
1111 
1112  if (hls->max_seg_size > 0) {
1113  return 0;
1114  }
1115  vs->sequence++;
1116 
1117  return 0;
1118 }
1119 
1120 static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
1121 {
1122  HLSContext *hls = s->priv_data;
1123  AVIOContext *in;
1124  int ret = 0, is_segment = 0;
1125  int64_t new_start_pos;
1126  char line[MAX_URL_SIZE];
1127  const char *ptr;
1128  const char *end;
1129 
1130  if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
1131  &s->interrupt_callback, NULL,
1133  return ret;
1134 
1135  ff_get_chomp_line(in, line, sizeof(line));
1136  if (strcmp(line, "#EXTM3U")) {
1137  ret = AVERROR_INVALIDDATA;
1138  goto fail;
1139  }
1140 
1141  vs->discontinuity = 0;
1142  while (!avio_feof(in)) {
1143  ff_get_chomp_line(in, line, sizeof(line));
1144  if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
1145  int64_t tmp_sequence = strtoll(ptr, NULL, 10);
1146  if (tmp_sequence < vs->sequence)
1147  av_log(hls, AV_LOG_VERBOSE,
1148  "Found playlist sequence number was smaller """
1149  "than specified start sequence number: %"PRId64" < %"PRId64", "
1150  "omitting\n", tmp_sequence, hls->start_sequence);
1151  else {
1152  av_log(hls, AV_LOG_DEBUG, "Found playlist sequence number: %"PRId64"\n", tmp_sequence);
1153  vs->sequence = tmp_sequence;
1154  }
1155  } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
1156  is_segment = 1;
1157  vs->discontinuity = 1;
1158  } else if (av_strstart(line, "#EXTINF:", &ptr)) {
1159  is_segment = 1;
1160  vs->duration = atof(ptr);
1161  } else if (av_stristart(line, "#EXT-X-KEY:", &ptr)) {
1162  ptr = av_stristr(line, "URI=\"");
1163  if (ptr) {
1164  ptr += strlen("URI=\"");
1165  end = av_stristr(ptr, ",");
1166  if (end) {
1167  av_strlcpy(hls->key_uri, ptr, end - ptr);
1168  } else {
1169  av_strlcpy(hls->key_uri, ptr, sizeof(hls->key_uri));
1170  }
1171  }
1172 
1173  ptr = av_stristr(line, "IV=0x");
1174  if (ptr) {
1175  ptr += strlen("IV=0x");
1176  end = av_stristr(ptr, ",");
1177  if (end) {
1178  av_strlcpy(hls->iv_string, ptr, end - ptr);
1179  } else {
1180  av_strlcpy(hls->iv_string, ptr, sizeof(hls->iv_string));
1181  }
1182  }
1183 
1184  } else if (av_strstart(line, "#", NULL)) {
1185  continue;
1186  } else if (line[0]) {
1187  if (is_segment) {
1188  char *new_file = av_strdup(line);
1189  if (!new_file) {
1190  ret = AVERROR(ENOMEM);
1191  goto fail;
1192  }
1193  ff_format_set_url(vs->avf, new_file);
1194  is_segment = 0;
1195  new_start_pos = avio_tell(vs->avf->pb);
1196  vs->size = new_start_pos - vs->start_pos;
1197  ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size);
1198  if (ret < 0)
1199  goto fail;
1200  vs->start_pos = new_start_pos;
1201  }
1202  }
1203  }
1204 
1205 fail:
1206  avio_close(in);
1207  return ret;
1208 }
1209 
1211 {
1212  HLSSegment *en;
1213 
1214  while (p) {
1215  en = p;
1216  p = p->next;
1217  av_freep(&en);
1218  }
1219 }
1220 
1222 {
1223  size_t len = strlen(oc->url);
1224  char *final_filename = av_strdup(oc->url);
1225  int ret;
1226 
1227  if (!final_filename)
1228  return AVERROR(ENOMEM);
1229  final_filename[len-4] = '\0';
1230  ret = ff_rename(oc->url, final_filename, s);
1231  oc->url[len-4] = '\0';
1232  av_freep(&final_filename);
1233  return ret;
1234 }
1235 
1236 static const char* get_relative_url(const char *master_url, const char *media_url)
1237 {
1238  const char *p = strrchr(master_url, '/');
1239  size_t base_len = 0;
1240 
1241  if (!p) p = strrchr(master_url, '\\');
1242 
1243  if (p) {
1244  base_len = p + 1 - master_url;
1245  if (av_strncasecmp(master_url, media_url, base_len)) {
1246  av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n");
1247  return NULL;
1248  }
1249  }
1250 
1251  return media_url + base_len;
1252 }
1253 
1254 static int64_t get_stream_bit_rate(AVStream *stream)
1255 {
1257  stream,
1259  NULL
1260  );
1261 
1262  if (stream->codecpar->bit_rate)
1263  return stream->codecpar->bit_rate;
1264  else if (props)
1265  return props->max_bitrate;
1266 
1267  return 0;
1268 }
1269 
1271  VariantStream * const input_vs)
1272 {
1273  HLSContext *hls = s->priv_data;
1274  VariantStream *vs, *temp_vs;
1275  AVStream *vid_st, *aud_st;
1277  unsigned int i, j;
1278  int ret, bandwidth;
1279  const char *m3u8_rel_name = NULL;
1280  char *ccgroup;
1281  ClosedCaptionsStream *ccs;
1282  const char *proto = avio_find_protocol_name(hls->master_m3u8_url);
1283  int is_file_proto = proto && !strcmp(proto, "file");
1284  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || hls->master_publish_rate);
1285  char temp_filename[MAX_URL_SIZE];
1286 
1287  input_vs->m3u8_created = 1;
1288  if (!hls->master_m3u8_created) {
1289  /* For the first time, wait until all the media playlists are created */
1290  for (i = 0; i < hls->nb_varstreams; i++)
1291  if (!hls->var_streams[i].m3u8_created)
1292  return 0;
1293  } else {
1294  /* Keep publishing the master playlist at the configured rate */
1295  if (&hls->var_streams[0] != input_vs || !hls->master_publish_rate ||
1296  input_vs->number % hls->master_publish_rate)
1297  return 0;
1298  }
1299 
1300  set_http_options(s, &options, hls);
1301  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", hls->master_m3u8_url);
1302  ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options);
1303  av_dict_free(&options);
1304  if (ret < 0) {
1305  av_log(s, AV_LOG_ERROR, "Failed to open master play list file '%s'\n",
1306  temp_filename);
1307  goto fail;
1308  }
1309 
1311 
1312  for (i = 0; i < hls->nb_ccstreams; i++) {
1313  ccs = &(hls->cc_streams[i]);
1314  avio_printf(hls->m3u8_out, "#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS");
1315  avio_printf(hls->m3u8_out, ",GROUP-ID=\"%s\"", ccs->ccgroup);
1316  avio_printf(hls->m3u8_out, ",NAME=\"%s\"", ccs->instreamid);
1317  if (ccs->language)
1318  avio_printf(hls->m3u8_out, ",LANGUAGE=\"%s\"", ccs->language);
1319  avio_printf(hls->m3u8_out, ",INSTREAM-ID=\"%s\"\n", ccs->instreamid);
1320  }
1321 
1322  /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/
1323  for (i = 0; i < hls->nb_varstreams; i++) {
1324  vs = &(hls->var_streams[i]);
1325 
1326  if (vs->has_video || vs->has_subtitle || !vs->agroup)
1327  continue;
1328 
1329  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1330  if (!m3u8_rel_name) {
1331  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1332  goto fail;
1333  }
1334 
1335  ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1);
1336  }
1337 
1338  /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/
1339  for (i = 0; i < hls->nb_varstreams; i++) {
1340  vs = &(hls->var_streams[i]);
1341 
1342  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1343  if (!m3u8_rel_name) {
1344  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1345  goto fail;
1346  }
1347 
1348  vid_st = NULL;
1349  aud_st = NULL;
1350  for (j = 0; j < vs->nb_streams; j++) {
1352  vid_st = vs->streams[j];
1353  else if (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
1354  aud_st = vs->streams[j];
1355  }
1356 
1357  if (!vid_st && !aud_st) {
1358  av_log(s, AV_LOG_WARNING, "Media stream not found\n");
1359  continue;
1360  }
1361 
1362  /**
1363  * Traverse through the list of audio only rendition streams and find
1364  * the rendition which has highest bitrate in the same audio group
1365  */
1366  if (vs->agroup) {
1367  for (j = 0; j < hls->nb_varstreams; j++) {
1368  temp_vs = &(hls->var_streams[j]);
1369  if (!temp_vs->has_video && !temp_vs->has_subtitle &&
1370  temp_vs->agroup &&
1371  !av_strcasecmp(temp_vs->agroup, vs->agroup)) {
1372  if (!aud_st)
1373  aud_st = temp_vs->streams[0];
1374  if (temp_vs->streams[0]->codecpar->bit_rate >
1375  aud_st->codecpar->bit_rate)
1376  aud_st = temp_vs->streams[0];
1377  }
1378  }
1379  }
1380 
1381  bandwidth = 0;
1382  if (vid_st)
1383  bandwidth += get_stream_bit_rate(vid_st);
1384  if (aud_st)
1385  bandwidth += get_stream_bit_rate(aud_st);
1386  bandwidth += bandwidth / 10;
1387 
1388  ccgroup = NULL;
1389  if (vid_st && vs->ccgroup) {
1390  /* check if this group name is available in the cc map string */
1391  for (j = 0; j < hls->nb_ccstreams; j++) {
1392  ccs = &(hls->cc_streams[j]);
1393  if (!av_strcasecmp(ccs->ccgroup, vs->ccgroup)) {
1394  ccgroup = vs->ccgroup;
1395  break;
1396  }
1397  }
1398  if (j == hls->nb_ccstreams)
1399  av_log(s, AV_LOG_WARNING, "mapping ccgroup %s not found\n",
1400  vs->ccgroup);
1401  }
1402 
1403  if (!hls->has_default_key || !hls->has_video_m3u8) {
1404  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name,
1405  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup);
1406  } else {
1407  if (vid_st) {
1408  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name,
1409  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup);
1410  }
1411  }
1412  }
1413 fail:
1414  if (ret >=0)
1415  hls->master_m3u8_created = 1;
1416  hlsenc_io_close(s, &hls->m3u8_out, temp_filename);
1417  if (use_temp_file)
1418  ff_rename(temp_filename, hls->master_m3u8_url, s);
1419 
1420  return ret;
1421 }
1422 
1423 static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
1424 {
1425  HLSContext *hls = s->priv_data;
1426  HLSSegment *en;
1427  int target_duration = 0;
1428  int ret = 0;
1429  char temp_filename[MAX_URL_SIZE];
1430  char temp_vtt_filename[MAX_URL_SIZE];
1431  int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries);
1432  const char *proto = avio_find_protocol_name(vs->m3u8_name);
1433  int is_file_proto = proto && !strcmp(proto, "file");
1434  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || !(hls->pl_type == PLAYLIST_TYPE_VOD));
1435  static unsigned warned_non_file;
1436  char *key_uri = NULL;
1437  char *iv_string = NULL;
1439  double prog_date_time = vs->initial_prog_date_time;
1440  double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? &prog_date_time : NULL;
1441  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1442 
1443  hls->version = 3;
1444  if (byterange_mode) {
1445  hls->version = 4;
1446  sequence = 0;
1447  }
1448 
1449  if (hls->flags & HLS_INDEPENDENT_SEGMENTS) {
1450  hls->version = 6;
1451  }
1452 
1453  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1454  hls->version = 7;
1455  }
1456 
1457  if (!is_file_proto && (hls->flags & HLS_TEMP_FILE) && !warned_non_file++)
1458  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
1459 
1460  set_http_options(s, &options, hls);
1461  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", vs->m3u8_name);
1462  if ((ret = hlsenc_io_open(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename, &options)) < 0) {
1463  if (hls->ignore_io_errors)
1464  ret = 0;
1465  goto fail;
1466  }
1467 
1468  for (en = vs->segments; en; en = en->next) {
1469  if (target_duration <= en->duration)
1470  target_duration = lrint(en->duration);
1471  }
1472 
1473  vs->discontinuity_set = 0;
1474  ff_hls_write_playlist_header(byterange_mode ? hls->m3u8_out : vs->out, hls->version, hls->allowcache,
1475  target_duration, sequence, hls->pl_type, hls->flags & HLS_I_FRAMES_ONLY);
1476 
1477  if ((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0 ) {
1478  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-DISCONTINUITY\n");
1479  vs->discontinuity_set = 1;
1480  }
1481  if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
1482  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
1483  }
1484  for (en = vs->segments; en; en = en->next) {
1485  if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) ||
1486  av_strcasecmp(en->iv_string, iv_string))) {
1487  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri);
1488  if (*en->iv_string)
1489  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, ",IV=0x%s", en->iv_string);
1490  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "\n");
1491  key_uri = en->key_uri;
1492  iv_string = en->iv_string;
1493  }
1494 
1495  if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) {
1496  ff_hls_write_init_file(byterange_mode ? hls->m3u8_out : vs->out, (hls->flags & HLS_SINGLE_FILE) ? en->filename : vs->fmp4_init_filename,
1497  hls->flags & HLS_SINGLE_FILE, vs->init_range_length, 0);
1498  }
1499 
1500  ret = ff_hls_write_file_entry(byterange_mode ? hls->m3u8_out : vs->out, en->discont, byterange_mode,
1501  en->duration, hls->flags & HLS_ROUND_DURATIONS,
1502  en->size, en->pos, vs->baseurl,
1503  en->filename, prog_date_time_p, en->keyframe_size, en->keyframe_pos, hls->flags & HLS_I_FRAMES_ONLY);
1504  if (ret < 0) {
1505  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1506  }
1507  }
1508 
1509  if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
1510  ff_hls_write_end_list(byterange_mode ? hls->m3u8_out : vs->out);
1511 
1512  if (vs->vtt_m3u8_name) {
1513  snprintf(temp_vtt_filename, sizeof(temp_vtt_filename), use_temp_file ? "%s.tmp" : "%s", vs->vtt_m3u8_name);
1514  if ((ret = hlsenc_io_open(s, &hls->sub_m3u8_out, temp_vtt_filename, &options)) < 0) {
1515  if (hls->ignore_io_errors)
1516  ret = 0;
1517  goto fail;
1518  }
1520  target_duration, sequence, PLAYLIST_TYPE_NONE, 0);
1521  for (en = vs->segments; en; en = en->next) {
1522  ret = ff_hls_write_file_entry(hls->sub_m3u8_out, 0, byterange_mode,
1523  en->duration, 0, en->size, en->pos,
1524  vs->baseurl, en->sub_filename, NULL, 0, 0, 0);
1525  if (ret < 0) {
1526  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1527  }
1528  }
1529 
1530  if (last)
1532 
1533  }
1534 
1535 fail:
1536  av_dict_free(&options);
1537  ret = hlsenc_io_close(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename);
1538  if (ret < 0) {
1539  return ret;
1540  }
1542  if (use_temp_file) {
1543  ff_rename(temp_filename, vs->m3u8_name, s);
1544  if (vs->vtt_m3u8_name)
1545  ff_rename(temp_vtt_filename, vs->vtt_m3u8_name, s);
1546  }
1547  if (ret >= 0 && hls->master_pl_name)
1548  if (create_master_playlist(s, vs) < 0)
1549  av_log(s, AV_LOG_WARNING, "Master playlist creation failed\n");
1550 
1551  return ret;
1552 }
1553 
1555 {
1556  HLSContext *c = s->priv_data;
1557  AVFormatContext *oc = vs->avf;
1558  AVFormatContext *vtt_oc = vs->vtt_avf;
1560  const char *proto = NULL;
1561  int use_temp_file = 0;
1562  char iv_string[KEYSIZE*2 + 1];
1563  int err = 0;
1564 
1565  if (c->flags & HLS_SINGLE_FILE) {
1566  char *new_name = av_strdup(vs->basename);
1567  if (!new_name)
1568  return AVERROR(ENOMEM);
1569  ff_format_set_url(oc, new_name);
1570  if (vs->vtt_basename) {
1571  new_name = av_strdup(vs->vtt_basename);
1572  if (!new_name)
1573  return AVERROR(ENOMEM);
1574  ff_format_set_url(vtt_oc, new_name);
1575  }
1576  } else if (c->max_seg_size > 0) {
1577  char *filename = NULL;
1578  if (replace_int_data_in_filename(&filename,
1579 #if FF_API_HLS_WRAP
1580  vs->basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) {
1581 #else
1582  vs->basename, 'd', vs->sequence) < 1) {
1583 #endif
1584  av_freep(&filename);
1585  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -strftime 1 with it\n", vs->basename);
1586  return AVERROR(EINVAL);
1587  }
1588  ff_format_set_url(oc, filename);
1589  } else {
1590  if (c->use_localtime) {
1591  time_t now0;
1592  struct tm *tm, tmpbuf;
1593  int bufsize = strlen(vs->basename) + MAX_URL_SIZE;
1594  char *buf = av_mallocz(bufsize);
1595  if (!buf)
1596  return AVERROR(ENOMEM);
1597  time(&now0);
1598  tm = localtime_r(&now0, &tmpbuf);
1599  ff_format_set_url(oc, buf);
1600  if (!strftime(oc->url, bufsize, vs->basename, tm)) {
1601  av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
1602  return AVERROR(EINVAL);
1603  }
1604 
1605  err = sls_flag_use_localtime_filename(oc, c, vs);
1606  if (err < 0) {
1607  return AVERROR(ENOMEM);
1608  }
1609 
1610  if (c->use_localtime_mkdir) {
1611  const char *dir;
1612  char *fn_copy = av_strdup(oc->url);
1613  dir = av_dirname(fn_copy);
1614  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1615  av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
1616  av_freep(&fn_copy);
1617  return AVERROR(errno);
1618  }
1619  av_freep(&fn_copy);
1620  }
1621  } else {
1622  char *filename = NULL;
1623  if (replace_int_data_in_filename(&filename,
1624 #if FF_API_HLS_WRAP
1625  vs->basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) {
1626 #else
1627  vs->basename, 'd', vs->sequence) < 1) {
1628 #endif
1629  av_freep(&filename);
1630  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -strftime 1 with it\n", vs->basename);
1631  return AVERROR(EINVAL);
1632  }
1633  ff_format_set_url(oc, filename);
1634  }
1635  if ( vs->vtt_basename) {
1636  char *filename = NULL;
1637  if (replace_int_data_in_filename(&filename,
1638 #if FF_API_HLS_WRAP
1639  vs->vtt_basename, 'd', c->wrap ? vs->sequence % c->wrap : vs->sequence) < 1) {
1640 #else
1641  vs->vtt_basename, 'd', vs->sequence) < 1) {
1642 #endif
1643  av_freep(&filename);
1644  av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename);
1645  return AVERROR(EINVAL);
1646  }
1647  ff_format_set_url(vtt_oc, filename);
1648  }
1649  }
1650  vs->number++;
1651 
1652  set_http_options(s, &options, c);
1653 
1654  proto = avio_find_protocol_name(oc->url);
1655  use_temp_file = proto && !strcmp(proto, "file") && (c->flags & HLS_TEMP_FILE);
1656 
1657  if (use_temp_file) {
1658  char *new_name = av_asprintf("%s.tmp", oc->url);
1659  if (!new_name)
1660  return AVERROR(ENOMEM);
1661  ff_format_set_url(oc, new_name);
1662  }
1663 
1664  if (c->key_info_file || c->encrypt) {
1665  if (c->segment_type == SEGMENT_TYPE_FMP4) {
1666  av_log(s, AV_LOG_ERROR, "Encrypted fmp4 not yet supported\n");
1667  return AVERROR_PATCHWELCOME;
1668  }
1669 
1670  if (c->key_info_file && c->encrypt) {
1671  av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file and -hls_enc,"
1672  " ignoring -hls_enc\n");
1673  }
1674 
1675  if (!c->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) {
1676  if (c->key_info_file) {
1677  if ((err = hls_encryption_start(s)) < 0)
1678  goto fail;
1679  } else {
1680  if ((err = do_encrypt(s, vs)) < 0)
1681  goto fail;
1682  }
1683  c->encrypt_started = 1;
1684  }
1685  err = av_strlcpy(iv_string, c->iv_string, sizeof(iv_string));
1686  if (!err) {
1687  snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, vs->sequence);
1688  memset(c->iv_string, 0, sizeof(c->iv_string));
1689  memcpy(c->iv_string, iv_string, sizeof(iv_string));
1690  }
1691  }
1692  if (c->segment_type != SEGMENT_TYPE_FMP4) {
1693  /* We only require one PAT/PMT per segment. */
1694  if (oc->oformat->priv_class && oc->priv_data) {
1695  char period[21];
1696 
1697  snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1);
1698 
1699  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
1700  av_opt_set(oc->priv_data, "sdt_period", period, 0);
1701  av_opt_set(oc->priv_data, "pat_period", period, 0);
1702  }
1703  if (c->flags & HLS_SINGLE_FILE) {
1704  if ((err = hlsenc_io_open(s, &vs->out, oc->url, &options)) < 0) {
1705  if (c->ignore_io_errors)
1706  err = 0;
1707  goto fail;
1708  }
1709  }
1710  }
1711  if (vs->vtt_basename) {
1712  set_http_options(s, &options, c);
1713  if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < 0) {
1714  if (c->ignore_io_errors)
1715  err = 0;
1716  goto fail;
1717  }
1718  }
1719  av_dict_free(&options);
1720 
1721  if (vs->vtt_basename) {
1722  err = avformat_write_header(vtt_oc,NULL);
1723  if (err < 0)
1724  return err;
1725  }
1726 
1727  return 0;
1728 fail:
1729  av_dict_free(&options);
1730 
1731  return err;
1732 }
1733 
1735 {
1736  char b[21];
1737  time_t t = time(NULL);
1738  struct tm *p, tmbuf;
1739  HLSContext *hls = s->priv_data;
1740 
1741  p = localtime_r(&t, &tmbuf);
1742  // no %s support when strftime returned error or left format string unchanged
1743  // also no %s support on MSVC, which invokes the invalid parameter handler on unsupported format strings, instead of returning an error
1744  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1745  return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.m4s" : "-%s.m4s";
1746  }
1747  return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.ts" : "-%s.ts";
1748 }
1749 
1750 static int append_postfix(char *name, int name_buf_len, int i)
1751 {
1752  char *p;
1753  char extension[10] = {'\0'};
1754 
1755  p = strrchr(name, '.');
1756  if (p) {
1757  av_strlcpy(extension, p, sizeof(extension));
1758  *p = '\0';
1759  }
1760 
1761  snprintf(name + strlen(name), name_buf_len - strlen(name), POSTFIX_PATTERN, i);
1762 
1763  if (strlen(extension))
1764  av_strlcat(name, extension, name_buf_len);
1765 
1766  return 0;
1767 }
1768 
1769 static int validate_name(int nb_vs, const char *fn)
1770 {
1771  const char *filename, *subdir_name;
1772  char *fn_dup = NULL;
1773  int ret = 0;
1774 
1775  if (!fn) {
1776  ret = AVERROR(EINVAL);
1777  goto fail;
1778  }
1779 
1780  fn_dup = av_strdup(fn);
1781  filename = av_basename(fn);
1782  subdir_name = av_dirname(fn_dup);
1783 
1784  if (nb_vs > 1 && !av_stristr(filename, "%v") && !av_stristr(subdir_name, "%v")) {
1785  av_log(NULL, AV_LOG_ERROR, "More than 1 variant streams are present, %%v is expected "
1786  "either in the filename or in the sub-directory name of file %s\n", fn);
1787  ret = AVERROR(EINVAL);
1788  goto fail;
1789  }
1790 
1791  if (av_stristr(filename, "%v") && av_stristr(subdir_name, "%v")) {
1792  av_log(NULL, AV_LOG_ERROR, "%%v is expected either in the filename or "
1793  "in the sub-directory name of file %s, but only in one of them\n", fn);
1794  ret = AVERROR(EINVAL);
1795  goto fail;
1796  }
1797 
1798 fail:
1799  av_freep(&fn_dup);
1800  return ret;
1801 }
1802 
1803 static int format_name(const char *buf, char **s, int index, const char *varname)
1804 {
1805  const char *proto, *dir;
1806  char *orig_buf_dup = NULL, *mod_buf_dup = NULL;
1807  int ret = 0;
1808 
1809  orig_buf_dup = av_strdup(buf);
1810  if (!orig_buf_dup) {
1811  ret = AVERROR(ENOMEM);
1812  goto fail;
1813  }
1814 
1815  if (!av_stristr(buf, "%v")) {
1816  *s = orig_buf_dup;
1817  return ret;
1818  }
1819 
1820  if (!varname) {
1821  if (replace_int_data_in_filename(s, orig_buf_dup, 'v', index) < 1) {
1822  ret = AVERROR(EINVAL);
1823  goto fail;
1824  }
1825  } else {
1826  if (replace_str_data_in_filename(s, orig_buf_dup, 'v', varname) < 1) {
1827  ret = AVERROR(EINVAL);
1828  goto fail;
1829  }
1830  }
1831 
1832  proto = avio_find_protocol_name(orig_buf_dup);
1833  dir = av_dirname(orig_buf_dup);
1834 
1835  /* if %v is present in the file's directory, create sub-directory */
1836  if (av_stristr(dir, "%v") && proto && !strcmp(proto, "file")) {
1837  mod_buf_dup = av_strdup(*s);
1838  dir = av_dirname(mod_buf_dup);
1839  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1840  ret = AVERROR(errno);
1841  goto fail;
1842  }
1843  }
1844 
1845 fail:
1846  av_freep(&orig_buf_dup);
1847  av_freep(&mod_buf_dup);
1848  return ret;
1849 }
1850 
1852  enum AVMediaType codec_type,
1853  int stream_id)
1854 {
1855  unsigned int stream_index, cnt;
1856  if (stream_id < 0 || stream_id > s->nb_streams - 1)
1857  return -1;
1858  cnt = 0;
1859  for (stream_index = 0; stream_index < s->nb_streams; stream_index++) {
1860  if (s->streams[stream_index]->codecpar->codec_type != codec_type)
1861  continue;
1862  if (cnt == stream_id)
1863  return stream_index;
1864  cnt++;
1865  }
1866  return -1;
1867 }
1868 
1870 {
1871  HLSContext *hls = s->priv_data;
1872  VariantStream *vs;
1873  int stream_index, i, j;
1874  enum AVMediaType codec_type;
1875  int nb_varstreams, nb_streams;
1876  char *p, *q, *saveptr1, *saveptr2, *varstr, *keyval;
1877  const char *val;
1878 
1879  /**
1880  * Expected format for var_stream_map string is as below:
1881  * "a:0,v:0 a:1,v:1"
1882  * "a:0,agroup:a0,default:1,language:ENG a:1,agroup:a1,default:0 v:0,agroup:a0 v:1,agroup:a1"
1883  * This string specifies how to group the audio, video and subtitle streams
1884  * into different variant streams. The variant stream groups are separated
1885  * by space.
1886  *
1887  * a:, v:, s: are keys to specify audio, video and subtitle streams
1888  * respectively. Allowed values are 0 to 9 digits (limited just based on
1889  * practical usage)
1890  *
1891  * agroup: is key to specify audio group. A string can be given as value.
1892  */
1893  p = av_strdup(hls->var_stream_map);
1894  if (!p)
1895  return AVERROR(ENOMEM);
1896 
1897  q = p;
1898  while (av_strtok(q, " \t", &saveptr1)) {
1899  q = NULL;
1900  hls->nb_varstreams++;
1901  }
1902  av_freep(&p);
1903 
1904  hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * hls->nb_varstreams);
1905  if (!hls->var_streams)
1906  return AVERROR(ENOMEM);
1907 
1908  p = hls->var_stream_map;
1909  nb_varstreams = 0;
1910  while (varstr = av_strtok(p, " \t", &saveptr1)) {
1911  p = NULL;
1912 
1913  if (nb_varstreams < hls->nb_varstreams) {
1914  vs = &(hls->var_streams[nb_varstreams]);
1915  vs->var_stream_idx = nb_varstreams;
1916  vs->is_default = 0;
1917  nb_varstreams++;
1918  } else
1919  return AVERROR(EINVAL);
1920 
1921  q = varstr;
1922  while (q < varstr + strlen(varstr)) {
1923  if (!av_strncasecmp(q, "a:", 2) || !av_strncasecmp(q, "v:", 2) ||
1924  !av_strncasecmp(q, "s:", 2))
1925  vs->nb_streams++;
1926  q++;
1927  }
1928  vs->streams = av_mallocz(sizeof(AVStream *) * vs->nb_streams);
1929  if (!vs->streams)
1930  return AVERROR(ENOMEM);
1931 
1932  nb_streams = 0;
1933  while (keyval = av_strtok(varstr, ",", &saveptr2)) {
1934  varstr = NULL;
1935  if (av_strstart(keyval, "language:", &val)) {
1936  vs->language = av_strdup(val);
1937  if (!vs->language)
1938  return AVERROR(ENOMEM);
1939  continue;
1940  } else if (av_strstart(keyval, "default:", &val)) {
1941  vs->is_default = (!av_strncasecmp(val, "YES", strlen("YES")) ||
1942  (!av_strncasecmp(val, "1", strlen("1"))));
1943  hls->has_default_key = 1;
1944  continue;
1945  } else if (av_strstart(keyval, "name:", &val)) {
1946  vs->varname = av_strdup(val);
1947  if (!vs->varname)
1948  return AVERROR(ENOMEM);
1949  continue;
1950  } else if (av_strstart(keyval, "agroup:", &val)) {
1951  vs->agroup = av_strdup(val);
1952  if (!vs->agroup)
1953  return AVERROR(ENOMEM);
1954  continue;
1955  } else if (av_strstart(keyval, "ccgroup:", &val)) {
1956  vs->ccgroup = av_strdup(val);
1957  if (!vs->ccgroup)
1958  return AVERROR(ENOMEM);
1959  continue;
1960  } else if (av_strstart(keyval, "v:", &val)) {
1961  codec_type = AVMEDIA_TYPE_VIDEO;
1962  hls->has_video_m3u8 = 1;
1963  } else if (av_strstart(keyval, "a:", &val)) {
1964  codec_type = AVMEDIA_TYPE_AUDIO;
1965  } else if (av_strstart(keyval, "s:", &val)) {
1966  codec_type = AVMEDIA_TYPE_SUBTITLE;
1967  } else {
1968  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
1969  return AVERROR(EINVAL);
1970  }
1971 
1972  stream_index = -1;
1973  if (av_isdigit(*val))
1974  stream_index = get_nth_codec_stream_index (s, codec_type,
1975  atoi(val));
1976 
1977  if (stream_index >= 0 && nb_streams < vs->nb_streams) {
1978  for (i = 0; nb_streams > 0 && i < nb_streams; i++) {
1979  if (vs->streams[i] == s->streams[stream_index]) {
1980  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once inside "
1981  "variant definition #%d\n", nb_varstreams - 1);
1982  return AVERROR(EINVAL);
1983  }
1984  }
1985  for (j = 0; nb_varstreams > 1 && j < nb_varstreams - 1; j++) {
1986  for (i = 0; i < hls->var_streams[j].nb_streams; i++) {
1987  if (hls->var_streams[j].streams[i] == s->streams[stream_index]) {
1988  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once "
1989  "in two different variant definitions #%d and #%d\n",
1990  j, nb_varstreams - 1);
1991  return AVERROR(EINVAL);
1992  }
1993  }
1994  }
1995  vs->streams[nb_streams++] = s->streams[stream_index];
1996  } else {
1997  av_log(s, AV_LOG_ERROR, "Unable to map stream at %s\n", keyval);
1998  return AVERROR(EINVAL);
1999  }
2000  }
2001  }
2002  av_log(s, AV_LOG_DEBUG, "Number of variant streams %d\n",
2003  hls->nb_varstreams);
2004 
2005  return 0;
2006 }
2007 
2009 {
2010  HLSContext *hls = s->priv_data;
2011  int nb_ccstreams;
2012  char *p, *q, *ccstr, *keyval;
2013  char *saveptr1 = NULL, *saveptr2 = NULL;
2014  const char *val;
2015  ClosedCaptionsStream *ccs;
2016 
2017  p = av_strdup(hls->cc_stream_map);
2018  if(!p)
2019  return AVERROR(ENOMEM);
2020 
2021  q = p;
2022  while (av_strtok(q, " \t", &saveptr1)) {
2023  q = NULL;
2024  hls->nb_ccstreams++;
2025  }
2026  av_freep(&p);
2027 
2028  hls->cc_streams = av_mallocz(sizeof(*hls->cc_streams) * hls->nb_ccstreams);
2029  if (!hls->cc_streams)
2030  return AVERROR(ENOMEM);
2031 
2032  p = hls->cc_stream_map;
2033  nb_ccstreams = 0;
2034  while (ccstr = av_strtok(p, " \t", &saveptr1)) {
2035  p = NULL;
2036 
2037  if (nb_ccstreams < hls->nb_ccstreams)
2038  ccs = &(hls->cc_streams[nb_ccstreams++]);
2039  else
2040  return AVERROR(EINVAL);
2041 
2042  while (keyval = av_strtok(ccstr, ",", &saveptr2)) {
2043  ccstr = NULL;
2044 
2045  if (av_strstart(keyval, "ccgroup:", &val)) {
2046  ccs->ccgroup = av_strdup(val);
2047  if (!ccs->ccgroup)
2048  return AVERROR(ENOMEM);
2049  } else if (av_strstart(keyval, "instreamid:", &val)) {
2050  ccs->instreamid = av_strdup(val);
2051  if (!ccs->instreamid)
2052  return AVERROR(ENOMEM);
2053  } else if (av_strstart(keyval, "language:", &val)) {
2054  ccs->language = av_strdup(val);
2055  if (!ccs->language)
2056  return AVERROR(ENOMEM);
2057  } else {
2058  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2059  return AVERROR(EINVAL);
2060  }
2061  }
2062 
2063  if (!ccs->ccgroup || !ccs->instreamid) {
2064  av_log(s, AV_LOG_ERROR, "Insufficient parameters in cc stream map string\n");
2065  return AVERROR(EINVAL);
2066  }
2067 
2068  if (av_strstart(ccs->instreamid, "CC", &val)) {
2069  if (atoi(val) < 1 || atoi(val) > 4) {
2070  av_log(s, AV_LOG_ERROR, "Invalid instream ID CC index %d in %s, range 1-4\n",
2071  atoi(val), ccs->instreamid);
2072  return AVERROR(EINVAL);
2073  }
2074  } else if (av_strstart(ccs->instreamid, "SERVICE", &val)) {
2075  if (atoi(val) < 1 || atoi(val) > 63) {
2076  av_log(s, AV_LOG_ERROR, "Invalid instream ID SERVICE index %d in %s, range 1-63 \n",
2077  atoi(val), ccs->instreamid);
2078  return AVERROR(EINVAL);
2079  }
2080  } else {
2081  av_log(s, AV_LOG_ERROR, "Invalid instream ID %s, supported are CCn or SERIVICEn\n",
2082  ccs->instreamid);
2083  return AVERROR(EINVAL);
2084  }
2085  }
2086 
2087  return 0;
2088 }
2089 
2091 {
2092  HLSContext *hls = s->priv_data;
2093  unsigned int i;
2094  int ret = 0;
2095 
2096  if (hls->cc_stream_map) {
2097  ret = parse_cc_stream_mapstring(s);
2098  if (ret < 0)
2099  return ret;
2100  }
2101 
2102  if (hls->var_stream_map) {
2104  } else {
2105  //By default, a single variant stream with all the codec streams is created
2106  hls->nb_varstreams = 1;
2107  hls->var_streams = av_mallocz(sizeof(*hls->var_streams) *
2108  hls->nb_varstreams);
2109  if (!hls->var_streams)
2110  return AVERROR(ENOMEM);
2111 
2112  hls->var_streams[0].var_stream_idx = 0;
2113  hls->var_streams[0].nb_streams = s->nb_streams;
2114  hls->var_streams[0].streams = av_mallocz(sizeof(AVStream *) *
2115  hls->var_streams[0].nb_streams);
2116  if (!hls->var_streams[0].streams) {
2117  av_freep(&hls->var_streams);
2118  return AVERROR(ENOMEM);
2119  }
2120 
2121  //by default, the first available ccgroup is mapped to the variant stream
2122  if (hls->nb_ccstreams) {
2123  hls->var_streams[0].ccgroup = av_strdup(hls->cc_streams[0].ccgroup);
2124  if (!hls->var_streams[0].ccgroup) {
2125  av_freep(&hls->var_streams);
2126  return AVERROR(ENOMEM);
2127  }
2128  }
2129 
2130  for (i = 0; i < s->nb_streams; i++)
2131  hls->var_streams[0].streams[i] = s->streams[i];
2132  }
2133  return 0;
2134 }
2135 
2137 {
2138  HLSContext *hls = s->priv_data;
2139  const char *dir;
2140  char *fn1= NULL, *fn2 = NULL;
2141  int ret = 0;
2142 
2143  fn1 = av_strdup(s->url);
2144  dir = av_dirname(fn1);
2145 
2146  /**
2147  * if output file's directory has %v, variants are created in sub-directories
2148  * then master is created at the sub-directories level
2149  */
2150  if (dir && av_stristr(av_basename(dir), "%v")) {
2151  fn2 = av_strdup(dir);
2152  dir = av_dirname(fn2);
2153  }
2154 
2155  if (dir && strcmp(dir, "."))
2157  else
2159 
2160  if (!hls->master_m3u8_url) {
2161  ret = AVERROR(ENOMEM);
2162  goto fail;
2163  }
2164 
2165 fail:
2166  av_freep(&fn1);
2167  av_freep(&fn2);
2168 
2169  return ret;
2170 }
2171 
2173 {
2174  HLSContext *hls = s->priv_data;
2175  int ret, i, j;
2176  VariantStream *vs = NULL;
2177 
2178  for (i = 0; i < hls->nb_varstreams; i++) {
2179  vs = &hls->var_streams[i];
2180 
2181  ret = avformat_write_header(vs->avf, NULL);
2182  if (ret < 0)
2183  return ret;
2184  //av_assert0(s->nb_streams == hls->avf->nb_streams);
2185  for (j = 0; j < vs->nb_streams; j++) {
2186  AVStream *inner_st;
2187  AVStream *outer_st = vs->streams[j];
2188 
2189  if (hls->max_seg_size > 0) {
2190  if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
2191  (outer_st->codecpar->bit_rate > hls->max_seg_size)) {
2192  av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, "
2193  "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.",
2194  outer_st->codecpar->bit_rate, hls->max_seg_size);
2195  }
2196  }
2197 
2198  if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
2199  inner_st = vs->avf->streams[j];
2200  else if (vs->vtt_avf)
2201  inner_st = vs->vtt_avf->streams[0];
2202  else {
2203  /* We have a subtitle stream, when the user does not want one */
2204  inner_st = NULL;
2205  continue;
2206  }
2207  avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
2208  write_codec_attr(outer_st, vs);
2209 
2210  }
2211  /* Update the Codec Attr string for the mapped audio groups */
2212  if (vs->has_video && vs->agroup) {
2213  for (j = 0; j < hls->nb_varstreams; j++) {
2214  VariantStream *vs_agroup = &(hls->var_streams[j]);
2215  if (!vs_agroup->has_video && !vs_agroup->has_subtitle &&
2216  vs_agroup->agroup &&
2217  !av_strcasecmp(vs_agroup->agroup, vs->agroup)) {
2218  write_codec_attr(vs_agroup->streams[0], vs);
2219  }
2220  }
2221  }
2222  }
2223 
2224  return ret;
2225 }
2226 
2228 {
2229  HLSContext *hls = s->priv_data;
2230  AVFormatContext *oc = NULL;
2231  AVStream *st = s->streams[pkt->stream_index];
2232  int64_t end_pts = 0;
2233  int is_ref_pkt = 1;
2234  int ret = 0, can_split = 1, i, j;
2235  int stream_index = 0;
2236  int range_length = 0;
2237  const char *proto = NULL;
2238  int use_temp_file = 0;
2239  uint8_t *buffer = NULL;
2240  VariantStream *vs = NULL;
2241  AVDictionary *options = NULL;
2242  char *old_filename = NULL;
2243 
2244  for (i = 0; i < hls->nb_varstreams; i++) {
2245  vs = &hls->var_streams[i];
2246  for (j = 0; j < vs->nb_streams; j++) {
2247  if (vs->streams[j] == st) {
2248  if ( st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
2249  oc = vs->vtt_avf;
2250  stream_index = 0;
2251  } else {
2252  oc = vs->avf;
2253  stream_index = j;
2254  }
2255  break;
2256  }
2257  }
2258 
2259  if (oc)
2260  break;
2261  }
2262 
2263  if (!oc) {
2264  av_log(s, AV_LOG_ERROR, "Unable to find mapping variant stream\n");
2265  return AVERROR(ENOMEM);
2266  }
2267 
2268  end_pts = hls->recording_time * vs->number;
2269 
2270  if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
2271  /* reset end_pts, hls->recording_time at end of the init hls list */
2272  int64_t init_list_dur = hls->init_time * vs->nb_entries * AV_TIME_BASE;
2273  int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries ) * (hls->time * AV_TIME_BASE);
2274  hls->recording_time = hls->time * AV_TIME_BASE;
2275  end_pts = init_list_dur + after_init_list_dur ;
2276  }
2277 
2278  if (vs->start_pts == AV_NOPTS_VALUE) {
2279  vs->start_pts = pkt->pts;
2280  }
2281 
2282  if (vs->has_video) {
2283  can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
2284  ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME));
2285  is_ref_pkt = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->stream_index == vs->reference_stream_index);
2286  }
2287  if (pkt->pts == AV_NOPTS_VALUE)
2288  is_ref_pkt = can_split = 0;
2289 
2290  if (is_ref_pkt) {
2291  if (vs->end_pts == AV_NOPTS_VALUE)
2292  vs->end_pts = pkt->pts;
2293  if (vs->new_start) {
2294  vs->new_start = 0;
2295  vs->duration = (double)(pkt->pts - vs->end_pts)
2296  * st->time_base.num / st->time_base.den;
2297  vs->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2298  } else {
2299  if (pkt->duration) {
2300  vs->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2301  } else {
2302  av_log(s, AV_LOG_WARNING, "pkt->duration = 0, maybe the hls segment duration will not precise\n");
2303  vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2304  }
2305  }
2306 
2307  }
2308 
2309  if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base,
2310  end_pts, AV_TIME_BASE_Q) >= 0) {
2311  int64_t new_start_pos;
2312  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2313 
2314  av_write_frame(oc, NULL); /* Flush any buffered data */
2315  new_start_pos = avio_tell(oc->pb);
2316  vs->size = new_start_pos - vs->start_pos;
2317  avio_flush(oc->pb);
2318  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2319  if (!vs->init_range_length) {
2320  range_length = avio_close_dyn_buf(oc->pb, &buffer);
2321  avio_write(vs->out, buffer, range_length);
2322  av_freep(&buffer);
2323  vs->init_range_length = range_length;
2324  avio_open_dyn_buf(&oc->pb);
2325  vs->packets_written = 0;
2326  vs->start_pos = range_length;
2327  if (!byterange_mode) {
2328  hlsenc_io_close(s, &vs->out, vs->base_output_dirname);
2329  }
2330  }
2331  }
2332  if (!byterange_mode) {
2333  if (vs->vtt_avf) {
2334  hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url);
2335  }
2336  }
2337 
2338  if (oc->url[0]) {
2339  proto = avio_find_protocol_name(oc->url);
2340  use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & HLS_TEMP_FILE);
2341  }
2342 
2343  // look to rename the asset name
2344  if (use_temp_file) {
2345  av_dict_set(&options, "mpegts_flags", "resend_headers", 0);
2346  }
2347 
2348  if (hls->flags & HLS_SINGLE_FILE) {
2349  ret = flush_dynbuf(vs, &range_length);
2350  av_freep(&vs->temp_buffer);
2351  if (ret < 0) {
2352  return ret;
2353  }
2354  vs->size = range_length;
2355  } else {
2356  set_http_options(s, &options, hls);
2357  if ((hls->max_seg_size > 0 && (vs->size >= hls->max_seg_size)) || !byterange_mode) {
2358  char *filename = NULL;
2359  if (hls->key_info_file || hls->encrypt) {
2360  av_dict_set(&options, "encryption_key", hls->key_string, 0);
2361  av_dict_set(&options, "encryption_iv", hls->iv_string, 0);
2362  filename = av_asprintf("crypto:%s", oc->url);
2363  } else {
2364  filename = av_asprintf("%s", oc->url);
2365  }
2366  if (!filename) {
2367  return AVERROR(ENOMEM);
2368  }
2369  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2370  if (ret < 0) {
2372  "Failed to open file '%s'\n", filename);
2373  return hls->ignore_io_errors ? 0 : ret;
2374  }
2375  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2376  write_styp(vs->out);
2377  }
2378  ret = flush_dynbuf(vs, &range_length);
2379  if (ret < 0) {
2380  return ret;
2381  }
2382  ret = hlsenc_io_close(s, &vs->out, filename);
2383  if (ret < 0) {
2384  av_log(s, AV_LOG_WARNING, "upload segment failed,"
2385  " will retry with a new http session.\n");
2386  ff_format_io_close(s, &vs->out);
2387  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2388  reflush_dynbuf(vs, &range_length);
2389  ret = hlsenc_io_close(s, &vs->out, filename);
2390  }
2391  av_freep(&vs->temp_buffer);
2392  av_freep(&filename);
2393  }
2394  }
2395 
2396  if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) {
2397  hls_rename_temp_file(s, oc);
2398  }
2399 
2400  old_filename = av_strdup(oc->url);
2401  if (!old_filename) {
2402  return AVERROR(ENOMEM);
2403  }
2404 
2405  if (vs->start_pos || hls->segment_type != SEGMENT_TYPE_FMP4) {
2406  ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size);
2407  vs->end_pts = pkt->pts;
2408  vs->duration = 0;
2409  if (ret < 0) {
2410  av_freep(&old_filename);
2411  return ret;
2412  }
2413  }
2414 
2415  // if we're building a VOD playlist, skip writing the manifest multiple times, and just wait until the end
2416  if (hls->pl_type != PLAYLIST_TYPE_VOD) {
2417  if ((ret = hls_window(s, 0, vs)) < 0) {
2418  av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2419  ff_format_io_close(s, &vs->out);
2420  vs->out = NULL;
2421  if ((ret = hls_window(s, 0, vs)) < 0) {
2422  av_freep(&old_filename);
2423  return ret;
2424  }
2425  }
2426  }
2427 
2428  if (hls->flags & HLS_SINGLE_FILE) {
2429  vs->number++;
2430  vs->start_pos += vs->size;
2431  } else if (hls->max_seg_size > 0) {
2432  vs->start_pos = new_start_pos;
2433  if (vs->size >= hls->max_seg_size) {
2434  vs->sequence++;
2435  sls_flag_file_rename(hls, vs, old_filename);
2436  ret = hls_start(s, vs);
2437  vs->start_pos = 0;
2438  /* When split segment by byte, the duration is short than hls_time,
2439  * so it is not enough one segment duration as hls_time, */
2440  vs->number--;
2441  }
2442  vs->number++;
2443  } else {
2444  vs->start_pos = new_start_pos;
2445  sls_flag_file_rename(hls, vs, old_filename);
2446  ret = hls_start(s, vs);
2447  }
2448  av_freep(&old_filename);
2449 
2450  if (ret < 0) {
2451  return ret;
2452  }
2453 
2454  }
2455 
2456  vs->packets_written++;
2457  if (oc->pb) {
2458  ret = ff_write_chained(oc, stream_index, pkt, s, 0);
2459  vs->video_keyframe_size += pkt->size;
2460  if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->flags & AV_PKT_FLAG_KEY)) {
2461  vs->video_keyframe_size = avio_tell(oc->pb);
2462  } else {
2463  vs->video_keyframe_pos = avio_tell(vs->out);
2464  }
2465  if (hls->ignore_io_errors)
2466  ret = 0;
2467  }
2468 
2469  return ret;
2470 }
2471 
2472 static void hls_free_variant_streams(struct HLSContext *hls)
2473 {
2474  int i = 0;
2475  AVFormatContext *vtt_oc = NULL;
2476  VariantStream *vs = NULL;
2477 
2478  for (i = 0; i < hls->nb_varstreams; i++) {
2479  vs = &hls->var_streams[i];
2480  vtt_oc = vs->vtt_avf;
2481 
2482  av_freep(&vs->basename);
2485  if (vtt_oc) {
2486  av_freep(&vs->vtt_basename);
2487  av_freep(&vs->vtt_m3u8_name);
2488  }
2489 
2492  av_freep(&vs->m3u8_name);
2493  av_freep(&vs->streams);
2494  av_freep(&vs->agroup);
2495  av_freep(&vs->language);
2496  av_freep(&vs->ccgroup);
2497  av_freep(&vs->baseurl);
2498  av_freep(&vs->varname);
2499  }
2500 }
2501 
2502 static int hls_write_trailer(struct AVFormatContext *s)
2503 {
2504  HLSContext *hls = s->priv_data;
2505  AVFormatContext *oc = NULL;
2506  AVFormatContext *vtt_oc = NULL;
2507  char *old_filename = NULL;
2508  const char *proto = NULL;
2509  int use_temp_file = 0;
2510  int i;
2511  int ret = 0;
2512  VariantStream *vs = NULL;
2513  AVDictionary *options = NULL;
2514  int range_length, byterange_mode;
2515 
2516  for (i = 0; i < hls->nb_varstreams; i++) {
2517  char *filename = NULL;
2518  vs = &hls->var_streams[i];
2519  oc = vs->avf;
2520  vtt_oc = vs->vtt_avf;
2521  old_filename = av_strdup(oc->url);
2522  use_temp_file = 0;
2523 
2524  if (!old_filename) {
2525  return AVERROR(ENOMEM);
2526  }
2527  if (hls->key_info_file || hls->encrypt) {
2528  av_dict_set(&options, "encryption_key", hls->key_string, 0);
2529  av_dict_set(&options, "encryption_iv", hls->iv_string, 0);
2530  filename = av_asprintf("crypto:%s", oc->url);
2531  } else {
2532  filename = av_asprintf("%s", oc->url);
2533  }
2534  if (!filename) {
2535  av_freep(&old_filename);
2536  return AVERROR(ENOMEM);
2537  }
2538 
2539  if ( hls->segment_type == SEGMENT_TYPE_FMP4) {
2540  int range_length = 0;
2541  if (!vs->init_range_length) {
2542  uint8_t *buffer = NULL;
2543  av_write_frame(oc, NULL); /* Flush any buffered data */
2544  avio_flush(oc->pb);
2545 
2546  range_length = avio_close_dyn_buf(oc->pb, &buffer);
2547  avio_write(vs->out, buffer, range_length);
2548  av_freep(&buffer);
2549  vs->init_range_length = range_length;
2550  avio_open_dyn_buf(&oc->pb);
2551  vs->packets_written = 0;
2552  vs->start_pos = range_length;
2553  byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2554  if (!byterange_mode) {
2555  ff_format_io_close(s, &vs->out);
2556  hlsenc_io_close(s, &vs->out, vs->base_output_dirname);
2557  }
2558  }
2559  }
2560  if (!(hls->flags & HLS_SINGLE_FILE)) {
2561  set_http_options(s, &options, hls);
2562  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2563  if (ret < 0) {
2564  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2565  goto failed;
2566  }
2567  if (hls->segment_type == SEGMENT_TYPE_FMP4)
2568  write_styp(vs->out);
2569  }
2570  ret = flush_dynbuf(vs, &range_length);
2571  if (ret < 0)
2572  goto failed;
2573 
2574  vs->size = range_length;
2575  hlsenc_io_close(s, &vs->out, filename);
2576  ret = hlsenc_io_close(s, &vs->out, filename);
2577  if (ret < 0) {
2578  av_log(s, AV_LOG_WARNING, "upload segment failed, will retry with a new http session.\n");
2579  ff_format_io_close(s, &vs->out);
2580  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2581  if (ret < 0) {
2582  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2583  goto failed;
2584  }
2585  reflush_dynbuf(vs, &range_length);
2586  ret = hlsenc_io_close(s, &vs->out, filename);
2587  if (ret < 0)
2588  av_log(s, AV_LOG_WARNING, "Failed to upload file '%s' at the end.\n", oc->url);
2589  }
2590  av_freep(&vs->temp_buffer);
2591 
2592 failed:
2593  av_freep(&filename);
2594  av_write_trailer(oc);
2595  if (oc->url[0]) {
2596  proto = avio_find_protocol_name(oc->url);
2597  use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & HLS_TEMP_FILE);
2598  }
2599 
2600  // rename that segment from .tmp to the real one
2601  if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) {
2602  hls_rename_temp_file(s, oc);
2603  av_freep(&old_filename);
2604  old_filename = av_strdup(oc->url);
2605 
2606  if (!old_filename) {
2607  return AVERROR(ENOMEM);
2608  }
2609  }
2610 
2611  /* after av_write_trailer, then duration + 1 duration per packet */
2612  hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size);
2613 
2614  sls_flag_file_rename(hls, vs, old_filename);
2615 
2616  if (vtt_oc) {
2617  if (vtt_oc->pb)
2618  av_write_trailer(vtt_oc);
2619  vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos;
2620  ff_format_io_close(s, &vtt_oc->pb);
2621  avformat_free_context(vtt_oc);
2622  }
2623  ret = hls_window(s, 1, vs);
2624  if (ret < 0) {
2625  av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2626  ff_format_io_close(s, &vs->out);
2627  hls_window(s, 1, vs);
2628  }
2629  ffio_free_dyn_buf(&oc->pb);
2631 
2632  vs->avf = NULL;
2633  av_free(old_filename);
2634  }
2635 
2637 
2638  for (i = 0; i < hls->nb_ccstreams; i++) {
2639  ClosedCaptionsStream *ccs = &hls->cc_streams[i];
2640  av_freep(&ccs->ccgroup);
2641  av_freep(&ccs->instreamid);
2642  av_freep(&ccs->language);
2643  }
2644 
2645  ff_format_io_close(s, &hls->m3u8_out);
2646  ff_format_io_close(s, &hls->sub_m3u8_out);
2647  av_freep(&hls->key_basename);
2648  av_freep(&hls->var_streams);
2649  av_freep(&hls->cc_streams);
2650  av_freep(&hls->master_m3u8_url);
2651  return 0;
2652 }
2653 
2654 
2656 {
2657  int ret = 0;
2658  int i = 0;
2659  int j = 0;
2660  HLSContext *hls = s->priv_data;
2661  const char *pattern = "%d.ts";
2662  VariantStream *vs = NULL;
2663  int basename_size = 0;
2664  const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s);
2665  const char *vtt_pattern = "%d.vtt";
2666  char *p = NULL;
2667  int vtt_basename_size = 0;
2668  int http_base_proto = ff_is_http_proto(s->url);
2669  int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;
2670 
2671  hls->has_default_key = 0;
2672  hls->has_video_m3u8 = 0;
2673  ret = update_variant_stream_info(s);
2674  if (ret < 0) {
2675  av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",
2676  ret);
2677  goto fail;
2678  }
2679  //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present
2680  if (hls->nb_varstreams > 1 && hls->flags & HLS_PERIODIC_REKEY) {
2681  ret = AVERROR(EINVAL);
2682  av_log(s, AV_LOG_ERROR, "Periodic re-key not supported when more than one variant streams are present\n");
2683  goto fail;
2684  }
2685 
2686  if (!hls->method && http_base_proto) {
2687  av_log(hls, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n");
2688  }
2689 
2690  ret = validate_name(hls->nb_varstreams, s->url);
2691  if (ret < 0)
2692  goto fail;
2693 
2694  if (hls->segment_filename) {
2695  ret = validate_name(hls->nb_varstreams, hls->segment_filename);
2696  if (ret < 0)
2697  goto fail;
2698  }
2699 
2700  if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {
2702  if (ret < 0)
2703  goto fail;
2704  }
2705 
2706  if (hls->subtitle_filename) {
2707  ret = validate_name(hls->nb_varstreams, hls->subtitle_filename);
2708  if (ret < 0)
2709  goto fail;
2710  }
2711 
2712  if (hls->master_pl_name) {
2713  ret = update_master_pl_info(s);
2714  if (ret < 0) {
2715  av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",
2716  ret);
2717  goto fail;
2718  }
2719  }
2720 
2721  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2722  pattern = "%d.m4s";
2723  }
2726  time_t t = time(NULL); // we will need it in either case
2728  hls->start_sequence = (int64_t)t;
2730  char b[15];
2731  struct tm *p, tmbuf;
2732  if (!(p = localtime_r(&t, &tmbuf)))
2733  return AVERROR(ENOMEM);
2734  if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
2735  return AVERROR(ENOMEM);
2736  hls->start_sequence = strtoll(b, NULL, 10);
2737  }
2738  av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
2739  }
2740 
2741  hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;
2742  for (i = 0; i < hls->nb_varstreams; i++) {
2743  vs = &hls->var_streams[i];
2744 
2745  ret = format_name(s->url, &vs->m3u8_name, i, vs->varname);
2746  if (ret < 0)
2747  goto fail;
2748 
2749  vs->sequence = hls->start_sequence;
2750  vs->start_pts = AV_NOPTS_VALUE;
2751  vs->end_pts = AV_NOPTS_VALUE;
2752  vs->current_segment_final_filename_fmt[0] = '\0';
2753 
2754  if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) {
2755  // Independent segments cannot be guaranteed when splitting by time
2758  "'split_by_time' and 'independent_segments' cannot be enabled together. "
2759  "Disabling 'independent_segments' flag\n");
2760  }
2761 
2762  if (hls->flags & HLS_PROGRAM_DATE_TIME) {
2763  time_t now0;
2764  time(&now0);
2765  vs->initial_prog_date_time = now0;
2766  }
2767  if (hls->format_options_str) {
2768  ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
2769  if (ret < 0) {
2770  av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str);
2771  goto fail;
2772  }
2773  }
2774 
2775  for (j = 0; j < vs->nb_streams; j++) {
2777  /* Get one video stream to reference for split segments
2778  * so use the first video stream index. */
2779  if ((vs->has_video == 1) && (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) {
2780  vs->reference_stream_index = vs->streams[j]->index;
2781  }
2783  }
2784 
2785  if (vs->has_video > 1)
2786  av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n");
2787  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2788  vs->oformat = av_guess_format("mp4", NULL, NULL);
2789  } else {
2790  vs->oformat = av_guess_format("mpegts", NULL, NULL);
2791  }
2792 
2793  if (!vs->oformat) {
2795  goto fail;
2796  }
2797 
2798  if (vs->has_subtitle) {
2799  vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
2800  if (!vs->oformat) {
2802  goto fail;
2803  }
2804  }
2805  if (hls->segment_filename) {
2806  ret = format_name(hls->segment_filename, &vs->basename, i, vs->varname);
2807  if (ret < 0)
2808  goto fail;
2809  } else {
2810  if (hls->flags & HLS_SINGLE_FILE) {
2811  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2812  pattern = ".m4s";
2813  } else {
2814  pattern = ".ts";
2815  }
2816  }
2817 
2818  if (hls->use_localtime) {
2819  basename_size = strlen(vs->m3u8_name) + strlen(pattern_localtime_fmt) + 1;
2820  } else {
2821  basename_size = strlen(vs->m3u8_name) + strlen(pattern) + 1;
2822  }
2823 
2824  vs->basename = av_malloc(basename_size);
2825  if (!vs->basename) {
2826  ret = AVERROR(ENOMEM);
2827  goto fail;
2828  }
2829 
2830  av_strlcpy(vs->basename, vs->m3u8_name, basename_size);
2831 
2832  p = strrchr(vs->basename, '.');
2833  if (p)
2834  *p = '\0';
2835  if (hls->use_localtime) {
2836  av_strlcat(vs->basename, pattern_localtime_fmt, basename_size);
2837  } else {
2838  av_strlcat(vs->basename, pattern, basename_size);
2839  }
2840  }
2841 
2842  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2843  if (hls->nb_varstreams > 1)
2844  fmp4_init_filename_len += strlen(POSTFIX_PATTERN);
2845  if (hls->flags & HLS_SINGLE_FILE) {
2847  if (!vs->fmp4_init_filename) {
2848  ret = AVERROR(ENOMEM);
2849  goto fail;
2850  }
2851  } else {
2852  vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);
2853  if (!vs->fmp4_init_filename ) {
2854  ret = AVERROR(ENOMEM);
2855  goto fail;
2856  }
2858  fmp4_init_filename_len);
2859  if (hls->nb_varstreams > 1) {
2860  if (av_stristr(vs->fmp4_init_filename, "%v")) {
2863  } else {
2864  ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i);
2865  }
2866  if (ret < 0)
2867  goto fail;
2868  }
2869 
2870  fmp4_init_filename_len = strlen(vs->m3u8_name) +
2871  strlen(vs->fmp4_init_filename) + 1;
2872 
2873  vs->base_output_dirname = av_malloc(fmp4_init_filename_len);
2874  if (!vs->base_output_dirname) {
2875  ret = AVERROR(ENOMEM);
2876  goto fail;
2877  }
2878 
2880  fmp4_init_filename_len);
2881  p = strrchr(vs->base_output_dirname, '/');
2882  if (p) {
2883  *(p + 1) = '\0';
2885  fmp4_init_filename_len);
2886  } else {
2888  fmp4_init_filename_len);
2889  }
2890  }
2891  }
2892 
2894  if (ret < 0)
2895  goto fail;
2896 
2897  if (vs->has_subtitle) {
2898 
2899  if (hls->flags & HLS_SINGLE_FILE)
2900  vtt_pattern = ".vtt";
2901  vtt_basename_size = strlen(vs->m3u8_name) + strlen(vtt_pattern) + 1;
2902 
2903  vs->vtt_basename = av_malloc(vtt_basename_size);
2904  if (!vs->vtt_basename) {
2905  ret = AVERROR(ENOMEM);
2906  goto fail;
2907  }
2908  vs->vtt_m3u8_name = av_malloc(vtt_basename_size);
2909  if (!vs->vtt_m3u8_name ) {
2910  ret = AVERROR(ENOMEM);
2911  goto fail;
2912  }
2913  av_strlcpy(vs->vtt_basename, vs->m3u8_name, vtt_basename_size);
2914  p = strrchr(vs->vtt_basename, '.');
2915  if (p)
2916  *p = '\0';
2917 
2918  if ( hls->subtitle_filename ) {
2919  av_freep(&vs->vtt_m3u8_name);
2920  ret = format_name(hls->subtitle_filename, &vs->vtt_m3u8_name, i, vs->varname);
2921  if (ret < 0)
2922  goto fail;
2923  } else {
2924  strcpy(vs->vtt_m3u8_name, vs->vtt_basename);
2925  av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size);
2926  }
2927  av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size);
2928  }
2929 
2930  if (hls->baseurl) {
2931  vs->baseurl = av_strdup(hls->baseurl);
2932  if (!vs->baseurl) {
2933  ret = AVERROR(ENOMEM);
2934  goto fail;
2935  }
2936  }
2937 
2938  if ((ret = hls_mux_init(s, vs)) < 0)
2939  goto fail;
2940 
2941  if (hls->flags & HLS_APPEND_LIST) {
2942  parse_playlist(s, vs->m3u8_name, vs);
2943  vs->discontinuity = 1;
2944  if (hls->init_time > 0) {
2945  av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
2946  " hls_init_time value will have no effect\n");
2947  hls->init_time = 0;
2948  hls->recording_time = hls->time * AV_TIME_BASE;
2949  }
2950  }
2951 
2952  if ((ret = hls_start(s, vs)) < 0)
2953  goto fail;
2954  }
2955 
2956 fail:
2957  if (ret < 0) {
2958  av_freep(&hls->key_basename);
2959  for (i = 0; i < hls->nb_varstreams && hls->var_streams; i++) {
2960  vs = &hls->var_streams[i];
2961  av_freep(&vs->basename);
2962  av_freep(&vs->vtt_basename);
2964  av_freep(&vs->m3u8_name);
2965  av_freep(&vs->vtt_m3u8_name);
2966  av_freep(&vs->streams);
2967  av_freep(&vs->language);
2968  av_freep(&vs->agroup);
2969  av_freep(&vs->ccgroup);
2970  av_freep(&vs->baseurl);
2971  av_freep(&vs->varname);
2972  if (vs->avf)
2974  if (vs->vtt_avf)
2976  }
2977  for (i = 0; i < hls->nb_ccstreams; i++) {
2978  ClosedCaptionsStream *ccs = &hls->cc_streams[i];
2979  av_freep(&ccs->ccgroup);
2980  av_freep(&ccs->instreamid);
2981  av_freep(&ccs->language);
2982  }
2983  av_freep(&hls->var_streams);
2984  av_freep(&hls->cc_streams);
2985  av_freep(&hls->master_m3u8_url);
2986  }
2987 
2988  return ret;
2989 }
2990 
2991 #define OFFSET(x) offsetof(HLSContext, x)
2992 #define E AV_OPT_FLAG_ENCODING_PARAM
2993 static const AVOption options[] = {
2994  {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
2995  {"hls_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E},
2996  {"hls_init_time", "set segment length in seconds at init list", OFFSET(init_time), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0, FLT_MAX, E},
2997  {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E},
2998  {"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},
2999  {"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},
3000  {"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},
3001 #if FF_API_HLS_WRAP
3002  {"hls_wrap", "set number after which the index wraps (will be deprecated)", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
3003 #endif
3004  {"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},
3005  {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3006  {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3007  {"hls_segment_size", "maximum size per segment file, (in bytes)", OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
3008  {"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},
3009  {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
3010  {"hls_enc_key", "hex-coded 16 byte key to encrypt the segments", OFFSET(key), AV_OPT_TYPE_STRING, .flags = E},
3011  {"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},
3012  {"hls_enc_iv", "hex-coded 16 byte initialization vector", OFFSET(iv), AV_OPT_TYPE_STRING, .flags = E},
3013  {"hls_subtitle_path", "set path of hls subtitles", OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3014  {"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"},
3015  {"mpegts", "make segment file to mpegts files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, UINT_MAX, E, "segment_type"},
3016  {"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"},
3017  {"hls_fmp4_init_filename", "set fragment mp4 file init filename", OFFSET(fmp4_init_filename), AV_OPT_TYPE_STRING, {.str = "init.mp4"}, 0, 0, E},
3018  {"hls_flags", "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "flags"},
3019  {"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"},
3020  {"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"},
3021  {"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"},
3022  {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, "flags"},
3023  {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, "flags"},
3024  {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, "flags"},
3025  {"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"},
3026  {"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"},
3027  {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX, E, "flags"},
3028  {"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"},
3029  {"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"},
3030  {"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"},
3031  {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX, E, "flags"},
3032  {"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, "flags"},
3033  {"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"},
3034 #if FF_API_HLS_USE_LOCALTIME
3035  {"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 },
3036 #endif
3037  {"strftime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3038 #if FF_API_HLS_USE_LOCALTIME
3039  {"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 },
3040 #endif
3041  {"strftime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3042  {"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" },
3043  {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, "pl_type" },
3044  {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, "pl_type" },
3045  {"method", "set the HTTP method(default: PUT)", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3046  {"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" },
3047  {"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" },
3048  {"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" },
3049  {"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" },
3050  {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3051  {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3052  {"cc_stream_map", "Closed captions stream map string", OFFSET(cc_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3053  {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3054  {"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},
3055  {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3056  {"timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
3057  {"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 },
3058  {"headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
3059  { NULL },
3060 };
3061 
3062 static const AVClass hls_class = {
3063  .class_name = "hls muxer",
3064  .item_name = av_default_item_name,
3065  .option = options,
3066  .version = LIBAVUTIL_VERSION_INT,
3067 };
3068 
3069 
3071  .name = "hls",
3072  .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
3073  .extensions = "m3u8",
3074  .priv_data_size = sizeof(HLSContext),
3075  .audio_codec = AV_CODEC_ID_AAC,
3076  .video_codec = AV_CODEC_ID_H264,
3077  .subtitle_codec = AV_CODEC_ID_WEBVTT,
3079  .init = hls_init,
3083  .priv_class = &hls_class,
3084 };
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:1459
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:2502
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:2090
#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:4929
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:1137
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:4846
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3968
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:1481
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:1554
#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:5691
#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:1423
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:656
static int update_master_pl_info(AVFormatContext *s)
Definition: hlsenc.c:2136
int m3u8_created
Definition: hlsenc.c:162
static void hls_free_variant_streams(struct HLSContext *hls)
Definition: hlsenc.c:2472
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:1498
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:1210
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5684
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:1750
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:4502
uint8_t * av_stream_get_side_data(const AVStream *stream, enum AVPacketSideDataType type, int *size)
Get side information from stream.
Definition: utils.c:5490
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:1851
#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:3997
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1512
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:2993
#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:2172
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:2991
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:566
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3964
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:1029
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:1221
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:1486
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:931
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:2227
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:1270
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:2992
#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:5844
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:974
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:1489
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:1131
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:1254
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:1769
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:4433
static int hls_init(AVFormatContext *s)
Definition: hlsenc.c:2655
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:472
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:881
static int format_name(const char *buf, char **s, int index, const char *varname)
Definition: hlsenc.c:1803
static const char * get_default_pattern_localtime_fmt(AVFormatContext *s)
Definition: hlsenc.c:1734
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:1120
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:209
static int sls_flag_check_duration_size(HLSContext *hls, VariantStream *vs)
Definition: hlsenc.c:954
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:1292
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:3982
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:891
AVOutputFormat ff_hls_muxer
Definition: hlsenc.c:3070
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:3972
int stream_index
Definition: avcodec.h:1482
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
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:3062
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:4880
This structure stores compressed data.
Definition: avcodec.h:1457
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:1869
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1473
int hls_delete_threshold
Definition: hlsenc.c:185
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
GLuint buffer
Definition: opengl_enc.c:101
static const char * get_relative_url(const char *master_url, const char *media_url)
Definition: hlsenc.c:1236
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:981
static int parse_cc_stream_mapstring(AVFormatContext *s)
Definition: hlsenc.c:2008