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