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