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