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