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