FFmpeg  4.2.1
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  ctx = avformat_alloc_context();
1211  if (!ctx)
1212  return AVERROR(ENOMEM);
1213 
1214  if (c->init_seg_name) {
1215  os->init_seg_name = av_strireplace(c->init_seg_name, "$ext$", os->extension_name);
1216  if (!os->init_seg_name)
1217  return AVERROR(ENOMEM);
1218  }
1219  if (c->media_seg_name) {
1221  if (!os->media_seg_name)
1222  return AVERROR(ENOMEM);
1223  }
1224  if (c->single_file_name) {
1226  if (!os->single_file_name)
1227  return AVERROR(ENOMEM);
1228  }
1229 
1230  if (os->segment_type == SEGMENT_TYPE_WEBM) {
1231  if ((!c->single_file && check_file_extension(os->init_seg_name, os->format_name) != 0) ||
1232  (!c->single_file && check_file_extension(os->media_seg_name, os->format_name) != 0) ||
1235  "One or many segment file names doesn't end with .webm. "
1236  "Override -init_seg_name and/or -media_seg_name and/or "
1237  "-single_file_name to end with the extension .webm\n");
1238  }
1239  if (c->streaming) {
1240  // Streaming not supported as matroskaenc buffers internally before writing the output
1241  av_log(s, AV_LOG_WARNING, "One or more streams in WebM output format. Streaming option will be ignored\n");
1242  c->streaming = 0;
1243  }
1244  }
1245 
1247  if (!ctx->oformat)
1248  return AVERROR_MUXER_NOT_FOUND;
1249  os->ctx = ctx;
1251  ctx->opaque = s->opaque;
1252  ctx->io_close = s->io_close;
1253  ctx->io_open = s->io_open;
1255 
1256  if (!(st = avformat_new_stream(ctx, NULL)))
1257  return AVERROR(ENOMEM);
1260  st->time_base = s->streams[i]->time_base;
1263  ctx->flags = s->flags;
1264 
1265  if (c->single_file) {
1266  if (os->single_file_name)
1267  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);
1268  else
1269  snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.%s", basename, i, os->format_name);
1270  } else {
1271  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->init_seg_name, i, 0, os->bit_rate, 0);
1272  }
1273  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
1274  set_http_options(&opts, c);
1275  if (!c->single_file) {
1276  if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0)
1277  return ret;
1278  ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts);
1279  } else {
1280  ctx->url = av_strdup(filename);
1281  ret = avio_open2(&ctx->pb, filename, AVIO_FLAG_WRITE, NULL, &opts);
1282  }
1283  av_dict_free(&opts);
1284  if (ret < 0)
1285  return ret;
1286  os->init_start_pos = 0;
1287 
1288  if (c->format_options_str) {
1289  ret = av_dict_parse_string(&opts, c->format_options_str, "=", ":", 0);
1290  if (ret < 0)
1291  return ret;
1292  }
1293 
1294  if (os->segment_type == SEGMENT_TYPE_MP4) {
1295  if (c->streaming)
1296  // frag_every_frame : Allows lower latency streaming
1297  // skip_sidx : Reduce bitrate overhead
1298  // skip_trailer : Avoids growing memory usage with time
1299  av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov+skip_sidx+skip_trailer", 0);
1300  else {
1301  if (c->global_sidx)
1302  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+global_sidx+skip_trailer", 0);
1303  else
1304  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+skip_trailer", 0);
1305  }
1306  } else {
1307  av_dict_set_int(&opts, "cluster_time_limit", c->seg_duration / 1000, 0);
1308  av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
1309  av_dict_set_int(&opts, "dash", 1, 0);
1310  av_dict_set_int(&opts, "dash_track_number", i + 1, 0);
1311  av_dict_set_int(&opts, "live", 1, 0);
1312  }
1313  ret = avformat_init_output(ctx, &opts);
1314  av_dict_free(&opts);
1315  if (ret < 0)
1316  return ret;
1317  os->ctx_inited = 1;
1318  avio_flush(ctx->pb);
1319 
1320  av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename);
1321 
1322  s->streams[i]->time_base = st->time_base;
1323  // If the muxer wants to shift timestamps, request to have them shifted
1324  // already before being handed to this muxer, so we don't have mismatches
1325  // between the MPD and the actual segments.
1327  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1328  AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
1329  if (avg_frame_rate.num > 0) {
1330  if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0)
1331  as->min_frame_rate = avg_frame_rate;
1332  if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0)
1333  as->max_frame_rate = avg_frame_rate;
1334  } else {
1335  as->ambiguous_frame_rate = 1;
1336  }
1337  c->has_video = 1;
1338  }
1339 
1340  set_codec_str(s, st->codecpar, &st->avg_frame_rate, os->codec_str,
1341  sizeof(os->codec_str));
1342  os->first_pts = AV_NOPTS_VALUE;
1343  os->max_pts = AV_NOPTS_VALUE;
1344  os->last_dts = AV_NOPTS_VALUE;
1345  os->segment_index = 1;
1346 
1349  }
1350 
1351  if (!c->has_video && c->seg_duration <= 0) {
1352  av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");
1353  return AVERROR(EINVAL);
1354  }
1355 
1356  c->nr_of_streams_flushed = 0;
1357 
1358  return 0;
1359 }
1360 
1362 {
1363  DASHContext *c = s->priv_data;
1364  int i, ret;
1365  for (i = 0; i < s->nb_streams; i++) {
1366  OutputStream *os = &c->streams[i];
1367  if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
1368  return ret;
1369 
1370  // Flush init segment
1371  // Only for WebM segment, since for mp4 delay_moov is set and
1372  // the init segment is thus flushed after the first packets.
1373  if (os->segment_type == SEGMENT_TYPE_WEBM &&
1374  (ret = flush_init_segment(s, os)) < 0)
1375  return ret;
1376  }
1377  return ret;
1378 }
1379 
1380 static int add_segment(OutputStream *os, const char *file,
1381  int64_t time, int64_t duration,
1382  int64_t start_pos, int64_t range_length,
1383  int64_t index_length, int next_exp_index)
1384 {
1385  int err;
1386  Segment *seg;
1387  if (os->nb_segments >= os->segments_size) {
1388  os->segments_size = (os->segments_size + 1) * 2;
1389  if ((err = av_reallocp(&os->segments, sizeof(*os->segments) *
1390  os->segments_size)) < 0) {
1391  os->segments_size = 0;
1392  os->nb_segments = 0;
1393  return err;
1394  }
1395  }
1396  seg = av_mallocz(sizeof(*seg));
1397  if (!seg)
1398  return AVERROR(ENOMEM);
1399  av_strlcpy(seg->file, file, sizeof(seg->file));
1400  seg->time = time;
1401  seg->duration = duration;
1402  if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
1403  seg->duration += seg->time;
1404  seg->time = 0;
1405  }
1406  seg->start_pos = start_pos;
1407  seg->range_length = range_length;
1408  seg->index_length = index_length;
1409  os->segments[os->nb_segments++] = seg;
1410  os->segment_index++;
1411  //correcting the segment index if it has fallen behind the expected value
1412  if (os->segment_index < next_exp_index) {
1413  av_log(NULL, AV_LOG_WARNING, "Correcting the segment index after file %s: current=%d corrected=%d\n",
1414  file, os->segment_index, next_exp_index);
1415  os->segment_index = next_exp_index;
1416  }
1417  return 0;
1418 }
1419 
1420 static void write_styp(AVIOContext *pb)
1421 {
1422  avio_wb32(pb, 24);
1423  ffio_wfourcc(pb, "styp");
1424  ffio_wfourcc(pb, "msdh");
1425  avio_wb32(pb, 0); /* minor */
1426  ffio_wfourcc(pb, "msdh");
1427  ffio_wfourcc(pb, "msix");
1428 }
1429 
1430 static void find_index_range(AVFormatContext *s, const char *full_path,
1431  int64_t pos, int *index_length)
1432 {
1433  uint8_t buf[8];
1434  AVIOContext *pb;
1435  int ret;
1436 
1437  ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL);
1438  if (ret < 0)
1439  return;
1440  if (avio_seek(pb, pos, SEEK_SET) != pos) {
1441  ff_format_io_close(s, &pb);
1442  return;
1443  }
1444  ret = avio_read(pb, buf, 8);
1445  ff_format_io_close(s, &pb);
1446  if (ret < 8)
1447  return;
1448  if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
1449  return;
1450  *index_length = AV_RB32(&buf[0]);
1451 }
1452 
1454  AVPacket *pkt, AVRational *frame_rate)
1455 {
1456  AVCodecParameters *par = os->ctx->streams[0]->codecpar;
1457  uint8_t *extradata;
1458  int ret, extradata_size;
1459 
1460  if (par->extradata_size)
1461  return 0;
1462 
1463  extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &extradata_size);
1464  if (!extradata_size)
1465  return 0;
1466 
1467  ret = ff_alloc_extradata(par, extradata_size);
1468  if (ret < 0)
1469  return ret;
1470 
1471  memcpy(par->extradata, extradata, extradata_size);
1472 
1473  set_codec_str(s, par, frame_rate, os->codec_str, sizeof(os->codec_str));
1474 
1475  return 0;
1476 }
1477 
1478 static void dashenc_delete_file(AVFormatContext *s, char *filename) {
1479  DASHContext *c = s->priv_data;
1480  int http_base_proto = ff_is_http_proto(filename);
1481 
1482  if (http_base_proto) {
1483  AVIOContext *out = NULL;
1484  AVDictionary *http_opts = NULL;
1485 
1486  set_http_options(&http_opts, c);
1487  av_dict_set(&http_opts, "method", "DELETE", 0);
1488 
1489  if (dashenc_io_open(s, &out, filename, &http_opts) < 0) {
1490  av_log(s, AV_LOG_ERROR, "failed to delete %s\n", filename);
1491  }
1492 
1493  av_dict_free(&http_opts);
1494  ff_format_io_close(s, &out);
1495  } else {
1496  int res = avpriv_io_delete(filename);
1497  if (res < 0) {
1498  char errbuf[AV_ERROR_MAX_STRING_SIZE];
1499  av_strerror(res, errbuf, sizeof(errbuf));
1500  av_log(s, (res == AVERROR(ENOENT) ? AV_LOG_WARNING : AV_LOG_ERROR), "failed to delete %s: %s\n", filename, errbuf);
1501  }
1502  }
1503 }
1504 
1506 {
1507  DASHContext *c = s->priv_data;
1508  size_t dirname_len, file_len;
1509  char filename[1024];
1510 
1511  dirname_len = strlen(c->dirname);
1512  if (dirname_len >= sizeof(filename)) {
1513  av_log(s, AV_LOG_WARNING, "Cannot delete segments as the directory path is too long: %"PRIu64" characters: %s\n",
1514  (uint64_t)dirname_len, c->dirname);
1515  return AVERROR(ENAMETOOLONG);
1516  }
1517 
1518  memcpy(filename, c->dirname, dirname_len);
1519 
1520  file_len = strlen(file);
1521  if ((dirname_len + file_len) >= sizeof(filename)) {
1522  av_log(s, AV_LOG_WARNING, "Cannot delete segments as the path is too long: %"PRIu64" characters: %s%s\n",
1523  (uint64_t)(dirname_len + file_len), c->dirname, file);
1524  return AVERROR(ENAMETOOLONG);
1525  }
1526 
1527  memcpy(filename + dirname_len, file, file_len + 1); // include the terminating zero
1528  dashenc_delete_file(s, filename);
1529 
1530  return 0;
1531 }
1532 
1533 static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
1534 {
1535  for (int i = 0; i < remove_count; ++i) {
1537 
1538  // Delete the segment regardless of whether the file was successfully deleted
1539  av_free(os->segments[i]);
1540  }
1541 
1542  os->nb_segments -= remove_count;
1543  memmove(os->segments, os->segments + remove_count, os->nb_segments * sizeof(*os->segments));
1544 }
1545 
1546 static int dash_flush(AVFormatContext *s, int final, int stream)
1547 {
1548  DASHContext *c = s->priv_data;
1549  int i, ret = 0;
1550 
1551  const char *proto = avio_find_protocol_name(s->url);
1552  int use_rename = proto && !strcmp(proto, "file");
1553 
1554  int cur_flush_segment_index = 0, next_exp_index = -1;
1555  if (stream >= 0) {
1556  cur_flush_segment_index = c->streams[stream].segment_index;
1557 
1558  //finding the next segment's expected index, based on the current pts value
1559  if (c->use_template && !c->use_timeline && c->index_correction &&
1560  c->streams[stream].last_pts != AV_NOPTS_VALUE &&
1561  c->streams[stream].first_pts != AV_NOPTS_VALUE) {
1562  int64_t pts_diff = av_rescale_q(c->streams[stream].last_pts -
1563  c->streams[stream].first_pts,
1564  s->streams[stream]->time_base,
1565  AV_TIME_BASE_Q);
1566  next_exp_index = (pts_diff / c->seg_duration) + 1;
1567  }
1568  }
1569 
1570  for (i = 0; i < s->nb_streams; i++) {
1571  OutputStream *os = &c->streams[i];
1572  AVStream *st = s->streams[i];
1573  int range_length, index_length = 0;
1574 
1575  if (!os->packets_written)
1576  continue;
1577 
1578  // Flush the single stream that got a keyframe right now.
1579  // Flush all audio streams as well, in sync with video keyframes,
1580  // but not the other video streams.
1581  if (stream >= 0 && i != stream) {
1583  continue;
1584  // Make sure we don't flush audio streams multiple times, when
1585  // all video streams are flushed one at a time.
1586  if (c->has_video && os->segment_index > cur_flush_segment_index)
1587  continue;
1588  }
1589 
1590  if (!c->single_file) {
1591  if (os->segment_type == SEGMENT_TYPE_MP4 && !os->written_len)
1592  write_styp(os->ctx->pb);
1593  } else {
1594  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile);
1595  }
1596 
1597  ret = flush_dynbuf(c, os, &range_length);
1598  if (ret < 0)
1599  break;
1600  os->packets_written = 0;
1601 
1602  if (c->single_file) {
1603  find_index_range(s, os->full_path, os->pos, &index_length);
1604  } else {
1605  dashenc_io_close(s, &os->out, os->temp_path);
1606 
1607  if (use_rename) {
1608  ret = avpriv_io_move(os->temp_path, os->full_path);
1609  if (ret < 0)
1610  break;
1611  }
1612  }
1613 
1614  if (!os->muxer_overhead)
1615  os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) *
1616  8 * AV_TIME_BASE) /
1617  av_rescale_q(os->max_pts - os->start_pts,
1618  st->time_base, AV_TIME_BASE_Q);
1619  os->total_pkt_size = 0;
1620 
1621  if (!os->bit_rate) {
1622  // calculate average bitrate of first segment
1623  int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / av_rescale_q(os->max_pts - os->start_pts,
1624  st->time_base,
1625  AV_TIME_BASE_Q);
1626  if (bitrate >= 0)
1627  os->bit_rate = bitrate;
1628  }
1629  add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index);
1630  av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path);
1631 
1632  os->pos += range_length;
1633  }
1634 
1635  if (c->window_size) {
1636  for (i = 0; i < s->nb_streams; i++) {
1637  OutputStream *os = &c->streams[i];
1638  int remove_count = os->nb_segments - c->window_size - c->extra_window_size;
1639  if (remove_count > 0)
1640  dashenc_delete_media_segments(s, os, remove_count);
1641  }
1642  }
1643 
1644  if (final) {
1645  for (i = 0; i < s->nb_streams; i++) {
1646  OutputStream *os = &c->streams[i];
1647  if (os->ctx && os->ctx_inited) {
1648  int64_t file_size = avio_tell(os->ctx->pb);
1649  av_write_trailer(os->ctx);
1650  if (c->global_sidx) {
1651  int j, start_index, start_number;
1652  int64_t sidx_size = avio_tell(os->ctx->pb) - file_size;
1653  get_start_index_number(os, c, &start_index, &start_number);
1654  if (start_index >= os->nb_segments ||
1656  continue;
1657  os->init_range_length += sidx_size;
1658  for (j = start_index; j < os->nb_segments; j++) {
1659  Segment *seg = os->segments[j];
1660  seg->start_pos += sidx_size;
1661  }
1662  }
1663 
1664  }
1665  }
1666  }
1667  if (ret >= 0) {
1668  if (c->has_video && !final) {
1669  c->nr_of_streams_flushed++;
1671  return ret;
1672 
1673  c->nr_of_streams_flushed = 0;
1674  }
1675  ret = write_manifest(s, final);
1676  }
1677  return ret;
1678 }
1679 
1681 {
1682  DASHContext *c = s->priv_data;
1683  AVStream *st = s->streams[pkt->stream_index];
1684  OutputStream *os = &c->streams[pkt->stream_index];
1685  int64_t seg_end_duration, elapsed_duration;
1686  int ret;
1687 
1688  ret = update_stream_extradata(s, os, pkt, &st->avg_frame_rate);
1689  if (ret < 0)
1690  return ret;
1691 
1692  // Fill in a heuristic guess of the packet duration, if none is available.
1693  // The mp4 muxer will do something similar (for the last packet in a fragment)
1694  // if nothing is set (setting it for the other packets doesn't hurt).
1695  // By setting a nonzero duration here, we can be sure that the mp4 muxer won't
1696  // invoke its heuristic (this doesn't have to be identical to that algorithm),
1697  // so that we know the exact timestamps of fragments.
1698  if (!pkt->duration && os->last_dts != AV_NOPTS_VALUE)
1699  pkt->duration = pkt->dts - os->last_dts;
1700  os->last_dts = pkt->dts;
1701 
1702  // If forcing the stream to start at 0, the mp4 muxer will set the start
1703  // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps.
1704  if (os->first_pts == AV_NOPTS_VALUE &&
1706  pkt->pts -= pkt->dts;
1707  pkt->dts = 0;
1708  }
1709 
1710  if (os->first_pts == AV_NOPTS_VALUE)
1711  os->first_pts = pkt->pts;
1712  os->last_pts = pkt->pts;
1713 
1714  if (!c->availability_start_time[0]) {
1715  int64_t start_time_us = av_gettime();
1716  c->start_time_s = start_time_us / 1000000;
1718  sizeof(c->availability_start_time));
1719  }
1720 
1721  if (!os->availability_time_offset && pkt->duration) {
1722  int64_t frame_duration = av_rescale_q(pkt->duration, st->time_base,
1723  AV_TIME_BASE_Q);
1724  os->availability_time_offset = ((double) c->seg_duration -
1725  frame_duration) / AV_TIME_BASE;
1726  }
1727 
1728  if (c->use_template && !c->use_timeline) {
1729  elapsed_duration = pkt->pts - os->first_pts;
1730  seg_end_duration = (int64_t) os->segment_index * c->seg_duration;
1731  } else {
1732  elapsed_duration = pkt->pts - os->start_pts;
1733  seg_end_duration = c->seg_duration;
1734  }
1735 
1736  if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
1737  pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
1738  av_compare_ts(elapsed_duration, st->time_base,
1739  seg_end_duration, AV_TIME_BASE_Q) >= 0) {
1740  int64_t prev_duration = c->last_duration;
1741 
1742  c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
1743  st->time_base,
1744  AV_TIME_BASE_Q);
1745  c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
1746  st->time_base,
1747  AV_TIME_BASE_Q);
1748 
1749  if ((!c->use_timeline || !c->use_template) && prev_duration) {
1750  if (c->last_duration < prev_duration*9/10 ||
1751  c->last_duration > prev_duration*11/10) {
1753  "Segment durations differ too much, enable use_timeline "
1754  "and use_template, or keep a stricter keyframe interval\n");
1755  }
1756  }
1757 
1758  if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0)
1759  return ret;
1760  }
1761 
1762  if (!os->packets_written) {
1763  // If we wrote a previous segment, adjust the start time of the segment
1764  // to the end of the previous one (which is the same as the mp4 muxer
1765  // does). This avoids gaps in the timeline.
1766  if (os->max_pts != AV_NOPTS_VALUE)
1767  os->start_pts = os->max_pts;
1768  else
1769  os->start_pts = pkt->pts;
1770  }
1771  if (os->max_pts == AV_NOPTS_VALUE)
1772  os->max_pts = pkt->pts + pkt->duration;
1773  else
1774  os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
1775  os->packets_written++;
1776  os->total_pkt_size += pkt->size;
1777  if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0)
1778  return ret;
1779 
1780  if (!os->init_range_length)
1781  flush_init_segment(s, os);
1782 
1783  //open the output context when the first frame of a segment is ready
1784  if (!c->single_file && os->packets_written == 1) {
1785  AVDictionary *opts = NULL;
1786  const char *proto = avio_find_protocol_name(s->url);
1787  int use_rename = proto && !strcmp(proto, "file");
1788  os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0';
1789  ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename),
1790  os->media_seg_name, pkt->stream_index,
1791  os->segment_index, os->bit_rate, os->start_pts);
1792  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname,
1793  os->filename);
1794  snprintf(os->temp_path, sizeof(os->temp_path),
1795  use_rename ? "%s.tmp" : "%s", os->full_path);
1796  set_http_options(&opts, c);
1797  ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
1798  av_dict_free(&opts);
1799  if (ret < 0) {
1800  return handle_io_open_error(s, ret, os->temp_path);
1801  }
1802  if (c->lhls) {
1803  char *prefetch_url = use_rename ? NULL : os->filename;
1804  write_hls_media_playlist(os, s, pkt->stream_index, 0, prefetch_url);
1805  }
1806  }
1807 
1808  //write out the data immediately in streaming mode
1809  if (c->streaming && os->segment_type == SEGMENT_TYPE_MP4) {
1810  int len = 0;
1811  uint8_t *buf = NULL;
1812  if (!os->written_len)
1813  write_styp(os->ctx->pb);
1814  avio_flush(os->ctx->pb);
1815  len = avio_get_dyn_buf (os->ctx->pb, &buf);
1816  if (os->out) {
1817  avio_write(os->out, buf + os->written_len, len - os->written_len);
1818  avio_flush(os->out);
1819  }
1820  os->written_len = len;
1821  }
1822 
1823  return ret;
1824 }
1825 
1827 {
1828  DASHContext *c = s->priv_data;
1829  int i;
1830 
1831  if (s->nb_streams > 0) {
1832  OutputStream *os = &c->streams[0];
1833  // If no segments have been written so far, try to do a crude
1834  // guess of the segment duration
1835  if (!c->last_duration)
1837  s->streams[0]->time_base,
1838  AV_TIME_BASE_Q);
1840  s->streams[0]->time_base,
1841  AV_TIME_BASE_Q);
1842  }
1843  dash_flush(s, 1, -1);
1844 
1845  if (c->remove_at_exit) {
1846  for (i = 0; i < s->nb_streams; ++i) {
1847  OutputStream *os = &c->streams[i];
1850  if (c->hls_playlist && os->segment_type == SEGMENT_TYPE_MP4) {
1851  char filename[1024];
1852  get_hls_playlist_name(filename, sizeof(filename), c->dirname, i);
1853  dashenc_delete_file(s, filename);
1854  }
1855  }
1856  dashenc_delete_file(s, s->url);
1857 
1858  if (c->hls_playlist && c->master_playlist_created) {
1859  char filename[1024];
1860  snprintf(filename, sizeof(filename), "%smaster.m3u8", c->dirname);
1861  dashenc_delete_file(s, filename);
1862  }
1863  }
1864 
1865  return 0;
1866 }
1867 
1868 static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
1869 {
1870  DASHContext *c = s->priv_data;
1871  OutputStream *os = &c->streams[avpkt->stream_index];
1872  AVFormatContext *oc = os->ctx;
1873  if (oc->oformat->check_bitstream) {
1874  int ret;
1875  AVPacket pkt = *avpkt;
1876  pkt.stream_index = 0;
1877  ret = oc->oformat->check_bitstream(oc, &pkt);
1878  if (ret == 1) {
1879  AVStream *st = s->streams[avpkt->stream_index];
1880  AVStream *ost = oc->streams[0];
1881  st->internal->bsfcs = ost->internal->bsfcs;
1882  st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
1883  ost->internal->bsfcs = NULL;
1884  ost->internal->nb_bsfcs = 0;
1885  }
1886  return ret;
1887  }
1888  return 1;
1889 }
1890 
1891 #define OFFSET(x) offsetof(DASHContext, x)
1892 #define E AV_OPT_FLAG_ENCODING_PARAM
1893 static const AVOption options[] = {
1894  { "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 },
1895  { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
1896  { "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 },
1897 #if FF_API_DASH_MIN_SEG_DURATION
1898  { "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 },
1899 #endif
1900  { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E },
1901  { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1902  { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1903  { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1904  { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1905  { "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 },
1906  { "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 },
1907  { "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 },
1908  { "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 },
1909  { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1910  { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1911  { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1912  { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1913  { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1914  { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
1915  { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1916  { "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},
1917  { "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 },
1918  { "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"},
1919  { "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX, E, "segment_type"},
1920  { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX, E, "segment_type"},
1921  { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX, E, "segment_type"},
1922  { "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 },
1923  { "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 },
1924  { "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},
1925  { NULL },
1926 };
1927 
1928 static const AVClass dash_class = {
1929  .class_name = "dash muxer",
1930  .item_name = av_default_item_name,
1931  .option = options,
1932  .version = LIBAVUTIL_VERSION_INT,
1933 };
1934 
1936  .name = "dash",
1937  .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
1938  .extensions = "mpd",
1939  .priv_data_size = sizeof(DASHContext),
1940  .audio_codec = AV_CODEC_ID_AAC,
1941  .video_codec = AV_CODEC_ID_H264,
1943  .init = dash_init,
1947  .deinit = dash_free,
1948  .check_bitstream = dash_check_bitstream,
1949  .priv_class = &dash_class,
1950 };
#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:689
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:1413
AVOption.
Definition: opt.h:246
static int parse_adaptation_sets(AVFormatContext *s)
Definition: dashenc.c:835
static const AVOption options[]
Definition: dashenc.c:1893
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:1453
int ff_is_http_proto(char *filename)
Utility function to check if the file uses http or https protocol.
Definition: utils.c:5648
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:1384
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:1380
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:5641
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:4459
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:1533
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:1505
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:149
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:1892
#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:2021
#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:1680
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:1183
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:1868
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:1478
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:1935
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:3288
#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:1891
#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:1443
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:1177
#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:4393
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:1430
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:561
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:290
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:1420
int64_t duration
Definition: dashenc.c:66
static int dash_write_header(AVFormatContext *s)
Definition: dashenc.c:1361
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:1826
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:1546
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:1928
#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:1396
static uint8_t tmp[11]
Definition: aes_ctr.c:26
uint8_t profile
Definition: av1.h:29