FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hlsenc.c
Go to the documentation of this file.
1 /*
2  * Apple HTTP Live Streaming segmenter
3  * Copyright (c) 2012, Luca Barbato
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "config.h"
23 #include <float.h>
24 #include <stdint.h>
25 #if HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28 
29 #if CONFIG_GCRYPT
30 #include <gcrypt.h>
31 #elif CONFIG_OPENSSL
32 #include <openssl/rand.h>
33 #endif
34 
35 #include "libavutil/avassert.h"
36 #include "libavutil/mathematics.h"
37 #include "libavutil/parseutils.h"
38 #include "libavutil/avstring.h"
39 #include "libavutil/intreadwrite.h"
40 #include "libavutil/random_seed.h"
41 #include "libavutil/opt.h"
42 #include "libavutil/log.h"
44 
45 #include "avformat.h"
46 #include "avio_internal.h"
47 #include "internal.h"
48 #include "os_support.h"
49 
50 typedef enum {
55 
56 #define KEYSIZE 16
57 #define LINE_BUFFER_SIZE 1024
58 #define HLS_MICROSECOND_UNIT 1000000
59 
60 typedef struct HLSSegment {
61  char filename[1024];
62  char sub_filename[1024];
63  double duration; /* in seconds */
64  int discont;
65  int64_t pos;
66  int64_t size;
67 
69  char iv_string[KEYSIZE*2 + 1];
70 
71  struct HLSSegment *next;
72 } HLSSegment;
73 
74 typedef enum HLSFlags {
75  // Generate a single media file and use byte ranges in the playlist.
76  HLS_SINGLE_FILE = (1 << 0),
77  HLS_DELETE_SEGMENTS = (1 << 1),
78  HLS_ROUND_DURATIONS = (1 << 2),
79  HLS_DISCONT_START = (1 << 3),
80  HLS_OMIT_ENDLIST = (1 << 4),
81  HLS_SPLIT_BY_TIME = (1 << 5),
82  HLS_APPEND_LIST = (1 << 6),
84  HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in segment filenames when use_localtime e.g.: %%03d
85  HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration (microsec) in segment filenames when use_localtime e.g.: %%09t
86  HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) in segment filenames when use_localtime e.g.: %%014s
87  HLS_TEMP_FILE = (1 << 11),
88 } HLSFlags;
89 
90 typedef enum {
95 } PlaylistType;
96 
97 typedef struct HLSContext {
98  const AVClass *class; // Class for private options.
99  unsigned number;
100  int64_t sequence;
101  int64_t start_sequence;
102  uint32_t start_sequence_source_type; // enum StartSequenceSourceType
105 
108 
109  float time; // Set by a private option.
110  float init_time; // Set by a private option.
111  int max_nb_segments; // Set by a private option.
112 #if FF_API_HLS_WRAP
113  int wrap; // Set by a private option.
114 #endif
115  uint32_t flags; // enum HLSFlags
116  uint32_t pl_type; // enum PlaylistType
118 
119  int use_localtime; ///< flag to expand filename with localtime
120  int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename
122  int64_t recording_time;
126  double dpp; // duration per packet
127  int64_t start_pts;
128  int64_t end_pts;
129  double duration; // last segment duration computed so far, in seconds
130  int64_t start_pos; // last segment starting position
131  int64_t size; // last segment size
132  int64_t max_seg_size; // every segment file max size
136 
140 
141  char *basename;
144  char *baseurl;
149 
150  int encrypt;
151  char *key;
152  char *key_url;
153  char *iv;
155 
159  char key_string[KEYSIZE*2 + 1];
160  char iv_string[KEYSIZE*2 + 1];
162 
163  char *method;
164 
166  char current_segment_final_filename_fmt[1024]; // when renaming segments
167 } HLSContext;
168 
169 static int get_int_from_double(double val)
170 {
171  return (int)((val - (int)val) >= 0.001) ? (int)(val + 1) : (int)val;
172 }
173 
174 static int mkdir_p(const char *path) {
175  int ret = 0;
176  char *temp = av_strdup(path);
177  char *pos = temp;
178  char tmp_ch = '\0';
179 
180  if (!path || !temp) {
181  return -1;
182  }
183 
184  if (!strncmp(temp, "/", 1) || !strncmp(temp, "\\", 1)) {
185  pos++;
186  } else if (!strncmp(temp, "./", 2) || !strncmp(temp, ".\\", 2)) {
187  pos += 2;
188  }
189 
190  for ( ; *pos != '\0'; ++pos) {
191  if (*pos == '/' || *pos == '\\') {
192  tmp_ch = *pos;
193  *pos = '\0';
194  ret = mkdir(temp, 0755);
195  *pos = tmp_ch;
196  }
197  }
198 
199  if ((*(pos - 1) != '/') || (*(pos - 1) != '\\')) {
200  ret = mkdir(temp, 0755);
201  }
202 
203  av_free(temp);
204  return ret;
205 }
206 
207 static int replace_int_data_in_filename(char *buf, int buf_size, const char *filename, char placeholder, int64_t number)
208 {
209  const char *p;
210  char *q, buf1[20], c;
211  int nd, len, addchar_count;
212  int found_count = 0;
213 
214  q = buf;
215  p = filename;
216  for (;;) {
217  c = *p;
218  if (c == '\0')
219  break;
220  if (c == '%' && *(p+1) == '%') // %%
221  addchar_count = 2;
222  else if (c == '%' && (av_isdigit(*(p+1)) || *(p+1) == placeholder)) {
223  nd = 0;
224  addchar_count = 1;
225  while (av_isdigit(*(p + addchar_count))) {
226  nd = nd * 10 + *(p + addchar_count) - '0';
227  addchar_count++;
228  }
229 
230  if (*(p + addchar_count) == placeholder) {
231  len = snprintf(buf1, sizeof(buf1), "%0*"PRId64, (number < 0) ? nd : nd++, number);
232  if (len < 1) // returned error or empty buf1
233  goto fail;
234  if ((q - buf + len) > buf_size - 1)
235  goto fail;
236  memcpy(q, buf1, len);
237  q += len;
238  p += (addchar_count + 1);
239  addchar_count = 0;
240  found_count++;
241  }
242 
243  } else
244  addchar_count = 1;
245 
246  while (addchar_count--)
247  if ((q - buf) < buf_size - 1)
248  *q++ = *p++;
249  else
250  goto fail;
251  }
252  *q = '\0';
253  return found_count;
254 fail:
255  *q = '\0';
256  return -1;
257 }
258 
260 
261  HLSSegment *segment, *previous_segment = NULL;
262  float playlist_duration = 0.0f;
263  int ret = 0, path_size, sub_path_size;
264  char *dirname = NULL, *p, *sub_path;
265  char *path = NULL;
267  AVIOContext *out = NULL;
268  const char *proto = NULL;
269 
270  segment = hls->segments;
271  while (segment) {
272  playlist_duration += segment->duration;
273  segment = segment->next;
274  }
275 
276  segment = hls->old_segments;
277  while (segment) {
278  playlist_duration -= segment->duration;
279  previous_segment = segment;
280  segment = previous_segment->next;
281  if (playlist_duration <= -previous_segment->duration) {
282  previous_segment->next = NULL;
283  break;
284  }
285  }
286 
287  if (segment && !hls->use_localtime_mkdir) {
288  if (hls->segment_filename) {
289  dirname = av_strdup(hls->segment_filename);
290  } else {
291  dirname = av_strdup(hls->avf->filename);
292  }
293  if (!dirname) {
294  ret = AVERROR(ENOMEM);
295  goto fail;
296  }
297  p = (char *)av_basename(dirname);
298  *p = '\0';
299  }
300 
301  while (segment) {
302  av_log(hls, AV_LOG_DEBUG, "deleting old segment %s\n",
303  segment->filename);
304  path_size = (hls->use_localtime_mkdir ? 0 : strlen(dirname)) + strlen(segment->filename) + 1;
305  path = av_malloc(path_size);
306  if (!path) {
307  ret = AVERROR(ENOMEM);
308  goto fail;
309  }
310 
311  if (hls->use_localtime_mkdir)
312  av_strlcpy(path, segment->filename, path_size);
313  else { // segment->filename contains basename only
314  av_strlcpy(path, dirname, path_size);
315  av_strlcat(path, segment->filename, path_size);
316  }
317 
318  proto = avio_find_protocol_name(s->filename);
319  if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
320  av_dict_set(&options, "method", "DELETE", 0);
321  if ((ret = hls->avf->io_open(hls->avf, &out, path, AVIO_FLAG_WRITE, &options)) < 0)
322  goto fail;
323  ff_format_io_close(hls->avf, &out);
324  } else if (unlink(path) < 0) {
325  av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
326  path, strerror(errno));
327  }
328 
329  if ((segment->sub_filename[0] != '\0')) {
330  sub_path_size = strlen(segment->sub_filename) + 1 + (dirname ? strlen(dirname) : 0);
331  sub_path = av_malloc(sub_path_size);
332  if (!sub_path) {
333  ret = AVERROR(ENOMEM);
334  goto fail;
335  }
336 
337  av_strlcpy(sub_path, dirname, sub_path_size);
338  av_strlcat(sub_path, segment->sub_filename, sub_path_size);
339 
340  if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
341  av_dict_set(&options, "method", "DELETE", 0);
342  if ((ret = hls->avf->io_open(hls->avf, &out, sub_path, AVIO_FLAG_WRITE, &options)) < 0) {
343  av_free(sub_path);
344  goto fail;
345  }
346  ff_format_io_close(hls->avf, &out);
347  } else if (unlink(sub_path) < 0) {
348  av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
349  sub_path, strerror(errno));
350  }
351  av_free(sub_path);
352  }
353  av_freep(&path);
354  previous_segment = segment;
355  segment = previous_segment->next;
356  av_free(previous_segment);
357  }
358 
359 fail:
360  av_free(path);
361  av_free(dirname);
362 
363  return ret;
364 }
365 
366 static int randomize(uint8_t *buf, int len)
367 {
368 #if CONFIG_GCRYPT
369  gcry_randomize(buf, len, GCRY_VERY_STRONG_RANDOM);
370  return 0;
371 #elif CONFIG_OPENSSL
372  if (RAND_bytes(buf, len))
373  return 0;
374 #else
375  return AVERROR(ENOSYS);
376 #endif
377  return AVERROR(EINVAL);
378 }
379 
381 {
382  HLSContext *hls = s->priv_data;
383  int ret;
384  int len;
385  AVIOContext *pb;
386  uint8_t key[KEYSIZE];
387 
388  len = strlen(hls->basename) + 4 + 1;
389  hls->key_basename = av_mallocz(len);
390  if (!hls->key_basename)
391  return AVERROR(ENOMEM);
392 
393  av_strlcpy(hls->key_basename, s->filename, len);
394  av_strlcat(hls->key_basename, ".key", len);
395 
396  if (hls->key_url) {
397  av_strlcpy(hls->key_file, hls->key_url, sizeof(hls->key_file));
398  av_strlcpy(hls->key_uri, hls->key_url, sizeof(hls->key_uri));
399  } else {
400  av_strlcpy(hls->key_file, hls->key_basename, sizeof(hls->key_file));
401  av_strlcpy(hls->key_uri, hls->key_basename, sizeof(hls->key_uri));
402  }
403 
404  if (!*hls->iv_string) {
405  uint8_t iv[16] = { 0 };
406  char buf[33];
407 
408  if (!hls->iv) {
409  AV_WB64(iv + 8, hls->sequence);
410  } else {
411  memcpy(iv, hls->iv, sizeof(iv));
412  }
413  ff_data_to_hex(buf, iv, sizeof(iv), 0);
414  buf[32] = '\0';
415  memcpy(hls->iv_string, buf, sizeof(hls->iv_string));
416  }
417 
418  if (!*hls->key_uri) {
419  av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
420  return AVERROR(EINVAL);
421  }
422 
423  if (!*hls->key_file) {
424  av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
425  return AVERROR(EINVAL);
426  }
427 
428  if (!*hls->key_string) {
429  if (!hls->key) {
430  if ((ret = randomize(key, sizeof(key))) < 0) {
431  av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n");
432  return ret;
433  }
434  } else {
435  memcpy(key, hls->key, sizeof(key));
436  }
437 
438  ff_data_to_hex(hls->key_string, key, sizeof(key), 0);
439  if ((ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_WRITE, NULL)) < 0)
440  return ret;
441  avio_seek(pb, 0, SEEK_CUR);
442  avio_write(pb, key, KEYSIZE);
443  avio_close(pb);
444  }
445  return 0;
446 }
447 
448 
450 {
451  HLSContext *hls = s->priv_data;
452  int ret;
453  AVIOContext *pb;
454  uint8_t key[KEYSIZE];
455 
456  if ((ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, NULL)) < 0) {
457  av_log(hls, AV_LOG_ERROR,
458  "error opening key info file %s\n", hls->key_info_file);
459  return ret;
460  }
461 
462  ff_get_line(pb, hls->key_uri, sizeof(hls->key_uri));
463  hls->key_uri[strcspn(hls->key_uri, "\r\n")] = '\0';
464 
465  ff_get_line(pb, hls->key_file, sizeof(hls->key_file));
466  hls->key_file[strcspn(hls->key_file, "\r\n")] = '\0';
467 
468  ff_get_line(pb, hls->iv_string, sizeof(hls->iv_string));
469  hls->iv_string[strcspn(hls->iv_string, "\r\n")] = '\0';
470 
471  ff_format_io_close(s, &pb);
472 
473  if (!*hls->key_uri) {
474  av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
475  return AVERROR(EINVAL);
476  }
477 
478  if (!*hls->key_file) {
479  av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
480  return AVERROR(EINVAL);
481  }
482 
483  if ((ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_READ, NULL)) < 0) {
484  av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", hls->key_file);
485  return ret;
486  }
487 
488  ret = avio_read(pb, key, sizeof(key));
489  ff_format_io_close(s, &pb);
490  if (ret != sizeof(key)) {
491  av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", hls->key_file);
492  if (ret >= 0 || ret == AVERROR_EOF)
493  ret = AVERROR(EINVAL);
494  return ret;
495  }
496  ff_data_to_hex(hls->key_string, key, sizeof(key), 0);
497 
498  return 0;
499 }
500 
501 static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
502 {
503  int len = ff_get_line(s, buf, maxlen);
504  while (len > 0 && av_isspace(buf[len - 1]))
505  buf[--len] = '\0';
506  return len;
507 }
508 
510 {
511  HLSContext *hls = s->priv_data;
512  AVFormatContext *oc;
513  AVFormatContext *vtt_oc = NULL;
514  int i, ret;
515 
516  ret = avformat_alloc_output_context2(&hls->avf, hls->oformat, NULL, NULL);
517  if (ret < 0)
518  return ret;
519  oc = hls->avf;
520 
521  oc->filename[0] = '\0';
522  oc->oformat = hls->oformat;
524  oc->max_delay = s->max_delay;
525  oc->opaque = s->opaque;
526  oc->io_open = s->io_open;
527  oc->io_close = s->io_close;
528  av_dict_copy(&oc->metadata, s->metadata, 0);
529 
530  if(hls->vtt_oformat) {
532  if (ret < 0)
533  return ret;
534  vtt_oc = hls->vtt_avf;
535  vtt_oc->oformat = hls->vtt_oformat;
536  av_dict_copy(&vtt_oc->metadata, s->metadata, 0);
537  }
538 
539  for (i = 0; i < s->nb_streams; i++) {
540  AVStream *st;
541  AVFormatContext *loc;
543  loc = vtt_oc;
544  else
545  loc = oc;
546 
547  if (!(st = avformat_new_stream(loc, NULL)))
548  return AVERROR(ENOMEM);
551  st->time_base = s->streams[i]->time_base;
552  av_dict_copy(&st->metadata, s->streams[i]->metadata, 0);
553  }
554  hls->start_pos = 0;
555  hls->new_start = 1;
556 
557  return 0;
558 }
559 
560 static HLSSegment *find_segment_by_filename(HLSSegment *segment, const char *filename)
561 {
562  while (segment) {
563  if (!av_strcasecmp(segment->filename,filename))
564  return segment;
565  segment = segment->next;
566  }
567  return (HLSSegment *) NULL;
568 }
569 
571  int64_t pos, int64_t size)
572 {
574  strlen(hls->current_segment_final_filename_fmt)) {
577  char * filename = av_strdup(hls->avf->filename); // %%s will be %s after strftime
578  if (!filename) {
579  av_free(en);
580  return AVERROR(ENOMEM);
581  }
582  if (replace_int_data_in_filename(hls->avf->filename, sizeof(hls->avf->filename),
583  filename, 's', pos + size) < 1) {
584  av_log(hls, AV_LOG_ERROR,
585  "Invalid second level segment filename template '%s', "
586  "you can try to remove second_level_segment_size flag\n",
587  filename);
588  av_free(filename);
589  av_free(en);
590  return AVERROR(EINVAL);
591  }
592  av_free(filename);
593  }
595  char * filename = av_strdup(hls->avf->filename); // %%t will be %t after strftime
596  if (!filename) {
597  av_free(en);
598  return AVERROR(ENOMEM);
599  }
600  if (replace_int_data_in_filename(hls->avf->filename, sizeof(hls->avf->filename),
601  filename, 't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) {
602  av_log(hls, AV_LOG_ERROR,
603  "Invalid second level segment filename template '%s', "
604  "you can try to remove second_level_segment_time flag\n",
605  filename);
606  av_free(filename);
607  av_free(en);
608  return AVERROR(EINVAL);
609  }
610  av_free(filename);
611  }
612  }
613  return 0;
614 }
615 
617 {
618  int ret = 0;
619 
621  av_log(hls, AV_LOG_ERROR,
622  "second_level_segment_duration hls_flag requires use_localtime to be true\n");
623  ret = AVERROR(EINVAL);
624  }
626  av_log(hls, AV_LOG_ERROR,
627  "second_level_segment_size hls_flag requires use_localtime to be true\n");
628  ret = AVERROR(EINVAL);
629  }
631  av_log(hls, AV_LOG_ERROR,
632  "second_level_segment_index hls_flag requires use_localtime to be true\n");
633  ret = AVERROR(EINVAL);
634  }
635 
636  return ret;
637 }
638 
640 {
641  const char *proto = avio_find_protocol_name(hls->basename);
642  int segment_renaming_ok = proto && !strcmp(proto, "file");
643  int ret = 0;
644 
645  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) && !segment_renaming_ok) {
646  av_log(hls, AV_LOG_ERROR,
647  "second_level_segment_duration hls_flag works only with file protocol segment names\n");
648  ret = AVERROR(EINVAL);
649  }
650  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) && !segment_renaming_ok) {
651  av_log(hls, AV_LOG_ERROR,
652  "second_level_segment_size hls_flag works only with file protocol segment names\n");
653  ret = AVERROR(EINVAL);
654  }
655 
656  return ret;
657 }
658 
659 static void sls_flag_file_rename(HLSContext *hls, char *old_filename) {
661  strlen(hls->current_segment_final_filename_fmt)) {
662  ff_rename(old_filename, hls->avf->filename, hls);
663  }
664 }
665 
667 {
669  char * filename = av_strdup(oc->filename); // %%d will be %d after strftime
670  if (!filename)
671  return AVERROR(ENOMEM);
672  if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename),
673 #if FF_API_HLS_WRAP
674  filename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) {
675 #else
676  filename, 'd', c->sequence) < 1) {
677 #endif
678  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
679  "you can try to remove second_level_segment_index flag\n",
680  filename);
681  av_free(filename);
682  return AVERROR(EINVAL);
683  }
684  av_free(filename);
685  }
690  char * filename = av_strdup(oc->filename); // %%s will be %s after strftime
691  if (!filename)
692  return AVERROR(ENOMEM);
693  if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), filename, 's', 0) < 1) {
694  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
695  "you can try to remove second_level_segment_size flag\n",
696  filename);
697  av_free(filename);
698  return AVERROR(EINVAL);
699  }
700  av_free(filename);
701  }
703  char * filename = av_strdup(oc->filename); // %%t will be %t after strftime
704  if (!filename)
705  return AVERROR(ENOMEM);
706  if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), filename, 't', 0) < 1) {
707  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
708  "you can try to remove second_level_segment_time flag\n",
709  filename);
710  av_free(filename);
711  return AVERROR(EINVAL);
712  }
713  av_free(filename);
714  }
715  }
716  return 0;
717 }
718 
719 /* Create a new segment and append it to the segment list */
720 static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double duration,
721  int64_t pos, int64_t size)
722 {
723  HLSSegment *en = av_malloc(sizeof(*en));
724  const char *filename;
725  int ret;
726 
727  if (!en)
728  return AVERROR(ENOMEM);
729 
730  ret = sls_flags_filename_process(s, hls, en, duration, pos, size);
731  if (ret < 0) {
732  return ret;
733  }
734 
735  filename = av_basename(hls->avf->filename);
736 
737  if (hls->use_localtime_mkdir) {
738  filename = hls->avf->filename;
739  }
740  if (find_segment_by_filename(hls->segments, filename)
741  || find_segment_by_filename(hls->old_segments, filename)) {
742  av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename);
743  }
744  av_strlcpy(en->filename, filename, sizeof(en->filename));
745 
746  if(hls->has_subtitle)
748  else
749  en->sub_filename[0] = '\0';
750 
751  en->duration = duration;
752  en->pos = pos;
753  en->size = size;
754  en->next = NULL;
755  en->discont = 0;
756 
757  if (hls->discontinuity) {
758  en->discont = 1;
759  hls->discontinuity = 0;
760  }
761 
762  if (hls->key_info_file || hls->encrypt) {
763  av_strlcpy(en->key_uri, hls->key_uri, sizeof(en->key_uri));
764  av_strlcpy(en->iv_string, hls->iv_string, sizeof(en->iv_string));
765  }
766 
767  if (!hls->segments)
768  hls->segments = en;
769  else
770  hls->last_segment->next = en;
771 
772  hls->last_segment = en;
773 
774  // EVENT or VOD playlists imply sliding window cannot be used
775  if (hls->pl_type != PLAYLIST_TYPE_NONE)
776  hls->max_nb_segments = 0;
777 
778  if (hls->max_nb_segments && hls->nb_entries >= hls->max_nb_segments) {
779  en = hls->segments;
780  hls->initial_prog_date_time += en->duration;
781  hls->segments = en->next;
782  if (en && hls->flags & HLS_DELETE_SEGMENTS &&
783 #if FF_API_HLS_WRAP
784  !(hls->flags & HLS_SINGLE_FILE || hls->wrap)) {
785 #else
786  !(hls->flags & HLS_SINGLE_FILE)) {
787 #endif
788  en->next = hls->old_segments;
789  hls->old_segments = en;
790  if ((ret = hls_delete_old_segments(s, hls)) < 0)
791  return ret;
792  } else
793  av_free(en);
794  } else
795  hls->nb_entries++;
796 
797  if (hls->max_seg_size > 0) {
798  return 0;
799  }
800  hls->sequence++;
801 
802  return 0;
803 }
804 
805 static int parse_playlist(AVFormatContext *s, const char *url)
806 {
807  HLSContext *hls = s->priv_data;
808  AVIOContext *in;
809  int ret = 0, is_segment = 0;
810  int64_t new_start_pos;
811  char line[1024];
812  const char *ptr;
813  const char *end;
814 
815  if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
818  return ret;
819 
820  read_chomp_line(in, line, sizeof(line));
821  if (strcmp(line, "#EXTM3U")) {
822  ret = AVERROR_INVALIDDATA;
823  goto fail;
824  }
825 
826  hls->discontinuity = 0;
827  while (!avio_feof(in)) {
828  read_chomp_line(in, line, sizeof(line));
829  if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
830  int64_t tmp_sequence = strtoll(ptr, NULL, 10);
831  if (tmp_sequence < hls->sequence)
832  av_log(hls, AV_LOG_VERBOSE,
833  "Found playlist sequence number was smaller """
834  "than specified start sequence number: %"PRId64" < %"PRId64", "
835  "omitting\n", tmp_sequence, hls->start_sequence);
836  else {
837  av_log(hls, AV_LOG_DEBUG, "Found playlist sequence number: %"PRId64"\n", tmp_sequence);
838  hls->sequence = tmp_sequence;
839  }
840  } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
841  is_segment = 1;
842  hls->discontinuity = 1;
843  } else if (av_strstart(line, "#EXTINF:", &ptr)) {
844  is_segment = 1;
845  hls->duration = atof(ptr);
846  } else if (av_stristart(line, "#EXT-X-KEY:", &ptr)) {
847  ptr = av_stristr(line, "URI=\"");
848  if (ptr) {
849  ptr += strlen("URI=\"");
850  end = av_stristr(ptr, ",");
851  if (end) {
852  av_strlcpy(hls->key_uri, ptr, end - ptr);
853  } else {
854  av_strlcpy(hls->key_uri, ptr, sizeof(hls->key_uri));
855  }
856  }
857 
858  ptr = av_stristr(line, "IV=0x");
859  if (ptr) {
860  ptr += strlen("IV=0x");
861  end = av_stristr(ptr, ",");
862  if (end) {
863  av_strlcpy(hls->iv_string, ptr, end - ptr);
864  } else {
865  av_strlcpy(hls->iv_string, ptr, sizeof(hls->iv_string));
866  }
867  }
868 
869  } else if (av_strstart(line, "#", NULL)) {
870  continue;
871  } else if (line[0]) {
872  if (is_segment) {
873  is_segment = 0;
874  new_start_pos = avio_tell(hls->avf->pb);
875  hls->size = new_start_pos - hls->start_pos;
876  av_strlcpy(hls->avf->filename, line, sizeof(line));
877  ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);
878  if (ret < 0)
879  goto fail;
880  hls->start_pos = new_start_pos;
881  }
882  }
883  }
884 
885 fail:
886  avio_close(in);
887  return ret;
888 }
889 
891 {
892  HLSSegment *en;
893 
894  while(p) {
895  en = p;
896  p = p->next;
897  av_free(en);
898  }
899 }
900 
902 {
903  const char *proto = avio_find_protocol_name(s->filename);
904  int http_base_proto = proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0;
905 
906  if (c->method) {
907  av_dict_set(options, "method", c->method, 0);
908  } else if (http_base_proto) {
909  av_log(c, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n");
910  av_dict_set(options, "method", "PUT", 0);
911  }
912 }
913 
915  int target_duration, int64_t sequence)
916 {
917  avio_printf(out, "#EXTM3U\n");
918  avio_printf(out, "#EXT-X-VERSION:%d\n", version);
919  if (hls->allowcache == 0 || hls->allowcache == 1) {
920  avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? "NO" : "YES");
921  }
922  avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
923  avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
924  av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
925 }
926 
928 {
929  size_t len = strlen(oc->filename);
930  char final_filename[sizeof(oc->filename)];
931 
932  av_strlcpy(final_filename, oc->filename, len);
933  final_filename[len-4] = '\0';
934  ff_rename(oc->filename, final_filename, s);
935  oc->filename[len-4] = '\0';
936 }
937 
938 static int hls_window(AVFormatContext *s, int last)
939 {
940  HLSContext *hls = s->priv_data;
941  HLSSegment *en;
942  int target_duration = 0;
943  int ret = 0;
944  AVIOContext *out = NULL;
945  AVIOContext *sub_out = NULL;
946  char temp_filename[1024];
947  int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->nb_entries);
948  int version = 3;
949  const char *proto = avio_find_protocol_name(s->filename);
950  int use_rename = proto && !strcmp(proto, "file");
951  static unsigned warned_non_file;
952  char *key_uri = NULL;
953  char *iv_string = NULL;
955  double prog_date_time = hls->initial_prog_date_time;
956  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
957 
958  if (byterange_mode) {
959  version = 4;
960  sequence = 0;
961  }
962 
963  if (!use_rename && !warned_non_file++)
964  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
965 
966  set_http_options(s, &options, hls);
967  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename);
968  if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &options)) < 0)
969  goto fail;
970 
971  for (en = hls->segments; en; en = en->next) {
972  if (target_duration <= en->duration)
973  target_duration = get_int_from_double(en->duration);
974  }
975 
976  hls->discontinuity_set = 0;
977  write_m3u8_head_block(hls, out, version, target_duration, sequence);
978  if (hls->pl_type == PLAYLIST_TYPE_EVENT) {
979  avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
980  } else if (hls->pl_type == PLAYLIST_TYPE_VOD) {
981  avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
982  }
983 
984  if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && hls->discontinuity_set==0 ){
985  avio_printf(out, "#EXT-X-DISCONTINUITY\n");
986  hls->discontinuity_set = 1;
987  }
988  for (en = hls->segments; en; en = en->next) {
989  if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) ||
990  av_strcasecmp(en->iv_string, iv_string))) {
991  avio_printf(out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri);
992  if (*en->iv_string)
993  avio_printf(out, ",IV=0x%s", en->iv_string);
994  avio_printf(out, "\n");
995  key_uri = en->key_uri;
996  iv_string = en->iv_string;
997  }
998 
999  if (en->discont) {
1000  avio_printf(out, "#EXT-X-DISCONTINUITY\n");
1001  }
1002 
1003  if (hls->flags & HLS_ROUND_DURATIONS)
1004  avio_printf(out, "#EXTINF:%ld,\n", lrint(en->duration));
1005  else
1006  avio_printf(out, "#EXTINF:%f,\n", en->duration);
1007  if (byterange_mode)
1008  avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
1009  en->size, en->pos);
1010  if (hls->flags & HLS_PROGRAM_DATE_TIME) {
1011  time_t tt, wrongsecs;
1012  int milli;
1013  struct tm *tm, tmpbuf;
1014  char buf0[128], buf1[128];
1015  tt = (int64_t)prog_date_time;
1016  milli = av_clip(lrint(1000*(prog_date_time - tt)), 0, 999);
1017  tm = localtime_r(&tt, &tmpbuf);
1018  strftime(buf0, sizeof(buf0), "%Y-%m-%dT%H:%M:%S", tm);
1019  if (!strftime(buf1, sizeof(buf1), "%z", tm) || buf1[1]<'0' ||buf1[1]>'2') {
1020  int tz_min, dst = tm->tm_isdst;
1021  tm = gmtime_r(&tt, &tmpbuf);
1022  tm->tm_isdst = dst;
1023  wrongsecs = mktime(tm);
1024  tz_min = (abs(wrongsecs - tt) + 30) / 60;
1025  snprintf(buf1, sizeof(buf1),
1026  "%c%02d%02d",
1027  wrongsecs <= tt ? '+' : '-',
1028  tz_min / 60,
1029  tz_min % 60);
1030  }
1031  avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1);
1032  prog_date_time += en->duration;
1033  }
1034  if (hls->baseurl)
1035  avio_printf(out, "%s", hls->baseurl);
1036  avio_printf(out, "%s\n", en->filename);
1037  }
1038 
1039  if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
1040  avio_printf(out, "#EXT-X-ENDLIST\n");
1041 
1042  if( hls->vtt_m3u8_name ) {
1043  if ((ret = s->io_open(s, &sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE, &options)) < 0)
1044  goto fail;
1045  write_m3u8_head_block(hls, sub_out, version, target_duration, sequence);
1046 
1047  for (en = hls->segments; en; en = en->next) {
1048  avio_printf(sub_out, "#EXTINF:%f,\n", en->duration);
1049  if (byterange_mode)
1050  avio_printf(sub_out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
1051  en->size, en->pos);
1052  if (hls->baseurl)
1053  avio_printf(sub_out, "%s", hls->baseurl);
1054  avio_printf(sub_out, "%s\n", en->sub_filename);
1055  }
1056 
1057  if (last)
1058  avio_printf(sub_out, "#EXT-X-ENDLIST\n");
1059 
1060  }
1061 
1062 fail:
1063  av_dict_free(&options);
1064  ff_format_io_close(s, &out);
1065  ff_format_io_close(s, &sub_out);
1066  if (ret >= 0 && use_rename)
1067  ff_rename(temp_filename, s->filename, s);
1068  return ret;
1069 }
1070 
1072 {
1073  HLSContext *c = s->priv_data;
1074  AVFormatContext *oc = c->avf;
1075  AVFormatContext *vtt_oc = c->vtt_avf;
1077  char *filename, iv_string[KEYSIZE*2 + 1];
1078  int err = 0;
1079 
1080  if (c->flags & HLS_SINGLE_FILE) {
1081  av_strlcpy(oc->filename, c->basename,
1082  sizeof(oc->filename));
1083  if (c->vtt_basename)
1084  av_strlcpy(vtt_oc->filename, c->vtt_basename,
1085  sizeof(vtt_oc->filename));
1086  } else if (c->max_seg_size > 0) {
1087  if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename),
1088 #if FF_API_HLS_WRAP
1089  c->basename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) {
1090 #else
1091  c->basename, 'd', c->sequence) < 1) {
1092 #endif
1093  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", c->basename);
1094  return AVERROR(EINVAL);
1095  }
1096  } else {
1097  if (c->use_localtime) {
1098  time_t now0;
1099  struct tm *tm, tmpbuf;
1100  time(&now0);
1101  tm = localtime_r(&now0, &tmpbuf);
1102  if (!strftime(oc->filename, sizeof(oc->filename), c->basename, tm)) {
1103  av_log(oc, AV_LOG_ERROR, "Could not get segment filename with use_localtime\n");
1104  return AVERROR(EINVAL);
1105  }
1106 
1107  err = sls_flag_use_localtime_filename(oc, c);
1108  if (err < 0) {
1109  return AVERROR(ENOMEM);
1110  }
1111 
1112  if (c->use_localtime_mkdir) {
1113  const char *dir;
1114  char *fn_copy = av_strdup(oc->filename);
1115  if (!fn_copy) {
1116  return AVERROR(ENOMEM);
1117  }
1118  dir = av_dirname(fn_copy);
1119  if (mkdir_p(dir) == -1 && errno != EEXIST) {
1120  av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
1121  av_free(fn_copy);
1122  return AVERROR(errno);
1123  }
1124  av_free(fn_copy);
1125  }
1126  } else if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename),
1127 #if FF_API_HLS_WRAP
1128  c->basename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) {
1129 #else
1130  c->basename, 'd', c->sequence) < 1) {
1131 #endif
1132  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", c->basename);
1133  return AVERROR(EINVAL);
1134  }
1135  if( c->vtt_basename) {
1136  if (replace_int_data_in_filename(vtt_oc->filename, sizeof(vtt_oc->filename),
1137 #if FF_API_HLS_WRAP
1138  c->vtt_basename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) {
1139 #else
1140  c->vtt_basename, 'd', c->sequence) < 1) {
1141 #endif
1142  av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename);
1143  return AVERROR(EINVAL);
1144  }
1145  }
1146  }
1147  c->number++;
1148 
1149  set_http_options(s, &options, c);
1150 
1151  if (c->flags & HLS_TEMP_FILE) {
1152  av_strlcat(oc->filename, ".tmp", sizeof(oc->filename));
1153  }
1154 
1155  if (c->key_info_file || c->encrypt) {
1156  if (c->key_info_file && c->encrypt) {
1157  av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file and -hls_enc,"
1158  " will use -hls_key_info_file priority\n");
1159  }
1160  if (c->key_info_file) {
1161  if ((err = hls_encryption_start(s)) < 0)
1162  goto fail;
1163  } else {
1164  if ((err = do_encrypt(s)) < 0)
1165  goto fail;
1166  }
1167  if ((err = av_dict_set(&options, "encryption_key", c->key_string, 0))
1168  < 0)
1169  goto fail;
1170  err = av_strlcpy(iv_string, c->iv_string, sizeof(iv_string));
1171  if (!err)
1172  snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, c->sequence);
1173  if ((err = av_dict_set(&options, "encryption_iv", iv_string, 0)) < 0)
1174  goto fail;
1175 
1176  filename = av_asprintf("crypto:%s", oc->filename);
1177  if (!filename) {
1178  err = AVERROR(ENOMEM);
1179  goto fail;
1180  }
1181  err = s->io_open(s, &oc->pb, filename, AVIO_FLAG_WRITE, &options);
1182  av_free(filename);
1183  av_dict_free(&options);
1184  if (err < 0)
1185  return err;
1186  } else
1187  if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &options)) < 0)
1188  goto fail;
1189  if (c->vtt_basename) {
1190  set_http_options(s, &options, c);
1191  if ((err = s->io_open(s, &vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE, &options)) < 0)
1192  goto fail;
1193  }
1194  av_dict_free(&options);
1195 
1196  /* We only require one PAT/PMT per segment. */
1197  if (oc->oformat->priv_class && oc->priv_data) {
1198  char period[21];
1199 
1200  snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1);
1201 
1202  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
1203  av_opt_set(oc->priv_data, "sdt_period", period, 0);
1204  av_opt_set(oc->priv_data, "pat_period", period, 0);
1205  }
1206 
1207  if (c->vtt_basename) {
1208  err = avformat_write_header(vtt_oc,NULL);
1209  if (err < 0)
1210  return err;
1211  }
1212 
1213  return 0;
1214 fail:
1215  av_dict_free(&options);
1216 
1217  return err;
1218 }
1219 
1220 static const char * get_default_pattern_localtime_fmt(void)
1221 {
1222  char b[21];
1223  time_t t = time(NULL);
1224  struct tm *p, tmbuf;
1225  p = localtime_r(&t, &tmbuf);
1226  // no %s support when strftime returned error or left format string unchanged
1227  // also no %s support on MSVC, which invokes the invalid parameter handler on unsupported format strings, instead of returning an error
1228  return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.ts" : "-%s.ts";
1229 }
1230 
1232 {
1233  HLSContext *hls = s->priv_data;
1234  int ret, i;
1235  char *p;
1236  const char *pattern = "%d.ts";
1237  const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt();
1238  const char *vtt_pattern = "%d.vtt";
1239  AVDictionary *options = NULL;
1240  int basename_size;
1241  int vtt_basename_size;
1242 
1245  time_t t = time(NULL); // we will need it in either case
1247  hls->start_sequence = (int64_t)t;
1249  char b[15];
1250  struct tm *p, tmbuf;
1251  if (!(p = localtime_r(&t, &tmbuf)))
1252  return AVERROR(ENOMEM);
1253  if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
1254  return AVERROR(ENOMEM);
1255  hls->start_sequence = strtoll(b, NULL, 10);
1256  }
1257  av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
1258  }
1259 
1260  hls->sequence = hls->start_sequence;
1261  hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;
1262  hls->start_pts = AV_NOPTS_VALUE;
1263  hls->current_segment_final_filename_fmt[0] = '\0';
1264 
1265  if (hls->flags & HLS_PROGRAM_DATE_TIME) {
1266  time_t now0;
1267  time(&now0);
1268  hls->initial_prog_date_time = now0;
1269  }
1270 
1271  if (hls->format_options_str) {
1272  ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
1273  if (ret < 0) {
1274  av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str);
1275  goto fail;
1276  }
1277  }
1278 
1279  for (i = 0; i < s->nb_streams; i++) {
1280  hls->has_video +=
1282  hls->has_subtitle +=
1284  }
1285 
1286  if (hls->has_video > 1)
1288  "More than a single video stream present, "
1289  "expect issues decoding it.\n");
1290 
1291  hls->oformat = av_guess_format("mpegts", NULL, NULL);
1292 
1293  if (!hls->oformat) {
1295  goto fail;
1296  }
1297 
1298  if(hls->has_subtitle) {
1299  hls->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
1300  if (!hls->oformat) {
1302  goto fail;
1303  }
1304  }
1305 
1306  if (hls->segment_filename) {
1307  hls->basename = av_strdup(hls->segment_filename);
1308  if (!hls->basename) {
1309  ret = AVERROR(ENOMEM);
1310  goto fail;
1311  }
1312  } else {
1313  if (hls->flags & HLS_SINGLE_FILE)
1314  pattern = ".ts";
1315 
1316  if (hls->use_localtime) {
1317  basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;
1318  } else {
1319  basename_size = strlen(s->filename) + strlen(pattern) + 1;
1320  }
1321  hls->basename = av_malloc(basename_size);
1322  if (!hls->basename) {
1323  ret = AVERROR(ENOMEM);
1324  goto fail;
1325  }
1326 
1327  av_strlcpy(hls->basename, s->filename, basename_size);
1328 
1329  p = strrchr(hls->basename, '.');
1330  if (p)
1331  *p = '\0';
1332  if (hls->use_localtime) {
1333  av_strlcat(hls->basename, pattern_localtime_fmt, basename_size);
1334  } else {
1335  av_strlcat(hls->basename, pattern, basename_size);
1336  }
1337  }
1338  if (!hls->use_localtime) {
1340  if (ret < 0) {
1341  goto fail;
1342  }
1343  } else {
1344  ret = sls_flag_check_duration_size(hls);
1345  if (ret < 0) {
1346  goto fail;
1347  }
1348  }
1349  if(hls->has_subtitle) {
1350 
1351  if (hls->flags & HLS_SINGLE_FILE)
1352  vtt_pattern = ".vtt";
1353  vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1;
1354  hls->vtt_basename = av_malloc(vtt_basename_size);
1355  if (!hls->vtt_basename) {
1356  ret = AVERROR(ENOMEM);
1357  goto fail;
1358  }
1359  hls->vtt_m3u8_name = av_malloc(vtt_basename_size);
1360  if (!hls->vtt_m3u8_name ) {
1361  ret = AVERROR(ENOMEM);
1362  goto fail;
1363  }
1364  av_strlcpy(hls->vtt_basename, s->filename, vtt_basename_size);
1365  p = strrchr(hls->vtt_basename, '.');
1366  if (p)
1367  *p = '\0';
1368 
1369  if( hls->subtitle_filename ) {
1370  strcpy(hls->vtt_m3u8_name, hls->subtitle_filename);
1371  } else {
1372  strcpy(hls->vtt_m3u8_name, hls->vtt_basename);
1373  av_strlcat(hls->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size);
1374  }
1375  av_strlcat(hls->vtt_basename, vtt_pattern, vtt_basename_size);
1376  }
1377 
1378  if ((ret = hls_mux_init(s)) < 0)
1379  goto fail;
1380 
1381  if (hls->flags & HLS_APPEND_LIST) {
1382  parse_playlist(s, s->filename);
1383  hls->discontinuity = 1;
1384  if (hls->init_time > 0) {
1385  av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
1386  " hls_init_time value will have no effect\n");
1387  hls->init_time = 0;
1388  hls->recording_time = hls->time * AV_TIME_BASE;
1389  }
1390  }
1391 
1392  if ((ret = hls_start(s)) < 0)
1393  goto fail;
1394 
1395  av_dict_copy(&options, hls->format_options, 0);
1396  ret = avformat_write_header(hls->avf, &options);
1397  if (av_dict_count(options)) {
1398  av_log(s, AV_LOG_ERROR, "Some of provided format options in '%s' are not recognized\n", hls->format_options_str);
1399  ret = AVERROR(EINVAL);
1400  goto fail;
1401  }
1402  //av_assert0(s->nb_streams == hls->avf->nb_streams);
1403  for (i = 0; i < s->nb_streams; i++) {
1404  AVStream *inner_st;
1405  AVStream *outer_st = s->streams[i];
1406 
1407  if (hls->max_seg_size > 0) {
1408  if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
1409  (outer_st->codecpar->bit_rate > hls->max_seg_size)) {
1410  av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, "
1411  "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.",
1412  outer_st->codecpar->bit_rate, hls->max_seg_size);
1413  }
1414  }
1415 
1416  if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
1417  inner_st = hls->avf->streams[i];
1418  else if (hls->vtt_avf)
1419  inner_st = hls->vtt_avf->streams[0];
1420  else {
1421  /* We have a subtitle stream, when the user does not want one */
1422  inner_st = NULL;
1423  continue;
1424  }
1425  avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
1426  }
1427 fail:
1428 
1429  av_dict_free(&options);
1430  if (ret < 0) {
1431  av_freep(&hls->basename);
1432  av_freep(&hls->vtt_basename);
1433  av_freep(&hls->key_basename);
1434  if (hls->avf)
1435  avformat_free_context(hls->avf);
1436  if (hls->vtt_avf)
1438 
1439  }
1440  return ret;
1441 }
1442 
1444 {
1445  HLSContext *hls = s->priv_data;
1446  AVFormatContext *oc = NULL;
1447  AVStream *st = s->streams[pkt->stream_index];
1448  int64_t end_pts = hls->recording_time * hls->number;
1449  int is_ref_pkt = 1;
1450  int ret, can_split = 1;
1451  int stream_index = 0;
1452 
1453  if (hls->sequence - hls->nb_entries > hls->start_sequence && hls->init_time > 0) {
1454  /* reset end_pts, hls->recording_time at end of the init hls list */
1455  int init_list_dur = hls->init_time * hls->nb_entries * AV_TIME_BASE;
1456  int after_init_list_dur = (hls->sequence - hls->nb_entries ) * hls->time * AV_TIME_BASE;
1457  hls->recording_time = hls->time * AV_TIME_BASE;
1458  end_pts = init_list_dur + after_init_list_dur ;
1459  }
1460 
1461  if( st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
1462  oc = hls->vtt_avf;
1463  stream_index = 0;
1464  } else {
1465  oc = hls->avf;
1466  stream_index = pkt->stream_index;
1467  }
1468  if (hls->start_pts == AV_NOPTS_VALUE) {
1469  hls->start_pts = pkt->pts;
1470  hls->end_pts = pkt->pts;
1471  }
1472 
1473  if (hls->has_video) {
1474  can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
1475  ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME));
1476  is_ref_pkt = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
1477  }
1478  if (pkt->pts == AV_NOPTS_VALUE)
1479  is_ref_pkt = can_split = 0;
1480 
1481  if (is_ref_pkt) {
1482  if (hls->new_start) {
1483  hls->new_start = 0;
1484  hls->duration = (double)(pkt->pts - hls->end_pts)
1485  * st->time_base.num / st->time_base.den;
1486  hls->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den;
1487  } else {
1488  if (pkt->duration) {
1489  hls->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;
1490  } else {
1491  av_log(s, AV_LOG_WARNING, "pkt->duration = 0, maybe the hls segment duration will not precise\n");
1492  hls->duration = (double)(pkt->pts - hls->end_pts) * st->time_base.num / st->time_base.den;
1493  }
1494  }
1495 
1496  }
1497  if (can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base,
1498  end_pts, AV_TIME_BASE_Q) >= 0) {
1499  int64_t new_start_pos;
1500  char *old_filename = av_strdup(hls->avf->filename);
1501  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1502 
1503  if (!old_filename) {
1504  return AVERROR(ENOMEM);
1505  }
1506 
1507  av_write_frame(oc, NULL); /* Flush any buffered data */
1508 
1509  new_start_pos = avio_tell(hls->avf->pb);
1510  hls->size = new_start_pos - hls->start_pos;
1511 
1512  if (!byterange_mode) {
1513  ff_format_io_close(s, &oc->pb);
1514  if (hls->vtt_avf) {
1515  ff_format_io_close(s, &hls->vtt_avf->pb);
1516  }
1517  }
1518  if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {
1519  if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0))
1520  if (hls->avf->oformat->priv_class && hls->avf->priv_data)
1521  av_opt_set(hls->avf->priv_data, "mpegts_flags", "resend_headers", 0);
1522  hls_rename_temp_file(s, oc);
1523  }
1524 
1525  ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);
1526  hls->start_pos = new_start_pos;
1527  if (ret < 0) {
1528  av_free(old_filename);
1529  return ret;
1530  }
1531 
1532  hls->end_pts = pkt->pts;
1533  hls->duration = 0;
1534 
1535  if (hls->flags & HLS_SINGLE_FILE) {
1536  hls->number++;
1537  } else if (hls->max_seg_size > 0) {
1538  if (hls->start_pos >= hls->max_seg_size) {
1539  hls->sequence++;
1540  sls_flag_file_rename(hls, old_filename);
1541  ret = hls_start(s);
1542  hls->start_pos = 0;
1543  /* When split segment by byte, the duration is short than hls_time,
1544  * so it is not enough one segment duration as hls_time, */
1545  hls->number--;
1546  }
1547  hls->number++;
1548  } else {
1549  sls_flag_file_rename(hls, old_filename);
1550  ret = hls_start(s);
1551  }
1552  av_free(old_filename);
1553 
1554  if (ret < 0) {
1555  return ret;
1556  }
1557 
1558  if ((ret = hls_window(s, 0)) < 0) {
1559  return ret;
1560  }
1561  }
1562 
1563  ret = ff_write_chained(oc, stream_index, pkt, s, 0);
1564 
1565  return ret;
1566 }
1567 
1568 static int hls_write_trailer(struct AVFormatContext *s)
1569 {
1570  HLSContext *hls = s->priv_data;
1571  AVFormatContext *oc = hls->avf;
1572  AVFormatContext *vtt_oc = hls->vtt_avf;
1573  char *old_filename = av_strdup(hls->avf->filename);
1574 
1575  if (!old_filename) {
1576  return AVERROR(ENOMEM);
1577  }
1578 
1579 
1580  av_write_trailer(oc);
1581  if (oc->pb) {
1582  hls->size = avio_tell(hls->avf->pb) - hls->start_pos;
1583  ff_format_io_close(s, &oc->pb);
1584 
1585  if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {
1586  hls_rename_temp_file(s, oc);
1587  }
1588 
1589  /* after av_write_trailer, then duration + 1 duration per packet */
1590  hls_append_segment(s, hls, hls->duration + hls->dpp, hls->start_pos, hls->size);
1591  }
1592 
1593  sls_flag_file_rename(hls, old_filename);
1594 
1595  if (vtt_oc) {
1596  if (vtt_oc->pb)
1597  av_write_trailer(vtt_oc);
1598  hls->size = avio_tell(hls->vtt_avf->pb) - hls->start_pos;
1599  ff_format_io_close(s, &vtt_oc->pb);
1600  }
1601  av_freep(&hls->basename);
1602  av_freep(&hls->key_basename);
1604 
1605  hls->avf = NULL;
1606  hls_window(s, 1);
1607 
1608  if (vtt_oc) {
1609  av_freep(&hls->vtt_basename);
1610  av_freep(&hls->vtt_m3u8_name);
1611  avformat_free_context(vtt_oc);
1612  }
1613 
1616  av_free(old_filename);
1617  return 0;
1618 }
1619 
1620 #define OFFSET(x) offsetof(HLSContext, x)
1621 #define E AV_OPT_FLAG_ENCODING_PARAM
1622 static const AVOption options[] = {
1623  {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
1624  {"hls_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E},
1625  {"hls_init_time", "set segment length in seconds at init list", OFFSET(init_time), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0, FLT_MAX, E},
1626  {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E},
1627  {"hls_ts_options","set hls mpegts list of options for the container format used for hls", OFFSET(format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1628  {"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},
1629 #if FF_API_HLS_WRAP
1630  {"hls_wrap", "set number after which the index wraps (will be deprecated)", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
1631 #endif
1632  {"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},
1633  {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1634  {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1635  {"hls_segment_size", "maximum size per segment file, (in bytes)", OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
1636  {"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},
1637  {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
1638  {"hls_enc_key", "hex-coded 16 byte key to encrypt the segments", OFFSET(key), AV_OPT_TYPE_STRING, .flags = E},
1639  {"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},
1640  {"hls_enc_iv", "hex-coded 16 byte initialization vector", OFFSET(iv), AV_OPT_TYPE_STRING, .flags = E},
1641  {"hls_subtitle_path", "set path of hls subtitles", OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1642  {"hls_flags", "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "flags"},
1643  {"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"},
1644  {"temp_file", "write segment to temporary file and rename when complete", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_TEMP_FILE }, 0, UINT_MAX, E, "flags"},
1645  {"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"},
1646  {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, "flags"},
1647  {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, "flags"},
1648  {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, "flags"},
1649  {"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"},
1650  {"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"},
1651  {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX, E, "flags"},
1652  {"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"},
1653  {"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"},
1654  {"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"},
1655  {"use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1656  {"use_localtime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1657  {"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" },
1658  {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, "pl_type" },
1659  {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, "pl_type" },
1660  {"method", "set the HTTP method(default: PUT)", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1661  {"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" },
1662  {"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" },
1663  {"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" },
1664  {"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" },
1665  { NULL },
1666 };
1667 
1668 static const AVClass hls_class = {
1669  .class_name = "hls muxer",
1670  .item_name = av_default_item_name,
1671  .option = options,
1672  .version = LIBAVUTIL_VERSION_INT,
1673 };
1674 
1675 
1677  .name = "hls",
1678  .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
1679  .extensions = "m3u8",
1680  .priv_data_size = sizeof(HLSContext),
1681  .audio_codec = AV_CODEC_ID_AAC,
1682  .video_codec = AV_CODEC_ID_H264,
1683  .subtitle_codec = AV_CODEC_ID_WEBVTT,
1688  .priv_class = &hls_class,
1689 };
float time
Definition: hlsenc.c:109
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:671
static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int version, int target_duration, int64_t sequence)
Definition: hlsenc.c:914
#define NULL
Definition: coverity.c:32
const char const char void * val
Definition: avisynth_c.h:771
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:158
const char * s
Definition: avisynth_c.h:768
Bytestream IO Context.
Definition: avio.h:155
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition: avstring.h:206
char * basename
Definition: hlsenc.c:141
PlaylistType
Definition: hlsenc.c:90
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1605
AVOption.
Definition: opt.h:246
static int hls_write_trailer(struct AVFormatContext *s)
Definition: hlsenc.c:1568
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:919
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:86
else temp
Definition: vf_mcdeint.c:259
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:4725
double duration
Definition: hlsenc.c:63
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 int replace_int_data_in_filename(char *buf, int buf_size, const char *filename, char placeholder, int64_t number)
Definition: hlsenc.c:207
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:1365
char * vtt_format_options_str
Definition: hlsenc.c:146
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:959
char * key_basename
Definition: hlsenc.c:154
int64_t size
Definition: hlsenc.c:66
int num
Numerator.
Definition: rational.h:59
int use_localtime_mkdir
flag to mkdir dirname in timebased filename
Definition: hlsenc.c:120
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition: dict.c:35
const char * b
Definition: vf_curves.c:113
static int mkdir_p(const char *path)
Definition: hlsenc.c:174
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:235
#define AVIO_FLAG_READ
read-only
Definition: avio.h:622
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:623
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
static int do_encrypt(AVFormatContext *s)
Definition: hlsenc.c:380
int version
Definition: avisynth_c.h:766
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:222
static AVPacket pkt
#define AVFMT_ALLOW_FLUSH
Format allows flushing.
Definition: avformat.h:495
static int hls_window(AVFormatContext *s, int last)
Definition: hlsenc.c:938
Format I/O context.
Definition: avformat.h:1349
int max_nb_segments
Definition: hlsenc.c:111
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:438
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:153
const char * av_basename(const char *path)
Thread safe basename.
Definition: avstring.c:257
int new_start
Definition: hlsenc.c:125
uint8_t
static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double duration, int64_t pos, int64_t size)
Definition: hlsenc.c:720
#define av_malloc(s)
float init_time
Definition: hlsenc.c:110
AVOptions.
miscellaneous OS support macros and functions.
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:1686
static void hls_free_segments(HLSSegment *p)
Definition: hlsenc.c:890
HLSSegment * old_segments
Definition: hlsenc.c:139
int64_t end_pts
Definition: hlsenc.c:128
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5437
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4355
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1417
int64_t duration
Definition: movenc.c:63
int discont
Definition: hlsenc.c:64
char * protocol_whitelist
',' separated list of allowed protocols.
Definition: avformat.h:1887
static int flags
Definition: log.c:57
#define AVERROR_EOF
End of file.
Definition: error.h:55
char * format_options_str
Definition: hlsenc.c:145
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
#define LINE_BUFFER_SIZE
Definition: hlsenc.c:57
ptrdiff_t size
Definition: opengl_enc.c:101
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:527
char * key
Definition: hlsenc.c:151
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:209
static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls, HLSSegment *en, double duration, int64_t pos, int64_t size)
Definition: hlsenc.c:570
#define av_log(a,...)
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:621
struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1368
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: avcodec.h:4141
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1700
int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
Definition: mux.c:148
static const AVOption options[]
Definition: hlsenc.c:1622
double initial_prog_date_time
Definition: hlsenc.c:165
static int hls_write_header(AVFormatContext *s)
Definition: hlsenc.c:1231
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2279
#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:1567
#define OFFSET(x)
Definition: hlsenc.c:1620
av_default_item_name
#define AVERROR(e)
Definition: error.h:43
struct HLSSegment * next
Definition: hlsenc.c:71
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:179
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:1096
static const char * get_default_pattern_localtime_fmt(void)
Definition: hlsenc.c:1220
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
char sub_filename[1024]
Definition: hlsenc.c:62
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:4108
AVDictionary * vtt_format_options
Definition: hlsenc.c:161
Definition: graph2dot.c:48
#define wrap(func)
Definition: neontest.h:65
simple assert() macros that are a bit more flexible than ISO C assert().
int has_video
Definition: hlsenc.c:123
double duration
Definition: hlsenc.c:129
static av_always_inline av_const double round(double x)
Definition: libm.h:444
#define FF_API_HLS_WRAP
Definition: version.h:89
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:68
int64_t recording_time
Definition: hlsenc.c:122
#define FFMAX(a, b)
Definition: common.h:94
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:90
int64_t pos
Definition: hlsenc.c:65
char * vtt_basename
Definition: hlsenc.c:142
static struct tm * gmtime_r(const time_t *clock, struct tm *result)
Definition: time_internal.h:26
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1674
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:1833
static int get_int_from_double(double val)
Definition: hlsenc.c:169
char * baseurl
Definition: hlsenc.c:144
static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c)
Definition: hlsenc.c:901
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
Definition: hls.c:67
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1405
int discontinuity_set
Definition: hlsenc.c:134
StartSequenceSourceType
Definition: hlsenc.c:50
static int sls_flag_check_duration_size_index(HLSContext *hls)
Definition: hlsenc.c:616
unsigned number
Definition: hlsenc.c:99
char key_string[KEYSIZE *2+1]
Definition: hlsenc.c:159
#define HLS_MICROSECOND_UNIT
Definition: hlsenc.c:58
static int randomize(uint8_t *buf, int len)
Definition: hlsenc.c:366
int64_t max_seg_size
Definition: hlsenc.c:132
char filename[1024]
input or output filename
Definition: avformat.h:1425
#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:519
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
static struct tm * localtime_r(const time_t *clock, struct tm *result)
Definition: time_internal.h:37
int64_t start_pts
Definition: hlsenc.c:127
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:94
static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: hlsenc.c:1443
const char * name
Definition: avformat.h:524
HLSSegment * last_segment
Definition: hlsenc.c:138
int discontinuity
Definition: hlsenc.c:135
#define E
Definition: hlsenc.c:1621
AVDictionary * metadata
Definition: avformat.h:961
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:98
HLSSegment * segments
Definition: hlsenc.c:137
AVDictionary * format_options
Definition: hlsenc.c:148
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
Read a whole line of text from AVIOContext.
Definition: aviobuf.c:782
const AVClass * priv_class
AVClass for the private context.
Definition: avformat.h:552
static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
Definition: hlsenc.c:501
static void sls_flag_file_rename(HLSContext *hls, char *old_filename)
Definition: hlsenc.c:659
int use_localtime
flag to expand filename with localtime
Definition: hlsenc.c:119
Stream structure.
Definition: avformat.h:889
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition: dict.c:180
char * key_url
Definition: hlsenc.c:152
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:69
int64_t start_sequence
Definition: hlsenc.c:101
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:237
static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c)
Definition: hlsenc.c:666
int has_subtitle
Definition: hlsenc.c:124
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
AVIOContext * pb
I/O context.
Definition: avformat.h:1391
static int hls_encryption_start(AVFormatContext *s)
Definition: hlsenc.c:449
char * key_info_file
Definition: hlsenc.c:156
AVOutputFormat * oformat
Definition: hlsenc.c:103
double dpp
Definition: hlsenc.c:126
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;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);returnNULL;}returnac;}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;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->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);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
char * method
Definition: hlsenc.c:163
void * buf
Definition: avisynth_c.h:690
int allowcache
Definition: hlsenc.c:121
HLSFlags
Definition: hlsenc.c:74
static int ff_rename(const char *oldpath, const char *newpath, void *logctx)
Wrap errno on rename() error.
Definition: internal.h:538
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
Describe the class of an AVClass context structure.
Definition: log.h:67
static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
Definition: hlsenc.c:927
int encrypt
Definition: hlsenc.c:150
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:160
#define snprintf
Definition: snprintf.h:34
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4290
int64_t sequence
Definition: hlsenc.c:100
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:1065
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
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:473
char key_file[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:157
static int hls_mux_init(AVFormatContext *s)
Definition: hlsenc.c:509
static HLSSegment * find_segment_by_filename(HLSSegment *segment, const char *filename)
Definition: hlsenc.c:560
int64_t size
Definition: hlsenc.c:131
char current_segment_final_filename_fmt[1024]
Definition: hlsenc.c:166
uint32_t pl_type
Definition: hlsenc.c:116
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
int nb_entries
Definition: hlsenc.c:133
Main libavformat public API header.
int
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:478
static double c[64]
const char * av_dirname(char *path)
Thread safe dirname.
Definition: avstring.c:274
uint32_t flags
Definition: hlsenc.c:115
static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls)
Definition: hlsenc.c:259
int pts_wrap_bits
number of bits in pts (used for wrapping control)
Definition: avformat.h:1055
int den
Denominator.
Definition: rational.h:60
static int parse_playlist(AVFormatContext *s, const char *url)
Definition: hlsenc.c:805
#define KEYSIZE
Definition: hlsenc.c:56
int64_t start_pos
Definition: hlsenc.c:130
char * segment_filename
Definition: hlsenc.c:117
#define av_free(p)
int len
char * vtt_m3u8_name
Definition: hlsenc.c:143
uint32_t start_sequence_source_type
Definition: hlsenc.c:102
char filename[1024]
Definition: hlsenc.c:61
static int hls_start(AVFormatContext *s)
Definition: hlsenc.c:1071
void * priv_data
Format private data.
Definition: avformat.h:1377
char * subtitle_filename
Definition: hlsenc.c:147
static const uint8_t start_sequence[]
Definition: rtpdec_h264.c:65
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:337
#define lrint
Definition: tablegen.h:53
AVFormatContext * avf
Definition: hlsenc.c:106
AVOutputFormat ff_hls_muxer
Definition: hlsenc.c:1676
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1294
char * protocol_blacklist
',' separated list of disallowed protocols.
Definition: avformat.h:1922
FILE * out
Definition: movenc.c:54
#define av_freep(p)
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:60
AVCodecParameters * codecpar
Definition: avformat.h:1252
int avio_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:345
AVOutputFormat * vtt_oformat
Definition: hlsenc.c:104
static int sls_flag_check_duration_size(HLSContext *hls)
Definition: hlsenc.c:639
int stream_index
Definition: avcodec.h:1670
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:926
static const AVClass hls_class
Definition: hlsenc.c:1668
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
Definition: avformat.h:1909
char * ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase)
Definition: utils.c:4676
This structure stores compressed data.
Definition: avcodec.h:1645
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:449
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1915
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1661
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
AVFormatContext * vtt_avf
Definition: hlsenc.c:107