FFmpeg  4.2.3
dashenc.c
Go to the documentation of this file.
1 /*
2  * MPEG-DASH ISO BMFF segmenter
3  * Copyright (c) 2014 Martin Storsjo
4  * Copyright (c) 2018 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 #if HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 
28 #include "libavutil/avassert.h"
29 #include "libavutil/avutil.h"
30 #include "libavutil/avstring.h"
31 #include "libavutil/intreadwrite.h"
32 #include "libavutil/mathematics.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/rational.h"
35 #include "libavutil/time.h"
37 
38 #include "av1.h"
39 #include "avc.h"
40 #include "avformat.h"
41 #include "avio_internal.h"
42 #include "hlsplaylist.h"
43 #if CONFIG_HTTP_PROTOCOL
44 #include "http.h"
45 #endif
46 #include "internal.h"
47 #include "isom.h"
48 #include "os_support.h"
49 #include "url.h"
50 #include "vpcc.h"
51 #include "dash.h"
52 
53 typedef enum {
58 } SegmentType;
59 
60 typedef struct Segment {
61  char file[1024];
62  int64_t start_pos;
64  int64_t time;
66  int64_t duration;
67  int n;
68 } Segment;
69 
70 typedef struct AdaptationSet {
71  char id[10];
72  enum AVMediaType media_type;
74  AVRational min_frame_rate, max_frame_rate;
77 
78 typedef struct OutputStream {
80  int ctx_inited, as_idx;
83  char initfile[1024];
84  int64_t init_start_pos, pos;
86  int nb_segments, segments_size, segment_index;
88  int64_t first_pts, start_pts, max_pts;
89  int64_t last_dts, last_pts;
90  int bit_rate;
91  SegmentType segment_type; /* segment type selected for this particular stream */
92  const char *format_name;
93  const char *extension_name;
94  const char *single_file_name; /* file names selected for this particular stream */
95  const char *init_seg_name;
96  const char *media_seg_name;
97 
98  char codec_str[100];
100  char filename[1024];
101  char full_path[1024];
102  char temp_path[1024];
106 } OutputStream;
107 
108 typedef struct DASHContext {
109  const AVClass *class; /* Class for private options. */
112  int nb_as;
115 #if FF_API_DASH_MIN_SEG_DURATION
116  int min_seg_duration;
117 #endif
118  int64_t seg_duration;
125  int64_t last_duration;
126  int64_t total_duration;
127  char availability_start_time[100];
128  time_t start_time_s;
129  char dirname[1024];
130  const char *single_file_name; /* file names as specified in options */
131  const char *init_seg_name;
132  const char *media_seg_name;
133  const char *utc_timing_url;
134  const char *method;
135  const char *user_agent;
142  int64_t timeout;
146  SegmentType segment_type_option; /* segment type as specified in options */
148  int lhls;
152 } DASHContext;
153 
154 static struct codec_string {
155  int id;
156  const char *str;
157 } codecs[] = {
158  { AV_CODEC_ID_VP8, "vp8" },
159  { AV_CODEC_ID_VP9, "vp9" },
160  { AV_CODEC_ID_VORBIS, "vorbis" },
161  { AV_CODEC_ID_OPUS, "opus" },
162  { AV_CODEC_ID_FLAC, "flac" },
163  { 0, NULL }
164 };
165 
166 static struct format_string {
168  const char *str;
169 } formats[] = {
170  { SEGMENT_TYPE_AUTO, "auto" },
171  { SEGMENT_TYPE_MP4, "mp4" },
172  { SEGMENT_TYPE_WEBM, "webm" },
173  { 0, NULL }
174 };
175 
176 static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
177  AVDictionary **options) {
178  DASHContext *c = s->priv_data;
179  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
180  int err = AVERROR_MUXER_NOT_FOUND;
181  if (!*pb || !http_base_proto || !c->http_persistent) {
182  err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
183 #if CONFIG_HTTP_PROTOCOL
184  } else {
185  URLContext *http_url_context = ffio_geturlcontext(*pb);
186  av_assert0(http_url_context);
187  err = ff_http_do_new_request(http_url_context, filename);
188  if (err < 0)
189  ff_format_io_close(s, pb);
190 #endif
191  }
192  return err;
193 }
194 
195 static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) {
196  DASHContext *c = s->priv_data;
197  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
198 
199  if (!*pb)
200  return;
201 
202  if (!http_base_proto || !c->http_persistent) {
203  ff_format_io_close(s, pb);
204 #if CONFIG_HTTP_PROTOCOL
205  } else {
206  URLContext *http_url_context = ffio_geturlcontext(*pb);
207  av_assert0(http_url_context);
208  avio_flush(*pb);
209  ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
210 #endif
211  }
212 }
213 
214 static const char *get_format_str(SegmentType segment_type) {
215  int i;
216  for (i = 0; i < SEGMENT_TYPE_NB; i++)
217  if (formats[i].segment_type == segment_type)
218  return formats[i].str;
219  return NULL;
220 }
221 
222 static const char *get_extension_str(SegmentType type, int single_file)
223 {
224  switch (type) {
225 
226  case SEGMENT_TYPE_MP4: return single_file ? "mp4" : "m4s";
227  case SEGMENT_TYPE_WEBM: return "webm";
228  default: return NULL;
229  }
230 }
231 
232 static int handle_io_open_error(AVFormatContext *s, int err, char *url) {
233  DASHContext *c = s->priv_data;
234  char errbuf[AV_ERROR_MAX_STRING_SIZE];
235  av_strerror(err, errbuf, sizeof(errbuf));
237  "Unable to open %s for writing: %s\n", url, errbuf);
238  return c->ignore_io_errors ? 0 : err;
239 }
240 
242 {
243  if (segment_type == SEGMENT_TYPE_AUTO) {
244  if (codec_id == AV_CODEC_ID_OPUS || codec_id == AV_CODEC_ID_VORBIS ||
245  codec_id == AV_CODEC_ID_VP8 || codec_id == AV_CODEC_ID_VP9) {
246  segment_type = SEGMENT_TYPE_WEBM;
247  } else {
248  segment_type = SEGMENT_TYPE_MP4;
249  }
250  }
251 
252  return segment_type;
253 }
254 
256 {
257  DASHContext *c = s->priv_data;
258  int has_mp4_streams = 0;
259  for (int i = 0; i < s->nb_streams; ++i) {
260  OutputStream *os = &c->streams[i];
261  SegmentType segment_type = select_segment_type(
263  os->segment_type = segment_type;
264  os->format_name = get_format_str(segment_type);
265  if (!os->format_name) {
266  av_log(s, AV_LOG_ERROR, "Could not select DASH segment type for stream %d\n", i);
268  }
269  os->extension_name = get_extension_str(segment_type, c->single_file);
270  if (!os->extension_name) {
271  av_log(s, AV_LOG_ERROR, "Could not get extension type for stream %d\n", i);
273  }
274 
275  has_mp4_streams |= segment_type == SEGMENT_TYPE_MP4;
276  }
277 
278  if (c->hls_playlist && !has_mp4_streams) {
279  av_log(s, AV_LOG_WARNING, "No mp4 streams, disabling HLS manifest generation\n");
280  c->hls_playlist = 0;
281  }
282 
283  return 0;
284 }
285 
286 static int check_file_extension(const char *filename, const char *extension) {
287  char *dot;
288  if (!filename || !extension)
289  return -1;
290  dot = strrchr(filename, '.');
291  if (dot && !strcmp(dot + 1, extension))
292  return 0;
293  return -1;
294 }
295 
297  AVRational *frame_rate, char *str, int size) {
298  VPCC vpcc;
299  int ret = ff_isom_get_vpcc_features(s, par, frame_rate, &vpcc);
300  if (ret == 0) {
301  av_strlcatf(str, size, "vp09.%02d.%02d.%02d",
302  vpcc.profile, vpcc.level, vpcc.bitdepth);
303  } else {
304  // Default to just vp9 in case of error while finding out profile or level
305  av_log(s, AV_LOG_WARNING, "Could not find VP9 profile and/or level\n");
306  av_strlcpy(str, "vp9", size);
307  }
308  return;
309 }
310 
312  AVRational *frame_rate, char *str, int size)
313 {
314  const AVCodecTag *tags[2] = { NULL, NULL };
315  uint32_t tag;
316  int i;
317 
318  // common Webm codecs are not part of RFC 6381
319  for (i = 0; codecs[i].id; i++)
320  if (codecs[i].id == par->codec_id) {
321  if (codecs[i].id == AV_CODEC_ID_VP9) {
322  set_vp9_codec_str(s, par, frame_rate, str, size);
323  } else {
324  av_strlcpy(str, codecs[i].str, size);
325  }
326  return;
327  }
328 
329  // for codecs part of RFC 6381
330  if (par->codec_type == AVMEDIA_TYPE_VIDEO)
331  tags[0] = ff_codec_movvideo_tags;
332  else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
333  tags[0] = ff_codec_movaudio_tags;
334  else
335  return;
336 
337  tag = par->codec_tag;
338  if (!tag)
339  tag = av_codec_get_tag(tags, par->codec_id);
340  if (!tag)
341  return;
342  if (size < 5)
343  return;
344 
345  AV_WL32(str, tag);
346  str[4] = '\0';
347  if (!strcmp(str, "mp4a") || !strcmp(str, "mp4v")) {
348  uint32_t oti;
349  tags[0] = ff_mp4_obj_type;
350  oti = av_codec_get_tag(tags, par->codec_id);
351  if (oti)
352  av_strlcatf(str, size, ".%02"PRIx32, oti);
353  else
354  return;
355 
356  if (tag == MKTAG('m', 'p', '4', 'a')) {
357  if (par->extradata_size >= 2) {
358  int aot = par->extradata[0] >> 3;
359  if (aot == 31)
360  aot = ((AV_RB16(par->extradata) >> 5) & 0x3f) + 32;
361  av_strlcatf(str, size, ".%d", aot);
362  }
363  } else if (tag == MKTAG('m', 'p', '4', 'v')) {
364  // Unimplemented, should output ProfileLevelIndication as a decimal number
365  av_log(s, AV_LOG_WARNING, "Incomplete RFC 6381 codec string for mp4v\n");
366  }
367  } else if (!strcmp(str, "avc1")) {
368  uint8_t *tmpbuf = NULL;
369  uint8_t *extradata = par->extradata;
370  int extradata_size = par->extradata_size;
371  if (!extradata_size)
372  return;
373  if (extradata[0] != 1) {
374  AVIOContext *pb;
375  if (avio_open_dyn_buf(&pb) < 0)
376  return;
377  if (ff_isom_write_avcc(pb, extradata, extradata_size) < 0) {
378  ffio_free_dyn_buf(&pb);
379  return;
380  }
381  extradata_size = avio_close_dyn_buf(pb, &extradata);
382  tmpbuf = extradata;
383  }
384 
385  if (extradata_size >= 4)
386  av_strlcatf(str, size, ".%02x%02x%02x",
387  extradata[1], extradata[2], extradata[3]);
388  av_free(tmpbuf);
389  } else if (!strcmp(str, "av01")) {
391  if (!par->extradata_size)
392  return;
393  if (ff_av1_parse_seq_header(&seq, par->extradata, par->extradata_size) < 0)
394  return;
395 
396  av_strlcatf(str, size, ".%01u.%02u%s.%02u",
397  seq.profile, seq.level, seq.tier ? "H" : "M", seq.bitdepth);
399  av_strlcatf(str, size, ".%01u.%01u%01u%01u.%02u.%02u.%02u.%01u",
400  seq.monochrome,
403  seq.color_range);
404  }
405 }
406 
408 {
409  uint8_t *buffer;
410 
411  if (!os->ctx->pb) {
412  return AVERROR(EINVAL);
413  }
414 
415  // flush
416  av_write_frame(os->ctx, NULL);
417  avio_flush(os->ctx->pb);
418 
419  if (!c->single_file) {
420  // write out to file
421  *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer);
422  os->ctx->pb = NULL;
423  if (os->out)
424  avio_write(os->out, buffer + os->written_len, *range_length - os->written_len);
425  os->written_len = 0;
426  av_free(buffer);
427 
428  // re-open buffer
429  return avio_open_dyn_buf(&os->ctx->pb);
430  } else {
431  *range_length = avio_tell(os->ctx->pb) - os->pos;
432  return 0;
433  }
434 }
435 
437 {
438  if (c->method)
439  av_dict_set(options, "method", c->method, 0);
440  if (c->user_agent)
441  av_dict_set(options, "user_agent", c->user_agent, 0);
442  if (c->http_persistent)
443  av_dict_set_int(options, "multiple_requests", 1, 0);
444  if (c->timeout >= 0)
445  av_dict_set_int(options, "timeout", c->timeout, 0);
446 }
447 
448 static void get_hls_playlist_name(char *playlist_name, int string_size,
449  const char *base_url, int id) {
450  if (base_url)
451  snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
452  else
453  snprintf(playlist_name, string_size, "media_%d.m3u8", id);
454 }
455 
457  int *start_index, int *start_number) {
458  *start_index = 0;
459  *start_number = 1;
460  if (c->window_size) {
461  *start_index = FFMAX(os->nb_segments - c->window_size, 0);
462  *start_number = FFMAX(os->segment_index - c->window_size, 1);
463  }
464 }
465 
467  int representation_id, int final,
468  char *prefetch_url) {
469  DASHContext *c = s->priv_data;
470  int timescale = os->ctx->streams[0]->time_base.den;
471  char temp_filename_hls[1024];
472  char filename_hls[1024];
473  AVDictionary *http_opts = NULL;
474  int target_duration = 0;
475  int ret = 0;
476  const char *proto = avio_find_protocol_name(c->dirname);
477  int use_rename = proto && !strcmp(proto, "file");
478  int i, start_index, start_number;
479  double prog_date_time = 0;
480 
481  get_start_index_number(os, c, &start_index, &start_number);
482 
483  if (!c->hls_playlist || start_index >= os->nb_segments ||
485  return;
486 
487  get_hls_playlist_name(filename_hls, sizeof(filename_hls),
488  c->dirname, representation_id);
489 
490  snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? "%s.tmp" : "%s", filename_hls);
491 
492  set_http_options(&http_opts, c);
493  ret = dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
494  av_dict_free(&http_opts);
495  if (ret < 0) {
496  handle_io_open_error(s, ret, temp_filename_hls);
497  return;
498  }
499  for (i = start_index; i < os->nb_segments; i++) {
500  Segment *seg = os->segments[i];
501  double duration = (double) seg->duration / timescale;
502  if (target_duration <= duration)
503  target_duration = lrint(duration);
504  }
505 
506  ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration,
507  start_number, PLAYLIST_TYPE_NONE, 0);
508 
511 
512  for (i = start_index; i < os->nb_segments; i++) {
513  Segment *seg = os->segments[i];
514 
515  if (prog_date_time == 0) {
516  if (os->nb_segments == 1)
517  prog_date_time = c->start_time_s;
518  else
519  prog_date_time = seg->prog_date_time;
520  }
522 
524  (double) seg->duration / timescale, 0,
525  seg->range_length, seg->start_pos, NULL,
526  c->single_file ? os->initfile : seg->file,
527  &prog_date_time, 0, 0, 0);
528  if (ret < 0) {
529  av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
530  }
531  }
532 
533  if (prefetch_url)
534  avio_printf(c->m3u8_out, "#EXT-X-PREFETCH:%s\n", prefetch_url);
535 
536  if (final)
538 
539  dashenc_io_close(s, &c->m3u8_out, temp_filename_hls);
540 
541  if (use_rename)
542  if (avpriv_io_move(temp_filename_hls, filename_hls) < 0) {
543  av_log(os->ctx, AV_LOG_WARNING, "renaming file %s to %s failed\n\n", temp_filename_hls, filename_hls);
544  }
545 }
546 
548 {
549  DASHContext *c = s->priv_data;
550  int ret, range_length;
551 
552  ret = flush_dynbuf(c, os, &range_length);
553  if (ret < 0)
554  return ret;
555 
556  os->pos = os->init_range_length = range_length;
557  if (!c->single_file) {
558  char filename[1024];
559  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
560  dashenc_io_close(s, &os->out, filename);
561  }
562  return 0;
563 }
564 
566 {
567  DASHContext *c = s->priv_data;
568  int i, j;
569 
570  if (c->as) {
571  for (i = 0; i < c->nb_as; i++)
572  av_dict_free(&c->as[i].metadata);
573  av_freep(&c->as);
574  c->nb_as = 0;
575  }
576 
577  if (!c->streams)
578  return;
579  for (i = 0; i < s->nb_streams; i++) {
580  OutputStream *os = &c->streams[i];
581  if (os->ctx && os->ctx->pb) {
582  if (!c->single_file)
583  ffio_free_dyn_buf(&os->ctx->pb);
584  else
585  avio_close(os->ctx->pb);
586  }
587  ff_format_io_close(s, &os->out);
588  if (os->ctx)
590  for (j = 0; j < os->nb_segments; j++)
591  av_free(os->segments[j]);
592  av_free(os->segments);
594  av_freep(&os->init_seg_name);
595  av_freep(&os->media_seg_name);
596  }
597  av_freep(&c->streams);
598 
599  ff_format_io_close(s, &c->mpd_out);
601 }
602 
604  int representation_id, int final)
605 {
606  DASHContext *c = s->priv_data;
607  int i, start_index, start_number;
608  get_start_index_number(os, c, &start_index, &start_number);
609 
610  if (c->use_template) {
611  int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE;
612  avio_printf(out, "\t\t\t\t<SegmentTemplate timescale=\"%d\" ", timescale);
613  if (!c->use_timeline) {
614  avio_printf(out, "duration=\"%"PRId64"\" ", c->seg_duration);
615  if (c->streaming && os->availability_time_offset)
616  avio_printf(out, "availabilityTimeOffset=\"%.3f\" ",
618  }
619  avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\">\n", os->init_seg_name, os->media_seg_name, c->use_timeline ? start_number : 1);
620  if (c->use_timeline) {
621  int64_t cur_time = 0;
622  avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
623  for (i = start_index; i < os->nb_segments; ) {
624  Segment *seg = os->segments[i];
625  int repeat = 0;
626  avio_printf(out, "\t\t\t\t\t\t<S ");
627  if (i == start_index || seg->time != cur_time) {
628  cur_time = seg->time;
629  avio_printf(out, "t=\"%"PRId64"\" ", seg->time);
630  }
631  avio_printf(out, "d=\"%"PRId64"\" ", seg->duration);
632  while (i + repeat + 1 < os->nb_segments &&
633  os->segments[i + repeat + 1]->duration == seg->duration &&
634  os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration)
635  repeat++;
636  if (repeat > 0)
637  avio_printf(out, "r=\"%d\" ", repeat);
638  avio_printf(out, "/>\n");
639  i += 1 + repeat;
640  cur_time += (1 + repeat) * seg->duration;
641  }
642  avio_printf(out, "\t\t\t\t\t</SegmentTimeline>\n");
643  }
644  avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
645  } else if (c->single_file) {
646  avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
647  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
648  avio_printf(out, "\t\t\t\t\t<Initialization range=\"%"PRId64"-%"PRId64"\" />\n", os->init_start_pos, os->init_start_pos + os->init_range_length - 1);
649  for (i = start_index; i < os->nb_segments; i++) {
650  Segment *seg = os->segments[i];
651  avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
652  if (seg->index_length)
653  avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
654  avio_printf(out, "/>\n");
655  }
656  avio_printf(out, "\t\t\t\t</SegmentList>\n");
657  } else {
658  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
659  avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
660  for (i = start_index; i < os->nb_segments; i++) {
661  Segment *seg = os->segments[i];
662  avio_printf(out, "\t\t\t\t\t<SegmentURL media=\"%s\" />\n", seg->file);
663  }
664  avio_printf(out, "\t\t\t\t</SegmentList>\n");
665  }
666  if (!c->lhls || final) {
667  write_hls_media_playlist(os, s, representation_id, final, NULL);
668  }
669 
670 }
671 
672 static char *xmlescape(const char *str) {
673  int outlen = strlen(str)*3/2 + 6;
674  char *out = av_realloc(NULL, outlen + 1);
675  int pos = 0;
676  if (!out)
677  return NULL;
678  for (; *str; str++) {
679  if (pos + 6 > outlen) {
680  char *tmp;
681  outlen = 2 * outlen + 6;
682  tmp = av_realloc(out, outlen + 1);
683  if (!tmp) {
684  av_free(out);
685  return NULL;
686  }
687  out = tmp;
688  }
689  if (*str == '&') {
690  memcpy(&out[pos], "&amp;", 5);
691  pos += 5;
692  } else if (*str == '<') {
693  memcpy(&out[pos], "&lt;", 4);
694  pos += 4;
695  } else if (*str == '>') {
696  memcpy(&out[pos], "&gt;", 4);
697  pos += 4;
698  } else if (*str == '\'') {
699  memcpy(&out[pos], "&apos;", 6);
700  pos += 6;
701  } else if (*str == '\"') {
702  memcpy(&out[pos], "&quot;", 6);
703  pos += 6;
704  } else {
705  out[pos++] = *str;
706  }
707  }
708  out[pos] = '\0';
709  return out;
710 }
711 
712 static void write_time(AVIOContext *out, int64_t time)
713 {
714  int seconds = time / AV_TIME_BASE;
715  int fractions = time % AV_TIME_BASE;
716  int minutes = seconds / 60;
717  int hours = minutes / 60;
718  seconds %= 60;
719  minutes %= 60;
720  avio_printf(out, "PT");
721  if (hours)
722  avio_printf(out, "%dH", hours);
723  if (hours || minutes)
724  avio_printf(out, "%dM", minutes);
725  avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
726 }
727 
728 static void format_date_now(char *buf, int size)
729 {
730  struct tm *ptm, tmbuf;
731  int64_t time_us = av_gettime();
732  int64_t time_ms = time_us / 1000;
733  const time_t time_s = time_ms / 1000;
734  int millisec = time_ms - (time_s * 1000);
735  ptm = gmtime_r(&time_s, &tmbuf);
736  if (ptm) {
737  int len;
738  if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%S", ptm)) {
739  buf[0] = '\0';
740  return;
741  }
742  len = strlen(buf);
743  snprintf(buf + len, size - len, ".%03dZ", millisec);
744  }
745 }
746 
748  int final)
749 {
750  DASHContext *c = s->priv_data;
751  AdaptationSet *as = &c->as[as_index];
752  AVDictionaryEntry *lang, *role;
753  int i;
754 
755  avio_printf(out, "\t\t<AdaptationSet id=\"%s\" contentType=\"%s\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
756  as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
758  avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
759  lang = av_dict_get(as->metadata, "language", NULL, 0);
760  if (lang)
761  avio_printf(out, " lang=\"%s\"", lang->value);
762  avio_printf(out, ">\n");
763 
764  role = av_dict_get(as->metadata, "role", NULL, 0);
765  if (role)
766  avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
767 
768  for (i = 0; i < s->nb_streams; i++) {
769  OutputStream *os = &c->streams[i];
770  char bandwidth_str[64] = {'\0'};
771 
772  if (os->as_idx - 1 != as_index)
773  continue;
774 
775  if (os->bit_rate > 0)
776  snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"",
777  os->bit_rate);
778 
779  if (as->media_type == AVMEDIA_TYPE_VIDEO) {
780  AVStream *st = s->streams[i];
781  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
782  i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
783  if (st->avg_frame_rate.num)
784  avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
785  avio_printf(out, ">\n");
786  } else {
787  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
788  i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->sample_rate);
789  avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
790  s->streams[i]->codecpar->channels);
791  }
792  output_segment_list(os, out, s, i, final);
793  avio_printf(out, "\t\t\t</Representation>\n");
794  }
795  avio_printf(out, "\t\t</AdaptationSet>\n");
796 
797  return 0;
798 }
799 
801 {
802  DASHContext *c = s->priv_data;
803 
804  void *mem = av_realloc(c->as, sizeof(*c->as) * (c->nb_as + 1));
805  if (!mem)
806  return AVERROR(ENOMEM);
807  c->as = mem;
808  ++c->nb_as;
809 
810  *as = &c->as[c->nb_as - 1];
811  memset(*as, 0, sizeof(**as));
812  (*as)->media_type = type;
813 
814  return 0;
815 }
816 
817 static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
818 {
819  DASHContext *c = s->priv_data;
820  AdaptationSet *as = &c->as[as_idx - 1];
821  OutputStream *os = &c->streams[i];
822 
823  if (as->media_type != s->streams[i]->codecpar->codec_type) {
824  av_log(s, AV_LOG_ERROR, "Codec type of stream %d doesn't match AdaptationSet's media type\n", i);
825  return AVERROR(EINVAL);
826  } else if (os->as_idx) {
827  av_log(s, AV_LOG_ERROR, "Stream %d is already assigned to an AdaptationSet\n", i);
828  return AVERROR(EINVAL);
829  }
830  os->as_idx = as_idx;
831 
832  return 0;
833 }
834 
836 {
837  DASHContext *c = s->priv_data;
838  const char *p = c->adaptation_sets;
839  enum { new_set, parse_id, parsing_streams } state;
840  AdaptationSet *as;
841  int i, n, ret;
842 
843  // default: one AdaptationSet for each stream
844  if (!p) {
845  for (i = 0; i < s->nb_streams; i++) {
846  if ((ret = add_adaptation_set(s, &as, s->streams[i]->codecpar->codec_type)) < 0)
847  return ret;
848  snprintf(as->id, sizeof(as->id), "%d", i);
849 
850  c->streams[i].as_idx = c->nb_as;
851  }
852  goto end;
853  }
854 
855  // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
856  state = new_set;
857  while (*p) {
858  if (*p == ' ') {
859  p++;
860  continue;
861  } else if (state == new_set && av_strstart(p, "id=", &p)) {
862 
863  if ((ret = add_adaptation_set(s, &as, AVMEDIA_TYPE_UNKNOWN)) < 0)
864  return ret;
865 
866  n = strcspn(p, ",");
867  snprintf(as->id, sizeof(as->id), "%.*s", n, p);
868 
869  p += n;
870  if (*p)
871  p++;
872  state = parse_id;
873  } else if (state == parse_id && av_strstart(p, "streams=", &p)) {
874  state = parsing_streams;
875  } else if (state == parsing_streams) {
876  AdaptationSet *as = &c->as[c->nb_as - 1];
877  char idx_str[8], *end_str;
878 
879  n = strcspn(p, " ,");
880  snprintf(idx_str, sizeof(idx_str), "%.*s", n, p);
881  p += n;
882 
883  // if value is "a" or "v", map all streams of that type
884  if (as->media_type == AVMEDIA_TYPE_UNKNOWN && (idx_str[0] == 'v' || idx_str[0] == 'a')) {
885  enum AVMediaType type = (idx_str[0] == 'v') ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
886  av_log(s, AV_LOG_DEBUG, "Map all streams of type %s\n", idx_str);
887 
888  for (i = 0; i < s->nb_streams; i++) {
889  if (s->streams[i]->codecpar->codec_type != type)
890  continue;
891 
892  as->media_type = s->streams[i]->codecpar->codec_type;
893 
894  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
895  return ret;
896  }
897  } else { // select single stream
898  i = strtol(idx_str, &end_str, 10);
899  if (idx_str == end_str || i < 0 || i >= s->nb_streams) {
900  av_log(s, AV_LOG_ERROR, "Selected stream \"%s\" not found!\n", idx_str);
901  return AVERROR(EINVAL);
902  }
903  av_log(s, AV_LOG_DEBUG, "Map stream %d\n", i);
904 
905  if (as->media_type == AVMEDIA_TYPE_UNKNOWN) {
906  as->media_type = s->streams[i]->codecpar->codec_type;
907  }
908 
909  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
910  return ret;
911  }
912 
913  if (*p == ' ')
914  state = new_set;
915  if (*p)
916  p++;
917  } else {
918  return AVERROR(EINVAL);
919  }
920  }
921 
922 end:
923  // check for unassigned streams
924  for (i = 0; i < s->nb_streams; i++) {
925  OutputStream *os = &c->streams[i];
926  if (!os->as_idx) {
927  av_log(s, AV_LOG_ERROR, "Stream %d is not mapped to an AdaptationSet\n", i);
928  return AVERROR(EINVAL);
929  }
930  }
931  return 0;
932 }
933 
934 static int write_manifest(AVFormatContext *s, int final)
935 {
936  DASHContext *c = s->priv_data;
937  AVIOContext *out;
938  char temp_filename[1024];
939  int ret, i;
940  const char *proto = avio_find_protocol_name(s->url);
941  int use_rename = proto && !strcmp(proto, "file");
942  static unsigned int warned_non_file = 0;
943  AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
945 
946  if (!use_rename && !warned_non_file++)
947  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
948 
949  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url);
950  set_http_options(&opts, c);
951  ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts);
952  av_dict_free(&opts);
953  if (ret < 0) {
954  return handle_io_open_error(s, ret, temp_filename);
955  }
956  out = c->mpd_out;
957  avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
958  avio_printf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
959  "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
960  "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
961  "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
962  "\tprofiles=\"urn:mpeg:dash:profile:isoff-live:2011\"\n"
963  "\ttype=\"%s\"\n", final ? "static" : "dynamic");
964  if (final) {
965  avio_printf(out, "\tmediaPresentationDuration=\"");
966  write_time(out, c->total_duration);
967  avio_printf(out, "\"\n");
968  } else {
969  int64_t update_period = c->last_duration / AV_TIME_BASE;
970  char now_str[100];
971  if (c->use_template && !c->use_timeline)
972  update_period = 500;
973  avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period);
974  avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE);
975  if (c->availability_start_time[0])
976  avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time);
977  format_date_now(now_str, sizeof(now_str));
978  if (now_str[0])
979  avio_printf(out, "\tpublishTime=\"%s\"\n", now_str);
980  if (c->window_size && c->use_template) {
981  avio_printf(out, "\ttimeShiftBufferDepth=\"");
982  write_time(out, c->last_duration * c->window_size);
983  avio_printf(out, "\"\n");
984  }
985  }
986  avio_printf(out, "\tminBufferTime=\"");
987  write_time(out, c->last_duration * 2);
988  avio_printf(out, "\">\n");
989  avio_printf(out, "\t<ProgramInformation>\n");
990  if (title) {
991  char *escaped = xmlescape(title->value);
992  avio_printf(out, "\t\t<Title>%s</Title>\n", escaped);
993  av_free(escaped);
994  }
995  avio_printf(out, "\t</ProgramInformation>\n");
996 
997  if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) {
998  OutputStream *os = &c->streams[0];
999  int start_index = FFMAX(os->nb_segments - c->window_size, 0);
1000  int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q);
1001  avio_printf(out, "\t<Period id=\"0\" start=\"");
1002  write_time(out, start_time);
1003  avio_printf(out, "\">\n");
1004  } else {
1005  avio_printf(out, "\t<Period id=\"0\" start=\"PT0.0S\">\n");
1006  }
1007 
1008  for (i = 0; i < c->nb_as; i++) {
1009  if ((ret = write_adaptation_set(s, out, i, final)) < 0)
1010  return ret;
1011  }
1012  avio_printf(out, "\t</Period>\n");
1013 
1014  if (c->utc_timing_url)
1015  avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
1016 
1017  avio_printf(out, "</MPD>\n");
1018  avio_flush(out);
1019  dashenc_io_close(s, &c->mpd_out, temp_filename);
1020 
1021  if (use_rename) {
1022  if ((ret = avpriv_io_move(temp_filename, s->url)) < 0)
1023  return ret;
1024  }
1025 
1026  if (c->hls_playlist) {
1027  char filename_hls[1024];
1028  const char *audio_group = "A1";
1029  char audio_codec_str[128] = "\0";
1030  int is_default = 1;
1031  int max_audio_bitrate = 0;
1032 
1033  // Publish master playlist only the configured rate
1036  return 0;
1037 
1038  if (*c->dirname)
1039  snprintf(filename_hls, sizeof(filename_hls), "%smaster.m3u8", c->dirname);
1040  else
1041  snprintf(filename_hls, sizeof(filename_hls), "master.m3u8");
1042 
1043  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", filename_hls);
1044 
1045  set_http_options(&opts, c);
1046  ret = dashenc_io_open(s, &c->m3u8_out, temp_filename, &opts);
1047  av_dict_free(&opts);
1048  if (ret < 0) {
1049  return handle_io_open_error(s, ret, temp_filename);
1050  }
1051 
1053 
1054  for (i = 0; i < s->nb_streams; i++) {
1055  char playlist_file[64];
1056  AVStream *st = s->streams[i];
1057  OutputStream *os = &c->streams[i];
1059  continue;
1060  if (os->segment_type != SEGMENT_TYPE_MP4)
1061  continue;
1062  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1063  ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group,
1064  playlist_file, NULL, i, is_default);
1065  max_audio_bitrate = FFMAX(st->codecpar->bit_rate +
1066  os->muxer_overhead, max_audio_bitrate);
1067  if (!av_strnstr(audio_codec_str, os->codec_str, sizeof(audio_codec_str))) {
1068  if (strlen(audio_codec_str))
1069  av_strlcat(audio_codec_str, ",", sizeof(audio_codec_str));
1070  av_strlcat(audio_codec_str, os->codec_str, sizeof(audio_codec_str));
1071  }
1072  is_default = 0;
1073  }
1074 
1075  for (i = 0; i < s->nb_streams; i++) {
1076  char playlist_file[64];
1077  char codec_str[128];
1078  AVStream *st = s->streams[i];
1079  OutputStream *os = &c->streams[i];
1080  char *agroup = NULL;
1081  char *codec_str_ptr = NULL;
1082  int stream_bitrate = st->codecpar->bit_rate + os->muxer_overhead;
1084  continue;
1085  if (os->segment_type != SEGMENT_TYPE_MP4)
1086  continue;
1087  av_strlcpy(codec_str, os->codec_str, sizeof(codec_str));
1088  if (max_audio_bitrate) {
1089  agroup = (char *)audio_group;
1090  stream_bitrate += max_audio_bitrate;
1091  av_strlcat(codec_str, ",", sizeof(codec_str));
1092  av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
1093  }
1094  if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) {
1095  codec_str_ptr = codec_str;
1096  }
1097  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1098  ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
1099  playlist_file, agroup,
1100  codec_str_ptr, NULL);
1101  }
1102  dashenc_io_close(s, &c->m3u8_out, temp_filename);
1103  if (use_rename)
1104  if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0)
1105  return ret;
1106  c->master_playlist_created = 1;
1107  }
1108 
1109  return 0;
1110 }
1111 
1112 static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
1113 {
1114  AVDictionaryEntry *entry = av_dict_get(src, key, NULL, 0);
1115  if (entry)
1116  av_dict_set(dst, key, entry->value, AV_DICT_DONT_OVERWRITE);
1117  return 0;
1118 }
1119 
1121 {
1122  DASHContext *c = s->priv_data;
1123  int ret = 0, i;
1124  char *ptr;
1125  char basename[1024];
1126 
1127  c->nr_of_streams_to_flush = 0;
1128  if (c->single_file_name)
1129  c->single_file = 1;
1130  if (c->single_file)
1131  c->use_template = 0;
1132 
1133 #if FF_API_DASH_MIN_SEG_DURATION
1134  if (c->min_seg_duration != 5000000) {
1135  av_log(s, AV_LOG_WARNING, "The min_seg_duration option is deprecated and will be removed. Please use the -seg_duration\n");
1136  c->seg_duration = c->min_seg_duration;
1137  }
1138 #endif
1140  av_log(s, AV_LOG_ERROR,
1141  "LHLS is experimental, Please set -strict experimental in order to enable it.\n");
1142  return AVERROR_EXPERIMENTAL;
1143  }
1144 
1145  if (c->lhls && !c->streaming) {
1146  av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as streaming is not enabled\n");
1147  c->lhls = 0;
1148  }
1149 
1150  if (c->lhls && !c->hls_playlist) {
1151  av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as hls_playlist is not enabled\n");
1152  c->lhls = 0;
1153  }
1154 
1155  if (c->global_sidx && !c->single_file) {
1156  av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as single_file is not enabled\n");
1157  c->global_sidx = 0;
1158  }
1159 
1160  if (c->global_sidx && c->streaming) {
1161  av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as streaming is enabled\n");
1162  c->global_sidx = 0;
1163  }
1164 
1165  av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
1166  ptr = strrchr(c->dirname, '/');
1167  if (ptr) {
1168  av_strlcpy(basename, &ptr[1], sizeof(basename));
1169  ptr[1] = '\0';
1170  } else {
1171  c->dirname[0] = '\0';
1172  av_strlcpy(basename, s->url, sizeof(basename));
1173  }
1174 
1175  ptr = strrchr(basename, '.');
1176  if (ptr)
1177  *ptr = '\0';
1178 
1179  c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
1180  if (!c->streams)
1181  return AVERROR(ENOMEM);
1182 
1183  if ((ret = parse_adaptation_sets(s)) < 0)
1184  return ret;
1185 
1186  if ((ret = init_segment_types(s)) < 0)
1187  return ret;
1188 
1189  for (i = 0; i < s->nb_streams; i++) {
1190  OutputStream *os = &c->streams[i];
1191  AdaptationSet *as = &c->as[os->as_idx - 1];
1193  AVStream *st;
1194  AVDictionary *opts = NULL;
1195  char filename[1024];
1196 
1197  os->bit_rate = s->streams[i]->codecpar->bit_rate;
1198  if (!os->bit_rate) {
1201  av_log(s, level, "No bit rate set for stream %d\n", i);
1203  return AVERROR(EINVAL);
1204  }
1205 
1206  // copy AdaptationSet language and role from stream metadata
1207  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "language");
1208  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "role");
1209 
1210  if (c->init_seg_name) {
1211  os->init_seg_name = av_strireplace(c->init_seg_name, "$ext$", os->extension_name);
1212  if (!os->init_seg_name)
1213  return AVERROR(ENOMEM);
1214  }
1215  if (c->media_seg_name) {
1217  if (!os->media_seg_name)
1218  return AVERROR(ENOMEM);
1219  }
1220  if (c->single_file_name) {
1222  if (!os->single_file_name)
1223  return AVERROR(ENOMEM);
1224  }
1225 
1226  if (os->segment_type == SEGMENT_TYPE_WEBM) {
1227  if ((!c->single_file && check_file_extension(os->init_seg_name, os->format_name) != 0) ||
1228  (!c->single_file && check_file_extension(os->media_seg_name, os->format_name) != 0) ||
1231  "One or many segment file names doesn't end with .webm. "
1232  "Override -init_seg_name and/or -media_seg_name and/or "
1233  "-single_file_name to end with the extension .webm\n");
1234  }
1235  if (c->streaming) {
1236  // Streaming not supported as matroskaenc buffers internally before writing the output
1237  av_log(s, AV_LOG_WARNING, "One or more streams in WebM output format. Streaming option will be ignored\n");
1238  c->streaming = 0;
1239  }
1240  }
1241 
1242  os->ctx = ctx = avformat_alloc_context();
1243  if (!ctx)
1244  return AVERROR(ENOMEM);
1245 
1247  if (!ctx->oformat)
1248  return AVERROR_MUXER_NOT_FOUND;
1250  ctx->opaque = s->opaque;
1251  ctx->io_close = s->io_close;
1252  ctx->io_open = s->io_open;
1254 
1255  if (!(st = avformat_new_stream(ctx, NULL)))
1256  return AVERROR(ENOMEM);
1259  st->time_base = s->streams[i]->time_base;
1262  ctx->flags = s->flags;
1263 
1264  if (c->single_file) {
1265  if (os->single_file_name)
1266  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);
1267  else
1268  snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.%s", basename, i, os->format_name);
1269  } else {
1270  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->init_seg_name, i, 0, os->bit_rate, 0);
1271  }
1272  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
1273  set_http_options(&opts, c);
1274  if (!c->single_file) {
1275  if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0)
1276  return ret;
1277  ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts);
1278  } else {
1279  ctx->url = av_strdup(filename);
1280  ret = avio_open2(&ctx->pb, filename, AVIO_FLAG_WRITE, NULL, &opts);
1281  }
1282  av_dict_free(&opts);
1283  if (ret < 0)
1284  return ret;
1285  os->init_start_pos = 0;
1286 
1287  if (c->format_options_str) {
1288  ret = av_dict_parse_string(&opts, c->format_options_str, "=", ":", 0);
1289  if (ret < 0)
1290  return ret;
1291  }
1292 
1293  if (os->segment_type == SEGMENT_TYPE_MP4) {
1294  if (c->streaming)
1295  // frag_every_frame : Allows lower latency streaming
1296  // skip_sidx : Reduce bitrate overhead
1297  // skip_trailer : Avoids growing memory usage with time
1298  av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov+skip_sidx+skip_trailer", 0);
1299  else {
1300  if (c->global_sidx)
1301  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+global_sidx+skip_trailer", 0);
1302  else
1303  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+skip_trailer", 0);
1304  }
1305  } else {
1306  av_dict_set_int(&opts, "cluster_time_limit", c->seg_duration / 1000, 0);
1307  av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
1308  av_dict_set_int(&opts, "dash", 1, 0);
1309  av_dict_set_int(&opts, "dash_track_number", i + 1, 0);
1310  av_dict_set_int(&opts, "live", 1, 0);
1311  }
1312  ret = avformat_init_output(ctx, &opts);
1313  av_dict_free(&opts);
1314  if (ret < 0)
1315  return ret;
1316  os->ctx_inited = 1;
1317  avio_flush(ctx->pb);
1318 
1319  av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename);
1320 
1321  s->streams[i]->time_base = st->time_base;
1322  // If the muxer wants to shift timestamps, request to have them shifted
1323  // already before being handed to this muxer, so we don't have mismatches
1324  // between the MPD and the actual segments.
1326  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1327  AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
1328  if (avg_frame_rate.num > 0) {
1329  if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0)
1330  as->min_frame_rate = avg_frame_rate;
1331  if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0)
1332  as->max_frame_rate = avg_frame_rate;
1333  } else {
1334  as->ambiguous_frame_rate = 1;
1335  }
1336  c->has_video = 1;
1337  }
1338 
1339  set_codec_str(s, st->codecpar, &st->avg_frame_rate, os->codec_str,
1340  sizeof(os->codec_str));
1341  os->first_pts = AV_NOPTS_VALUE;
1342  os->max_pts = AV_NOPTS_VALUE;
1343  os->last_dts = AV_NOPTS_VALUE;
1344  os->segment_index = 1;
1345 
1348  }
1349 
1350  if (!c->has_video && c->seg_duration <= 0) {
1351  av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");
1352  return AVERROR(EINVAL);
1353  }
1354 
1355  c->nr_of_streams_flushed = 0;
1356 
1357  return 0;
1358 }
1359 
1361 {
1362  DASHContext *c = s->priv_data;
1363  int i, ret;
1364  for (i = 0; i < s->nb_streams; i++) {
1365  OutputStream *os = &c->streams[i];
1366  if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
1367  return ret;
1368 
1369  // Flush init segment
1370  // Only for WebM segment, since for mp4 delay_moov is set and
1371  // the init segment is thus flushed after the first packets.
1372  if (os->segment_type == SEGMENT_TYPE_WEBM &&
1373  (ret = flush_init_segment(s, os)) < 0)
1374  return ret;
1375  }
1376  return ret;
1377 }
1378 
1379 static int add_segment(OutputStream *os, const char *file,
1380  int64_t time, int64_t duration,
1381  int64_t start_pos, int64_t range_length,
1382  int64_t index_length, int next_exp_index)
1383 {
1384  int err;
1385  Segment *seg;
1386  if (os->nb_segments >= os->segments_size) {
1387  os->segments_size = (os->segments_size + 1) * 2;
1388  if ((err = av_reallocp(&os->segments, sizeof(*os->segments) *
1389  os->segments_size)) < 0) {
1390  os->segments_size = 0;
1391  os->nb_segments = 0;
1392  return err;
1393  }
1394  }
1395  seg = av_mallocz(sizeof(*seg));
1396  if (!seg)
1397  return AVERROR(ENOMEM);
1398  av_strlcpy(seg->file, file, sizeof(seg->file));
1399  seg->time = time;
1400  seg->duration = duration;
1401  if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
1402  seg->duration += seg->time;
1403  seg->time = 0;
1404  }
1405  seg->start_pos = start_pos;
1406  seg->range_length = range_length;
1407  seg->index_length = index_length;
1408  os->segments[os->nb_segments++] = seg;
1409  os->segment_index++;
1410  //correcting the segment index if it has fallen behind the expected value
1411  if (os->segment_index < next_exp_index) {
1412  av_log(NULL, AV_LOG_WARNING, "Correcting the segment index after file %s: current=%d corrected=%d\n",
1413  file, os->segment_index, next_exp_index);
1414  os->segment_index = next_exp_index;
1415  }
1416  return 0;
1417 }
1418 
1419 static void write_styp(AVIOContext *pb)
1420 {
1421  avio_wb32(pb, 24);
1422  ffio_wfourcc(pb, "styp");
1423  ffio_wfourcc(pb, "msdh");
1424  avio_wb32(pb, 0); /* minor */
1425  ffio_wfourcc(pb, "msdh");
1426  ffio_wfourcc(pb, "msix");
1427 }
1428 
1429 static void find_index_range(AVFormatContext *s, const char *full_path,
1430  int64_t pos, int *index_length)
1431 {
1432  uint8_t buf[8];
1433  AVIOContext *pb;
1434  int ret;
1435 
1436  ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL);
1437  if (ret < 0)
1438  return;
1439  if (avio_seek(pb, pos, SEEK_SET) != pos) {
1440  ff_format_io_close(s, &pb);
1441  return;
1442  }
1443  ret = avio_read(pb, buf, 8);
1444  ff_format_io_close(s, &pb);
1445  if (ret < 8)
1446  return;
1447  if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
1448  return;
1449  *index_length = AV_RB32(&buf[0]);
1450 }
1451 
1453  AVPacket *pkt, AVRational *frame_rate)
1454 {
1455  AVCodecParameters *par = os->ctx->streams[0]->codecpar;
1456  uint8_t *extradata;
1457  int ret, extradata_size;
1458 
1459  if (par->extradata_size)
1460  return 0;
1461 
1462  extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &extradata_size);
1463  if (!extradata_size)
1464  return 0;
1465 
1466  ret = ff_alloc_extradata(par, extradata_size);
1467  if (ret < 0)
1468  return ret;
1469 
1470  memcpy(par->extradata, extradata, extradata_size);
1471 
1472  set_codec_str(s, par, frame_rate, os->codec_str, sizeof(os->codec_str));
1473 
1474  return 0;
1475 }
1476 
1477 static void dashenc_delete_file(AVFormatContext *s, char *filename) {
1478  DASHContext *c = s->priv_data;
1479  int http_base_proto = ff_is_http_proto(filename);
1480 
1481  if (http_base_proto) {
1482  AVIOContext *out = NULL;
1483  AVDictionary *http_opts = NULL;
1484 
1485  set_http_options(&http_opts, c);
1486  av_dict_set(&http_opts, "method", "DELETE", 0);
1487 
1488  if (dashenc_io_open(s, &out, filename, &http_opts) < 0) {
1489  av_log(s, AV_LOG_ERROR, "failed to delete %s\n", filename);
1490  }
1491 
1492  av_dict_free(&http_opts);
1493  ff_format_io_close(s, &out);
1494  } else {
1495  int res = avpriv_io_delete(filename);
1496  if (res < 0) {
1497  char errbuf[AV_ERROR_MAX_STRING_SIZE];
1498  av_strerror(res, errbuf, sizeof(errbuf));
1499  av_log(s, (res == AVERROR(ENOENT) ? AV_LOG_WARNING : AV_LOG_ERROR), "failed to delete %s: %s\n", filename, errbuf);
1500  }
1501  }
1502 }
1503 
1505 {
1506  DASHContext *c = s->priv_data;
1507  size_t dirname_len, file_len;
1508  char filename[1024];
1509 
1510  dirname_len = strlen(c->dirname);
1511  if (dirname_len >= sizeof(filename)) {
1512  av_log(s, AV_LOG_WARNING, "Cannot delete segments as the directory path is too long: %"PRIu64" characters: %s\n",
1513  (uint64_t)dirname_len, c->dirname);
1514  return AVERROR(ENAMETOOLONG);
1515  }
1516 
1517  memcpy(filename, c->dirname, dirname_len);
1518 
1519  file_len = strlen(file);
1520  if ((dirname_len + file_len) >= sizeof(filename)) {
1521  av_log(s, AV_LOG_WARNING, "Cannot delete segments as the path is too long: %"PRIu64" characters: %s%s\n",
1522  (uint64_t)(dirname_len + file_len), c->dirname, file);
1523  return AVERROR(ENAMETOOLONG);
1524  }
1525 
1526  memcpy(filename + dirname_len, file, file_len + 1); // include the terminating zero
1527  dashenc_delete_file(s, filename);
1528 
1529  return 0;
1530 }
1531 
1532 static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
1533 {
1534  for (int i = 0; i < remove_count; ++i) {
1536 
1537  // Delete the segment regardless of whether the file was successfully deleted
1538  av_free(os->segments[i]);
1539  }
1540 
1541  os->nb_segments -= remove_count;
1542  memmove(os->segments, os->segments + remove_count, os->nb_segments * sizeof(*os->segments));
1543 }
1544 
1545 static int dash_flush(AVFormatContext *s, int final, int stream)
1546 {
1547  DASHContext *c = s->priv_data;
1548  int i, ret = 0;
1549 
1550  const char *proto = avio_find_protocol_name(s->url);
1551  int use_rename = proto && !strcmp(proto, "file");
1552 
1553  int cur_flush_segment_index = 0, next_exp_index = -1;
1554  if (stream >= 0) {
1555  cur_flush_segment_index = c->streams[stream].segment_index;
1556 
1557  //finding the next segment's expected index, based on the current pts value
1558  if (c->use_template && !c->use_timeline && c->index_correction &&
1559  c->streams[stream].last_pts != AV_NOPTS_VALUE &&
1560  c->streams[stream].first_pts != AV_NOPTS_VALUE) {
1561  int64_t pts_diff = av_rescale_q(c->streams[stream].last_pts -
1562  c->streams[stream].first_pts,
1563  s->streams[stream]->time_base,
1564  AV_TIME_BASE_Q);
1565  next_exp_index = (pts_diff / c->seg_duration) + 1;
1566  }
1567  }
1568 
1569  for (i = 0; i < s->nb_streams; i++) {
1570  OutputStream *os = &c->streams[i];
1571  AVStream *st = s->streams[i];
1572  int range_length, index_length = 0;
1573 
1574  if (!os->packets_written)
1575  continue;
1576 
1577  // Flush the single stream that got a keyframe right now.
1578  // Flush all audio streams as well, in sync with video keyframes,
1579  // but not the other video streams.
1580  if (stream >= 0 && i != stream) {
1582  continue;
1583  // Make sure we don't flush audio streams multiple times, when
1584  // all video streams are flushed one at a time.
1585  if (c->has_video && os->segment_index > cur_flush_segment_index)
1586  continue;
1587  }
1588 
1589  if (!c->single_file) {
1590  if (os->segment_type == SEGMENT_TYPE_MP4 && !os->written_len)
1591  write_styp(os->ctx->pb);
1592  } else {
1593  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile);
1594  }
1595 
1596  ret = flush_dynbuf(c, os, &range_length);
1597  if (ret < 0)
1598  break;
1599  os->packets_written = 0;
1600 
1601  if (c->single_file) {
1602  find_index_range(s, os->full_path, os->pos, &index_length);
1603  } else {
1604  dashenc_io_close(s, &os->out, os->temp_path);
1605 
1606  if (use_rename) {
1607  ret = avpriv_io_move(os->temp_path, os->full_path);
1608  if (ret < 0)
1609  break;
1610  }
1611  }
1612 
1613  if (!os->muxer_overhead)
1614  os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) *
1615  8 * AV_TIME_BASE) /
1616  av_rescale_q(os->max_pts - os->start_pts,
1617  st->time_base, AV_TIME_BASE_Q);
1618  os->total_pkt_size = 0;
1619 
1620  if (!os->bit_rate) {
1621  // calculate average bitrate of first segment
1622  int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / av_rescale_q(os->max_pts - os->start_pts,
1623  st->time_base,
1624  AV_TIME_BASE_Q);
1625  if (bitrate >= 0)
1626  os->bit_rate = bitrate;
1627  }
1628  add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index);
1629  av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path);
1630 
1631  os->pos += range_length;
1632  }
1633 
1634  if (c->window_size) {
1635  for (i = 0; i < s->nb_streams; i++) {
1636  OutputStream *os = &c->streams[i];
1637  int remove_count = os->nb_segments - c->window_size - c->extra_window_size;
1638  if (remove_count > 0)
1639  dashenc_delete_media_segments(s, os, remove_count);
1640  }
1641  }
1642 
1643  if (final) {
1644  for (i = 0; i < s->nb_streams; i++) {
1645  OutputStream *os = &c->streams[i];
1646  if (os->ctx && os->ctx_inited) {
1647  int64_t file_size = avio_tell(os->ctx->pb);
1648  av_write_trailer(os->ctx);
1649  if (c->global_sidx) {
1650  int j, start_index, start_number;
1651  int64_t sidx_size = avio_tell(os->ctx->pb) - file_size;
1652  get_start_index_number(os, c, &start_index, &start_number);
1653  if (start_index >= os->nb_segments ||
1655  continue;
1656  os->init_range_length += sidx_size;
1657  for (j = start_index; j < os->nb_segments; j++) {
1658  Segment *seg = os->segments[j];
1659  seg->start_pos += sidx_size;
1660  }
1661  }
1662 
1663  }
1664  }
1665  }
1666  if (ret >= 0) {
1667  if (c->has_video && !final) {
1668  c->nr_of_streams_flushed++;
1670  return ret;
1671 
1672  c->nr_of_streams_flushed = 0;
1673  }
1674  ret = write_manifest(s, final);
1675  }
1676  return ret;
1677 }
1678 
1680 {
1681  DASHContext *c = s->priv_data;
1682  AVStream *st = s->streams[pkt->stream_index];
1683  OutputStream *os = &c->streams[pkt->stream_index];
1684  int64_t seg_end_duration, elapsed_duration;
1685  int ret;
1686 
1687  ret = update_stream_extradata(s, os, pkt, &st->avg_frame_rate);
1688  if (ret < 0)
1689  return ret;
1690 
1691  // Fill in a heuristic guess of the packet duration, if none is available.
1692  // The mp4 muxer will do something similar (for the last packet in a fragment)
1693  // if nothing is set (setting it for the other packets doesn't hurt).
1694  // By setting a nonzero duration here, we can be sure that the mp4 muxer won't
1695  // invoke its heuristic (this doesn't have to be identical to that algorithm),
1696  // so that we know the exact timestamps of fragments.
1697  if (!pkt->duration && os->last_dts != AV_NOPTS_VALUE)
1698  pkt->duration = pkt->dts - os->last_dts;
1699  os->last_dts = pkt->dts;
1700 
1701  // If forcing the stream to start at 0, the mp4 muxer will set the start
1702  // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps.
1703  if (os->first_pts == AV_NOPTS_VALUE &&
1705  pkt->pts -= pkt->dts;
1706  pkt->dts = 0;
1707  }
1708 
1709  if (os->first_pts == AV_NOPTS_VALUE)
1710  os->first_pts = pkt->pts;
1711  os->last_pts = pkt->pts;
1712 
1713  if (!c->availability_start_time[0]) {
1714  int64_t start_time_us = av_gettime();
1715  c->start_time_s = start_time_us / 1000000;
1717  sizeof(c->availability_start_time));
1718  }
1719 
1720  if (!os->availability_time_offset && pkt->duration) {
1721  int64_t frame_duration = av_rescale_q(pkt->duration, st->time_base,
1722  AV_TIME_BASE_Q);
1723  os->availability_time_offset = ((double) c->seg_duration -
1724  frame_duration) / AV_TIME_BASE;
1725  }
1726 
1727  if (c->use_template && !c->use_timeline) {
1728  elapsed_duration = pkt->pts - os->first_pts;
1729  seg_end_duration = (int64_t) os->segment_index * c->seg_duration;
1730  } else {
1731  elapsed_duration = pkt->pts - os->start_pts;
1732  seg_end_duration = c->seg_duration;
1733  }
1734 
1735  if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
1736  pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
1737  av_compare_ts(elapsed_duration, st->time_base,
1738  seg_end_duration, AV_TIME_BASE_Q) >= 0) {
1739  int64_t prev_duration = c->last_duration;
1740 
1741  c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
1742  st->time_base,
1743  AV_TIME_BASE_Q);
1744  c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
1745  st->time_base,
1746  AV_TIME_BASE_Q);
1747 
1748  if ((!c->use_timeline || !c->use_template) && prev_duration) {
1749  if (c->last_duration < prev_duration*9/10 ||
1750  c->last_duration > prev_duration*11/10) {
1752  "Segment durations differ too much, enable use_timeline "
1753  "and use_template, or keep a stricter keyframe interval\n");
1754  }
1755  }
1756 
1757  if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0)
1758  return ret;
1759  }
1760 
1761  if (!os->packets_written) {
1762  // If we wrote a previous segment, adjust the start time of the segment
1763  // to the end of the previous one (which is the same as the mp4 muxer
1764  // does). This avoids gaps in the timeline.
1765  if (os->max_pts != AV_NOPTS_VALUE)
1766  os->start_pts = os->max_pts;
1767  else
1768  os->start_pts = pkt->pts;
1769  }
1770  if (os->max_pts == AV_NOPTS_VALUE)
1771  os->max_pts = pkt->pts + pkt->duration;
1772  else
1773  os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
1774  os->packets_written++;
1775  os->total_pkt_size += pkt->size;
1776  if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0)
1777  return ret;
1778 
1779  if (!os->init_range_length)
1780  flush_init_segment(s, os);
1781 
1782  //open the output context when the first frame of a segment is ready
1783  if (!c->single_file && os->packets_written == 1) {
1784  AVDictionary *opts = NULL;
1785  const char *proto = avio_find_protocol_name(s->url);
1786  int use_rename = proto && !strcmp(proto, "file");
1787  os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0';
1788  ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename),
1789  os->media_seg_name, pkt->stream_index,
1790  os->segment_index, os->bit_rate, os->start_pts);
1791  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname,
1792  os->filename);
1793  snprintf(os->temp_path, sizeof(os->temp_path),
1794  use_rename ? "%s.tmp" : "%s", os->full_path);
1795  set_http_options(&opts, c);
1796  ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
1797  av_dict_free(&opts);
1798  if (ret < 0) {
1799  return handle_io_open_error(s, ret, os->temp_path);
1800  }
1801  if (c->lhls) {
1802  char *prefetch_url = use_rename ? NULL : os->filename;
1803  write_hls_media_playlist(os, s, pkt->stream_index, 0, prefetch_url);
1804  }
1805  }
1806 
1807  //write out the data immediately in streaming mode
1808  if (c->streaming && os->segment_type == SEGMENT_TYPE_MP4) {
1809  int len = 0;
1810  uint8_t *buf = NULL;
1811  if (!os->written_len)
1812  write_styp(os->ctx->pb);
1813  avio_flush(os->ctx->pb);
1814  len = avio_get_dyn_buf (os->ctx->pb, &buf);
1815  if (os->out) {
1816  avio_write(os->out, buf + os->written_len, len - os->written_len);
1817  avio_flush(os->out);
1818  }
1819  os->written_len = len;
1820  }
1821 
1822  return ret;
1823 }
1824 
1826 {
1827  DASHContext *c = s->priv_data;
1828  int i;
1829 
1830  if (s->nb_streams > 0) {
1831  OutputStream *os = &c->streams[0];
1832  // If no segments have been written so far, try to do a crude
1833  // guess of the segment duration
1834  if (!c->last_duration)
1836  s->streams[0]->time_base,
1837  AV_TIME_BASE_Q);
1839  s->streams[0]->time_base,
1840  AV_TIME_BASE_Q);
1841  }
1842  dash_flush(s, 1, -1);
1843 
1844  if (c->remove_at_exit) {
1845  for (i = 0; i < s->nb_streams; ++i) {
1846  OutputStream *os = &c->streams[i];
1849  if (c->hls_playlist && os->segment_type == SEGMENT_TYPE_MP4) {
1850  char filename[1024];
1851  get_hls_playlist_name(filename, sizeof(filename), c->dirname, i);
1852  dashenc_delete_file(s, filename);
1853  }
1854  }
1855  dashenc_delete_file(s, s->url);
1856 
1857  if (c->hls_playlist && c->master_playlist_created) {
1858  char filename[1024];
1859  snprintf(filename, sizeof(filename), "%smaster.m3u8", c->dirname);
1860  dashenc_delete_file(s, filename);
1861  }
1862  }
1863 
1864  return 0;
1865 }
1866 
1867 static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
1868 {
1869  DASHContext *c = s->priv_data;
1870  OutputStream *os = &c->streams[avpkt->stream_index];
1871  AVFormatContext *oc = os->ctx;
1872  if (oc->oformat->check_bitstream) {
1873  int ret;
1874  AVPacket pkt = *avpkt;
1875  pkt.stream_index = 0;
1876  ret = oc->oformat->check_bitstream(oc, &pkt);
1877  if (ret == 1) {
1878  AVStream *st = s->streams[avpkt->stream_index];
1879  AVStream *ost = oc->streams[0];
1880  st->internal->bsfcs = ost->internal->bsfcs;
1881  st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
1882  ost->internal->bsfcs = NULL;
1883  ost->internal->nb_bsfcs = 0;
1884  }
1885  return ret;
1886  }
1887  return 1;
1888 }
1889 
1890 #define OFFSET(x) offsetof(DASHContext, x)
1891 #define E AV_OPT_FLAG_ENCODING_PARAM
1892 static const AVOption options[] = {
1893  { "adaptation_sets", "Adaptation sets. Syntax: id=0,streams=0,1,2 id=1,streams=3,4 and so on", OFFSET(adaptation_sets), AV_OPT_TYPE_STRING, { 0 }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
1894  { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
1895  { "extra_window_size", "number of segments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E },
1896 #if FF_API_DASH_MIN_SEG_DURATION
1897  { "min_seg_duration", "minimum segment duration (in microseconds) (will be deprecated)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT, { .i64 = 5000000 }, 0, INT_MAX, E },
1898 #endif
1899  { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E },
1900  { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1901  { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1902  { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1903  { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1904  { "single_file_name", "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges", OFFSET(single_file_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
1905  { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.$ext$"}, 0, 0, E },
1906  { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.$ext$"}, 0, 0, E },
1907  { "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E },
1908  { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1909  { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1910  { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1911  { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1912  { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1913  { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
1914  { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1915  { "format_options","set list of options for the container format (mp4/webm) used for dash", OFFSET(format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1916  { "global_sidx", "Write global SIDX atom. Applicable only for single file, mp4 output, non-streaming mode", OFFSET(global_sidx), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1917  { "dash_segment_type", "set dash segment files type", OFFSET(segment_type_option), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_AUTO }, 0, SEGMENT_TYPE_NB - 1, E, "segment_type"},
1918  { "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX, E, "segment_type"},
1919  { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX, E, "segment_type"},
1920  { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX, E, "segment_type"},
1921  { "ignore_io_errors", "Ignore IO errors during open and write. Useful for long-duration runs with network output", OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1922  { "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag with current segment's URI", OFFSET(lhls), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1923  { "master_m3u8_publish_rate", "Publish master playlist every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E},
1924  { NULL },
1925 };
1926 
1927 static const AVClass dash_class = {
1928  .class_name = "dash muxer",
1929  .item_name = av_default_item_name,
1930  .option = options,
1931  .version = LIBAVUTIL_VERSION_INT,
1932 };
1933 
1935  .name = "dash",
1936  .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
1937  .extensions = "mpd",
1938  .priv_data_size = sizeof(DASHContext),
1939  .audio_codec = AV_CODEC_ID_AAC,
1940  .video_codec = AV_CODEC_ID_H264,
1942  .init = dash_init,
1946  .deinit = dash_free,
1947  .check_bitstream = dash_check_bitstream,
1948  .priv_class = &dash_class,
1949 };
#define FF_COMPLIANCE_EXPERIMENTAL
Allow nonstandardized experimental things.
Definition: avcodec.h:2633
SegmentType segment_type
Definition: dashenc.c:91
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:690
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
Definition: avformat.h:1940
#define NULL
Definition: coverity.c:32
char * format_options_str
Definition: dashenc.c:144
Bytestream IO Context.
Definition: avio.h:161
int use_timeline
Definition: dashenc.c:121
static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
Definition: dashenc.c:1112
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
static int init_segment_types(AVFormatContext *s)
Definition: dashenc.c:255
int size
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1636
static void set_http_options(AVDictionary **options, DASHContext *c)
Definition: dashenc.c:436
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1415
AVOption.
Definition: opt.h:246
static int parse_adaptation_sets(AVFormatContext *s)
Definition: dashenc.c:835
static const AVOption options[]
Definition: dashenc.c:1892
AVIOContext * mpd_out
Definition: dashenc.c:139
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:878
const char * media_seg_name
Definition: dashenc.c:96
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
const char * single_file_name
Definition: dashenc.c:94
int ambiguous_frame_rate
Definition: dashenc.c:75
#define AV_DICT_DONT_OVERWRITE
Don&#39;t overwrite existing entries.
Definition: dict.h:79
int range_length
Definition: dashenc.c:63
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
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:1318
enum AVCodecID codec_id
Definition: qsv.c:72
int nb_segments
Definition: dashenc.c:86
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3957
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:943
int num
Numerator.
Definition: rational.h:59
static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
Definition: dashenc.c:195
int size
Definition: avcodec.h:1478
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:246
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
#define AVIO_FLAG_READ
read-only
Definition: avio.h:654
int n
Definition: dashenc.c:67
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:655
uint8_t transfer_characteristics
Definition: av1.h:39
char codec_str[100]
Definition: dashenc.c:98
Convenience header that includes libavutil&#39;s core.
char filename[1024]
Definition: dashenc.c:100
const char * str
Definition: dashenc.c:168
int64_t timeout
Definition: dashenc.c:142
const char * key
AVFormatContext * ctx
Definition: dashenc.c:79
int single_file
Definition: dashenc.c:122
static AVPacket pkt
static int update_stream_extradata(AVFormatContext *s, OutputStream *os, AVPacket *pkt, AVRational *frame_rate)
Definition: dashenc.c:1452
int ff_is_http_proto(char *filename)
Utility function to check if the file uses http or https protocol.
Definition: utils.c:5665
int nr_of_streams_to_flush
Definition: dashenc.c:150
#define src
Definition: vp8dsp.c:254
int packets_written
Definition: dashenc.c:82
int as_idx
Definition: dashenc.c:80
static void set_codec_str(AVFormatContext *s, AVCodecParameters *par, AVRational *frame_rate, char *str, int size)
Definition: dashenc.c:311
int64_t start_pts
Definition: dashenc.c:88
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1386
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1666
static int dash_init(AVFormatContext *s)
Definition: dashenc.c:1120
uint8_t chroma_sample_position
Definition: av1.h:36
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3949
int64_t last_pts
Definition: dashenc.c:89
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:657
uint8_t monochrome
Definition: av1.h:33
int avpriv_io_move(const char *url_src, const char *url_dst)
Move or rename a resource.
Definition: avio.c:499
static struct codec_string codecs[]
int64_t last_dts
Definition: dashenc.c:89
uint8_t chroma_subsampling_x
Definition: av1.h:34
Format I/O context.
Definition: avformat.h:1358
int global_sidx
Definition: dashenc.c:145
#define gmtime_r
Definition: time_internal.h:34
int64_t init_start_pos
Definition: dashenc.c:84
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_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static int add_segment(OutputStream *os, const char *file, int64_t time, int64_t duration, int64_t start_pos, int64_t range_length, int64_t index_length, int next_exp_index)
Definition: dashenc.c:1379
static char buffer[20]
Definition: seek.c:32
static int64_t start_time
Definition: ffplay.c:331
int streaming
Definition: dashenc.c:141
char * adaptation_sets
Definition: dashenc.c:110
int mem
Definition: avisynth_c.h:916
AdaptationSet * as
Definition: dashenc.c:111
uint8_t
int width
Video only.
Definition: avcodec.h:4023
AVRational min_frame_rate
Definition: dashenc.c:74
AVOptions.
miscellaneous OS support macros and functions.
const AVCodecTag ff_codec_movvideo_tags[]
Definition: isom.c:75
static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type)
Definition: dashenc.c:800
#define AV_RB32
Definition: intreadwrite.h:130
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1495
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5658
int extra_window_size
Definition: dashenc.c:114
static void get_start_index_number(OutputStream *os, DASHContext *c, int *start_index, int *start_number)
Definition: dashenc.c:456
int ctx_inited
Definition: dashenc.c:80
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4476
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1426
const char * method
Definition: dashenc.c:134
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:144
SegmentType
Definition: dashenc.c:53
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1489
uint32_t tag
Definition: movenc.c:1496
static void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
Definition: dashenc.c:1532
int ignore_io_errors
Definition: dashenc.c:147
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
time_t start_time_s
Definition: dashenc.c:128
static int dashenc_delete_segment_file(AVFormatContext *s, const char *file)
Definition: dashenc.c:1504
AVIOContext * m3u8_out
Definition: dashenc.c:140
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:218
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
Definition: avio_internal.h:58
uint64_t availability_start_time
Definition: dashdec.c:136
char initfile[1024]
Definition: dashenc.c:83
static void format_date_now(char *buf, int size)
Definition: dashenc.c:728
int64_t seg_duration
Definition: dashenc.c:118
#define av_log(a,...)
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:276
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:647
void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char *filename, char *language, int name_id, int is_default)
Definition: hlsplaylist.c:38
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: avcodec.h:3986
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1509
static void get_hls_playlist_name(char *playlist_name, int string_size, const char *base_url, int id)
Definition: dashenc.c:448
static void write_time(AVIOContext *out, int64_t time)
Definition: dashenc.c:712
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
static int write_manifest(AVFormatContext *s, int final)
Definition: dashenc.c:934
#define E
Definition: dashenc.c:1891
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2040
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1598
int hls_playlist
Definition: dashenc.c:136
AVDictionary * metadata
Definition: dashenc.c:73
const char * init_seg_name
Definition: dashenc.c:95
int remove_at_exit
Definition: dashenc.c:119
int bitdepth
Definition: vpcc.h:38
#define AV_RB16
Definition: intreadwrite.h:53
#define AVERROR(e)
Definition: error.h:43
int64_t last_duration
Definition: dashenc.c:125
uint8_t * av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:350
static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: dashenc.c:1679
int nb_as
Definition: dashenc.c:112
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
int(* check_bitstream)(struct AVFormatContext *, const AVPacket *pkt)
Set up any necessary bitstream filtering and extract any extra data needed for the global header...
Definition: avformat.h:639
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:1185
char * url
input or output URL.
Definition: avformat.h:1454
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
uint8_t color_range
Definition: av1.h:41
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3953
simple assert() macros that are a bit more flexible than ISO C assert().
char * av_strireplace(const char *str, const char *from, const char *to)
Locale-independent strings replace.
Definition: avstring.c:235
static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
Definition: dashenc.c:1867
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
static int flush_init_segment(AVFormatContext *s, OutputStream *os)
Definition: dashenc.c:547
static SegmentType select_segment_type(SegmentType segment_type, enum AVCodecID codec_id)
Definition: dashenc.c:241
int64_t start_pos
Definition: dashenc.c:62
double availability_time_offset
Definition: dashenc.c:103
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:954
#define FFMAX(a, b)
Definition: common.h:94
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:83
const AVCodecTag ff_mp4_obj_type[]
Definition: isom.c:34
static void dashenc_delete_file(AVFormatContext *s, char *filename)
Definition: dashenc.c:1477
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1483
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: avcodec.h:3975
void * opaque
User data.
Definition: avformat.h:1864
AVOutputFormat ff_dash_muxer
Definition: dashenc.c:1934
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1414
AVDictionary * opts
Definition: movenc.c:50
AVBSFContext ** bsfcs
bitstream filters to run on stream
Definition: internal.h:161
const char * media_seg_name
Definition: dashenc.c:132
int void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:238
int ff_alloc_extradata(AVCodecParameters *par, int size)
Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end which is always set to 0...
Definition: utils.c:3305
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: mux.c:508
int segment_index
Definition: dashenc.c:86
static struct @313 state
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:94
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:466
void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type, int iframe_mode)
Definition: hlsplaylist.c:77
const char * name
Definition: avformat.h:505
int master_playlist_created
Definition: dashenc.c:138
AVFormatContext * ctx
Definition: movenc.c:48
char full_path[1024]
Definition: dashenc.c:101
char dirname[1024]
Definition: dashenc.c:129
enum AVMediaType media_type
Definition: dashenc.c:72
#define s(width, name)
Definition: cbs_vp9.c:257
int avoid_negative_ts
Avoid negative timestamps during muxing.
Definition: avformat.h:1689
int index_correction
Definition: dashenc.c:143
uint8_t color_description_present_flag
Definition: av1.h:37
#define AV_RL32
Definition: intreadwrite.h:146
AVDictionary * metadata
Definition: avformat.h:945
static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par, AVRational *frame_rate, char *str, int size)
Definition: dashenc.c:296
Usually treated as AVMEDIA_TYPE_DATA.
Definition: avutil.h:200
int64_t pos
Definition: dashenc.c:84
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:488
int segments_size
Definition: dashenc.c:86
#define AV_ERROR_MAX_STRING_SIZE
Definition: error.h:83
if(ret< 0)
Definition: vf_mcdeint.c:279
#define OFFSET(x)
Definition: dashenc.c:1890
#define AVERROR_EXPERIMENTAL
Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it...
Definition: error.h:72
ff_const59 struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1377
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1445
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:881
static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length)
Definition: dashenc.c:407
void ff_dash_fill_tmpl_params(char *dst, size_t buffer_size, const char *template, int rep_id, int number, int bit_rate, int64_t time)
Definition: dash.c:96
int64_t time
Definition: dashenc.c:64
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition: dict.c:180
Segment ** segments
Definition: dashenc.c:87
void ff_hls_write_playlist_version(AVIOContext *out, int version)
Definition: hlsplaylist.c:31
int index_length
Definition: dashenc.c:63
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition: avcodec.h:1199
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
AVStreamInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1238
const AVCodecTag ff_codec_movaudio_tags[]
Definition: isom.c:318
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, int byterange_mode, double duration, int round_duration, int64_t size, int64_t pos, char *baseurl, char *filename, double *prog_date_time, int64_t video_keyframe_size, int64_t video_keyframe_pos, int iframe_mode)
Definition: hlsplaylist.c:109
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
int bit_rate
Definition: dashenc.c:90
SegmentType segment_type
Definition: dashenc.c:167
int use_template
Definition: dashenc.c:120
int written_len
Definition: dashenc.c:99
AVRational max_frame_rate
Definition: dashenc.c:74
double prog_date_time
Definition: dashenc.c:65
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1946
void * buf
Definition: avisynth_c.h:766
Definition: url.h:38
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
uint8_t color_primaries
Definition: av1.h:38
Describe the class of an AVClass context structure.
Definition: log.h:67
const char * init_seg_name
Definition: dashenc.c:131
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
Rational number (pair of numerator and denominator).
Definition: rational.h:58
const char * format_name
Definition: dashenc.c:92
static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index, int final)
Definition: dashenc.c:747
cl_device_type type
AVMediaType
Definition: avutil.h:199
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
static const char * get_format_str(SegmentType segment_type)
Definition: dashenc.c:214
int avio_open2(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create and initialize a AVIOContext for accessing the resource indicated by url.
Definition: aviobuf.c:1179
#define FF_COMPLIANCE_STRICT
Strictly conform to all the things in the spec no matter what consequences.
Definition: avcodec.h:2630
#define snprintf
Definition: snprintf.h:34
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4410
static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
Definition: dashenc.c:817
int64_t total_duration
Definition: dashenc.c:126
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
static void find_index_range(AVFormatContext *s, const char *full_path, int64_t pos, int *index_length)
Definition: dashenc.c:1429
char file[1024]
Definition: dashenc.c:61
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:473
static const char * get_extension_str(SegmentType type, int single_file)
Definition: dashenc.c:222
static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, AVDictionary **options)
Definition: dashenc.c:176
URLContext * ffio_geturlcontext(AVIOContext *s)
Return the URLContext associated with the AVIOContext.
Definition: aviobuf.c:1038
#define flags(name, subs,...)
Definition: cbs_av1.c:564
uint8_t level
Definition: svq3.c:207
OutputStream * streams
Definition: dashenc.c:123
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename, char *agroup, char *codecs, char *ccgroup)
Definition: hlsplaylist.c:51
int init_range_length
Definition: dashenc.c:85
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition: http.c:308
SegmentType segment_type_option
Definition: dashenc.c:146
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
Put a description of the AVERROR code errnum in errbuf.
Definition: error.c:105
Definition: vpcc.h:35
int sample_rate
Audio only.
Definition: avcodec.h:4067
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO
Shift timestamps so that they start at 0.
Definition: avformat.h:1692
int64_t bitrate
Definition: h264_levels.c:131
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
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
static AVStream * ost
Main libavformat public API header.
char * av_strnstr(const char *haystack, const char *needle, size_t hay_length)
Locate the first occurrence of the string needle in the string haystack where not more than hay_lengt...
Definition: avstring.c:69
int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, AVRational *frame_rate, VPCC *vpcc)
Definition: vpcc.c:116
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:463
Utilties for rational number calculation.
const char * user_agent
Definition: dashenc.c:135
const char * single_file_name
Definition: dashenc.c:130
static double c[64]
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
int level
Definition: vpcc.h:37
void ff_hls_write_init_file(AVIOContext *out, char *filename, int byterange_mode, int64_t size, int64_t pos)
Definition: hlsplaylist.c:100
uint8_t chroma_subsampling_y
Definition: av1.h:35
int ff_av1_parse_seq_header(AV1SequenceParameters *seq, const uint8_t *buf, int size)
Parses a Sequence Header from the the provided buffer.
Definition: av1.c:293
uint8_t level
Definition: av1.h:30
static int handle_io_open_error(AVFormatContext *s, int err, char *url)
Definition: dashenc.c:232
int muxer_overhead
Definition: dashenc.c:105
int den
Denominator.
Definition: rational.h:60
static void write_styp(AVIOContext *pb)
Definition: dashenc.c:1419
int64_t duration
Definition: dashenc.c:66
static int dash_write_header(AVFormatContext *s)
Definition: dashenc.c:1360
int nr_of_streams_flushed
Definition: dashenc.c:151
uint8_t tier
Definition: av1.h:31
char id[10]
Definition: dashenc.c:71
static int check_file_extension(const char *filename, const char *extension)
Definition: dashenc.c:286
#define av_free(p)
char * value
Definition: dict.h:87
int len
int lhls
Definition: dashenc.c:148
const char * str
Definition: dashenc.c:156
void * priv_data
Format private data.
Definition: avformat.h:1386
const char * utc_timing_url
Definition: dashenc.c:133
int profile
Definition: vpcc.h:36
static int dash_write_trailer(AVFormatContext *s)
Definition: dashenc.c:1825
int window_size
Definition: dashenc.c:113
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:337
#define lrint
Definition: tablegen.h:53
static void dash_free(AVFormatContext *s)
Definition: dashenc.c:565
static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s, int representation_id, int final, char *prefetch_url)
Definition: dashenc.c:466
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3971
int has_video
Definition: dashenc.c:124
int channels
Audio only.
Definition: avcodec.h:4063
int64_t max_pts
Definition: dashenc.c:88
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1476
int avpriv_io_delete(const char *url)
Delete a resource.
Definition: avio.c:521
void ff_hls_write_end_list(AVIOContext *out)
Definition: hlsplaylist.c:164
int total_pkt_size
Definition: dashenc.c:104
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1254
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:377
static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatContext *s, int representation_id, int final)
Definition: dashenc.c:603
FILE * out
Definition: movenc.c:54
const char * extension_name
Definition: dashenc.c:93
#define av_freep(p)
internal header for VPx codec configuration utilities.
uint8_t matrix_coefficients
Definition: av1.h:40
SegmentType
Definition: pgssubdec.c:41
unbuffered private I/O API
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:60
int master_publish_rate
Definition: dashenc.c:149
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
static char * xmlescape(const char *str)
Definition: dashenc.c:672
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: avcodec.h:3961
formats
Definition: signature.h:48
AVIOContext * out
Definition: dashenc.c:81
char temp_path[1024]
Definition: dashenc.c:102
static int dash_flush(AVFormatContext *s, int final, int stream)
Definition: dashenc.c:1545
int stream_index
Definition: avcodec.h:1479
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:910
int64_t first_pts
Definition: ffmpeg.h:455
#define MKTAG(a, b, c, d)
Definition: common.h:366
unsigned int av_codec_get_tag(const struct AVCodecTag *const *tags, enum AVCodecID id)
Get the codec tag for the given codec id id.
#define AVFMT_TS_NEGATIVE
Format allows muxing negative timestamps.
Definition: avformat.h:482
This structure stores compressed data.
Definition: avcodec.h:1454
uint8_t bitdepth
Definition: av1.h:32
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1470
int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
Definition: avc.c:108
static const AVClass dash_class
Definition: dashenc.c:1927
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
int http_persistent
Definition: dashenc.c:137
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1398
static uint8_t tmp[11]
Definition: aes_ctr.c:26
uint8_t profile
Definition: av1.h:29