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