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 "config_components.h"
25 #include <stdint.h>
26 #include <time.h>
27 #if HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 
32 #include "libavutil/avassert.h"
33 #include "libavutil/mathematics.h"
34 #include "libavutil/avstring.h"
35 #include "libavutil/bprint.h"
36 #include "libavutil/intreadwrite.h"
37 #include "libavutil/mem.h"
38 #include "libavutil/opt.h"
39 #include "libavutil/parseutils.h"
40 #include "libavutil/log.h"
41 #include "libavutil/random_seed.h"
42 #include "libavutil/time.h"
44 
45 #include "libavcodec/defs.h"
46 
47 #include "avformat.h"
48 #include "avio_internal.h"
49 #if CONFIG_HTTP_PROTOCOL
50 #include "http.h"
51 #endif
52 #include "hlsplaylist.h"
53 #include "internal.h"
54 #include "mux.h"
55 #include "os_support.h"
56 #include "url.h"
57 
58 typedef enum {
65 
66 typedef enum {
70 
71 #define KEYSIZE 16
72 #define LINE_BUFFER_SIZE MAX_URL_SIZE
73 #define HLS_MICROSECOND_UNIT 1000000
74 #define BUFSIZE (16 * 1024)
75 #define POSTFIX_PATTERN "_%d"
76 
77 typedef struct HLSSegment {
78  const char *filename;
79  const char *sub_filename;
80  double duration; /* in seconds */
81  int discont;
84  unsigned var_stream_idx;
85 
86  const char *key_uri;
87  char iv_string[KEYSIZE*2 + 1];
88 
89  struct HLSSegment *next;
91 
92  char buf[]; /* for filename, sub_filename and key_uri */
93 } HLSSegment;
94 
95 typedef enum HLSFlags {
96  // Generate a single media file and use byte ranges in the playlist.
97  HLS_SINGLE_FILE = (1 << 0),
98  HLS_DELETE_SEGMENTS = (1 << 1),
99  HLS_ROUND_DURATIONS = (1 << 2),
100  HLS_DISCONT_START = (1 << 3),
101  HLS_OMIT_ENDLIST = (1 << 4),
102  HLS_SPLIT_BY_TIME = (1 << 5),
103  HLS_APPEND_LIST = (1 << 6),
105  HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in segment filenames when use_localtime e.g.: %%03d
106  HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration (microsec) in segment filenames when use_localtime e.g.: %%09t
107  HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) in segment filenames when use_localtime e.g.: %%014s
108  HLS_TEMP_FILE = (1 << 11),
109  HLS_PERIODIC_REKEY = (1 << 12),
111  HLS_I_FRAMES_ONLY = (1 << 14),
112 } HLSFlags;
113 
114 typedef enum {
117 } SegmentType;
118 
119 typedef struct VariantStream {
120  unsigned var_stream_idx;
121  unsigned number;
129  uint8_t *temp_buffer;
130  uint8_t *init_buffer;
131 
134 
139  double dpp; // duration per packet
143  double duration; // last segment duration computed so far, in seconds
144  int64_t start_pos; // last segment starting position
145  int64_t size; // last segment size
150 
155 
159 
161  char *basename;
164  char *m3u8_name;
165 
167  char current_segment_final_filename_fmt[MAX_URL_SIZE]; // when renaming segments
168 
171 
173 
176  char key_string[KEYSIZE*2 + 1];
177  char iv_string[KEYSIZE*2 + 1];
178 
180  char codec_attr[128];
182  unsigned int nb_streams;
183  int m3u8_created; /* status of media play-list creation */
184  int is_default; /* default status of audio group */
185  const char *language; /* audio language name */
186  const char *agroup; /* audio group name */
187  const char *sgroup; /* subtitle group name */
188  const char *ccgroup; /* closed caption group name */
189  const char *varname; /* variant name */
190  const char *subtitle_varname; /* subtitle variant name */
191 } VariantStream;
192 
193 typedef struct ClosedCaptionsStream {
194  const char *ccgroup; /* closed caption group name */
195  const char *instreamid; /* closed captions INSTREAM-ID */
196  const char *language; /* closed captions language */
198 
199 typedef struct HLSContext {
200  const AVClass *class; // Class for private options.
202  uint32_t start_sequence_source_type; // enum StartSequenceSourceType
203 
204  int64_t time; // Set by a private option.
205  int64_t init_time; // Set by a private option.
206  int max_nb_segments; // Set by a private option.
207  int hls_delete_threshold; // Set by a private option.
208  uint32_t flags; // enum HLSFlags
209  uint32_t pl_type; // enum PlaylistType
213  int resend_init_file; ///< resend init file into disk after refresh m3u8
214 
215  int use_localtime; ///< flag to expand filename with localtime
216  int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename
219  int64_t max_seg_size; // every segment file max size
220 
221  char *baseurl;
225 
226  int encrypt;
227  char *key;
228  char *key_url;
229  char *iv;
232 
236  char key_string[KEYSIZE*2 + 1];
237  char iv_string[KEYSIZE*2 + 1];
239 
240  char *method;
241  char *user_agent;
242 
244  unsigned int nb_varstreams;
246  unsigned int nb_ccstreams;
247 
248  int master_m3u8_created; /* status of master play-list creation */
249  char *master_m3u8_url; /* URL of the master m3u8 file */
250  int version; /* HLS version */
251  char *var_stream_map; /* user specified variant stream map string */
252  char *cc_stream_map; /* user specified closed caption streams map string */
254  unsigned int master_publish_rate;
255  int http_persistent;
261  char *headers;
262  int has_default_key; /* has DEFAULT field of var_stream_map */
263  int has_video_m3u8; /* has video stream m3u8 list */
264 } HLSContext;
265 
266 static int strftime_expand(const char *fmt, char **dest)
267 {
268  int r = 1;
269  time_t now0;
270  struct tm *tm, tmpbuf;
271  char *buf;
272 
273  buf = av_mallocz(MAX_URL_SIZE);
274  if (!buf)
275  return AVERROR(ENOMEM);
276 
277  time(&now0);
278  tm = localtime_r(&now0, &tmpbuf);
279  r = strftime(buf, MAX_URL_SIZE, fmt, tm);
280  if (!r) {
281  av_free(buf);
282  return AVERROR(EINVAL);
283  }
284  *dest = buf;
285 
286  return r;
287 }
288 
289 static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, const char *filename,
291 {
292  HLSContext *hls = s->priv_data;
293  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
294  int err = AVERROR_MUXER_NOT_FOUND;
295  if (!*pb || !http_base_proto || !hls->http_persistent) {
296  err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
297 #if CONFIG_HTTP_PROTOCOL
298  } else {
299  URLContext *http_url_context = ffio_geturlcontext(*pb);
300  av_assert0(http_url_context);
301  err = ff_http_do_new_request(http_url_context, filename);
302  if (err < 0)
303  ff_format_io_close(s, pb);
304 
305 #endif
306  }
307  return err;
308 }
309 
310 static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
311 {
312  HLSContext *hls = s->priv_data;
313  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
314  int ret = 0;
315  if (!*pb)
316  return ret;
317  if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) {
318  ff_format_io_close(s, pb);
319 #if CONFIG_HTTP_PROTOCOL
320  } else {
321  URLContext *http_url_context = ffio_geturlcontext(*pb);
322  av_assert0(http_url_context);
323  avio_flush(*pb);
324  ret = ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
325 #endif
326  }
327  return ret;
328 }
329 
331 {
332  int http_base_proto = ff_is_http_proto(s->url);
333 
334  if (c->method) {
335  av_dict_set(options, "method", c->method, 0);
336  } else if (http_base_proto) {
337  av_dict_set(options, "method", "PUT", 0);
338  }
339  if (c->user_agent)
340  av_dict_set(options, "user_agent", c->user_agent, 0);
341  if (c->http_persistent)
342  av_dict_set_int(options, "multiple_requests", 1, 0);
343  if (c->timeout >= 0)
344  av_dict_set_int(options, "timeout", c->timeout, 0);
345  if (c->headers)
346  av_dict_set(options, "headers", c->headers, 0);
347 }
348 
350 {
351  int codec_strlen = strlen(vs->codec_attr);
352  char attr[32];
353  AVBPrint buffer;
354 
356  return;
358  return;
359 
360  av_bprint_init_for_buffer(&buffer, attr, sizeof(attr));
361  if (ff_make_codec_str(vs->avf, st->codecpar, &st->avg_frame_rate,
362  &buffer) < 0)
363  goto fail;
364 
365  // Don't write the same attribute multiple times
366  if (!av_stristr(vs->codec_attr, attr)) {
367  snprintf(vs->codec_attr + codec_strlen,
368  sizeof(vs->codec_attr) - codec_strlen,
369  "%s%s", codec_strlen ? "," : "", attr);
370  }
371  return;
372 
373 fail:
374  vs->codec_attr[0] = '\0';
376  return;
377 }
378 
379 static int replace_str_data_in_filename(char **s, const char *filename, char placeholder, const char *datastring)
380 {
381  const char *p;
382  char c;
383  int addchar_count;
384  int found_count = 0;
385  AVBPrint buf;
386  int ret;
387 
389 
390  p = filename;
391  for (;;) {
392  c = *p;
393  if (c == '\0')
394  break;
395  if (c == '%' && *(p+1) == '%') // %%
396  addchar_count = 2;
397  else if (c == '%' && *(p+1) == placeholder) {
398  av_bprintf(&buf, "%s", datastring);
399  p += 2;
400  addchar_count = 0;
401  found_count ++;
402  } else
403  addchar_count = 1;
404 
405  if (addchar_count > 0) {
406  av_bprint_append_data(&buf, p, addchar_count);
407  p += addchar_count;
408  }
409  }
410  if (!av_bprint_is_complete(&buf)) {
411  av_bprint_finalize(&buf, NULL);
412  return AVERROR(ENOMEM);
413  }
414  if ((ret = av_bprint_finalize(&buf, s)) < 0)
415  return ret;
416  return found_count;
417 }
418 
419 static int replace_int_data_in_filename(char **s, const char *filename, char placeholder, int64_t number)
420 {
421  const char *p;
422  char c;
423  int nd, addchar_count;
424  int found_count = 0;
425  AVBPrint buf;
426  int ret;
427 
429 
430  p = filename;
431  for (;;) {
432  c = *p;
433  if (c == '\0')
434  break;
435  if (c == '%' && *(p+1) == '%') // %%
436  addchar_count = 2;
437  else if (c == '%' && (av_isdigit(*(p+1)) || *(p+1) == placeholder)) {
438  nd = 0;
439  addchar_count = 1;
440  while (av_isdigit(*(p + addchar_count))) {
441  nd = nd * 10 + *(p + addchar_count) - '0';
442  addchar_count++;
443  }
444 
445  if (*(p + addchar_count) == placeholder) {
446  av_bprintf(&buf, "%0*"PRId64, (number < 0) ? nd : nd++, number);
447  p += (addchar_count + 1);
448  addchar_count = 0;
449  found_count++;
450  }
451 
452  } else
453  addchar_count = 1;
454 
455  av_bprint_append_data(&buf, p, addchar_count);
456  p += addchar_count;
457  }
458  if (!av_bprint_is_complete(&buf)) {
459  av_bprint_finalize(&buf, NULL);
460  return AVERROR(ENOMEM);
461  }
462  if ((ret = av_bprint_finalize(&buf, s)) < 0)
463  return ret;
464  return found_count;
465 }
466 
467 static void write_styp(AVIOContext *pb)
468 {
469  avio_wb32(pb, 24);
470  ffio_wfourcc(pb, "styp");
471  ffio_wfourcc(pb, "msdh");
472  avio_wb32(pb, 0); /* minor */
473  ffio_wfourcc(pb, "msdh");
474  ffio_wfourcc(pb, "msix");
475 }
476 
477 static int flush_dynbuf(VariantStream *vs, int *range_length)
478 {
479  AVFormatContext *ctx = vs->avf;
480 
481  if (!ctx->pb) {
482  return AVERROR(EINVAL);
483  }
484 
485  // flush
487 
488  // write out to file
489  *range_length = avio_close_dyn_buf(ctx->pb, &vs->temp_buffer);
490  ctx->pb = NULL;
491  avio_write(vs->out, vs->temp_buffer, *range_length);
492  avio_flush(vs->out);
493 
494  // re-open buffer
495  return avio_open_dyn_buf(&ctx->pb);
496 }
497 
498 static void reflush_dynbuf(VariantStream *vs, int *range_length)
499 {
500  // re-open buffer
501  avio_write(vs->out, vs->temp_buffer, *range_length);
502 }
503 
505  char *path, const char *proto)
506 {
507  if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
508  AVDictionary *opt = NULL;
509  int ret;
510 
511  set_http_options(avf, &opt, hls);
512  av_dict_set(&opt, "method", "DELETE", 0);
513 
514  ret = hlsenc_io_open(avf, &hls->http_delete, path, &opt);
515  av_dict_free(&opt);
516  if (ret < 0)
517  return hls->ignore_io_errors ? 1 : ret;
518 
519  //Nothing to write
520  hlsenc_io_close(avf, &hls->http_delete, path);
521  } else if (unlink(path) < 0) {
522  av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
523  path, strerror(errno));
524  }
525  return 0;
526 }
527 
529  VariantStream *vs)
530 {
531 
532  HLSSegment *segment, *previous_segment = NULL;
533  float playlist_duration = 0.0f;
534  int ret = 0;
535  int segment_cnt = 0;
536  AVBPrint path;
537  const char *dirname = NULL;
538  char *dirname_r = NULL;
539  char *dirname_repl = NULL;
540  const char *vtt_dirname = NULL;
541  char *vtt_dirname_r = NULL;
542  const char *proto = NULL;
543 
545 
546  segment = vs->segments;
547  while (segment) {
548  playlist_duration += segment->duration;
549  segment = segment->next;
550  }
551 
552  segment = vs->old_segments;
553  segment_cnt = 0;
554  while (segment) {
555  playlist_duration -= segment->duration;
556  previous_segment = segment;
557  segment = previous_segment->next;
558  segment_cnt++;
559  if (playlist_duration <= -previous_segment->duration) {
560  previous_segment->next = NULL;
561  break;
562  }
563  if (segment_cnt >= hls->hls_delete_threshold) {
564  previous_segment->next = NULL;
565  break;
566  }
567  }
568 
569  if (segment && !hls->use_localtime_mkdir) {
570  dirname_r = hls->segment_filename ? av_strdup(hls->segment_filename): av_strdup(vs->avf->url);
571  dirname = av_dirname(dirname_r);
572  }
573 
574  /* if %v is present in the file's directory
575  * all segment belongs to the same variant, so do it only once before the loop*/
576  if (dirname && av_stristr(dirname, "%v")) {
577  if (!vs->varname) {
578  if (replace_int_data_in_filename(&dirname_repl, dirname, 'v', segment->var_stream_idx) < 1) {
579  ret = AVERROR(EINVAL);
580  goto fail;
581  }
582  } else {
583  if (replace_str_data_in_filename(&dirname_repl, dirname, 'v', vs->varname) < 1) {
584  ret = AVERROR(EINVAL);
585  goto fail;
586  }
587  }
588 
589  dirname = dirname_repl;
590  }
591 
592  while (segment) {
593  av_log(hls, AV_LOG_DEBUG, "deleting old segment %s\n",
594  segment->filename);
595  if (!hls->use_localtime_mkdir) // segment->filename contains basename only
596  av_bprintf(&path, "%s/", dirname);
597  av_bprintf(&path, "%s", segment->filename);
598 
599  if (!av_bprint_is_complete(&path)) {
600  ret = AVERROR(ENOMEM);
601  goto fail;
602  }
603 
604  proto = avio_find_protocol_name(s->url);
605  if (ret = hls_delete_file(hls, s, path.str, proto))
606  goto fail;
607 
608  if ((segment->sub_filename[0] != '\0')) {
609  vtt_dirname_r = av_strdup(vs->vtt_avf->url);
610  vtt_dirname = av_dirname(vtt_dirname_r);
611 
612  av_bprint_clear(&path);
613  av_bprintf(&path, "%s/%s", vtt_dirname, segment->sub_filename);
614  av_freep(&vtt_dirname_r);
615 
616  if (!av_bprint_is_complete(&path)) {
617  ret = AVERROR(ENOMEM);
618  goto fail;
619  }
620 
621  if (ret = hls_delete_file(hls, s, path.str, proto))
622  goto fail;
623  }
624  av_bprint_clear(&path);
625  previous_segment = segment;
626  segment = previous_segment->next;
627  av_freep(&previous_segment);
628  }
629 
630 fail:
631  av_bprint_finalize(&path, NULL);
632  av_freep(&dirname_r);
633  av_freep(&dirname_repl);
634 
635  return ret;
636 }
637 
639 {
640  HLSContext *hls = s->priv_data;
641  int ret;
642  int len;
643  AVIOContext *pb;
644  uint8_t key[KEYSIZE];
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  memcpy(hls->iv_string, buf, sizeof(hls->iv_string));
674  }
675 
676  if (!*hls->key_uri) {
677  av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
678  return AVERROR(EINVAL);
679  }
680 
681  if (!*hls->key_file) {
682  av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
683  return AVERROR(EINVAL);
684  }
685 
686  if (!*hls->key_string) {
688  if (!hls->key) {
689  if ((ret = av_random_bytes(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  set_http_options(s, &options, hls);
699  ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_WRITE, &options);
701  if (ret < 0)
702  return ret;
703  avio_seek(pb, 0, SEEK_CUR);
704  avio_write(pb, key, KEYSIZE);
705  ff_format_io_close(s, &pb);
706  }
707  return 0;
708 }
709 
710 
712 {
713  HLSContext *hls = s->priv_data;
714  int ret;
715  AVIOContext *pb;
716  uint8_t key[KEYSIZE];
718 
719  set_http_options(s, &options, hls);
720  ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, &options);
722  if (ret < 0) {
723  av_log(hls, AV_LOG_ERROR,
724  "error opening key info file %s\n", hls->key_info_file);
725  return ret;
726  }
727 
728  ff_get_line(pb, vs->key_uri, sizeof(vs->key_uri));
729  vs->key_uri[strcspn(vs->key_uri, "\r\n")] = '\0';
730 
731  ff_get_line(pb, vs->key_file, sizeof(vs->key_file));
732  vs->key_file[strcspn(vs->key_file, "\r\n")] = '\0';
733 
734  ff_get_line(pb, vs->iv_string, sizeof(vs->iv_string));
735  vs->iv_string[strcspn(vs->iv_string, "\r\n")] = '\0';
736 
737  ff_format_io_close(s, &pb);
738 
739  if (!*vs->key_uri) {
740  av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
741  return AVERROR(EINVAL);
742  }
743 
744  if (!*vs->key_file) {
745  av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
746  return AVERROR(EINVAL);
747  }
748 
749  set_http_options(s, &options, hls);
750  ret = s->io_open(s, &pb, vs->key_file, AVIO_FLAG_READ, &options);
752  if (ret < 0) {
753  av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", vs->key_file);
754  return ret;
755  }
756 
757  ret = avio_read(pb, key, sizeof(key));
758  ff_format_io_close(s, &pb);
759  if (ret != sizeof(key)) {
760  av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", vs->key_file);
761  if (ret >= 0 || ret == AVERROR_EOF)
762  ret = AVERROR(EINVAL);
763  return ret;
764  }
765  ff_data_to_hex(vs->key_string, key, sizeof(key), 0);
766 
767  return 0;
768 }
769 
771 {
773  HLSContext *hls = s->priv_data;
774  AVFormatContext *oc;
775  AVFormatContext *vtt_oc = NULL;
776  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
777  int remaining_options;
778  int i, ret;
779 
781  if (ret < 0)
782  return ret;
783  oc = vs->avf;
784 
785  oc->url = av_strdup("");
786  if (!oc->url)
787  return AVERROR(ENOMEM);
788 
789  oc->interrupt_callback = s->interrupt_callback;
790  oc->max_delay = s->max_delay;
791  oc->opaque = s->opaque;
792  oc->io_open = s->io_open;
793  oc->io_close2 = s->io_close2;
794  oc->strict_std_compliance = s->strict_std_compliance;
795  oc->flags = s->flags;
796  av_dict_copy(&oc->metadata, s->metadata, 0);
797 
798  if (vs->vtt_oformat) {
800  if (ret < 0)
801  return ret;
802  vtt_oc = vs->vtt_avf;
803  vtt_oc->flags = s->flags;
804  av_dict_copy(&vtt_oc->metadata, s->metadata, 0);
805  }
806 
807  for (i = 0; i < vs->nb_streams; i++) {
808  AVStream *st;
809  AVFormatContext *loc;
811  loc = vtt_oc;
812  else
813  loc = oc;
814 
815  if (!(st = avformat_new_stream(loc, NULL)))
816  return AVERROR(ENOMEM);
818  if (ret < 0)
819  return ret;
820  if (!oc->oformat->codec_tag ||
824  } else {
825  st->codecpar->codec_tag = 0;
826  }
827 
829  st->time_base = vs->streams[i]->time_base;
830  av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0);
831  st->id = vs->streams[i]->id;
832  }
833 
834  for (i = 0; i < s->nb_programs; i++) {
835  ret = av_program_copy(oc, (const AVFormatContext *)s, s->programs[i]->id, 0);
836  if (ret < 0) {
837  av_log(s, AV_LOG_ERROR, "unable to transfer program %d to child muxer\n", s->programs[i]->id);
838  return ret;
839  }
840  }
841 
842  vs->start_pos = 0;
843  vs->new_start = 1;
844 
845  if (hls->segment_type == SEGMENT_TYPE_FMP4 && hls->max_seg_size > 0) {
846  if (hls->http_persistent > 0) {
847  //TODO: Support fragment fmp4 for http persistent in HLS muxer.
848  av_log(s, AV_LOG_WARNING, "http persistent mode is currently unsupported for fragment mp4 in the HLS muxer.\n");
849  }
850  if (hls->max_seg_size > 0) {
851  av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n");
852  return AVERROR_PATCHWELCOME;
853  }
854  }
855 
856  if ((ret = avio_open_dyn_buf(&oc->pb)) < 0)
857  return ret;
858 
859  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
860  set_http_options(s, &options, hls);
861  if (byterange_mode) {
862  ret = hlsenc_io_open(s, &vs->out, vs->basename, &options);
863  } else {
865  }
867  }
868  if (ret < 0) {
869  av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename);
870  return ret;
871  }
872 
874  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
875  av_dict_set(&options, "fflags", "-autobsf", 0);
876  av_dict_set(&options, "movflags", "+frag_custom+dash+delay_moov", AV_DICT_APPEND);
877  } else {
878  /* We only require one PAT/PMT per segment. */
879  char period[21];
880  snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1);
883  }
885  remaining_options = av_dict_count(options);
887  if (ret < 0)
888  return ret;
889  if (remaining_options) {
890  av_log(s, AV_LOG_ERROR, "Some of the provided format options are not recognized\n");
891  return AVERROR(EINVAL);
892  }
893  avio_flush(oc->pb);
894  return 0;
895 }
896 
897 static HLSSegment *find_segment_by_filename(HLSSegment *segment, const char *filename)
898 {
899  while (segment) {
900  if (!av_strcasecmp(segment->filename,filename))
901  return segment;
902  segment = segment->next;
903  }
904  return (HLSSegment *) NULL;
905 }
906 
908  VariantStream *vs,
909  double duration, int64_t pos, int64_t size)
910 {
913  char * new_url = av_strdup(vs->current_segment_final_filename_fmt);
914  if (!new_url) {
915  return AVERROR(ENOMEM);
916  }
917  ff_format_set_url(vs->avf, new_url);
919  char *filename = NULL;
920  if (replace_int_data_in_filename(&filename, vs->avf->url, 's', pos + size) < 1) {
921  av_log(hls, AV_LOG_ERROR,
922  "Invalid second level segment filename template '%s', "
923  "you can try to remove second_level_segment_size flag\n",
924  vs->avf->url);
925  av_freep(&filename);
926  return AVERROR(EINVAL);
927  }
928  ff_format_set_url(vs->avf, filename);
929  }
931  char *filename = NULL;
932  if (replace_int_data_in_filename(&filename, vs->avf->url,
933  't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) {
934  av_log(hls, AV_LOG_ERROR,
935  "Invalid second level segment filename template '%s', "
936  "you can try to remove second_level_segment_duration flag\n",
937  vs->avf->url);
938  av_freep(&filename);
939  return AVERROR(EINVAL);
940  }
941  ff_format_set_url(vs->avf, filename);
942  }
943  }
944  return 0;
945 }
946 
948 {
949  int ret = 0;
950 
952  av_log(hls, AV_LOG_ERROR,
953  "second_level_segment_duration hls_flag requires strftime to be true\n");
954  ret = AVERROR(EINVAL);
955  }
957  av_log(hls, AV_LOG_ERROR,
958  "second_level_segment_size hls_flag requires strfime to be true\n");
959  ret = AVERROR(EINVAL);
960  }
962  av_log(hls, AV_LOG_ERROR,
963  "second_level_segment_index hls_flag requires strftime to be true\n");
964  ret = AVERROR(EINVAL);
965  }
966 
967  return ret;
968 }
969 
971 {
972  const char *proto = avio_find_protocol_name(vs->basename);
973  int segment_renaming_ok = proto && !strcmp(proto, "file");
974  int ret = 0;
975 
976  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) && !segment_renaming_ok) {
977  av_log(hls, AV_LOG_ERROR,
978  "second_level_segment_duration hls_flag works only with file protocol segment names\n");
979  ret = AVERROR(EINVAL);
980  }
981  if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) && !segment_renaming_ok) {
982  av_log(hls, AV_LOG_ERROR,
983  "second_level_segment_size hls_flag works only with file protocol segment names\n");
984  ret = AVERROR(EINVAL);
985  }
986 
987  return ret;
988 }
989 
990 static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename) {
993  ff_rename(old_filename, vs->avf->url, hls);
994  }
995 }
996 
998 {
999  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) {
1000  char *filename = NULL;
1001  if (replace_int_data_in_filename(&filename,
1002  oc->url, 'd', vs->sequence) < 1) {
1003  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1004  "you can try to remove second_level_segment_index flag\n",
1005  oc->url);
1006  av_freep(&filename);
1007  return AVERROR(EINVAL);
1008  }
1009  ff_format_set_url(oc, filename);
1010  }
1014  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
1015  char *filename = NULL;
1016  if (replace_int_data_in_filename(&filename, oc->url, 's', 0) < 1) {
1017  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1018  "you can try to remove second_level_segment_size flag\n",
1019  oc->url);
1020  av_freep(&filename);
1021  return AVERROR(EINVAL);
1022  }
1023  ff_format_set_url(oc, filename);
1024  }
1025  if (c->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) {
1026  char *filename = NULL;
1027  if (replace_int_data_in_filename(&filename, oc->url, 't', 0) < 1) {
1028  av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1029  "you can try to remove second_level_segment_duration flag\n",
1030  oc->url);
1031  av_freep(&filename);
1032  return AVERROR(EINVAL);
1033  }
1034  ff_format_set_url(oc, filename);
1035  }
1036  }
1037  return 0;
1038 }
1039 
1040 /* Create a new segment and append it to the segment list */
1042  VariantStream *vs, double duration, int64_t pos,
1043  int64_t size)
1044 {
1045  HLSSegment en0 = {0};
1046  HLSSegment *en = &en0;
1047  const char *filename;
1048  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1049  int ret;
1050  AVBPrint bp;
1051 
1052  vs->total_size += size;
1053  vs->total_duration += duration;
1054  if (duration > 0.5) {
1055  // Don't include the final, possibly very short segment in the
1056  // calculation of the max bitrate.
1057  int cur_bitrate = (int)(8 * size / duration);
1058  if (cur_bitrate > vs->max_bitrate)
1059  vs->max_bitrate = cur_bitrate;
1060  }
1061  if (vs->total_duration > 0)
1062  vs->avg_bitrate = (int)(8 * vs->total_size / vs->total_duration);
1063 
1064  en->var_stream_idx = vs->var_stream_idx;
1066  if (ret < 0)
1067  return ret;
1068 
1069  filename = av_basename(vs->avf->url);
1070 
1071  if (hls->use_localtime_mkdir) {
1072  filename = vs->avf->url;
1073  }
1074  if (vs->nb_entries <= 5000 && (find_segment_by_filename(vs->segments, filename) || find_segment_by_filename(vs->old_segments, filename))
1075  && !byterange_mode) {
1076  av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename);
1077  }
1078 
1080  av_bprintf(&bp, "%s%c", filename, 0);
1081  av_bprintf(&bp, "%s%c", vs->has_subtitle ? av_basename(vs->vtt_avf->url) : "", 0);
1082 
1083  en->duration = duration;
1084  en->pos = pos;
1085  en->size = size;
1086 
1087  if (vs->discontinuity) {
1088  en->discont = 1;
1089  vs->discontinuity = 0;
1090  }
1091 
1092  if (hls->key_info_file || hls->encrypt) {
1093  av_bprintf(&bp, "%s%c", vs->key_uri, 0);
1094  av_strlcpy(en->iv_string, vs->iv_string, sizeof(en->iv_string));
1095  } else {
1096  av_bprint_chars(&bp, 0, 1);
1097  }
1098 
1099  en = ff_bprint_finalize_as_fam(&bp, &en0, offsetof(HLSSegment, buf));
1100  if (!en)
1101  return AVERROR(ENOMEM);
1102 #define NEXT(s) ((s) + strlen(s) + 1)
1103  en->filename = en->buf;
1104  en->sub_filename = NEXT(en->filename);
1105  en->key_uri = NEXT(en->sub_filename);
1106 #undef NEXT
1107 
1108  if (!vs->segments)
1109  vs->segments = en;
1110  else
1111  vs->last_segment->next = en;
1112 
1113  vs->last_segment = en;
1114 
1115  // EVENT or VOD playlists imply sliding window cannot be used
1116  if (hls->pl_type != PLAYLIST_TYPE_NONE)
1117  hls->max_nb_segments = 0;
1118 
1119  if (hls->max_nb_segments && vs->nb_entries >= hls->max_nb_segments) {
1120  en = vs->segments;
1122  vs->initial_prog_date_time += en->duration;
1123  vs->segments = en->next;
1124  if (en && hls->flags & HLS_DELETE_SEGMENTS &&
1125  !(hls->flags & HLS_SINGLE_FILE)) {
1126  en->next = vs->old_segments;
1127  vs->old_segments = en;
1128  if ((ret = hls_delete_old_segments(s, hls, vs)) < 0)
1129  return ret;
1130  } else
1131  av_freep(&en);
1132  } else
1133  vs->nb_entries++;
1134 
1135  if (hls->max_seg_size > 0) {
1136  return 0;
1137  }
1138  vs->sequence++;
1139 
1140  return 0;
1141 }
1142 
1143 static int extract_segment_number(const char *filename) {
1144  const char *dot = strrchr(filename, '.');
1145  const char *num_start = dot - 1;
1146 
1147  while (num_start > filename && *num_start >= '0' && *num_start <= '9') {
1148  num_start--;
1149  }
1150 
1151  num_start++;
1152 
1153  if (num_start == dot)
1154  return -1;
1155 
1156  return atoi(num_start);
1157 }
1158 
1159 static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
1160 {
1161  HLSContext *hls = s->priv_data;
1162  AVIOContext *in;
1163  int ret = 0, is_segment = 0;
1164  int64_t new_start_pos;
1165  char line[MAX_URL_SIZE];
1166  const char *ptr;
1167  const char *end;
1168  double discont_program_date_time = 0;
1169 
1170  if ((ret = s->io_open(s, &in, url, AVIO_FLAG_READ, NULL)) < 0)
1171  return ret;
1172 
1173  ff_get_chomp_line(in, line, sizeof(line));
1174  if (strcmp(line, "#EXTM3U")) {
1176  goto fail;
1177  }
1178 
1179  vs->discontinuity = 0;
1180  while (!avio_feof(in)) {
1181  ff_get_chomp_line(in, line, sizeof(line));
1182  if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
1183  int64_t tmp_sequence = strtoll(ptr, NULL, 10);
1184  if (tmp_sequence < vs->sequence)
1185  av_log(hls, AV_LOG_VERBOSE,
1186  "Found playlist sequence number was smaller """
1187  "than specified start sequence number: %"PRId64" < %"PRId64", "
1188  "omitting\n", tmp_sequence, hls->start_sequence);
1189  else {
1190  av_log(hls, AV_LOG_DEBUG, "Found playlist sequence number: %"PRId64"\n", tmp_sequence);
1191  vs->sequence = tmp_sequence;
1192  }
1193  } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
1194  is_segment = 1;
1195  vs->discontinuity = 1;
1196  } else if (av_strstart(line, "#EXTINF:", &ptr)) {
1197  is_segment = 1;
1198  vs->duration = atof(ptr);
1199  } else if (av_stristart(line, "#EXT-X-KEY:", &ptr)) {
1200  ptr = av_stristr(line, "URI=\"");
1201  if (ptr) {
1202  ptr += strlen("URI=\"");
1203  end = av_stristr(ptr, ",");
1204  if (end) {
1205  av_strlcpy(vs->key_uri, ptr, end - ptr);
1206  } else {
1207  av_strlcpy(vs->key_uri, ptr, sizeof(vs->key_uri));
1208  }
1209  }
1210 
1211  ptr = av_stristr(line, "IV=0x");
1212  if (ptr) {
1213  ptr += strlen("IV=0x");
1214  end = av_stristr(ptr, ",");
1215  if (end) {
1216  av_strlcpy(vs->iv_string, ptr, end - ptr);
1217  } else {
1218  av_strlcpy(vs->iv_string, ptr, sizeof(vs->iv_string));
1219  }
1220  }
1221  } else if (av_strstart(line, "#EXT-X-PROGRAM-DATE-TIME:", &ptr)) {
1222  struct tm program_date_time = { 0 };
1223  double ms = 0;
1224  char *q = av_small_strptime(ptr, "%Y-%m-%dT%H:%M:%S", &program_date_time);
1225 
1226  if (!q) {
1228  goto fail;
1229  }
1230  if (*q == '.')
1231  ms = atof(q + 1);
1232  program_date_time.tm_isdst = -1;
1233 
1234  errno = 0;
1235  time_t t = mktime(&program_date_time);
1236  if (t == (time_t)-1 && errno == EOVERFLOW) {
1238  goto fail;
1239  }
1240  discont_program_date_time = t;
1241 
1242  discont_program_date_time += (double)(ms / 1000);
1243  } else if (av_strstart(line, "#", NULL)) {
1244  continue;
1245  } else if (line[0]) {
1246  if (is_segment) {
1247  char *new_file = av_strdup(line);
1248  if (!new_file) {
1249  ret = AVERROR(ENOMEM);
1250  goto fail;
1251  }
1252  ff_format_set_url(vs->avf, new_file);
1253 
1254  if (vs->has_subtitle) {
1255  int vtt_index = extract_segment_number(line);
1256  const char *vtt_basename = av_basename(vs->vtt_basename);
1257  char *vtt_file = NULL;
1258  ret = replace_int_data_in_filename(&vtt_file, vtt_basename, 'd', vtt_index);
1259  if (ret < 0 || !vtt_file) {
1260  ret = AVERROR(ENOMEM);
1261  goto fail;
1262  }
1263 
1264  ff_format_set_url(vs->vtt_avf, vtt_file);
1265  }
1266 
1267  is_segment = 0;
1268  new_start_pos = avio_tell(vs->avf->pb);
1269  vs->size = new_start_pos - vs->start_pos;
1270  ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size);
1271  if (discont_program_date_time) {
1272  vs->last_segment->discont_program_date_time = discont_program_date_time;
1273  discont_program_date_time += vs->duration;
1274  }
1275  if (ret < 0)
1276  goto fail;
1277  vs->start_pos = new_start_pos;
1278  }
1279  }
1280  }
1281 
1282 fail:
1283  ff_format_io_close(s, &in);
1284  return ret;
1285 }
1286 
1288 {
1289  HLSSegment *en;
1290 
1291  while (p) {
1292  en = p;
1293  p = p->next;
1294  av_freep(&en);
1295  }
1296 }
1297 
1299 {
1300  size_t len = strlen(oc->url);
1301  char *final_filename = av_strdup(oc->url);
1302  int ret;
1303 
1304  if (!final_filename)
1305  return AVERROR(ENOMEM);
1306  final_filename[len-4] = '\0';
1307  ret = ff_rename(oc->url, final_filename, s);
1308  oc->url[len-4] = '\0';
1309  av_freep(&final_filename);
1310  return ret;
1311 }
1312 
1313 static const char* get_relative_url(const char *master_url, const char *media_url)
1314 {
1315  const char *p = strrchr(master_url, '/');
1316  size_t base_len = 0;
1317 
1318  if (!p) p = strrchr(master_url, '\\');
1319 
1320  if (p) {
1321  base_len = p - master_url;
1322  if (av_strncasecmp(master_url, media_url, base_len)) {
1323  av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n");
1324  return NULL;
1325  }
1326  } else {
1327  return media_url;
1328  }
1329 
1330  return media_url + base_len + 1;
1331 }
1332 
1334 {
1338  );
1339 
1340  if (stream->codecpar->bit_rate)
1341  return stream->codecpar->bit_rate;
1342  else if (sd) {
1343  AVCPBProperties *props = (AVCPBProperties*)sd->data;
1344  return props->max_bitrate;
1345  }
1346 
1347  return 0;
1348 }
1349 
1351  VariantStream * const input_vs,
1352  int final)
1353 {
1354  HLSContext *hls = s->priv_data;
1355  VariantStream *vs, *temp_vs;
1356  AVStream *vid_st, *aud_st;
1358  unsigned int i, j;
1359  int ret, bandwidth, avg_bandwidth;
1360  const char *m3u8_rel_name = NULL;
1361  const char *vtt_m3u8_rel_name = NULL;
1362  const char *ccgroup;
1363  const char *sgroup = NULL;
1364  ClosedCaptionsStream *ccs;
1365  const char *proto = avio_find_protocol_name(hls->master_m3u8_url);
1366  int is_file_proto = proto && !strcmp(proto, "file");
1367  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || hls->master_publish_rate);
1368  char temp_filename[MAX_URL_SIZE];
1369  int nb_channels;
1370 
1371  input_vs->m3u8_created = 1;
1372  if (!hls->master_m3u8_created) {
1373  /* For the first time, wait until all the media playlists are created */
1374  for (i = 0; i < hls->nb_varstreams; i++)
1375  if (!hls->var_streams[i].m3u8_created)
1376  return 0;
1377  } else {
1378  /* Keep publishing the master playlist at the configured rate */
1379  if ((&hls->var_streams[0] != input_vs || !hls->master_publish_rate ||
1380  input_vs->number % hls->master_publish_rate) && !final)
1381  return 0;
1382  }
1383 
1384  set_http_options(s, &options, hls);
1385  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", hls->master_m3u8_url);
1386  ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options);
1388  if (ret < 0) {
1389  av_log(s, AV_LOG_ERROR, "Failed to open master play list file '%s'\n",
1390  temp_filename);
1391  goto fail;
1392  }
1393 
1395 
1396  for (i = 0; i < hls->nb_ccstreams; i++) {
1397  ccs = &(hls->cc_streams[i]);
1398  avio_printf(hls->m3u8_out, "#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS");
1399  avio_printf(hls->m3u8_out, ",GROUP-ID=\"%s\"", ccs->ccgroup);
1400  avio_printf(hls->m3u8_out, ",NAME=\"%s\"", ccs->instreamid);
1401  if (ccs->language)
1402  avio_printf(hls->m3u8_out, ",LANGUAGE=\"%s\"", ccs->language);
1403  avio_printf(hls->m3u8_out, ",INSTREAM-ID=\"%s\"\n", ccs->instreamid);
1404  }
1405 
1406  /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/
1407  for (i = 0; i < hls->nb_varstreams; i++) {
1408  vs = &(hls->var_streams[i]);
1409 
1410  if (vs->has_video || vs->has_subtitle || !vs->agroup)
1411  continue;
1412 
1413  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1414  if (!m3u8_rel_name) {
1415  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1416  goto fail;
1417  }
1418  nb_channels = 0;
1419  for (j = 0; j < vs->nb_streams; j++)
1421  if (vs->streams[j]->codecpar->ch_layout.nb_channels > nb_channels)
1422  nb_channels = vs->streams[j]->codecpar->ch_layout.nb_channels;
1423 
1424  ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1, nb_channels);
1425  }
1426 
1427  /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/
1428  for (i = 0; i < hls->nb_varstreams; i++) {
1429  vs = &(hls->var_streams[i]);
1430 
1431  m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1432  if (!m3u8_rel_name) {
1433  av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1434  goto fail;
1435  }
1436 
1437  vid_st = NULL;
1438  aud_st = NULL;
1439  for (j = 0; j < vs->nb_streams; j++) {
1441  vid_st = vs->streams[j];
1442  else if (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
1443  aud_st = vs->streams[j];
1444  }
1445 
1446  if (!vid_st && !aud_st) {
1447  av_log(s, AV_LOG_WARNING, "Media stream not found\n");
1448  continue;
1449  }
1450 
1451  /**
1452  * Traverse through the list of audio only rendition streams and find
1453  * the rendition which has highest bitrate in the same audio group
1454  */
1455  if (vs->agroup) {
1456  for (j = 0; j < hls->nb_varstreams; j++) {
1457  temp_vs = &(hls->var_streams[j]);
1458  if (!temp_vs->has_video && !temp_vs->has_subtitle &&
1459  temp_vs->agroup &&
1460  !av_strcasecmp(temp_vs->agroup, vs->agroup)) {
1461  if (!aud_st)
1462  aud_st = temp_vs->streams[0];
1463  if (temp_vs->streams[0]->codecpar->bit_rate >
1464  aud_st->codecpar->bit_rate)
1465  aud_st = temp_vs->streams[0];
1466  }
1467  }
1468  }
1469 
1470  if (final) {
1471  bandwidth = vs->max_bitrate;
1472  avg_bandwidth = vs->avg_bitrate;
1473  } else {
1474  bandwidth = 0;
1475  avg_bandwidth = 0;
1476  if (vid_st)
1477  bandwidth += get_stream_bit_rate(vid_st);
1478  if (aud_st)
1479  bandwidth += get_stream_bit_rate(aud_st);
1480  bandwidth += bandwidth / 10;
1481  }
1482 
1483  ccgroup = NULL;
1484  if (vid_st && vs->ccgroup) {
1485  /* check if this group name is available in the cc map string */
1486  for (j = 0; j < hls->nb_ccstreams; j++) {
1487  ccs = &(hls->cc_streams[j]);
1488  if (!av_strcasecmp(ccs->ccgroup, vs->ccgroup)) {
1489  ccgroup = vs->ccgroup;
1490  break;
1491  }
1492  }
1493  if (j == hls->nb_ccstreams)
1494  av_log(s, AV_LOG_WARNING, "mapping ccgroup %s not found\n",
1495  vs->ccgroup);
1496  }
1497 
1498  if (vid_st && vs->sgroup) {
1499  sgroup = vs->sgroup;
1500  vtt_m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->vtt_m3u8_name);
1501  if (!vtt_m3u8_rel_name) {
1502  av_log(s, AV_LOG_WARNING, "Unable to find relative subtitle URL\n");
1503  break;
1504  }
1505 
1506  ff_hls_write_subtitle_rendition(hls->m3u8_out, sgroup, vtt_m3u8_rel_name, vs->language,
1507  vs->subtitle_varname, i, hls->has_default_key ? vs->is_default : 1);
1508  }
1509 
1510  if (!hls->has_default_key || !hls->has_video_m3u8) {
1511  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, avg_bandwidth, m3u8_rel_name,
1512  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1513  } else {
1514  if (vid_st) {
1515  ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, avg_bandwidth, m3u8_rel_name,
1516  aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1517  }
1518  }
1519  }
1520 fail:
1521  if (ret >=0)
1522  hls->master_m3u8_created = 1;
1523  hlsenc_io_close(s, &hls->m3u8_out, temp_filename);
1524  if (use_temp_file)
1525  ff_rename(temp_filename, hls->master_m3u8_url, s);
1526 
1527  return ret;
1528 }
1529 
1530 static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
1531 {
1532  HLSContext *hls = s->priv_data;
1533  HLSSegment *en;
1534  int target_duration = 0;
1535  int ret = 0;
1536  char temp_filename[MAX_URL_SIZE];
1537  char temp_vtt_filename[MAX_URL_SIZE];
1538  int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries);
1539  const char *proto = avio_find_protocol_name(vs->m3u8_name);
1540  int is_file_proto = proto && !strcmp(proto, "file");
1541  int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || !(hls->pl_type == PLAYLIST_TYPE_VOD));
1542  static unsigned warned_non_file;
1543  const char *key_uri = NULL;
1544  char *iv_string = NULL;
1546  double prog_date_time = vs->initial_prog_date_time;
1547  double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? &prog_date_time : NULL;
1548  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1549 
1550  hls->version = 2;
1551  if (!(hls->flags & HLS_ROUND_DURATIONS)) {
1552  hls->version = 3;
1553  }
1554 
1555  if (byterange_mode) {
1556  hls->version = 4;
1557  sequence = 0;
1558  }
1559 
1560  if (hls->flags & HLS_I_FRAMES_ONLY) {
1561  hls->version = 4;
1562  }
1563 
1564  if (hls->flags & HLS_INDEPENDENT_SEGMENTS) {
1565  hls->version = 6;
1566  }
1567 
1568  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1569  hls->version = 7;
1570  }
1571 
1572  if (!is_file_proto && (hls->flags & HLS_TEMP_FILE) && !warned_non_file++)
1573  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
1574 
1575  set_http_options(s, &options, hls);
1576  snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", vs->m3u8_name);
1577  ret = hlsenc_io_open(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename, &options);
1579  if (ret < 0) {
1580  goto fail;
1581  }
1582 
1583  for (en = vs->segments; en; en = en->next) {
1584  if (target_duration <= en->duration)
1585  target_duration = lrint(en->duration);
1586  }
1587 
1588  vs->discontinuity_set = 0;
1589  ff_hls_write_playlist_header(byterange_mode ? hls->m3u8_out : vs->out, hls->version, hls->allowcache,
1590  target_duration, sequence, hls->pl_type, hls->flags & HLS_I_FRAMES_ONLY);
1591 
1592  if ((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0) {
1593  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-DISCONTINUITY\n");
1594  vs->discontinuity_set = 1;
1595  }
1596  if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
1597  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
1598  }
1599  for (en = vs->segments; en; en = en->next) {
1600  if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) ||
1601  av_strcasecmp(en->iv_string, iv_string))) {
1602  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri);
1603  if (*en->iv_string)
1604  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, ",IV=0x%s", en->iv_string);
1605  avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "\n");
1606  key_uri = en->key_uri;
1607  iv_string = en->iv_string;
1608  }
1609 
1610  if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) {
1611  ff_hls_write_init_file(byterange_mode ? hls->m3u8_out : vs->out, (hls->flags & HLS_SINGLE_FILE) ? en->filename : vs->fmp4_init_filename,
1612  hls->flags & HLS_SINGLE_FILE, vs->init_range_length, 0);
1613  }
1614 
1615  ret = ff_hls_write_file_entry(byterange_mode ? hls->m3u8_out : vs->out, en->discont, byterange_mode,
1616  en->duration, hls->flags & HLS_ROUND_DURATIONS,
1617  en->size, en->pos, hls->baseurl,
1618  en->filename,
1619  en->discont_program_date_time ? &en->discont_program_date_time : prog_date_time_p,
1620  hls->flags & HLS_I_FRAMES_ONLY);
1621  if (en->discont_program_date_time)
1623  if (ret < 0) {
1624  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1625  }
1626  }
1627 
1628  if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
1629  ff_hls_write_end_list(byterange_mode ? hls->m3u8_out : vs->out);
1630 
1631  if (vs->vtt_m3u8_name) {
1632  set_http_options(vs->vtt_avf, &options, hls);
1633  snprintf(temp_vtt_filename, sizeof(temp_vtt_filename), use_temp_file ? "%s.tmp" : "%s", vs->vtt_m3u8_name);
1634  ret = hlsenc_io_open(s, &hls->sub_m3u8_out, temp_vtt_filename, &options);
1636  if (ret < 0) {
1637  goto fail;
1638  }
1640  target_duration, sequence, PLAYLIST_TYPE_NONE, 0);
1641  for (en = vs->segments; en; en = en->next) {
1642  ret = ff_hls_write_file_entry(hls->sub_m3u8_out, en->discont, byterange_mode,
1643  en->duration, 0, en->size, en->pos,
1644  hls->baseurl, en->sub_filename, NULL, 0);
1645  if (ret < 0) {
1646  av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1647  }
1648  }
1649 
1650  if (last && !(hls->flags & HLS_OMIT_ENDLIST))
1652 
1653  }
1654 
1655 fail:
1657  ret = hlsenc_io_close(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename);
1658  if (ret < 0) {
1659  return ret;
1660  }
1662  if (use_temp_file) {
1663  ff_rename(temp_filename, vs->m3u8_name, s);
1664  if (vs->vtt_m3u8_name)
1665  ff_rename(temp_vtt_filename, vs->vtt_m3u8_name, s);
1666  }
1667  if (ret >= 0 && hls->master_pl_name)
1668  if (create_master_playlist(s, vs, last) < 0)
1669  av_log(s, AV_LOG_WARNING, "Master playlist creation failed\n");
1670 
1671  return ret;
1672 }
1673 
1675 {
1676  HLSContext *c = s->priv_data;
1677  AVFormatContext *oc = vs->avf;
1678  AVFormatContext *vtt_oc = vs->vtt_avf;
1680  const char *proto = NULL;
1681  int use_temp_file = 0;
1682  char iv_string[KEYSIZE*2 + 1];
1683  int err = 0;
1684 
1685  if (c->flags & HLS_SINGLE_FILE) {
1686  char *new_name = av_strdup(vs->basename);
1687  if (!new_name)
1688  return AVERROR(ENOMEM);
1689  ff_format_set_url(oc, new_name);
1690  if (vs->vtt_basename) {
1691  new_name = av_strdup(vs->vtt_basename);
1692  if (!new_name)
1693  return AVERROR(ENOMEM);
1694  ff_format_set_url(vtt_oc, new_name);
1695  }
1696  } else if (c->max_seg_size > 0) {
1697  char *filename = NULL;
1698  if (replace_int_data_in_filename(&filename,
1699  vs->basename, 'd', vs->sequence) < 1) {
1700  av_freep(&filename);
1701  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -strftime 1 with it\n", vs->basename);
1702  return AVERROR(EINVAL);
1703  }
1704  ff_format_set_url(oc, filename);
1705  } else {
1706  if (c->use_localtime) {
1707  int r;
1708  char *expanded = NULL;
1709 
1710  r = strftime_expand(vs->basename, &expanded);
1711  if (r < 0) {
1712  av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
1713  return r;
1714  }
1715  ff_format_set_url(oc, expanded);
1716 
1717  err = sls_flag_use_localtime_filename(oc, c, vs);
1718  if (err < 0) {
1719  return AVERROR(ENOMEM);
1720  }
1721 
1722  if (c->use_localtime_mkdir) {
1723  const char *dir;
1724  char *fn_copy = av_strdup(oc->url);
1725  if (!fn_copy)
1726  return AVERROR(ENOMEM);
1727  dir = av_dirname(fn_copy);
1728  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1729  av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
1730  av_freep(&fn_copy);
1731  return AVERROR(errno);
1732  }
1733  av_freep(&fn_copy);
1734  }
1735  } else {
1736  char *filename = NULL;
1737  if (replace_int_data_in_filename(&filename,
1738  vs->basename, 'd', vs->sequence) < 1) {
1739  av_freep(&filename);
1740  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -strftime 1 with it\n", vs->basename);
1741  return AVERROR(EINVAL);
1742  }
1743  ff_format_set_url(oc, filename);
1744  }
1745  if (vs->vtt_basename) {
1746  char *filename = NULL;
1747  if (replace_int_data_in_filename(&filename,
1748  vs->vtt_basename, 'd', vs->sequence) < 1) {
1749  av_freep(&filename);
1750  av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename);
1751  return AVERROR(EINVAL);
1752  }
1753  ff_format_set_url(vtt_oc, filename);
1754  }
1755  }
1756 
1757  proto = avio_find_protocol_name(oc->url);
1758  use_temp_file = proto && !strcmp(proto, "file") && (c->flags & HLS_TEMP_FILE);
1759 
1760  if (use_temp_file) {
1761  char *new_name = av_asprintf("%s.tmp", oc->url);
1762  if (!new_name)
1763  return AVERROR(ENOMEM);
1764  ff_format_set_url(oc, new_name);
1765  }
1766 
1767  if (c->key_info_file || c->encrypt) {
1768  if (c->segment_type == SEGMENT_TYPE_FMP4) {
1769  av_log(s, AV_LOG_ERROR, "Encrypted fmp4 not yet supported\n");
1770  return AVERROR_PATCHWELCOME;
1771  }
1772 
1773  if (c->key_info_file && c->encrypt) {
1774  av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file and -hls_enc,"
1775  " ignoring -hls_enc\n");
1776  }
1777 
1778  if (!vs->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) {
1779  if (c->key_info_file) {
1780  if ((err = hls_encryption_start(s, vs)) < 0)
1781  goto fail;
1782  } else {
1783  if (!c->encrypt_started) {
1784  if ((err = do_encrypt(s, vs)) < 0)
1785  goto fail;
1786  c->encrypt_started = 1;
1787  }
1788  av_strlcpy(vs->key_uri, c->key_uri, sizeof(vs->key_uri));
1789  av_strlcpy(vs->key_string, c->key_string, sizeof(vs->key_string));
1790  av_strlcpy(vs->iv_string, c->iv_string, sizeof(vs->iv_string));
1791  }
1792  vs->encrypt_started = 1;
1793  }
1794  err = av_strlcpy(iv_string, vs->iv_string, sizeof(iv_string));
1795  if (!err) {
1796  snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, vs->sequence);
1797  memset(vs->iv_string, 0, sizeof(vs->iv_string));
1798  memcpy(vs->iv_string, iv_string, sizeof(iv_string));
1799  }
1800  }
1801  if (c->segment_type != SEGMENT_TYPE_FMP4) {
1802  if (oc->oformat->priv_class && oc->priv_data) {
1803  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
1804  }
1805  if (c->flags & HLS_SINGLE_FILE) {
1806  if (c->key_info_file || c->encrypt) {
1807  av_dict_set(&options, "encryption_key", vs->key_string, 0);
1808  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
1809 
1810  /* Write temp file with cryption content */
1811  av_freep(&vs->basename_tmp);
1812  vs->basename_tmp = av_asprintf("crypto:%s.tmp", oc->url);
1813 
1814  /* append temp file content into single file */
1815  av_freep(&vs->basename);
1816  vs->basename = av_asprintf("%s", oc->url);
1817  } else {
1818  vs->basename_tmp = vs->basename;
1819  }
1821  if (!vs->out_single_file)
1822  if ((err = hlsenc_io_open(s, &vs->out_single_file, vs->basename, &options)) < 0) {
1823  if (c->ignore_io_errors)
1824  err = 0;
1825  goto fail;
1826  }
1827 
1828  if ((err = hlsenc_io_open(s, &vs->out, vs->basename_tmp, &options)) < 0) {
1829  if (c->ignore_io_errors)
1830  err = 0;
1831  goto fail;
1832  }
1833 
1834  }
1835  }
1836  if (vs->vtt_basename) {
1838  if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < 0) {
1839  if (c->ignore_io_errors)
1840  err = 0;
1841  goto fail;
1842  }
1843  }
1845 
1846  if (vs->vtt_basename) {
1847  err = avformat_write_header(vtt_oc,NULL);
1848  if (err < 0)
1849  return err;
1850  }
1851 
1852  return 0;
1853 fail:
1855 
1856  return err;
1857 }
1858 
1860 {
1861  HLSContext *hls = s->priv_data;
1862 #if HAVE_LIBC_MSVCRT
1863  // no %s support on MSVC, which invokes the invalid parameter handler
1864  // on unsupported format strings, instead of returning an error
1865  int strftime_s_supported = 0;
1866 #else
1867  char b[21];
1868  time_t t = time(NULL);
1869  struct tm tmbuf, *p = localtime_r(&t, &tmbuf);
1870  // no %s support when strftime returned error or left format string unchanged
1871  int strftime_s_supported = strftime(b, sizeof(b), "%s", p) && strcmp(b, "%s");
1872 #endif
1873 
1874  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1875  return strftime_s_supported ? "-%s.m4s" : "-%Y%m%d%H%M%S.m4s";
1876  }
1877  return strftime_s_supported ? "-%s.ts" : "-%Y%m%d%H%M%S.ts";
1878 }
1879 
1880 static int append_postfix(char *name, int name_buf_len, int i)
1881 {
1882  char *p;
1883  char extension[10] = {'\0'};
1884 
1885  p = strrchr(name, '.');
1886  if (p) {
1887  av_strlcpy(extension, p, sizeof(extension));
1888  *p = '\0';
1889  }
1890 
1891  snprintf(name + strlen(name), name_buf_len - strlen(name), POSTFIX_PATTERN, i);
1892 
1893  if (strlen(extension))
1894  av_strlcat(name, extension, name_buf_len);
1895 
1896  return 0;
1897 }
1898 
1899 static int validate_name(int nb_vs, const char *fn)
1900 {
1901  const char *filename, *subdir_name;
1902  char *fn_dup = NULL;
1903  int ret = 0;
1904 
1905  if (!fn)
1906  return AVERROR(EINVAL);
1907 
1908  fn_dup = av_strdup(fn);
1909  if (!fn_dup)
1910  return AVERROR(ENOMEM);
1911  filename = av_basename(fn);
1912  subdir_name = av_dirname(fn_dup);
1913 
1914  if (nb_vs > 1 && !av_stristr(filename, "%v") && !av_stristr(subdir_name, "%v")) {
1915  av_log(NULL, AV_LOG_ERROR, "More than 1 variant streams are present, %%v is expected "
1916  "either in the filename or in the sub-directory name of file %s\n", fn);
1917  ret = AVERROR(EINVAL);
1918  goto fail;
1919  }
1920 
1921  if (av_stristr(filename, "%v") && av_stristr(subdir_name, "%v")) {
1922  av_log(NULL, AV_LOG_ERROR, "%%v is expected either in the filename or "
1923  "in the sub-directory name of file %s, but only in one of them\n", fn);
1924  ret = AVERROR(EINVAL);
1925  goto fail;
1926  }
1927 
1928 fail:
1929  av_freep(&fn_dup);
1930  return ret;
1931 }
1932 
1933 static int format_name(const char *buf, char **s, int index, const char *varname)
1934 {
1935  const char *proto, *dir;
1936  char *orig_buf_dup = NULL, *mod_buf_dup = NULL;
1937  int ret = 0;
1938 
1939  orig_buf_dup = av_strdup(buf);
1940  if (!orig_buf_dup)
1941  return AVERROR(ENOMEM);
1942 
1943  if (!av_stristr(buf, "%v")) {
1944  *s = orig_buf_dup;
1945  return 0;
1946  }
1947 
1948  if (!varname) {
1949  if (replace_int_data_in_filename(s, orig_buf_dup, 'v', index) < 1) {
1950  ret = AVERROR(EINVAL);
1951  goto fail;
1952  }
1953  } else {
1954  if (replace_str_data_in_filename(s, orig_buf_dup, 'v', varname) < 1) {
1955  ret = AVERROR(EINVAL);
1956  goto fail;
1957  }
1958  }
1959 
1960  proto = avio_find_protocol_name(orig_buf_dup);
1961  dir = av_dirname(orig_buf_dup);
1962 
1963  /* if %v is present in the file's directory, create sub-directory */
1964  if (av_stristr(dir, "%v") && proto && !strcmp(proto, "file")) {
1965  mod_buf_dup = av_strdup(*s);
1966  dir = av_dirname(mod_buf_dup);
1967  if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1968  ret = AVERROR(errno);
1969  goto fail;
1970  }
1971  }
1972 
1973 fail:
1974  av_freep(&orig_buf_dup);
1975  av_freep(&mod_buf_dup);
1976  return ret;
1977 }
1978 
1980  enum AVMediaType codec_type,
1981  int64_t stream_id)
1982 {
1983  unsigned int stream_index, cnt;
1984  if (stream_id < 0 || stream_id > s->nb_streams - 1)
1985  return -1;
1986  cnt = 0;
1987  for (stream_index = 0; stream_index < s->nb_streams; stream_index++) {
1988  if (s->streams[stream_index]->codecpar->codec_type != codec_type)
1989  continue;
1990  if (cnt == stream_id)
1991  return stream_index;
1992  cnt++;
1993  }
1994  return -1;
1995 }
1996 
1998 {
1999  HLSContext *hls = s->priv_data;
2000  VariantStream *vs;
2001  int stream_index, i, j;
2002  enum AVMediaType codec_type;
2003  int nb_varstreams = 0, nb_streams;
2004  char *p, *q, *saveptr1, *saveptr2, *varstr, *keyval;
2005  const char *val;
2006 
2007  /**
2008  * Expected format for var_stream_map string is as below:
2009  * "a:0,v:0 a:1,v:1"
2010  * "a:0,agroup:a0,default:1,language:ENG a:1,agroup:a1,default:0 v:0,agroup:a0 v:1,agroup:a1"
2011  * This string specifies how to group the audio, video and subtitle streams
2012  * into different variant streams. The variant stream groups are separated
2013  * by space.
2014  *
2015  * a:, v:, s: are keys to specify audio, video and subtitle streams
2016  * respectively. Allowed values are 0 to 9 digits (limited just based on
2017  * practical usage)
2018  *
2019  * agroup: is key to specify audio group. A string can be given as value.
2020  * sgroup: is key to specify subtitle group. A string can be given as value.
2021  */
2022  p = av_strdup(hls->var_stream_map);
2023  if (!p)
2024  return AVERROR(ENOMEM);
2025 
2026  q = p;
2027  while (av_strtok(q, " \t", &saveptr1)) {
2028  q = NULL;
2029  nb_varstreams++;
2030  }
2031  av_freep(&p);
2032 
2033  hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * nb_varstreams);
2034  if (!hls->var_streams)
2035  return AVERROR(ENOMEM);
2036  hls->nb_varstreams = nb_varstreams;
2037 
2038  p = hls->var_stream_map;
2039  nb_varstreams = 0;
2040  while (varstr = av_strtok(p, " \t", &saveptr1)) {
2041  p = NULL;
2042 
2043  if (nb_varstreams < hls->nb_varstreams) {
2044  vs = &(hls->var_streams[nb_varstreams]);
2045  vs->var_stream_idx = nb_varstreams;
2046  vs->is_default = 0;
2047  nb_varstreams++;
2048  } else
2049  return AVERROR(EINVAL);
2050 
2051  q = varstr;
2052  while (1) {
2053  if (!av_strncasecmp(q, "a:", 2) || !av_strncasecmp(q, "v:", 2) ||
2054  !av_strncasecmp(q, "s:", 2))
2055  vs->nb_streams++;
2056  q = strchr(q, ',');
2057  if (!q)
2058  break;
2059  q++;
2060  }
2061  vs->streams = av_mallocz(sizeof(AVStream *) * vs->nb_streams);
2062  if (!vs->streams)
2063  return AVERROR(ENOMEM);
2064 
2065  nb_streams = 0;
2066  while (keyval = av_strtok(varstr, ",", &saveptr2)) {
2067  int64_t num;
2068  char *end;
2069  varstr = NULL;
2070  if (av_strstart(keyval, "language:", &val)) {
2071  vs->language = val;
2072  continue;
2073  } else if (av_strstart(keyval, "default:", &val)) {
2074  vs->is_default = (!av_strncasecmp(val, "YES", strlen("YES")) ||
2075  (!av_strncasecmp(val, "1", strlen("1"))));
2076  hls->has_default_key = 1;
2077  continue;
2078  } else if (av_strstart(keyval, "name:", &val)) {
2079  vs->varname = val;
2080  continue;
2081  } else if (av_strstart(keyval, "sname:", &val)) {
2082  vs->subtitle_varname = val;
2083  continue;
2084  } else if (av_strstart(keyval, "agroup:", &val)) {
2085  vs->agroup = val;
2086  continue;
2087  } else if (av_strstart(keyval, "sgroup:", &val)) {
2088  vs->sgroup = val;
2089  continue;
2090  } else if (av_strstart(keyval, "ccgroup:", &val)) {
2091  vs->ccgroup = val;
2092  continue;
2093  } else if (av_strstart(keyval, "v:", &val)) {
2095  hls->has_video_m3u8 = 1;
2096  } else if (av_strstart(keyval, "a:", &val)) {
2098  } else if (av_strstart(keyval, "s:", &val)) {
2100  } else {
2101  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2102  return AVERROR(EINVAL);
2103  }
2104 
2105  num = strtoll(val, &end, 10);
2106  if (!av_isdigit(*val) || *end != '\0') {
2107  av_log(s, AV_LOG_ERROR, "Invalid stream number: '%s'\n", val);
2108  return AVERROR(EINVAL);
2109  }
2110  stream_index = get_nth_codec_stream_index(s, codec_type, num);
2111 
2112  if (stream_index >= 0 && nb_streams < vs->nb_streams) {
2113  for (i = 0; nb_streams > 0 && i < nb_streams; i++) {
2114  if (vs->streams[i] == s->streams[stream_index]) {
2115  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once inside "
2116  "variant definition #%d\n", nb_varstreams - 1);
2117  return AVERROR(EINVAL);
2118  }
2119  }
2120  for (j = 0; nb_varstreams > 1 && j < nb_varstreams - 1; j++) {
2121  for (i = 0; i < hls->var_streams[j].nb_streams; i++) {
2122  if (hls->var_streams[j].streams[i] == s->streams[stream_index]) {
2123  av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once "
2124  "in two different variant definitions #%d and #%d\n",
2125  j, nb_varstreams - 1);
2126  return AVERROR(EINVAL);
2127  }
2128  }
2129  }
2130  vs->streams[nb_streams++] = s->streams[stream_index];
2131  } else {
2132  av_log(s, AV_LOG_ERROR, "Unable to map stream at %s\n", keyval);
2133  return AVERROR(EINVAL);
2134  }
2135  }
2136  }
2137  av_log(s, AV_LOG_DEBUG, "Number of variant streams %d\n",
2138  hls->nb_varstreams);
2139 
2140  return 0;
2141 }
2142 
2144 {
2145  HLSContext *hls = s->priv_data;
2146  int nb_ccstreams = 0;
2147  char *p, *q, *ccstr, *keyval;
2148  char *saveptr1 = NULL, *saveptr2 = NULL;
2149  const char *val;
2150  ClosedCaptionsStream *ccs;
2151 
2152  p = av_strdup(hls->cc_stream_map);
2153  if(!p)
2154  return AVERROR(ENOMEM);
2155 
2156  q = p;
2157  while (av_strtok(q, " \t", &saveptr1)) {
2158  q = NULL;
2159  nb_ccstreams++;
2160  }
2161  av_freep(&p);
2162 
2163  hls->cc_streams = av_mallocz(sizeof(*hls->cc_streams) * nb_ccstreams);
2164  if (!hls->cc_streams)
2165  return AVERROR(ENOMEM);
2166  hls->nb_ccstreams = nb_ccstreams;
2167 
2168  p = hls->cc_stream_map;
2169  nb_ccstreams = 0;
2170  while (ccstr = av_strtok(p, " \t", &saveptr1)) {
2171  p = NULL;
2172 
2173  if (nb_ccstreams < hls->nb_ccstreams)
2174  ccs = &(hls->cc_streams[nb_ccstreams++]);
2175  else
2176  return AVERROR(EINVAL);
2177 
2178  while (keyval = av_strtok(ccstr, ",", &saveptr2)) {
2179  ccstr = NULL;
2180 
2181  if (av_strstart(keyval, "ccgroup:", &val)) {
2182  ccs->ccgroup = val;
2183  } else if (av_strstart(keyval, "instreamid:", &val)) {
2184  ccs->instreamid = val;
2185  } else if (av_strstart(keyval, "language:", &val)) {
2186  ccs->language = val;
2187  } else {
2188  av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2189  return AVERROR(EINVAL);
2190  }
2191  }
2192 
2193  if (!ccs->ccgroup || !ccs->instreamid) {
2194  av_log(s, AV_LOG_ERROR, "Insufficient parameters in cc stream map string\n");
2195  return AVERROR(EINVAL);
2196  }
2197 
2198  if (av_strstart(ccs->instreamid, "CC", &val)) {
2199  if (atoi(val) < 1 || atoi(val) > 4) {
2200  av_log(s, AV_LOG_ERROR, "Invalid instream ID CC index %d in %s, range 1-4\n",
2201  atoi(val), ccs->instreamid);
2202  return AVERROR(EINVAL);
2203  }
2204  } else if (av_strstart(ccs->instreamid, "SERVICE", &val)) {
2205  if (atoi(val) < 1 || atoi(val) > 63) {
2206  av_log(s, AV_LOG_ERROR, "Invalid instream ID SERVICE index %d in %s, range 1-63 \n",
2207  atoi(val), ccs->instreamid);
2208  return AVERROR(EINVAL);
2209  }
2210  } else {
2211  av_log(s, AV_LOG_ERROR, "Invalid instream ID %s, supported are CCn or SERVICEn\n",
2212  ccs->instreamid);
2213  return AVERROR(EINVAL);
2214  }
2215  }
2216 
2217  return 0;
2218 }
2219 
2221 {
2222  HLSContext *hls = s->priv_data;
2223  unsigned int i;
2224  int ret = 0;
2225 
2226  if (hls->cc_stream_map) {
2228  if (ret < 0)
2229  return ret;
2230  }
2231 
2232  if (hls->var_stream_map) {
2234  } else {
2235  //By default, a single variant stream with all the codec streams is created
2236  hls->var_streams = av_mallocz(sizeof(*hls->var_streams));
2237  if (!hls->var_streams)
2238  return AVERROR(ENOMEM);
2239  hls->nb_varstreams = 1;
2240 
2241  hls->var_streams[0].var_stream_idx = 0;
2242  hls->var_streams[0].nb_streams = s->nb_streams;
2243  hls->var_streams[0].streams = av_mallocz(sizeof(AVStream *) *
2244  hls->var_streams[0].nb_streams);
2245  if (!hls->var_streams[0].streams)
2246  return AVERROR(ENOMEM);
2247 
2248  //by default, the first available ccgroup is mapped to the variant stream
2249  if (hls->nb_ccstreams)
2250  hls->var_streams[0].ccgroup = hls->cc_streams[0].ccgroup;
2251 
2252  for (i = 0; i < s->nb_streams; i++)
2253  hls->var_streams[0].streams[i] = s->streams[i];
2254  }
2255  return 0;
2256 }
2257 
2259 {
2260  HLSContext *hls = s->priv_data;
2261  const char *dir;
2262  char *fn1= NULL, *fn2 = NULL;
2263  int ret = 0;
2264 
2265  fn1 = av_strdup(s->url);
2266  if (!fn1)
2267  return AVERROR(ENOMEM);
2268  dir = av_dirname(fn1);
2269 
2270  /**
2271  * if output file's directory has %v, variants are created in sub-directories
2272  * then master is created at the sub-directories level
2273  */
2274  if (dir && av_stristr(av_basename(dir), "%v")) {
2275  fn2 = av_strdup(dir);
2276  if (!fn2) {
2277  ret = AVERROR(ENOMEM);
2278  goto fail;
2279  }
2280  dir = av_dirname(fn2);
2281  }
2282 
2283  if (dir && strcmp(dir, "."))
2285  else
2287 
2288  if (!hls->master_m3u8_url) {
2289  ret = AVERROR(ENOMEM);
2290  goto fail;
2291  }
2292 
2293 fail:
2294  av_freep(&fn1);
2295  av_freep(&fn2);
2296 
2297  return ret;
2298 }
2299 
2301 {
2302  HLSContext *hls = s->priv_data;
2303  int ret, i, j;
2304  VariantStream *vs = NULL;
2305 
2306  for (i = 0; i < hls->nb_varstreams; i++) {
2307  int subtitle_streams = 0;
2308  vs = &hls->var_streams[i];
2309 
2311  if (ret < 0)
2312  return ret;
2313  //av_assert0(s->nb_streams == hls->avf->nb_streams);
2314  for (j = 0; j < vs->nb_streams; j++) {
2315  AVStream *inner_st;
2316  AVStream *outer_st = vs->streams[j];
2317 
2318  if (hls->max_seg_size > 0) {
2319  if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
2320  (outer_st->codecpar->bit_rate > hls->max_seg_size)) {
2321  av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, "
2322  "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.",
2323  outer_st->codecpar->bit_rate, hls->max_seg_size);
2324  }
2325  }
2326 
2327  if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
2328  inner_st = vs->avf->streams[j - subtitle_streams];
2329  else if (vs->vtt_avf) {
2330  inner_st = vs->vtt_avf->streams[0];
2331  subtitle_streams++;
2332  } else {
2333  /* We have a subtitle stream, when the user does not want one */
2334  inner_st = NULL;
2335  continue;
2336  }
2337  avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
2338  if (outer_st->codecpar->codec_id == AV_CODEC_ID_HEVC &&
2339  outer_st->codecpar->codec_tag != MKTAG('h','v','c','1')) {
2340  av_log(s, AV_LOG_WARNING, "Stream HEVC is not hvc1, you should use tag:v hvc1 to set it.\n");
2341  }
2342  write_codec_attr(outer_st, vs);
2343 
2344  }
2345  /* Update the Codec Attr string for the mapped audio groups */
2346  if (vs->has_video && vs->agroup) {
2347  for (j = 0; j < hls->nb_varstreams; j++) {
2348  VariantStream *vs_agroup = &(hls->var_streams[j]);
2349  if (!vs_agroup->has_video && !vs_agroup->has_subtitle &&
2350  vs_agroup->agroup &&
2351  !av_strcasecmp(vs_agroup->agroup, vs->agroup)) {
2352  write_codec_attr(vs_agroup->streams[0], vs);
2353  }
2354  }
2355  }
2356  }
2357 
2358  return 0;
2359 }
2360 
2362 {
2363  HLSContext *hls = s->priv_data;
2365  int ret = 0;
2366 
2367  set_http_options(s, &options, hls);
2370  if (ret < 0)
2371  return ret;
2373  hlsenc_io_close(s, &vs->out, hls->fmp4_init_filename);
2374 
2375  return ret;
2376 }
2377 
2379 {
2380  int64_t ret = 0;
2381  int64_t read_byte = 0;
2382  int64_t total_size = 0;
2383  char *filename = NULL;
2384  char buf[BUFSIZE];
2385  AVFormatContext *oc = vs->avf;
2386 
2387  hlsenc_io_close(s, &vs->out, vs->basename_tmp);
2388  filename = av_asprintf("%s.tmp", oc->url);
2389  ret = s->io_open(s, &vs->out, filename, AVIO_FLAG_READ, NULL);
2390  if (ret < 0) {
2391  av_free(filename);
2392  return ret;
2393  }
2394 
2395  do {
2396  read_byte = avio_read(vs->out, buf, BUFSIZE);
2397  if (read_byte > 0) {
2398  avio_write(vs->out_single_file, buf, read_byte);
2399  total_size += read_byte;
2400  ret = total_size;
2401  }
2402  } while (read_byte > 0);
2403 
2404  hlsenc_io_close(s, &vs->out, filename);
2405  av_free(filename);
2406 
2407  return ret;
2408 }
2410 {
2411  HLSContext *hls = s->priv_data;
2412  AVFormatContext *oc = NULL;
2413  AVStream *st = s->streams[pkt->stream_index];
2414  int64_t end_pts = 0;
2415  int is_ref_pkt = 1;
2416  int ret = 0, can_split = 1, i, j;
2417  int stream_index = 0;
2418  int range_length = 0;
2419  const char *proto = NULL;
2420  int use_temp_file = 0;
2421  VariantStream *vs = NULL;
2422  char *old_filename = NULL;
2423 
2424  for (i = 0; i < hls->nb_varstreams; i++) {
2425  int subtitle_streams = 0;
2426  vs = &hls->var_streams[i];
2427  for (j = 0; j < vs->nb_streams; j++) {
2429  subtitle_streams++;
2430  }
2431  if (vs->streams[j] == st) {
2433  oc = vs->vtt_avf;
2434  stream_index = 0;
2435  } else {
2436  oc = vs->avf;
2437  stream_index = j - subtitle_streams;
2438  }
2439  break;
2440  }
2441  }
2442 
2443  if (oc)
2444  break;
2445  }
2446 
2447  if (!oc) {
2448  av_log(s, AV_LOG_ERROR, "Unable to find mapping variant stream\n");
2449  return AVERROR(ENOMEM);
2450  }
2451 
2452  end_pts = hls->recording_time * vs->number;
2453 
2454  if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
2455  /* reset end_pts, hls->recording_time at end of the init hls list */
2456  int64_t init_list_dur = hls->init_time * vs->nb_entries;
2457  int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries) * hls->time;
2458  hls->recording_time = hls->time;
2459  end_pts = init_list_dur + after_init_list_dur ;
2460  }
2461 
2462  if (vs->start_pts == AV_NOPTS_VALUE) {
2465  vs->start_pts_from_audio = 1;
2466  }
2468  int64_t video_start = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q);
2469  if (vs->start_pts > video_start) {
2470  vs->start_pts = video_start;
2471  vs->start_pts_from_audio = 0;
2472  }
2473  }
2474 
2475  if (vs->has_video) {
2477  ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME));
2478  is_ref_pkt = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->stream_index == vs->reference_stream_index);
2479  }
2480  if (pkt->pts == AV_NOPTS_VALUE)
2481  is_ref_pkt = can_split = 0;
2482 
2483  if (is_ref_pkt) {
2484  if (vs->end_pts == AV_NOPTS_VALUE)
2485  vs->end_pts = pkt->pts;
2486  if (vs->new_start) {
2487  vs->new_start = 0;
2488  vs->duration = (double)(pkt->pts - vs->end_pts)
2489  * st->time_base.num / st->time_base.den;
2490  vs->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2491  } else {
2492  if (pkt->duration) {
2493  vs->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2494  } else {
2495  av_log(s, AV_LOG_WARNING, "Stream %d packet with pts %" PRId64 " has duration 0. The segment duration may not be precise.\n",
2496  pkt->stream_index, pkt->pts);
2497  vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2498  }
2499  }
2500  }
2501 
2502  can_split = can_split && (pkt->pts - vs->end_pts > 0);
2504  >= end_pts)) {
2505  int64_t new_start_pos;
2506  int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2507  double cur_duration;
2508 
2509  av_write_frame(oc, NULL); /* Flush any buffered data */
2510  new_start_pos = avio_tell(oc->pb);
2511  vs->size = new_start_pos - vs->start_pos;
2512  avio_flush(oc->pb);
2513  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2514  if (!vs->init_range_length) {
2515  range_length = avio_close_dyn_buf(oc->pb, &vs->init_buffer);
2516  if (range_length <= 0)
2517  return AVERROR(EINVAL);
2518  avio_write(vs->out, vs->init_buffer, range_length);
2519  if (!hls->resend_init_file)
2520  av_freep(&vs->init_buffer);
2521  vs->init_range_length = range_length;
2522  avio_open_dyn_buf(&oc->pb);
2523  vs->packets_written = 0;
2524  vs->start_pos = range_length;
2525  if (!byterange_mode) {
2527  }
2528  }
2529  }
2530  if (!byterange_mode) {
2531  if (vs->vtt_avf) {
2532  hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url);
2533  }
2534  }
2535 
2536  if (hls->flags & HLS_SINGLE_FILE) {
2537  ret = flush_dynbuf(vs, &range_length);
2538  av_freep(&vs->temp_buffer);
2539  if (ret < 0) {
2540  return ret;
2541  }
2542  vs->size = range_length;
2543  if (hls->key_info_file || hls->encrypt)
2544  vs->size = append_single_file(s, vs);
2545  } else {
2546  if (oc->url[0]) {
2547  proto = avio_find_protocol_name(oc->url);
2548  use_temp_file = proto && !strcmp(proto, "file")
2549  && (hls->flags & HLS_TEMP_FILE);
2550  }
2551 
2552  if ((hls->max_seg_size > 0 && (vs->size + vs->start_pos >= hls->max_seg_size)) || !byterange_mode) {
2554  char *filename = NULL;
2555  if (hls->key_info_file || hls->encrypt) {
2556  av_dict_set(&options, "encryption_key", vs->key_string, 0);
2557  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2558  filename = av_asprintf("crypto:%s", oc->url);
2559  } else {
2560  filename = av_asprintf("%s", oc->url);
2561  }
2562  if (!filename) {
2564  return AVERROR(ENOMEM);
2565  }
2566 
2567  // look to rename the asset name
2568  if (use_temp_file)
2569  av_dict_set(&options, "mpegts_flags", "resend_headers", 0);
2570 
2571  set_http_options(s, &options, hls);
2572 
2573  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2574  if (ret < 0) {
2576  "Failed to open file '%s'\n", filename);
2577  av_freep(&filename);
2579  return hls->ignore_io_errors ? 0 : ret;
2580  }
2581  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2582  write_styp(vs->out);
2583  }
2584  ret = flush_dynbuf(vs, &range_length);
2585  if (ret < 0) {
2586  av_freep(&filename);
2588  return ret;
2589  }
2590  vs->size = range_length;
2591  ret = hlsenc_io_close(s, &vs->out, filename);
2592  if (ret < 0) {
2593  av_log(s, AV_LOG_WARNING, "upload segment failed,"
2594  " will retry with a new http session.\n");
2595  ff_format_io_close(s, &vs->out);
2596  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2597  if (ret >= 0) {
2598  reflush_dynbuf(vs, &range_length);
2599  ret = hlsenc_io_close(s, &vs->out, filename);
2600  }
2601  }
2603  av_freep(&vs->temp_buffer);
2604  av_freep(&filename);
2605  }
2606 
2607  if (use_temp_file)
2608  hls_rename_temp_file(s, oc);
2609  }
2610 
2611  if (ret < 0)
2612  return ret;
2613 
2614  old_filename = av_strdup(oc->url);
2615  if (!old_filename) {
2616  return AVERROR(ENOMEM);
2617  }
2618 
2619  cur_duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2620  ret = hls_append_segment(s, hls, vs, cur_duration, vs->start_pos, vs->size);
2621  vs->end_pts = pkt->pts;
2622  vs->duration = 0;
2623  if (ret < 0) {
2624  av_freep(&old_filename);
2625  return ret;
2626  }
2627 
2628  // if we're building a VOD playlist, skip writing the manifest multiple times, and just wait until the end
2629  if (hls->pl_type != PLAYLIST_TYPE_VOD) {
2630  if ((ret = hls_window(s, 0, vs)) < 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  if ((ret = hls_window(s, 0, vs)) < 0) {
2634  av_freep(&old_filename);
2635  return ret;
2636  }
2637  }
2638  }
2639 
2640  if (hls->resend_init_file && hls->segment_type == SEGMENT_TYPE_FMP4) {
2641  ret = hls_init_file_resend(s, vs);
2642  if (ret < 0) {
2643  av_freep(&old_filename);
2644  return ret;
2645  }
2646  }
2647 
2648  if (hls->flags & HLS_SINGLE_FILE) {
2649  vs->start_pos += vs->size;
2650  if (hls->key_info_file || hls->encrypt)
2651  ret = hls_start(s, vs);
2652  if (hls->segment_type == SEGMENT_TYPE_MPEGTS && oc->oformat->priv_class && oc->priv_data) {
2653  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
2654  }
2655  } else if (hls->max_seg_size > 0) {
2656  if (vs->size + vs->start_pos >= hls->max_seg_size) {
2657  vs->sequence++;
2658  sls_flag_file_rename(hls, vs, old_filename);
2659  ret = hls_start(s, vs);
2660  vs->start_pos = 0;
2661  /* When split segment by byte, the duration is short than hls_time,
2662  * so it is not enough one segment duration as hls_time, */
2663  } else {
2664  vs->start_pos = new_start_pos;
2665  }
2666  } else {
2667  vs->start_pos = 0;
2668  sls_flag_file_rename(hls, vs, old_filename);
2669  ret = hls_start(s, vs);
2670  }
2671  vs->number++;
2672  av_freep(&old_filename);
2673 
2674  if (ret < 0) {
2675  return ret;
2676  }
2677  }
2678 
2679  vs->packets_written++;
2680  if (oc->pb) {
2681  ret = ff_write_chained(oc, stream_index, pkt, s, 0);
2682  if (hls->ignore_io_errors)
2683  ret = 0;
2684  }
2685 
2686  return ret;
2687 }
2688 
2690 {
2691  HLSContext *hls = s->priv_data;
2692  int i = 0;
2693  VariantStream *vs = NULL;
2694 
2695  for (i = 0; i < hls->nb_varstreams; i++) {
2696  vs = &hls->var_streams[i];
2697 
2698  av_freep(&vs->basename);
2701  av_freep(&vs->vtt_basename);
2702  av_freep(&vs->vtt_m3u8_name);
2703 
2706  if (hls->resend_init_file)
2707  av_freep(&vs->init_buffer);
2710  av_freep(&vs->m3u8_name);
2711  av_freep(&vs->streams);
2712  }
2713 
2714  ff_format_io_close(s, &hls->m3u8_out);
2717  av_freep(&hls->key_basename);
2718  av_freep(&hls->var_streams);
2719  av_freep(&hls->cc_streams);
2720  av_freep(&hls->master_m3u8_url);
2721 }
2722 
2724 {
2725  HLSContext *hls = s->priv_data;
2726  AVFormatContext *oc = NULL;
2727  AVFormatContext *vtt_oc = NULL;
2728  char *old_filename = NULL;
2729  const char *proto = NULL;
2730  int use_temp_file = 0;
2731  int i;
2732  int ret = 0;
2733  VariantStream *vs = NULL;
2735  int range_length, byterange_mode;
2736 
2737  for (i = 0; i < hls->nb_varstreams; i++) {
2738  char *filename = NULL;
2739  vs = &hls->var_streams[i];
2740  oc = vs->avf;
2741  vtt_oc = vs->vtt_avf;
2742  old_filename = av_strdup(oc->url);
2743  use_temp_file = 0;
2744 
2745  if (!old_filename) {
2746  return AVERROR(ENOMEM);
2747  }
2748  if (hls->key_info_file || hls->encrypt) {
2749  av_dict_set(&options, "encryption_key", vs->key_string, 0);
2750  av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2751  filename = av_asprintf("crypto:%s", oc->url);
2752  } else {
2753  filename = av_asprintf("%s", oc->url);
2754  }
2755  if (!filename) {
2757  av_freep(&old_filename);
2758  return AVERROR(ENOMEM);
2759  }
2760 
2761  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2762  if (!vs->init_range_length) {
2763  uint8_t *buffer = NULL;
2764  av_write_frame(oc, NULL); /* Flush any buffered data */
2765 
2766  int init_range_length = avio_close_dyn_buf(oc->pb, &buffer);
2767  avio_write(vs->out, buffer, init_range_length);
2768  av_freep(&buffer);
2769  vs->init_range_length = init_range_length;
2770  avio_open_dyn_buf(&oc->pb);
2771  vs->packets_written = 0;
2772  vs->start_pos = init_range_length;
2773  byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2774  if (!byterange_mode) {
2775  ff_format_io_close(s, &vs->out);
2777  }
2778  }
2779  }
2780  if (!(hls->flags & HLS_SINGLE_FILE)) {
2781  set_http_options(s, &options, hls);
2782  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2783  if (ret < 0) {
2784  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2785  goto failed;
2786  }
2787  if (hls->segment_type == SEGMENT_TYPE_FMP4)
2788  write_styp(vs->out);
2789  }
2790  ret = flush_dynbuf(vs, &range_length);
2791  if (ret < 0)
2792  goto failed;
2793 
2794  vs->size = range_length;
2795  ret = hlsenc_io_close(s, &vs->out, filename);
2796  if (ret < 0) {
2797  av_log(s, AV_LOG_WARNING, "upload segment failed, will retry with a new http session.\n");
2798  ff_format_io_close(s, &vs->out);
2799  ret = hlsenc_io_open(s, &vs->out, filename, &options);
2800  if (ret < 0) {
2801  av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2802  goto failed;
2803  }
2804  reflush_dynbuf(vs, &range_length);
2805  ret = hlsenc_io_close(s, &vs->out, filename);
2806  if (ret < 0)
2807  av_log(s, AV_LOG_WARNING, "Failed to upload file '%s' at the end.\n", oc->url);
2808  }
2809  if (hls->flags & HLS_SINGLE_FILE) {
2810  if (hls->key_info_file || hls->encrypt) {
2811  vs->size = append_single_file(s, vs);
2812  }
2814  }
2815 failed:
2816  av_freep(&vs->temp_buffer);
2818  av_freep(&filename);
2819  av_write_trailer(oc);
2820  if (oc->url[0]) {
2821  proto = avio_find_protocol_name(oc->url);
2822  use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & HLS_TEMP_FILE);
2823  }
2824 
2825  // rename that segment from .tmp to the real one
2826  if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) {
2827  hls_rename_temp_file(s, oc);
2828  av_freep(&old_filename);
2829  old_filename = av_strdup(oc->url);
2830 
2831  if (!old_filename) {
2832  return AVERROR(ENOMEM);
2833  }
2834  }
2835 
2836  /* after av_write_trailer, then duration + 1 duration per packet */
2837  hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size);
2838 
2839  sls_flag_file_rename(hls, vs, old_filename);
2840 
2841  if (vtt_oc) {
2842  if (vtt_oc->pb)
2843  av_write_trailer(vtt_oc);
2844  vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos;
2845  ff_format_io_close(s, &vtt_oc->pb);
2846  }
2847  ret = hls_window(s, 1, vs);
2848  if (ret < 0) {
2849  av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2850  ff_format_io_close(s, &vs->out);
2851  hls_window(s, 1, vs);
2852  }
2853  ffio_free_dyn_buf(&oc->pb);
2854 
2855  av_free(old_filename);
2856  }
2857 
2858  return 0;
2859 }
2860 
2861 
2863 {
2864  int ret = 0;
2865  int i = 0;
2866  int j = 0;
2867  HLSContext *hls = s->priv_data;
2868  const char *pattern;
2869  VariantStream *vs = NULL;
2870  const char *vtt_pattern = hls->flags & HLS_SINGLE_FILE ? ".vtt" : "%d.vtt";
2871  int http_base_proto = ff_is_http_proto(s->url);
2872  int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;
2873  double initial_program_date_time = av_gettime() / 1000000.0;
2874 
2875  if (hls->use_localtime) {
2877  } else {
2878  pattern = hls->segment_type == SEGMENT_TYPE_FMP4 ? "%d.m4s" : "%d.ts";
2879  if (hls->flags & HLS_SINGLE_FILE)
2880  pattern += 2;
2881  }
2882 
2883  hls->has_default_key = 0;
2884  hls->has_video_m3u8 = 0;
2886  if (ret < 0) {
2887  av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",
2888  ret);
2889  return ret;
2890  }
2891 
2892  if (!hls->method && http_base_proto) {
2893  av_log(hls, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n");
2894  }
2895 
2896  ret = validate_name(hls->nb_varstreams, s->url);
2897  if (ret < 0)
2898  return ret;
2899 
2900  if (hls->segment_filename) {
2902  if (ret < 0)
2903  return ret;
2904  }
2905 
2906  if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {
2908  if (ret < 0)
2909  return ret;
2910  }
2911 
2912  if (hls->subtitle_filename) {
2914  if (ret < 0)
2915  return ret;
2916  }
2917 
2918  if (hls->master_pl_name) {
2920  if (ret < 0) {
2921  av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",
2922  ret);
2923  return ret;
2924  }
2925  }
2926 
2930  time_t t = time(NULL);
2932  hls->start_sequence = av_gettime();
2934  hls->start_sequence = (int64_t)t;
2936  char b[15];
2937  struct tm *p, tmbuf;
2938  if (!(p = localtime_r(&t, &tmbuf)))
2939  return AVERROR(errno);
2940  if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
2941  return AVERROR(ENOMEM);
2942  hls->start_sequence = strtoll(b, NULL, 10);
2943  }
2944  av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
2945  }
2946 
2947  hls->recording_time = hls->init_time && hls->max_nb_segments > 0 ? hls->init_time : hls->time;
2948 
2949  if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) {
2950  // Independent segments cannot be guaranteed when splitting by time
2953  "'split_by_time' and 'independent_segments' cannot be "
2954  "enabled together. Disabling 'independent_segments' flag\n");
2955  }
2956 
2957  for (i = 0; i < hls->nb_varstreams; i++) {
2958  vs = &hls->var_streams[i];
2959 
2960  ret = format_name(s->url, &vs->m3u8_name, i, vs->varname);
2961  if (ret < 0)
2962  return ret;
2963 
2964  vs->sequence = hls->start_sequence;
2965  vs->start_pts = AV_NOPTS_VALUE;
2966  vs->end_pts = AV_NOPTS_VALUE;
2967  vs->current_segment_final_filename_fmt[0] = '\0';
2968  vs->initial_prog_date_time = initial_program_date_time;
2969 
2970  for (j = 0; j < vs->nb_streams; j++) {
2972  /* Get one video stream to reference for split segments
2973  * so use the first video stream index. */
2974  if ((vs->has_video == 1) && (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) {
2975  vs->reference_stream_index = vs->streams[j]->index;
2976  }
2978  }
2979 
2980  if (vs->has_video > 1)
2981  av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n");
2982  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2983 #if CONFIG_MP4_MUXER
2985  vs->oformat = &ff_mp4_muxer.p;
2986 #else
2987  return AVERROR_MUXER_NOT_FOUND;
2988 #endif
2989  } else {
2991  vs->oformat = &ff_mpegts_muxer.p;
2992  }
2993 
2994  if (hls->segment_filename) {
2995  ret = format_name(hls->segment_filename, &vs->basename, i, vs->varname);
2996  if (ret < 0)
2997  return ret;
2998  } else {
2999  char *p = strrchr(vs->m3u8_name, '.');
3000  if (p)
3001  *p = '\0';
3002 
3003  vs->basename = av_asprintf("%s%s", vs->m3u8_name, pattern);
3004  if (!vs->basename)
3005  return AVERROR(ENOMEM);
3006 
3007  if (p)
3008  *p = '.';
3009  }
3010 
3011  if (hls->segment_type == SEGMENT_TYPE_FMP4) {
3012  if (hls->nb_varstreams > 1)
3013  fmp4_init_filename_len += strlen(POSTFIX_PATTERN);
3014  if (hls->flags & HLS_SINGLE_FILE) {
3016  if (!vs->fmp4_init_filename)
3017  return AVERROR(ENOMEM);
3018  } else {
3019  vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);
3020  if (!vs->fmp4_init_filename)
3021  return AVERROR(ENOMEM);
3023  fmp4_init_filename_len);
3024  if (hls->nb_varstreams > 1) {
3025  if (av_stristr(vs->fmp4_init_filename, "%v")) {
3028  &vs->fmp4_init_filename, i, vs->varname);
3029  } else {
3030  ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i);
3031  }
3032  if (ret < 0)
3033  return ret;
3034  }
3035 
3036  if (hls->use_localtime) {
3037  int r;
3038  char *expanded = NULL;
3039 
3040  r = strftime_expand(vs->fmp4_init_filename, &expanded);
3041  if (r < 0) {
3042  av_log(s, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
3043  return r;
3044  }
3046  vs->fmp4_init_filename = expanded;
3047  }
3048 
3049  char *p = strrchr(vs->m3u8_name, '/');
3050  if (p) {
3051  char tmp = *(++p);
3052  *p = '\0';
3053  vs->base_output_dirname = av_asprintf("%s%s", vs->m3u8_name,
3054  vs->fmp4_init_filename);
3055  *p = tmp;
3056  } else {
3058  }
3059  if (!vs->base_output_dirname)
3060  return AVERROR(ENOMEM);
3061  }
3062  }
3063 
3065  if (ret < 0)
3066  return ret;
3067 
3068  if (vs->has_subtitle) {
3070  vs->vtt_oformat = &ff_webvtt_muxer.p;
3071 
3072  char *p = strrchr(vs->m3u8_name, '.');
3073  if (p)
3074  *p = '\0';
3075 
3076  vs->vtt_basename = av_asprintf("%s%s", vs->m3u8_name, vtt_pattern);
3077  if (!vs->vtt_basename)
3078  return AVERROR(ENOMEM);
3079 
3080  if (hls->subtitle_filename) {
3082  if (ret < 0)
3083  return ret;
3084  } else {
3085  vs->vtt_m3u8_name = av_asprintf("%s_vtt.m3u8", vs->m3u8_name);
3086  if (!vs->vtt_m3u8_name)
3087  return AVERROR(ENOMEM);
3088  }
3089  if (p)
3090  *p = '.';
3091  }
3092 
3093  if ((ret = hls_mux_init(s, vs)) < 0)
3094  return ret;
3095 
3096  if (hls->flags & HLS_APPEND_LIST) {
3097  parse_playlist(s, vs->m3u8_name, vs);
3098  vs->discontinuity = 1;
3099  if (hls->init_time > 0) {
3100  av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
3101  " hls_init_time value will have no effect\n");
3102  hls->init_time = 0;
3103  hls->recording_time = hls->time;
3104  }
3105  }
3106 
3107  if ((ret = hls_start(s, vs)) < 0)
3108  return ret;
3109  vs->number++;
3110  }
3111 
3112  return ret;
3113 }
3114 
3115 #define OFFSET(x) offsetof(HLSContext, x)
3116 #define E AV_OPT_FLAG_ENCODING_PARAM
3117 static const AVOption options[] = {
3118  {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
3119  {"hls_time", "set segment length", OFFSET(time), AV_OPT_TYPE_DURATION, {.i64 = 2000000}, 0, INT64_MAX, E},
3120  {"hls_init_time", "set segment length at init list", OFFSET(init_time), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E},
3121  {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E},
3122  {"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},
3123  {"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},
3124  {"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},
3125  {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3126  {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3127  {"hls_segment_options","set segments files format options of hls", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
3128  {"hls_segment_size", "maximum size per segment file, (in bytes)", OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
3129  {"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},
3130  {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
3131  {"hls_enc_key", "hex-coded 16 byte key to encrypt the segments", OFFSET(key), AV_OPT_TYPE_STRING, .flags = E},
3132  {"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},
3133  {"hls_enc_iv", "hex-coded 16 byte initialization vector", OFFSET(iv), AV_OPT_TYPE_STRING, .flags = E},
3134  {"hls_subtitle_path", "set path of hls subtitles", OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3135  {"hls_segment_type", "set hls segment files type", OFFSET(segment_type), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, SEGMENT_TYPE_FMP4, E, .unit = "segment_type"},
3136  {"mpegts", "make segment file to mpegts files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, UINT_MAX, E, .unit = "segment_type"},
3137  {"fmp4", "make segment file to fragment mp4 files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_FMP4 }, 0, UINT_MAX, E, .unit = "segment_type"},
3138  {"hls_fmp4_init_filename", "set fragment mp4 file init filename", OFFSET(fmp4_init_filename), AV_OPT_TYPE_STRING, {.str = "init.mp4"}, 0, 0, E},
3139  {"hls_fmp4_init_resend", "resend fragment mp4 init file after refresh m3u8 every time", OFFSET(resend_init_file), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3140  {"hls_flags", "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, .unit = "flags"},
3141  {"single_file", "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX, E, .unit = "flags"},
3142  {"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, .unit = "flags"},
3143  {"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, .unit = "flags"},
3144  {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, .unit = "flags"},
3145  {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, .unit = "flags"},
3146  {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, .unit = "flags"},
3147  {"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, .unit = "flags"},
3148  {"append_list", "append the new segments into old hls segment list", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX, E, .unit = "flags"},
3149  {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX, E, .unit = "flags"},
3150  {"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, .unit = "flags"},
3151  {"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, .unit = "flags"},
3152  {"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, .unit = "flags"},
3153  {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX, E, .unit = "flags"},
3154  {"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, .unit = "flags"},
3155  {"iframes_only", "add EXT-X-I-FRAMES-ONLY, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_I_FRAMES_ONLY }, 0, UINT_MAX, E, .unit = "flags"},
3156  {"strftime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3157  {"strftime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3158  {"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, .unit = "pl_type" },
3159  {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, .unit = "pl_type" },
3160  {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, .unit = "pl_type" },
3161  {"method", "set the HTTP method(default: PUT)", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3162  {"hls_start_number_source", "set source of first number in sequence", OFFSET(start_sequence_source_type), AV_OPT_TYPE_INT, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, 0, HLS_START_SEQUENCE_LAST-1, E, .unit = "start_sequence_source_type" },
3163  {"generic", "start_number value (default)", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3164  {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3165  {"epoch_us", "microseconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3166  {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3167  {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3168  {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3169  {"cc_stream_map", "Closed captions stream map string", OFFSET(cc_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3170  {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3171  {"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},
3172  {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3173  {"timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
3174  {"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 },
3175  {"headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
3176  { NULL },
3177 };
3178 
3179 static const AVClass hls_class = {
3180  .class_name = "hls muxer",
3181  .item_name = av_default_item_name,
3182  .option = options,
3183  .version = LIBAVUTIL_VERSION_INT,
3184 };
3185 
3186 
3188  .p.name = "hls",
3189  .p.long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
3190  .p.extensions = "m3u8",
3191  .p.audio_codec = AV_CODEC_ID_AAC,
3192  .p.video_codec = AV_CODEC_ID_H264,
3193  .p.subtitle_codec = AV_CODEC_ID_WEBVTT,
3195  .p.priv_class = &hls_class,
3196  .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
3197  .priv_data_size = sizeof(HLSContext),
3198  .init = hls_init,
3202  .deinit = hls_deinit,
3203 };
flags
const SwsFlags flags[]
Definition: swscale.c:85
ff_get_chomp_line
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:789
ff_webvtt_muxer
const FFOutputFormat ff_webvtt_muxer
Definition: webvttenc.c:100
VariantStream::vtt_avf
AVFormatContext * vtt_avf
Definition: hlsenc.c:133
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:203
hls_write_header
static int hls_write_header(AVFormatContext *s)
Definition: hlsenc.c:2300
av_codec_get_id
enum AVCodecID av_codec_get_id(const struct AVCodecTag *const *tags, unsigned int tag)
Get the AVCodecID for the given codec tag tag.
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
get_relative_url
static const char * get_relative_url(const char *master_url, const char *media_url)
Definition: hlsenc.c:1313
name
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 name
Definition: writing_filters.txt:88
find_segment_by_filename
static HLSSegment * find_segment_by_filename(HLSSegment *segment, const char *filename)
Definition: hlsenc.c:897
append_postfix
static int append_postfix(char *name, int name_buf_len, int i)
Definition: hlsenc.c:1880
HLSContext::timeout
int64_t timeout
Definition: hlsenc.c:259
sls_flag_use_localtime_filename
static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c, VariantStream *vs)
Definition: hlsenc.c:997
HLS_TEMP_FILE
@ HLS_TEMP_FILE
Definition: hlsenc.c:108
AVOutputFormat::name
const char * name
Definition: avformat.h:508
av_bprint_is_complete
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:218
r
const char * r
Definition: vf_curves.c:127
AVERROR
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
opt.h
strftime_expand
static int strftime_expand(const char *fmt, char **dest)
Definition: hlsenc.c:266
VariantStream::has_subtitle
int has_subtitle
Definition: hlsenc.c:136
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:53
HLSContext::resend_init_file
int resend_init_file
resend init file into disk after refresh m3u8
Definition: hlsenc.c:213
HLSContext::hls_delete_threshold
int hls_delete_threshold
Definition: hlsenc.c:207
AVFMT_NODIMENSIONS
#define AVFMT_NODIMENSIONS
Format does not need width/height.
Definition: avformat.h:483
VariantStream::codec_attr
char codec_attr[128]
Definition: hlsenc.c:180
ffio_wfourcc
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
Definition: avio_internal.h:124
HLSContext::key_file
char key_file[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:234
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
ff_hls_write_end_list
void ff_hls_write_end_list(AVIOContext *out)
Definition: hlsplaylist.c:199
hls_init_file_resend
static int hls_init_file_resend(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:2361
av_stristr
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:58
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
av_dict_count
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition: dict.c:37
fn1
#define fn1(name, depth)
Definition: blend_modes.c:90
PLAYLIST_TYPE_VOD
@ PLAYLIST_TYPE_VOD
Definition: hlsplaylist.h:34
VariantStream::key_uri
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:175
NEXT
#define NEXT(s)
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:263
int64_t
long long int64_t
Definition: coverity.c:34
VariantStream::init_range_length
int init_range_length
Definition: hlsenc.c:128
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:115
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:208
write_styp
static void write_styp(AVIOContext *pb)
Definition: hlsenc.c:467
VariantStream::var_stream_idx
unsigned var_stream_idx
Definition: hlsenc.c:120
HLSContext::cc_stream_map
char * cc_stream_map
Definition: hlsenc.c:252
PLAYLIST_TYPE_EVENT
@ PLAYLIST_TYPE_EVENT
Definition: hlsplaylist.h:33
HLS_APPEND_LIST
@ HLS_APPEND_LIST
Definition: hlsenc.c:103
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1382
deinit
static void deinit(AVFormatContext *s)
Definition: chromaprint.c:53
create_master_playlist
static int create_master_playlist(AVFormatContext *s, VariantStream *const input_vs, int final)
Definition: hlsenc.c:1350
AVPacketSideData
This structure stores auxiliary information for decoding, presenting, or otherwise processing the cod...
Definition: packet.h:424
HLS_SECOND_LEVEL_SEGMENT_INDEX
@ HLS_SECOND_LEVEL_SEGMENT_INDEX
Definition: hlsenc.c:105
HLS_DELETE_SEGMENTS
@ HLS_DELETE_SEGMENTS
Definition: hlsenc.c:98
AVFormatContext::strict_std_compliance
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1673
HLSContext::ignore_io_errors
int ignore_io_errors
Definition: hlsenc.c:260
KEYSIZE
#define KEYSIZE
Definition: hlsenc.c:71
HLS_MICROSECOND_UNIT
#define HLS_MICROSECOND_UNIT
Definition: hlsenc.c:73
ClosedCaptionsStream
Definition: hlsenc.c:193
AVOption
AVOption.
Definition: opt.h:428
HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH
@ HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH
Definition: hlsenc.c:62
b
#define b
Definition: input.c:43
AVStream::avg_frame_rate
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:836
HLS_INDEPENDENT_SEGMENTS
@ HLS_INDEPENDENT_SEGMENTS
Definition: hlsenc.c:110
HLS_OMIT_ENDLIST
@ HLS_OMIT_ENDLIST
Definition: hlsenc.c:101
HLSContext::iv
char * iv
Definition: hlsenc.c:229
VariantStream::iv_string
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:177
AV_OPT_TYPE_DURATION
@ AV_OPT_TYPE_DURATION
Underlying C type is int64_t.
Definition: opt.h:318
AV_DICT_APPEND
#define AV_DICT_APPEND
If the entry already exists, append to it.
Definition: dict.h:82
VariantStream::total_duration
double total_duration
Definition: hlsenc.c:152
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
VariantStream::start_pts
int64_t start_pts
Definition: hlsenc.c:140
ff_hls_write_file_entry
int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, int byterange_mode, double duration, int round_duration, int64_t size, int64_t pos, const char *baseurl, const char *filename, double *prog_date_time, int iframe_mode)
Definition: hlsplaylist.c:144
nb_streams
static unsigned int nb_streams
Definition: ffprobe.c:352
HLSContext::nb_ccstreams
unsigned int nb_ccstreams
Definition: hlsenc.c:246
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:621
AVCodecParameters::codec_tag
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:61
PLAYLIST_TYPE_NONE
@ PLAYLIST_TYPE_NONE
Definition: hlsplaylist.h:32
mathematics.h
AVDictionary
Definition: dict.c:32
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
BUFSIZE
#define BUFSIZE
Definition: hlsenc.c:74
avformat_init_output
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:446
extract_segment_number
static int extract_segment_number(const char *filename)
Definition: hlsenc.c:1143
hls_write_trailer
static int hls_write_trailer(struct AVFormatContext *s)
Definition: hlsenc.c:2723
get_nth_codec_stream_index
static int get_nth_codec_stream_index(AVFormatContext *s, enum AVMediaType codec_type, int64_t stream_id)
Definition: hlsenc.c:1979
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:329
LINE_BUFFER_SIZE
#define LINE_BUFFER_SIZE
Definition: hlsenc.c:72
codec_type
enum AVMediaType codec_type
Definition: rtp.c:37
E
#define E
Definition: hlsenc.c:3116
os_support.h
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:650
update_variant_stream_info
static int update_variant_stream_info(AVFormatContext *s)
Definition: hlsenc.c:2220
av_basename
const char * av_basename(const char *path)
Thread safe basename.
Definition: avstring.c:253
AV_WB64
#define AV_WB64(p, v)
Definition: intreadwrite.h:429
FFOutputFormat::p
AVOutputFormat p
The public AVOutputFormat.
Definition: mux.h:65
hlsplaylist.h
HLSContext::allowcache
int allowcache
Definition: hlsenc.c:217
HLSContext::user_agent
char * user_agent
Definition: hlsenc.c:241
sls_flag_check_duration_size
static int sls_flag_check_duration_size(HLSContext *hls, VariantStream *vs)
Definition: hlsenc.c:970
av_append_path_component
char * av_append_path_component(const char *path, const char *component)
Append path component to the existing path.
Definition: avstring.c:297
VariantStream::key_file
char key_file[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:174
HLSSegment::duration
double duration
Definition: hlsenc.c:80
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1584
do_encrypt
static int do_encrypt(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:638
HLSContext::use_localtime
int use_localtime
flag to expand filename with localtime
Definition: hlsenc.c:215
SEGMENT_TYPE_FMP4
@ SEGMENT_TYPE_FMP4
Definition: hlsenc.c:116
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: avformat.c:830
ff_hls_write_playlist_header
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:110
av_bprint_init_for_buffer
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size)
Init a print buffer using a pre-existing buffer.
Definition: bprint.c:85
HLSSegment::sub_filename
const char * sub_filename
Definition: hlsenc.c:79
segment::duration
int64_t duration
Definition: hls.c:78
ff_hls_muxer
const FFOutputFormat ff_hls_muxer
Definition: hlsenc.c:3187
hls_start
static int hls_start(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:1674
hls_delete_file
static int hls_delete_file(HLSContext *hls, AVFormatContext *avf, char *path, const char *proto)
Definition: hlsenc.c:504
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:494
val
static double val(void *priv, double ch)
Definition: aeval.c:77
VariantStream::oformat
const AVOutputFormat * oformat
Definition: hlsenc.c:123
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:824
VariantStream::start_pts_from_audio
int start_pts_from_audio
Definition: hlsenc.c:138
ff_rename
int ff_rename(const char *url_src, const char *url_dst, void *logctx)
Wrap ffurl_move() and log if error happens.
Definition: avio.c:867
ff_data_to_hex
char * ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase)
Write hexadecimal string corresponding to given binary data.
Definition: utils.c:458
AVRational::num
int num
Numerator.
Definition: rational.h:59
HLS_PERIODIC_REKEY
@ HLS_PERIODIC_REKEY
Definition: hlsenc.c:109
av_dirname
const char * av_dirname(char *path)
Thread safe dirname.
Definition: avstring.c:276
sls_flag_file_rename
static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename)
Definition: hlsenc.c:990
fn
Definition: uops_tmpl.c:762
HLS_ROUND_DURATIONS
@ HLS_ROUND_DURATIONS
Definition: hlsenc.c:99
HLSContext::use_localtime_mkdir
int use_localtime_mkdir
flag to mkdir dirname in timebased filename
Definition: hlsenc.c:216
avio_close_dyn_buf
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1410
ff_mp4_muxer
const FFOutputFormat ff_mp4_muxer
avassert.h
lrint
#define lrint
Definition: tablegen.h:53
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
AVFormatContext::metadata
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1546
get_stream_bit_rate
static int64_t get_stream_bit_rate(AVStream *stream)
Definition: hlsenc.c:1333
HLSSegment::discont
int discont
Definition: hlsenc.c:81
VariantStream::avg_bitrate
int64_t avg_bitrate
Definition: hlsenc.c:153
HLSContext::key_basename
char * key_basename
Definition: hlsenc.c:230
HLSContext::m3u8_out
AVIOContext * m3u8_out
Definition: hlsenc.c:256
avio_open_dyn_buf
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1365
HLSContext::encrypt_started
int encrypt_started
Definition: hlsenc.c:231
HLSSegment::buf
char buf[]
Definition: hlsenc.c:92
HLSSegment::next
struct HLSSegment * next
Definition: hlsenc.c:89
validate_name
static int validate_name(int nb_vs, const char *fn)
Definition: hlsenc.c:1899
attributes_internal.h
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
HLSContext::method
char * method
Definition: hlsenc.c:240
set_http_options
static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c)
Definition: hlsenc.c:330
CODEC_ATTRIBUTE_WRITTEN
@ CODEC_ATTRIBUTE_WRITTEN
Definition: hlsenc.c:67
VariantStream::vtt_oformat
const AVOutputFormat * vtt_oformat
Definition: hlsenc.c:124
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1465
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:201
HLSContext::has_default_key
int has_default_key
Definition: hlsenc.c:262
av_strtok
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:179
flush_dynbuf
static int flush_dynbuf(VariantStream *vs, int *range_length)
Definition: hlsenc.c:477
hls_deinit
static void hls_deinit(AVFormatContext *s)
Definition: hlsenc.c:2689
HLS_SECOND_LEVEL_SEGMENT_SIZE
@ HLS_SECOND_LEVEL_SEGMENT_SIZE
Definition: hlsenc.c:107
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Underlying C type is int64_t.
Definition: opt.h:262
VariantStream::has_video
int has_video
Definition: hlsenc.c:135
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:42
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:618
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
AVPacketSideData::data
uint8_t * data
Definition: packet.h:425
VariantStream::language
const char * language
Definition: hlsenc.c:185
headers
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 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 fate list failing List the fate tests that failed the last time they were executed fate clear reports Remove the test reports from previous test libraries and programs examples Build all examples located in doc examples checkheaders Check headers dependencies alltools Build all tools in tools directory config Reconfigure the project with the current configuration tools target_dec_< decoder > _fuzzer Build fuzzer to fuzz the specified decoder tools target_bsf_< filter > _fuzzer Build fuzzer to fuzz the specified bitstream filter Useful standard make this is useful to reduce unneeded rebuilding when changing headers
Definition: build_system.txt:59
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
HLSContext::time
int64_t time
Definition: hlsenc.c:204
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
ff_bprint_finalize_as_fam
void * ff_bprint_finalize_as_fam(struct AVBPrint *bp, const void *struct_ptr, size_t fam_offset)
Allocate copy of a structure and copy contents of an AVBPrint buffer to the flexible array member of ...
Definition: utils.c:688
HLSContext::key_url
char * key_url
Definition: hlsenc.c:228
av_program_copy
int av_program_copy(AVFormatContext *dst, const AVFormatContext *src, int progid, int flags)
Copy an AVProgram from one AVFormatContext to another.
Definition: avformat.c:344
AVOutputFormat::codec_tag
const struct AVCodecTag *const * codec_tag
List of supported codec_id-codec_tag pairs, ordered by "better choice first".
Definition: avformat.h:533
av_stristart
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:47
AVFormatContext::opaque
void * opaque
User data.
Definition: avformat.h:1878
VariantStream::key_string
char key_string[KEYSIZE *2+1]
Definition: hlsenc.c:176
key
const char * key
Definition: hwcontext_opencl.c:189
AVCodecParameters::nb_coded_side_data
int nb_coded_side_data
Amount of entries in coded_side_data.
Definition: codec_par.h:88
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
AVCPBProperties
This structure describes the bitrate properties of an encoded bitstream.
Definition: defs.h:282
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:77
avformat_write_header
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:467
tmp
static uint8_t tmp[40]
Definition: aes_ctr.c:52
VariantStream::attr_status
CodecAttributeStatus attr_status
Definition: hlsenc.c:181
VariantStream::video_lastpos
int64_t video_lastpos
Definition: hlsenc.c:142
VariantStream::reference_stream_index
int reference_stream_index
Definition: hlsenc.c:149
EXTERN
#define EXTERN
Definition: attributes_internal.h:34
VariantStream::base_output_dirname
char * base_output_dirname
Definition: hlsenc.c:170
VariantStream::segments
HLSSegment * segments
Definition: hlsenc.c:156
write_codec_attr
static void write_codec_attr(AVStream *st, VariantStream *vs)
Definition: hlsenc.c:349
time_internal.h
ff_http_do_new_request
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition: http.c:523
avio_flush
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:228
AV_CODEC_ID_WEBVTT
@ AV_CODEC_ID_WEBVTT
Definition: codec_id.h:583
AVFormatContext
Format I/O context.
Definition: avformat.h:1314
fail
#define fail
Definition: test.h:478
internal.h
ff_hls_write_subtitle_rendition
void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup, const char *filename, const char *language, const char *sname, int name_id, int is_default)
Definition: hlsplaylist.c:58
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:770
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
replace_str_data_in_filename
static int replace_str_data_in_filename(char **s, const char *filename, char placeholder, const char *datastring)
Definition: hlsenc.c:379
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
reflush_dynbuf
static void reflush_dynbuf(VariantStream *vs, int *range_length)
Definition: hlsenc.c:498
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:786
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
StartSequenceSourceType
StartSequenceSourceType
Definition: hlsenc.c:58
VariantStream::m3u8_name
char * m3u8_name
Definition: hlsenc.c:164
write_trailer
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:101
VariantStream::new_start
int new_start
Definition: hlsenc.c:137
HLS_PROGRAM_DATE_TIME
@ HLS_PROGRAM_DATE_TIME
Definition: hlsenc.c:104
VariantStream::subtitle_varname
const char * subtitle_varname
Definition: hlsenc.c:190
HLSSegment::iv_string
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:87
period
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
Definition: writing_filters.txt:89
HLSContext::vtt_format_options_str
char * vtt_format_options_str
Definition: hlsenc.c:222
HLSContext::http_delete
AVIOContext * http_delete
Definition: hlsenc.c:258
AV_OPT_TYPE_DICT
@ AV_OPT_TYPE_DICT
Underlying C type is AVDictionary*.
Definition: opt.h:289
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:242
ffurl_shutdown
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:853
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1356
parseutils.h
HLS_START_SEQUENCE_LAST
@ HLS_START_SEQUENCE_LAST
Definition: hlsenc.c:63
hlsenc_io_open
static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, const char *filename, AVDictionary **options)
Definition: hlsenc.c:289
options
Definition: swscale.c:50
ff_mpegts_muxer
const FFOutputFormat ff_mpegts_muxer
Definition: mpegtsenc.c:2408
AVStream::metadata
AVDictionary * metadata
Definition: avformat.h:827
FFOutputFormat
Definition: mux.h:61
double
double
Definition: af_crystalizer.c:132
HLSSegment
Definition: hlsenc.c:77
AV_DICT_DONT_OVERWRITE
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition: dict.h:81
time.h
VariantStream::discontinuity_set
int discontinuity_set
Definition: hlsenc.c:147
ffio_geturlcontext
URLContext * ffio_geturlcontext(AVIOContext *s)
Return the URLContext associated with the AVIOContext.
Definition: avio.c:107
AVOutputFormat::priv_class
const AVClass * priv_class
AVClass for the private context.
Definition: avformat.h:536
av_write_frame
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:1176
HLSContext::vtt_format_options
AVDictionary * vtt_format_options
Definition: hlsenc.c:238
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition: codec_par.h:207
PLAYLIST_TYPE_NB
@ PLAYLIST_TYPE_NB
Definition: hlsplaylist.h:35
SegmentType
SegmentType
Definition: hlsenc.c:114
index
int index
Definition: gxfenc.c:90
c
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
HLS_START_SEQUENCE_AS_START_NUMBER
@ HLS_START_SEQUENCE_AS_START_NUMBER
Definition: hlsenc.c:59
HLSContext::key
char * key
Definition: hlsenc.c:227
VariantStream::old_segments
HLSSegment * old_segments
Definition: hlsenc.c:158
av_packet_side_data_get
const AVPacketSideData * av_packet_side_data_get(const AVPacketSideData *sd, int nb_sd, enum AVPacketSideDataType type)
Get side information from a side data array.
Definition: packet.c:570
VariantStream::is_default
int is_default
Definition: hlsenc.c:184
HLS_I_FRAMES_ONLY
@ HLS_I_FRAMES_ONLY
Definition: hlsenc.c:111
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:454
av_strncasecmp
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:218
VariantStream::initial_prog_date_time
double initial_prog_date_time
Definition: hlsenc.c:166
HLSContext::segment_filename
char * segment_filename
Definition: hlsenc.c:210
hls_append_segment
static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, VariantStream *vs, double duration, int64_t pos, int64_t size)
Definition: hlsenc.c:1041
ff_hls_write_stream_info
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, int avg_bandwidth, const char *filename, const char *agroup, const char *codecs, const char *ccgroup, const char *sgroup)
Definition: hlsplaylist.c:78
HLSFlags
HLSFlags
Definition: hlsenc.c:95
HLSContext::cc_streams
ClosedCaptionsStream * cc_streams
Definition: hlsenc.c:245
ff_hls_write_playlist_version
void ff_hls_write_playlist_version(AVIOContext *out, int version)
Definition: hlsplaylist.c:32
HLSContext::has_video_m3u8
int has_video_m3u8
Definition: hlsenc.c:263
VariantStream::init_buffer
uint8_t * init_buffer
Definition: hlsenc.c:130
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
VariantStream::ccgroup
const char * ccgroup
Definition: hlsenc.c:188
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:579
hls_rename_temp_file
static int hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
Definition: hlsenc.c:1298
AVMediaType
AVMediaType
Definition: avutil.h:198
HLSContext::master_pl_name
char * master_pl_name
Definition: hlsenc.c:253
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:88
av_codec_get_tag
unsigned int av_codec_get_tag(const struct AVCodecTag *const *tags, enum AVCodecID id)
Get the codec tag for the given codec id id.
FF_OFMT_FLAG_ALLOW_FLUSH
#define FF_OFMT_FLAG_ALLOW_FLUSH
This flag indicates that the muxer stores data internally and supports flushing it.
Definition: mux.h:38
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
HLS_SPLIT_BY_TIME
@ HLS_SPLIT_BY_TIME
Definition: hlsenc.c:102
VariantStream::basename_tmp
char * basename_tmp
Definition: hlsenc.c:160
localtime_r
#define localtime_r
Definition: time_internal.h:46
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
HLSContext::start_sequence_source_type
uint32_t start_sequence_source_type
Definition: hlsenc.c:202
AVFormatContext::url
char * url
input or output URL.
Definition: avformat.h:1430
size
int size
Definition: twinvq_data.h:10344
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:247
HLSSegment::pos
int64_t pos
Definition: hlsenc.c:82
HLSContext::pl_type
uint32_t pl_type
Definition: hlsenc.c:209
CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN
@ CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN
Definition: hlsenc.c:68
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:469
ff_is_http_proto
int ff_is_http_proto(const char *filename)
Utility function to check if the file uses http or https protocol.
Definition: utils.c:582
ff_format_io_close
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: avformat.c:952
ff_hls_write_init_file
void ff_hls_write_init_file(AVIOContext *out, const char *filename, int byterange_mode, int64_t size, int64_t pos)
Definition: hlsplaylist.c:134
HLSSegment::discont_program_date_time
double discont_program_date_time
Definition: hlsenc.c:90
AVStream::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:825
parse_variant_stream_mapstring
static int parse_variant_stream_mapstring(AVFormatContext *s)
Definition: hlsenc.c:1997
hls_init
static int hls_init(AVFormatContext *s)
Definition: hlsenc.c:2862
VariantStream::agroup
const char * agroup
Definition: hlsenc.c:186
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:206
avio_wb32
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:368
av_isdigit
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition: avstring.h:202
VariantStream::sequence
int64_t sequence
Definition: hlsenc.c:122
line
Definition: graph2dot.c:48
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:609
HLSContext::start_sequence
int64_t start_sequence
Definition: hlsenc.c:201
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:233
av_strstart
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:36
VariantStream::temp_buffer
uint8_t * temp_buffer
Definition: hlsenc.c:129
HLSContext::format_options
AVDictionary * format_options
Definition: hlsenc.c:224
OFFSET
#define OFFSET(x)
Definition: hlsenc.c:3115
HLS_DISCONT_START
@ HLS_DISCONT_START
Definition: hlsenc.c:100
VariantStream::basename
char * basename
Definition: hlsenc.c:161
HLS_START_SEQUENCE_AS_FORMATTED_DATETIME
@ HLS_START_SEQUENCE_AS_FORMATTED_DATETIME
Definition: hlsenc.c:61
parse_playlist
static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
Definition: hlsenc.c:1159
hls_write_packet
static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: hlsenc.c:2409
ff_make_codec_str
int ff_make_codec_str(void *logctx, const AVCodecParameters *par, const AVRational *frame_rate, struct AVBPrint *out)
Make a RFC 4281/6381 like string describing a codec.
Definition: codecstring.c:64
VariantStream::last_segment
HLSSegment * last_segment
Definition: hlsenc.c:157
av_write_trailer
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1238
AV_PKT_DATA_CPB_PROPERTIES
@ AV_PKT_DATA_CPB_PROPERTIES
This side data corresponds to the AVCPBProperties struct.
Definition: packet.h:142
VariantStream::m3u8_created
int m3u8_created
Definition: hlsenc.c:183
bprint.h
ff_hls_write_audio_rendition
void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, const char *filename, const char *language, int name_id, int is_default, int nb_channels)
Definition: hlsplaylist.c:40
URLContext
Definition: url.h:35
HLSContext::iv_string
char iv_string[KEYSIZE *2+1]
Definition: hlsenc.c:237
log.h
AVFMT_GLOBALHEADER
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:478
av_malloc
#define av_malloc(s)
Definition: ops_asmgen.c:44
AVOutputFormat
Definition: avformat.h:507
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:596
avio_internal.h
round
static av_always_inline av_const double round(double x)
Definition: libm.h:446
fn2
#define fn2(a, b)
Definition: aap_template.c:36
AVERROR_MUXER_NOT_FOUND
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:62
HLSContext::key_string
char key_string[KEYSIZE *2+1]
Definition: hlsenc.c:236
VariantStream::sgroup
const char * sgroup
Definition: hlsenc.c:187
HLSContext::max_nb_segments
int max_nb_segments
Definition: hlsenc.c:206
VariantStream::start_pos
int64_t start_pos
Definition: hlsenc.c:144
AVCPBProperties::max_bitrate
int64_t max_bitrate
Maximum bitrate of the stream, in bits per second.
Definition: defs.h:287
VariantStream::nb_streams
unsigned int nb_streams
Definition: hlsenc.c:182
HLSContext::sub_m3u8_out
AVIOContext * sub_m3u8_out
Definition: hlsenc.c:257
hls_encryption_start
static int hls_encryption_start(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:711
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:223
HLSContext
Definition: hls.c:218
options
static const AVOption options[]
Definition: hlsenc.c:3117
url.h
hlsenc_io_close
static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
Definition: hlsenc.c:310
av_random_bytes
int av_random_bytes(uint8_t *buf, size_t len)
Generate cryptographically secure random data, i.e.
Definition: random_seed.c:159
AVFormatContext::max_delay
int max_delay
Definition: avformat.h:1459
VariantStream::number
unsigned number
Definition: hlsenc.c:121
ff_get_line
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
Read a whole line of text from AVIOContext.
Definition: aviobuf.c:772
HLSSegment::var_stream_idx
unsigned var_stream_idx
Definition: hlsenc.c:84
len
int len
Definition: vorbis_enc_data.h:426
start_sequence
static const uint8_t start_sequence[]
Definition: rtpdec_h264.c:66
VariantStream::duration
double duration
Definition: hlsenc.c:143
VariantStream::streams
AVStream ** streams
Definition: hlsenc.c:179
AVCodecParameters::coded_side_data
AVPacketSideData * coded_side_data
Additional data associated with the entire stream.
Definition: codec_par.h:83
write_packet
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
Definition: ffmpeg_mux.c:204
HLSContext::fmp4_init_filename
char * fmp4_init_filename
Definition: hlsenc.c:211
AVCodecParameters::avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: codec_par.c:107
HLSContext::encrypt
int encrypt
Definition: hlsenc.c:226
VariantStream::max_bitrate
int64_t max_bitrate
Definition: hlsenc.c:154
HLSContext::http_persistent
int http_persistent
Definition: hls.c:243
HLS_SINGLE_FILE
@ HLS_SINGLE_FILE
Definition: hlsenc.c:97
ffio_free_dyn_buf
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1438
AVStream::id
int id
Format-specific stream ID.
Definition: avformat.h:759
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:747
VariantStream::out_single_file
AVIOContext * out_single_file
Definition: hlsenc.c:126
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:236
AVClass::class_name
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:81
VariantStream::fmp4_init_filename
char * fmp4_init_filename
Definition: hlsenc.c:169
HLSContext::subtitle_filename
char * subtitle_filename
Definition: hlsenc.c:223
AVFormatContext::oformat
const struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1333
av_strlcat
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:95
replace_int_data_in_filename
static int replace_int_data_in_filename(char **s, const char *filename, char placeholder, int64_t number)
Definition: hlsenc.c:419
hls_delete_old_segments
static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, VariantStream *vs)
Definition: hlsenc.c:528
pos
unsigned int pos
Definition: spdifenc.c:414
avformat.h
VariantStream::end_pts
int64_t end_pts
Definition: hlsenc.c:141
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:122
VariantStream::encrypt_started
int encrypt_started
Definition: hlsenc.c:172
VariantStream::discontinuity
int discontinuity
Definition: hlsenc.c:148
VariantStream::nb_entries
int nb_entries
Definition: hlsenc.c:146
SEGMENT_TYPE_MPEGTS
@ SEGMENT_TYPE_MPEGTS
Definition: hlsenc.c:115
avio_printf
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
av_small_strptime
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
Definition: parseutils.c:494
VariantStream::current_segment_final_filename_fmt
char current_segment_final_filename_fmt[MAX_URL_SIZE]
Definition: hlsenc.c:167
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:753
can_split
static void can_split(const VVCLocalContext *lc, int x0, int y0, int cb_width, int cb_height, int mtt_depth, int depth_offset, int part_idx, VVCSplitMode last_split_mode, VVCTreeType tree_type, VVCModeType mode_type, VVCAllowedSplit *split)
Definition: ctu.c:526
random_seed.h
format_name
static int format_name(const char *buf, char **s, int index, const char *varname)
Definition: hlsenc.c:1933
MAX_URL_SIZE
#define MAX_URL_SIZE
Definition: internal.h:30
get_default_pattern_localtime_fmt
static const char * get_default_pattern_localtime_fmt(AVFormatContext *s)
Definition: hlsenc.c:1859
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
AVRational::den
int den
Denominator.
Definition: rational.h:60
VariantStream::packets_written
int packets_written
Definition: hlsenc.c:127
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:258
defs.h
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: avformat.c:148
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:615
update_master_pl_info
static int update_master_pl_info(AVFormatContext *s)
Definition: hlsenc.c:2258
AVFormatContext::io_open
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:1919
sls_flag_check_duration_size_index
static int sls_flag_check_duration_size_index(HLSContext *hls)
Definition: hlsenc.c:947
ClosedCaptionsStream::language
const char * language
Definition: hlsenc.c:196
VariantStream::vtt_m3u8_name
char * vtt_m3u8_name
Definition: hlsenc.c:163
HLSContext::baseurl
char * baseurl
Definition: hlsenc.c:221
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
AVPacket::stream_index
int stream_index
Definition: packet.h:605
CodecAttributeStatus
CodecAttributeStatus
Definition: hlsenc.c:66
segment
Definition: hls.c:77
HLSContext::key_info_file
char * key_info_file
Definition: hlsenc.c:233
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
av_dict_set_int
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:177
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:617
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
mem.h
VariantStream::out
AVIOContext * out
Definition: hlsenc.c:125
HLSContext::nb_varstreams
unsigned int nb_varstreams
Definition: hlsenc.c:244
av_strdup
#define av_strdup(s)
Definition: ops_asmgen.c:47
HLSContext::master_m3u8_created
int master_m3u8_created
Definition: hlsenc.c:248
VariantStream::size
int64_t size
Definition: hlsenc.c:145
HLSContext::version
int version
Definition: hlsenc.c:250
ff_mkdir_p
int ff_mkdir_p(const char *path)
Automatically create sub-directories.
Definition: utils.c:424
HLSContext::var_streams
VariantStream * var_streams
Definition: hlsenc.c:243
VariantStream::dpp
double dpp
Definition: hlsenc.c:139
VariantStream::avf
AVFormatContext * avf
Definition: hlsenc.c:132
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:57
POSTFIX_PATTERN
#define POSTFIX_PATTERN
Definition: hlsenc.c:75
AVPacket
This structure stores compressed data.
Definition: packet.h:580
hls_free_segments
static void hls_free_segments(HLSSegment *p)
Definition: hlsenc.c:1287
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:326
HLSContext::flags
uint32_t flags
Definition: hlsenc.c:208
hls_mux_init
static int hls_mux_init(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:770
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_dict_set
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:86
av_dict_copy
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:247
VariantStream::varname
const char * varname
Definition: hlsenc.c:189
HLSSegment::filename
const char * filename
Definition: hlsenc.c:78
AVFormatContext::io_close2
int(* io_close2)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1929
append_single_file
static int64_t append_single_file(AVFormatContext *s, VariantStream *vs)
Definition: hlsenc.c:2378
avio_find_protocol_name
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:663
AV_OPT_TYPE_FLAGS
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition: opt.h:254
HLSContext::init_time
int64_t init_time
Definition: hlsenc.c:205
av_strlcpy
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:85
AVCodecParameters::bit_rate
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:99
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
hls_window
static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
Definition: hlsenc.c:1530
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
HLSSegment::key_uri
const char * key_uri
Definition: hlsenc.c:86
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
sls_flags_filename_process
static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls, VariantStream *vs, double duration, int64_t pos, int64_t size)
Definition: hlsenc.c:907
av_bprint_chars
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition: bprint.c:130
pkt
static AVPacket * pkt
Definition: demux_decode.c:55
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:275
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:384
HLSContext::key_uri
char key_uri[LINE_BUFFER_SIZE+1]
Definition: hlsenc.c:235
avformat_alloc_output_context2
int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
Definition: mux.c:95
AVStream::pts_wrap_bits
int pts_wrap_bits
Number of bits in timestamps.
Definition: avformat.h:890
http.h
HLS_SECOND_LEVEL_SEGMENT_DURATION
@ HLS_SECOND_LEVEL_SEGMENT_DURATION
Definition: hlsenc.c:106
av_bprint_append_data
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
Definition: bprint.c:148
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:298
snprintf
#define snprintf
Definition: snprintf.h:34
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1342
ff_format_set_url
void ff_format_set_url(AVFormatContext *s, char *url)
Set AVFormatContext url field to the provided pointer.
Definition: avformat.c:914
parse_cc_stream_mapstring
static int parse_cc_stream_mapstring(AVFormatContext *s)
Definition: hlsenc.c:2143
HLSContext::segment_type
int segment_type
Definition: hlsenc.c:212
HLSContext::master_m3u8_url
char * master_m3u8_url
Definition: hlsenc.c:249
HLSContext::recording_time
int64_t recording_time
Definition: hlsenc.c:218
HLSContext::max_seg_size
int64_t max_seg_size
Definition: hlsenc.c:219
HLSContext::master_publish_rate
unsigned int master_publish_rate
Definition: hlsenc.c:254
ClosedCaptionsStream::instreamid
const char * instreamid
Definition: hlsenc.c:195
HLSSegment::size
int64_t size
Definition: hlsenc.c:83
duration
static int64_t duration
Definition: ffplay.c:329
HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH
@ HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH
Definition: hlsenc.c:60
VariantStream::vtt_basename
char * vtt_basename
Definition: hlsenc.c:162
ClosedCaptionsStream::ccgroup
const char * ccgroup
Definition: hlsenc.c:194
HLSContext::headers
char * headers
Definition: hlsenc.c:261
hls_class
static const AVClass hls_class
Definition: hlsenc.c:3179
VariantStream
Definition: hlsenc.c:119
VariantStream::total_size
int64_t total_size
Definition: hlsenc.c:151
avio_feof
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:349
HLSContext::var_stream_map
char * var_stream_map
Definition: hlsenc.c:251
mux.h
ff_write_chained
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:1337