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