FFmpeg
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/parseutils.h"
35 #include "libavutil/rational.h"
36 #include "libavutil/time.h"
38 
39 #include "av1.h"
40 #include "avc.h"
41 #include "avformat.h"
42 #include "avio_internal.h"
43 #include "hlsplaylist.h"
44 #if CONFIG_HTTP_PROTOCOL
45 #include "http.h"
46 #endif
47 #include "internal.h"
48 #include "isom.h"
49 #include "os_support.h"
50 #include "url.h"
51 #include "vpcc.h"
52 #include "dash.h"
53 
54 typedef enum {
59 } SegmentType;
60 
61 enum {
67 };
68 
69 #define MPD_PROFILE_DASH 1
70 #define MPD_PROFILE_DVB 2
71 
72 typedef struct Segment {
73  char file[1024];
74  int64_t start_pos;
76  int64_t time;
78  int64_t duration;
79  int n;
80 } Segment;
81 
82 typedef struct AdaptationSet {
83  int id;
84  char *descriptor;
85  int64_t seg_duration;
86  int64_t frag_duration;
87  int frag_type;
88  enum AVMediaType media_type;
90  AVRational min_frame_rate, max_frame_rate;
93  int max_width, max_height;
96  int trick_idx;
98 
99 typedef struct OutputStream {
101  int ctx_inited, as_idx;
106  char initfile[1024];
107  int64_t init_start_pos, pos;
109  int nb_segments, segments_size, segment_index;
110  int64_t seg_duration;
111  int64_t frag_duration;
112  int64_t last_duration;
114  int64_t first_pts, start_pts, max_pts;
115  int64_t last_dts, last_pts;
117  int bit_rate;
119  SegmentType segment_type; /* segment type selected for this particular stream */
120  const char *format_name;
121  const char *extension_name;
122  const char *single_file_name; /* file names selected for this particular stream */
123  const char *init_seg_name;
124  const char *media_seg_name;
125 
126  char codec_str[100];
128  char filename[1024];
129  char full_path[1024];
130  char temp_path[1024];
133  char producer_reference_time_str[100];
138  int64_t gop_size;
141 } OutputStream;
142 
143 typedef struct DASHContext {
144  const AVClass *class; /* Class for private options. */
147  int nb_as;
150 #if FF_API_DASH_MIN_SEG_DURATION
151  int min_seg_duration;
152 #endif
153  int64_t seg_duration;
154  int64_t frag_duration;
161  int64_t last_duration;
162  int64_t total_duration;
163  char availability_start_time[100];
164  time_t start_time_s;
166  char dirname[1024];
167  const char *single_file_name; /* file names as specified in options */
168  const char *init_seg_name;
169  const char *media_seg_name;
170  const char *utc_timing_url;
171  const char *method;
172  const char *user_agent;
175  const char *hls_master_name;
181  int64_t timeout;
185  SegmentType segment_type_option; /* segment type as specified in options */
187  int lhls;
188  int ldash;
194  int64_t max_gop_size;
196  int profile;
197  int64_t target_latency;
201 } DASHContext;
202 
203 static struct codec_string {
204  int id;
205  const char *str;
206 } codecs[] = {
207  { AV_CODEC_ID_VP8, "vp8" },
208  { AV_CODEC_ID_VP9, "vp9" },
209  { AV_CODEC_ID_VORBIS, "vorbis" },
210  { AV_CODEC_ID_OPUS, "opus" },
211  { AV_CODEC_ID_FLAC, "flac" },
212  { 0, NULL }
213 };
214 
215 static struct format_string {
217  const char *str;
218 } formats[] = {
219  { SEGMENT_TYPE_AUTO, "auto" },
220  { SEGMENT_TYPE_MP4, "mp4" },
221  { SEGMENT_TYPE_WEBM, "webm" },
222  { 0, NULL }
223 };
224 
225 static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
226  AVDictionary **options) {
227  DASHContext *c = s->priv_data;
228  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
229  int err = AVERROR_MUXER_NOT_FOUND;
230  if (!*pb || !http_base_proto || !c->http_persistent) {
231  err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
232 #if CONFIG_HTTP_PROTOCOL
233  } else {
234  URLContext *http_url_context = ffio_geturlcontext(*pb);
235  av_assert0(http_url_context);
236  err = ff_http_do_new_request(http_url_context, filename);
237  if (err < 0)
238  ff_format_io_close(s, pb);
239 #endif
240  }
241  return err;
242 }
243 
244 static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) {
245  DASHContext *c = s->priv_data;
246  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
247 
248  if (!*pb)
249  return;
250 
251  if (!http_base_proto || !c->http_persistent) {
252  ff_format_io_close(s, pb);
253 #if CONFIG_HTTP_PROTOCOL
254  } else {
255  URLContext *http_url_context = ffio_geturlcontext(*pb);
256  av_assert0(http_url_context);
257  avio_flush(*pb);
258  ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
259 #endif
260  }
261 }
262 
263 static const char *get_format_str(SegmentType segment_type) {
264  int i;
265  for (i = 0; i < SEGMENT_TYPE_NB; i++)
266  if (formats[i].segment_type == segment_type)
267  return formats[i].str;
268  return NULL;
269 }
270 
271 static const char *get_extension_str(SegmentType type, int single_file)
272 {
273  switch (type) {
274 
275  case SEGMENT_TYPE_MP4: return single_file ? "mp4" : "m4s";
276  case SEGMENT_TYPE_WEBM: return "webm";
277  default: return NULL;
278  }
279 }
280 
281 static int handle_io_open_error(AVFormatContext *s, int err, char *url) {
282  DASHContext *c = s->priv_data;
283  char errbuf[AV_ERROR_MAX_STRING_SIZE];
284  av_strerror(err, errbuf, sizeof(errbuf));
286  "Unable to open %s for writing: %s\n", url, errbuf);
287  return c->ignore_io_errors ? 0 : err;
288 }
289 
291 {
292  if (segment_type == SEGMENT_TYPE_AUTO) {
293  if (codec_id == AV_CODEC_ID_OPUS || codec_id == AV_CODEC_ID_VORBIS ||
294  codec_id == AV_CODEC_ID_VP8 || codec_id == AV_CODEC_ID_VP9) {
295  segment_type = SEGMENT_TYPE_WEBM;
296  } else {
297  segment_type = SEGMENT_TYPE_MP4;
298  }
299  }
300 
301  return segment_type;
302 }
303 
305 {
306  DASHContext *c = s->priv_data;
307  int has_mp4_streams = 0;
308  for (int i = 0; i < s->nb_streams; ++i) {
309  OutputStream *os = &c->streams[i];
310  SegmentType segment_type = select_segment_type(
312  os->segment_type = segment_type;
313  os->format_name = get_format_str(segment_type);
314  if (!os->format_name) {
315  av_log(s, AV_LOG_ERROR, "Could not select DASH segment type for stream %d\n", i);
317  }
318  os->extension_name = get_extension_str(segment_type, c->single_file);
319  if (!os->extension_name) {
320  av_log(s, AV_LOG_ERROR, "Could not get extension type for stream %d\n", i);
322  }
323 
324  has_mp4_streams |= segment_type == SEGMENT_TYPE_MP4;
325  }
326 
327  if (c->hls_playlist && !has_mp4_streams) {
328  av_log(s, AV_LOG_WARNING, "No mp4 streams, disabling HLS manifest generation\n");
329  c->hls_playlist = 0;
330  }
331 
332  return 0;
333 }
334 
335 static int check_file_extension(const char *filename, const char *extension) {
336  char *dot;
337  if (!filename || !extension)
338  return -1;
339  dot = strrchr(filename, '.');
340  if (dot && !strcmp(dot + 1, extension))
341  return 0;
342  return -1;
343 }
344 
346  AVRational *frame_rate, char *str, int size) {
347  VPCC vpcc;
348  int ret = ff_isom_get_vpcc_features(s, par, frame_rate, &vpcc);
349  if (ret == 0) {
350  av_strlcatf(str, size, "vp09.%02d.%02d.%02d",
351  vpcc.profile, vpcc.level, vpcc.bitdepth);
352  } else {
353  // Default to just vp9 in case of error while finding out profile or level
354  av_log(s, AV_LOG_WARNING, "Could not find VP9 profile and/or level\n");
355  av_strlcpy(str, "vp9", size);
356  }
357  return;
358 }
359 
361  AVRational *frame_rate, char *str, int size)
362 {
363  const AVCodecTag *tags[2] = { NULL, NULL };
364  uint32_t tag;
365  int i;
366 
367  // common Webm codecs are not part of RFC 6381
368  for (i = 0; codecs[i].id; i++)
369  if (codecs[i].id == par->codec_id) {
370  if (codecs[i].id == AV_CODEC_ID_VP9) {
371  set_vp9_codec_str(s, par, frame_rate, str, size);
372  } else {
373  av_strlcpy(str, codecs[i].str, size);
374  }
375  return;
376  }
377 
378  // for codecs part of RFC 6381
379  if (par->codec_type == AVMEDIA_TYPE_VIDEO)
380  tags[0] = ff_codec_movvideo_tags;
381  else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
382  tags[0] = ff_codec_movaudio_tags;
383  else
384  return;
385 
386  tag = par->codec_tag;
387  if (!tag)
388  tag = av_codec_get_tag(tags, par->codec_id);
389  if (!tag)
390  return;
391  if (size < 5)
392  return;
393 
394  AV_WL32(str, tag);
395  str[4] = '\0';
396  if (!strcmp(str, "mp4a") || !strcmp(str, "mp4v")) {
397  uint32_t oti;
398  tags[0] = ff_mp4_obj_type;
399  oti = av_codec_get_tag(tags, par->codec_id);
400  if (oti)
401  av_strlcatf(str, size, ".%02"PRIx32, oti);
402  else
403  return;
404 
405  if (tag == MKTAG('m', 'p', '4', 'a')) {
406  if (par->extradata_size >= 2) {
407  int aot = par->extradata[0] >> 3;
408  if (aot == 31)
409  aot = ((AV_RB16(par->extradata) >> 5) & 0x3f) + 32;
410  av_strlcatf(str, size, ".%d", aot);
411  }
412  } else if (tag == MKTAG('m', 'p', '4', 'v')) {
413  // Unimplemented, should output ProfileLevelIndication as a decimal number
414  av_log(s, AV_LOG_WARNING, "Incomplete RFC 6381 codec string for mp4v\n");
415  }
416  } else if (!strcmp(str, "avc1")) {
417  uint8_t *tmpbuf = NULL;
418  uint8_t *extradata = par->extradata;
419  int extradata_size = par->extradata_size;
420  if (!extradata_size)
421  return;
422  if (extradata[0] != 1) {
423  AVIOContext *pb;
424  if (avio_open_dyn_buf(&pb) < 0)
425  return;
426  if (ff_isom_write_avcc(pb, extradata, extradata_size) < 0) {
427  ffio_free_dyn_buf(&pb);
428  return;
429  }
430  extradata_size = avio_close_dyn_buf(pb, &extradata);
431  tmpbuf = extradata;
432  }
433 
434  if (extradata_size >= 4)
435  av_strlcatf(str, size, ".%02x%02x%02x",
436  extradata[1], extradata[2], extradata[3]);
437  av_free(tmpbuf);
438  } else if (!strcmp(str, "av01")) {
440  if (!par->extradata_size)
441  return;
442  if (ff_av1_parse_seq_header(&seq, par->extradata, par->extradata_size) < 0)
443  return;
444 
445  av_strlcatf(str, size, ".%01u.%02u%s.%02u",
446  seq.profile, seq.level, seq.tier ? "H" : "M", seq.bitdepth);
448  av_strlcatf(str, size, ".%01u.%01u%01u%01u.%02u.%02u.%02u.%01u",
449  seq.monochrome,
452  seq.color_range);
453  }
454 }
455 
457 {
458  uint8_t *buffer;
459 
460  if (!os->ctx->pb) {
461  return AVERROR(EINVAL);
462  }
463 
464  // flush
465  av_write_frame(os->ctx, NULL);
466  avio_flush(os->ctx->pb);
467 
468  if (!c->single_file) {
469  // write out to file
470  *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer);
471  os->ctx->pb = NULL;
472  if (os->out)
473  avio_write(os->out, buffer + os->written_len, *range_length - os->written_len);
474  os->written_len = 0;
475  av_free(buffer);
476 
477  // re-open buffer
478  return avio_open_dyn_buf(&os->ctx->pb);
479  } else {
480  *range_length = avio_tell(os->ctx->pb) - os->pos;
481  return 0;
482  }
483 }
484 
486 {
487  if (c->method)
488  av_dict_set(options, "method", c->method, 0);
489  av_dict_copy(options, c->http_opts, 0);
490  if (c->user_agent)
491  av_dict_set(options, "user_agent", c->user_agent, 0);
492  if (c->http_persistent)
493  av_dict_set_int(options, "multiple_requests", 1, 0);
494  if (c->timeout >= 0)
495  av_dict_set_int(options, "timeout", c->timeout, 0);
496 }
497 
498 static void get_hls_playlist_name(char *playlist_name, int string_size,
499  const char *base_url, int id) {
500  if (base_url)
501  snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
502  else
503  snprintf(playlist_name, string_size, "media_%d.m3u8", id);
504 }
505 
507  int *start_index, int *start_number) {
508  *start_index = 0;
509  *start_number = 1;
510  if (c->window_size) {
511  *start_index = FFMAX(os->nb_segments - c->window_size, 0);
512  *start_number = FFMAX(os->segment_index - c->window_size, 1);
513  }
514 }
515 
517  int representation_id, int final,
518  char *prefetch_url) {
519  DASHContext *c = s->priv_data;
520  int timescale = os->ctx->streams[0]->time_base.den;
521  char temp_filename_hls[1024];
522  char filename_hls[1024];
523  AVDictionary *http_opts = NULL;
524  int target_duration = 0;
525  int ret = 0;
526  const char *proto = avio_find_protocol_name(c->dirname);
527  int use_rename = proto && !strcmp(proto, "file");
528  int i, start_index, start_number;
529  double prog_date_time = 0;
530 
531  get_start_index_number(os, c, &start_index, &start_number);
532 
533  if (!c->hls_playlist || start_index >= os->nb_segments ||
535  return;
536 
537  get_hls_playlist_name(filename_hls, sizeof(filename_hls),
538  c->dirname, representation_id);
539 
540  snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? "%s.tmp" : "%s", filename_hls);
541 
542  set_http_options(&http_opts, c);
543  ret = dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
544  av_dict_free(&http_opts);
545  if (ret < 0) {
546  handle_io_open_error(s, ret, temp_filename_hls);
547  return;
548  }
549  for (i = start_index; i < os->nb_segments; i++) {
550  Segment *seg = os->segments[i];
551  double duration = (double) seg->duration / timescale;
552  if (target_duration <= duration)
553  target_duration = lrint(duration);
554  }
555 
556  ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration,
557  start_number, PLAYLIST_TYPE_NONE, 0);
558 
561 
562  for (i = start_index; i < os->nb_segments; i++) {
563  Segment *seg = os->segments[i];
564 
565  if (prog_date_time == 0) {
566  if (os->nb_segments == 1)
567  prog_date_time = c->start_time_s;
568  else
569  prog_date_time = seg->prog_date_time;
570  }
572 
574  (double) seg->duration / timescale, 0,
575  seg->range_length, seg->start_pos, NULL,
576  c->single_file ? os->initfile : seg->file,
577  &prog_date_time, 0, 0, 0);
578  if (ret < 0) {
579  av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
580  }
581  }
582 
583  if (prefetch_url)
584  avio_printf(c->m3u8_out, "#EXT-X-PREFETCH:%s\n", prefetch_url);
585 
586  if (final)
588 
589  dashenc_io_close(s, &c->m3u8_out, temp_filename_hls);
590 
591  if (use_rename)
592  ff_rename(temp_filename_hls, filename_hls, os->ctx);
593 }
594 
596 {
597  DASHContext *c = s->priv_data;
598  int ret, range_length;
599 
600  ret = flush_dynbuf(c, os, &range_length);
601  if (ret < 0)
602  return ret;
603 
604  os->pos = os->init_range_length = range_length;
605  if (!c->single_file) {
606  char filename[1024];
607  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
608  dashenc_io_close(s, &os->out, filename);
609  }
610  return 0;
611 }
612 
614 {
615  DASHContext *c = s->priv_data;
616  int i, j;
617 
618  if (c->as) {
619  for (i = 0; i < c->nb_as; i++) {
620  av_dict_free(&c->as[i].metadata);
621  av_freep(&c->as[i].descriptor);
622  }
623  av_freep(&c->as);
624  c->nb_as = 0;
625  }
626 
627  if (!c->streams)
628  return;
629  for (i = 0; i < s->nb_streams; i++) {
630  OutputStream *os = &c->streams[i];
631  if (os->ctx && os->ctx->pb) {
632  if (!c->single_file)
633  ffio_free_dyn_buf(&os->ctx->pb);
634  else
635  avio_close(os->ctx->pb);
636  }
637  ff_format_io_close(s, &os->out);
640  av_parser_close(os->parser);
641  for (j = 0; j < os->nb_segments; j++)
642  av_free(os->segments[j]);
643  av_free(os->segments);
645  av_freep(&os->init_seg_name);
646  av_freep(&os->media_seg_name);
647  }
648  av_freep(&c->streams);
649 
650  ff_format_io_close(s, &c->mpd_out);
652 }
653 
655  int representation_id, int final)
656 {
657  DASHContext *c = s->priv_data;
658  int i, start_index, start_number;
659  get_start_index_number(os, c, &start_index, &start_number);
660 
661  if (c->use_template) {
662  int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE;
663  avio_printf(out, "\t\t\t\t<SegmentTemplate timescale=\"%d\" ", timescale);
664  if (!c->use_timeline) {
665  avio_printf(out, "duration=\"%"PRId64"\" ", os->seg_duration);
666  if (c->streaming && os->availability_time_offset)
667  avio_printf(out, "availabilityTimeOffset=\"%.3f\" ",
669  }
670  if (c->streaming && os->availability_time_offset && !final)
671  avio_printf(out, "availabilityTimeComplete=\"false\" ");
672 
673  avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\"", os->init_seg_name, os->media_seg_name, c->use_timeline ? start_number : 1);
675  avio_printf(out, " presentationTimeOffset=\"%"PRId64"\"", c->presentation_time_offset);
676  avio_printf(out, ">\n");
677  if (c->use_timeline) {
678  int64_t cur_time = 0;
679  avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
680  for (i = start_index; i < os->nb_segments; ) {
681  Segment *seg = os->segments[i];
682  int repeat = 0;
683  avio_printf(out, "\t\t\t\t\t\t<S ");
684  if (i == start_index || seg->time != cur_time) {
685  cur_time = seg->time;
686  avio_printf(out, "t=\"%"PRId64"\" ", seg->time);
687  }
688  avio_printf(out, "d=\"%"PRId64"\" ", seg->duration);
689  while (i + repeat + 1 < os->nb_segments &&
690  os->segments[i + repeat + 1]->duration == seg->duration &&
691  os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration)
692  repeat++;
693  if (repeat > 0)
694  avio_printf(out, "r=\"%d\" ", repeat);
695  avio_printf(out, "/>\n");
696  i += 1 + repeat;
697  cur_time += (1 + repeat) * seg->duration;
698  }
699  avio_printf(out, "\t\t\t\t\t</SegmentTimeline>\n");
700  }
701  avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
702  } else if (c->single_file) {
703  avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
704  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
705  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);
706  for (i = start_index; i < os->nb_segments; i++) {
707  Segment *seg = os->segments[i];
708  avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
709  if (seg->index_length)
710  avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
711  avio_printf(out, "/>\n");
712  }
713  avio_printf(out, "\t\t\t\t</SegmentList>\n");
714  } else {
715  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
716  avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
717  for (i = start_index; i < os->nb_segments; i++) {
718  Segment *seg = os->segments[i];
719  avio_printf(out, "\t\t\t\t\t<SegmentURL media=\"%s\" />\n", seg->file);
720  }
721  avio_printf(out, "\t\t\t\t</SegmentList>\n");
722  }
723  if (!c->lhls || final) {
724  write_hls_media_playlist(os, s, representation_id, final, NULL);
725  }
726 
727 }
728 
729 static char *xmlescape(const char *str) {
730  int outlen = strlen(str)*3/2 + 6;
731  char *out = av_realloc(NULL, outlen + 1);
732  int pos = 0;
733  if (!out)
734  return NULL;
735  for (; *str; str++) {
736  if (pos + 6 > outlen) {
737  char *tmp;
738  outlen = 2 * outlen + 6;
739  tmp = av_realloc(out, outlen + 1);
740  if (!tmp) {
741  av_free(out);
742  return NULL;
743  }
744  out = tmp;
745  }
746  if (*str == '&') {
747  memcpy(&out[pos], "&amp;", 5);
748  pos += 5;
749  } else if (*str == '<') {
750  memcpy(&out[pos], "&lt;", 4);
751  pos += 4;
752  } else if (*str == '>') {
753  memcpy(&out[pos], "&gt;", 4);
754  pos += 4;
755  } else if (*str == '\'') {
756  memcpy(&out[pos], "&apos;", 6);
757  pos += 6;
758  } else if (*str == '\"') {
759  memcpy(&out[pos], "&quot;", 6);
760  pos += 6;
761  } else {
762  out[pos++] = *str;
763  }
764  }
765  out[pos] = '\0';
766  return out;
767 }
768 
769 static void write_time(AVIOContext *out, int64_t time)
770 {
771  int seconds = time / AV_TIME_BASE;
772  int fractions = time % AV_TIME_BASE;
773  int minutes = seconds / 60;
774  int hours = minutes / 60;
775  seconds %= 60;
776  minutes %= 60;
777  avio_printf(out, "PT");
778  if (hours)
779  avio_printf(out, "%dH", hours);
780  if (hours || minutes)
781  avio_printf(out, "%dM", minutes);
782  avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
783 }
784 
785 static void format_date(char *buf, int size, int64_t time_us)
786 {
787  struct tm *ptm, tmbuf;
788  int64_t time_ms = time_us / 1000;
789  const time_t time_s = time_ms / 1000;
790  int millisec = time_ms - (time_s * 1000);
791  ptm = gmtime_r(&time_s, &tmbuf);
792  if (ptm) {
793  int len;
794  if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%S", ptm)) {
795  buf[0] = '\0';
796  return;
797  }
798  len = strlen(buf);
799  snprintf(buf + len, size - len, ".%03dZ", millisec);
800  }
801 }
802 
804  int final)
805 {
806  DASHContext *c = s->priv_data;
807  AdaptationSet *as = &c->as[as_index];
808  AVDictionaryEntry *lang, *role;
809  int i;
810 
811  avio_printf(out, "\t\t<AdaptationSet id=\"%d\" contentType=\"%s\" startWithSAP=\"1\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
812  as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
814  avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
816  avio_printf(out, " frameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
817  if (as->media_type == AVMEDIA_TYPE_VIDEO) {
818  avio_printf(out, " maxWidth=\"%d\" maxHeight=\"%d\"", as->max_width, as->max_height);
819  avio_printf(out, " par=\"%d:%d\"", as->par.num, as->par.den);
820  }
821  lang = av_dict_get(as->metadata, "language", NULL, 0);
822  if (lang)
823  avio_printf(out, " lang=\"%s\"", lang->value);
824  avio_printf(out, ">\n");
825 
826  if (!final && c->ldash && as->max_frag_duration && !(c->profile & MPD_PROFILE_DVB))
827  avio_printf(out, "\t\t\t<Resync dT=\"%"PRId64"\" type=\"0\"/>\n", as->max_frag_duration);
828  if (as->trick_idx >= 0)
829  avio_printf(out, "\t\t\t<EssentialProperty id=\"%d\" schemeIdUri=\"http://dashif.org/guidelines/trickmode\" value=\"%d\"/>\n", as->id, as->trick_idx);
830  role = av_dict_get(as->metadata, "role", NULL, 0);
831  if (role)
832  avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
833  if (as->descriptor)
834  avio_printf(out, "\t\t\t%s\n", as->descriptor);
835  for (i = 0; i < s->nb_streams; i++) {
836  AVStream *st = s->streams[i];
837  OutputStream *os = &c->streams[i];
838  char bandwidth_str[64] = {'\0'};
839 
840  if (os->as_idx - 1 != as_index)
841  continue;
842 
843  if (os->bit_rate > 0)
844  snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"", os->bit_rate);
845  else if (final) {
846  int average_bit_rate = os->pos * 8 * AV_TIME_BASE / c->total_duration;
847  snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"", average_bit_rate);
848  } else if (os->first_segment_bit_rate > 0)
849  snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"", os->first_segment_bit_rate);
850 
851  if (as->media_type == AVMEDIA_TYPE_VIDEO) {
852  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
853  i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
855  avio_printf(out, " scanType=\"unknown\"");
856  else if (st->codecpar->field_order != AV_FIELD_PROGRESSIVE)
857  avio_printf(out, " scanType=\"interlaced\"");
858  avio_printf(out, " sar=\"%d:%d\"", os->sar.num, os->sar.den);
859  if (st->avg_frame_rate.num && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0)
860  avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
861  if (as->trick_idx >= 0) {
862  AdaptationSet *tas = &c->as[as->trick_idx];
863  if (!as->ambiguous_frame_rate && !tas->ambiguous_frame_rate)
864  avio_printf(out, " maxPlayoutRate=\"%d\"", FFMAX((int)av_q2d(av_div_q(tas->min_frame_rate, as->min_frame_rate)), 1));
865  }
866  if (!os->coding_dependency)
867  avio_printf(out, " codingDependency=\"false\"");
868  avio_printf(out, ">\n");
869  } else {
870  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
871  i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->sample_rate);
872  avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
873  s->streams[i]->codecpar->channels);
874  }
875  if (!final && c->write_prft && os->producer_reference_time_str[0]) {
876  avio_printf(out, "\t\t\t\t<ProducerReferenceTime id=\"%d\" inband=\"true\" type=\"%s\" wallClockTime=\"%s\" presentationTime=\"%"PRId64"\">\n",
877  i, os->producer_reference_time.flags ? "captured" : "encoder", os->producer_reference_time_str, c->presentation_time_offset);
878  avio_printf(out, "\t\t\t\t\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
879  avio_printf(out, "\t\t\t\t</ProducerReferenceTime>\n");
880  }
881  if (!final && c->ldash && os->gop_size && os->frag_type != FRAG_TYPE_NONE && !(c->profile & MPD_PROFILE_DVB) &&
883  avio_printf(out, "\t\t\t\t<Resync dT=\"%"PRId64"\" type=\"1\"/>\n", os->gop_size);
884  output_segment_list(os, out, s, i, final);
885  avio_printf(out, "\t\t\t</Representation>\n");
886  }
887  avio_printf(out, "\t\t</AdaptationSet>\n");
888 
889  return 0;
890 }
891 
893 {
894  DASHContext *c = s->priv_data;
895  void *mem;
896 
897  if (c->profile & MPD_PROFILE_DVB && (c->nb_as + 1) > 16) {
898  av_log(s, AV_LOG_ERROR, "DVB-DASH profile allows a max of 16 Adaptation Sets\n");
899  return AVERROR(EINVAL);
900  }
901  mem = av_realloc(c->as, sizeof(*c->as) * (c->nb_as + 1));
902  if (!mem)
903  return AVERROR(ENOMEM);
904  c->as = mem;
905  ++c->nb_as;
906 
907  *as = &c->as[c->nb_as - 1];
908  memset(*as, 0, sizeof(**as));
909  (*as)->media_type = type;
910  (*as)->frag_type = -1;
911  (*as)->trick_idx = -1;
912 
913  return 0;
914 }
915 
916 static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
917 {
918  DASHContext *c = s->priv_data;
919  AdaptationSet *as = &c->as[as_idx - 1];
920  OutputStream *os = &c->streams[i];
921 
922  if (as->media_type != s->streams[i]->codecpar->codec_type) {
923  av_log(s, AV_LOG_ERROR, "Codec type of stream %d doesn't match AdaptationSet's media type\n", i);
924  return AVERROR(EINVAL);
925  } else if (os->as_idx) {
926  av_log(s, AV_LOG_ERROR, "Stream %d is already assigned to an AdaptationSet\n", i);
927  return AVERROR(EINVAL);
928  }
929  if (c->profile & MPD_PROFILE_DVB && (as->nb_streams + 1) > 16) {
930  av_log(s, AV_LOG_ERROR, "DVB-DASH profile allows a max of 16 Representations per Adaptation Set\n");
931  return AVERROR(EINVAL);
932  }
933  os->as_idx = as_idx;
934  ++as->nb_streams;
935 
936  return 0;
937 }
938 
940 {
941  DASHContext *c = s->priv_data;
942  const char *p = c->adaptation_sets;
943  enum { new_set, parse_default, parsing_streams, parse_seg_duration, parse_frag_duration } state;
944  AdaptationSet *as;
945  int i, n, ret;
946 
947  // default: one AdaptationSet for each stream
948  if (!p) {
949  for (i = 0; i < s->nb_streams; i++) {
950  if ((ret = add_adaptation_set(s, &as, s->streams[i]->codecpar->codec_type)) < 0)
951  return ret;
952  as->id = i;
953 
954  c->streams[i].as_idx = c->nb_as;
955  ++as->nb_streams;
956  }
957  goto end;
958  }
959 
960  // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
961  // option id=0,descriptor=descriptor_str,streams=0,1,2 and so on
962  // option id=0,seg_duration=2.5,frag_duration=0.5,streams=0,1,2
963  // id=1,trick_id=0,seg_duration=10,frag_type=none,streams=3 and so on
964  // descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015
965  // descriptor_str should be a self-closing xml tag.
966  // seg_duration and frag_duration have the same syntax as the global options of
967  // the same name, and the former have precedence over them if set.
968  state = new_set;
969  while (*p) {
970  if (*p == ' ') {
971  p++;
972  continue;
973  } else if (state == new_set && av_strstart(p, "id=", &p)) {
974  char id_str[10], *end_str;
975 
976  n = strcspn(p, ",");
977  snprintf(id_str, sizeof(id_str), "%.*s", n, p);
978 
979  i = strtol(id_str, &end_str, 10);
980  if (id_str == end_str || i < 0 || i > c->nb_as) {
981  av_log(s, AV_LOG_ERROR, "\"%s\" is not a valid value for an AdaptationSet id\n", id_str);
982  return AVERROR(EINVAL);
983  }
984 
985  if ((ret = add_adaptation_set(s, &as, AVMEDIA_TYPE_UNKNOWN)) < 0)
986  return ret;
987  as->id = i;
988 
989  p += n;
990  if (*p)
991  p++;
992  state = parse_default;
993  } else if (state != new_set && av_strstart(p, "seg_duration=", &p)) {
994  state = parse_seg_duration;
995  } else if (state != new_set && av_strstart(p, "frag_duration=", &p)) {
996  state = parse_frag_duration;
997  } else if (state == parse_seg_duration || state == parse_frag_duration) {
998  char str[32];
999  int64_t usecs = 0;
1000 
1001  n = strcspn(p, ",");
1002  snprintf(str, sizeof(str), "%.*s", n, p);
1003  p += n;
1004  if (*p)
1005  p++;
1006 
1007  ret = av_parse_time(&usecs, str, 1);
1008  if (ret < 0) {
1009  av_log(s, AV_LOG_ERROR, "Unable to parse option value \"%s\" as duration\n", str);
1010  return ret;
1011  }
1012 
1013  if (state == parse_seg_duration)
1014  as->seg_duration = usecs;
1015  else
1016  as->frag_duration = usecs;
1017  state = parse_default;
1018  } else if (state != new_set && av_strstart(p, "frag_type=", &p)) {
1019  char type_str[16];
1020 
1021  n = strcspn(p, ",");
1022  snprintf(type_str, sizeof(type_str), "%.*s", n, p);
1023  p += n;
1024  if (*p)
1025  p++;
1026 
1027  if (!strcmp(type_str, "duration"))
1029  else if (!strcmp(type_str, "pframes"))
1031  else if (!strcmp(type_str, "every_frame"))
1033  else if (!strcmp(type_str, "none"))
1034  as->frag_type = FRAG_TYPE_NONE;
1035  else {
1036  av_log(s, AV_LOG_ERROR, "Unable to parse option value \"%s\" as fragment type\n", type_str);
1037  return ret;
1038  }
1039  state = parse_default;
1040  } else if (state != new_set && av_strstart(p, "descriptor=", &p)) {
1041  n = strcspn(p, ">") + 1; //followed by one comma, so plus 1
1042  if (n < strlen(p)) {
1043  as->descriptor = av_strndup(p, n);
1044  } else {
1045  av_log(s, AV_LOG_ERROR, "Parse error, descriptor string should be a self-closing xml tag\n");
1046  return AVERROR(EINVAL);
1047  }
1048  p += n;
1049  if (*p)
1050  p++;
1051  state = parse_default;
1052  } else if ((state != new_set) && av_strstart(p, "trick_id=", &p)) {
1053  char trick_id_str[10], *end_str;
1054 
1055  n = strcspn(p, ",");
1056  snprintf(trick_id_str, sizeof(trick_id_str), "%.*s", n, p);
1057  p += n;
1058 
1059  as->trick_idx = strtol(trick_id_str, &end_str, 10);
1060  if (trick_id_str == end_str || as->trick_idx < 0)
1061  return AVERROR(EINVAL);
1062 
1063  if (*p)
1064  p++;
1065  state = parse_default;
1066  } else if ((state != new_set) && av_strstart(p, "streams=", &p)) { //descriptor and durations are optional
1067  state = parsing_streams;
1068  } else if (state == parsing_streams) {
1069  AdaptationSet *as = &c->as[c->nb_as - 1];
1070  char idx_str[8], *end_str;
1071 
1072  n = strcspn(p, " ,");
1073  snprintf(idx_str, sizeof(idx_str), "%.*s", n, p);
1074  p += n;
1075 
1076  // if value is "a" or "v", map all streams of that type
1077  if (as->media_type == AVMEDIA_TYPE_UNKNOWN && (idx_str[0] == 'v' || idx_str[0] == 'a')) {
1078  enum AVMediaType type = (idx_str[0] == 'v') ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
1079  av_log(s, AV_LOG_DEBUG, "Map all streams of type %s\n", idx_str);
1080 
1081  for (i = 0; i < s->nb_streams; i++) {
1082  if (s->streams[i]->codecpar->codec_type != type)
1083  continue;
1084 
1085  as->media_type = s->streams[i]->codecpar->codec_type;
1086 
1087  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
1088  return ret;
1089  }
1090  } else { // select single stream
1091  i = strtol(idx_str, &end_str, 10);
1092  if (idx_str == end_str || i < 0 || i >= s->nb_streams) {
1093  av_log(s, AV_LOG_ERROR, "Selected stream \"%s\" not found!\n", idx_str);
1094  return AVERROR(EINVAL);
1095  }
1096  av_log(s, AV_LOG_DEBUG, "Map stream %d\n", i);
1097 
1098  if (as->media_type == AVMEDIA_TYPE_UNKNOWN) {
1099  as->media_type = s->streams[i]->codecpar->codec_type;
1100  }
1101 
1102  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
1103  return ret;
1104  }
1105 
1106  if (*p == ' ')
1107  state = new_set;
1108  if (*p)
1109  p++;
1110  } else {
1111  return AVERROR(EINVAL);
1112  }
1113  }
1114 
1115 end:
1116  // check for unassigned streams
1117  for (i = 0; i < s->nb_streams; i++) {
1118  OutputStream *os = &c->streams[i];
1119  if (!os->as_idx) {
1120  av_log(s, AV_LOG_ERROR, "Stream %d is not mapped to an AdaptationSet\n", i);
1121  return AVERROR(EINVAL);
1122  }
1123  }
1124 
1125  // check references for trick mode AdaptationSet
1126  for (i = 0; i < c->nb_as; i++) {
1127  as = &c->as[i];
1128  if (as->trick_idx < 0)
1129  continue;
1130  for (n = 0; n < c->nb_as; n++) {
1131  if (c->as[n].id == as->trick_idx)
1132  break;
1133  }
1134  if (n >= c->nb_as) {
1135  av_log(s, AV_LOG_ERROR, "reference AdaptationSet id \"%d\" not found for trick mode AdaptationSet id \"%d\"\n", as->trick_idx, as->id);
1136  return AVERROR(EINVAL);
1137  }
1138  }
1139 
1140  return 0;
1141 }
1142 
1143 static int write_manifest(AVFormatContext *s, int final)
1144 {
1145  DASHContext *c = s->priv_data;
1146  AVIOContext *out;
1147  char temp_filename[1024];
1148  int ret, i;
1149  const char *proto = avio_find_protocol_name(s->url);
1150  int use_rename = proto && !strcmp(proto, "file");
1151  static unsigned int warned_non_file = 0;
1152  AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
1153  AVDictionary *opts = NULL;
1154 
1155  if (!use_rename && !warned_non_file++)
1156  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
1157 
1158  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url);
1159  set_http_options(&opts, c);
1160  ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts);
1161  av_dict_free(&opts);
1162  if (ret < 0) {
1163  return handle_io_open_error(s, ret, temp_filename);
1164  }
1165  out = c->mpd_out;
1166  avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
1167  avio_printf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
1168  "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
1169  "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
1170  "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
1171  "\tprofiles=\"");
1172  if (c->profile & MPD_PROFILE_DASH)
1173  avio_printf(out, "%s%s", "urn:mpeg:dash:profile:isoff-live:2011", c->profile & MPD_PROFILE_DVB ? "," : "\"\n");
1174  if (c->profile & MPD_PROFILE_DVB)
1175  avio_printf(out, "%s", "urn:dvb:dash:profile:dvb-dash:2014\"\n");
1176  avio_printf(out, "\ttype=\"%s\"\n",
1177  final ? "static" : "dynamic");
1178  if (final) {
1179  avio_printf(out, "\tmediaPresentationDuration=\"");
1180  write_time(out, c->total_duration);
1181  avio_printf(out, "\"\n");
1182  } else {
1183  int64_t update_period = c->last_duration / AV_TIME_BASE;
1184  char now_str[100];
1185  if (c->use_template && !c->use_timeline)
1186  update_period = 500;
1187  avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period);
1188  if (!c->ldash)
1189  avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE);
1190  if (c->availability_start_time[0])
1191  avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time);
1192  format_date(now_str, sizeof(now_str), av_gettime());
1193  if (now_str[0])
1194  avio_printf(out, "\tpublishTime=\"%s\"\n", now_str);
1195  if (c->window_size && c->use_template) {
1196  avio_printf(out, "\ttimeShiftBufferDepth=\"");
1197  write_time(out, c->last_duration * c->window_size);
1198  avio_printf(out, "\"\n");
1199  }
1200  }
1201  avio_printf(out, "\tmaxSegmentDuration=\"");
1203  avio_printf(out, "\"\n");
1204  avio_printf(out, "\tminBufferTime=\"");
1205  write_time(out, c->ldash && c->max_gop_size ? c->max_gop_size : c->last_duration * 2);
1206  avio_printf(out, "\">\n");
1207  avio_printf(out, "\t<ProgramInformation>\n");
1208  if (title) {
1209  char *escaped = xmlescape(title->value);
1210  avio_printf(out, "\t\t<Title>%s</Title>\n", escaped);
1211  av_free(escaped);
1212  }
1213  avio_printf(out, "\t</ProgramInformation>\n");
1214 
1215  avio_printf(out, "\t<ServiceDescription id=\"0\">\n");
1216  if (!final && c->target_latency && c->target_latency_refid >= 0) {
1217  avio_printf(out, "\t\t<Latency target=\"%"PRId64"\"", c->target_latency / 1000);
1218  if (s->nb_streams > 1)
1219  avio_printf(out, " referenceId=\"%d\"", c->target_latency_refid);
1220  avio_printf(out, "/>\n");
1221  }
1222  if (av_cmp_q(c->min_playback_rate, (AVRational) {1, 1}) ||
1223  av_cmp_q(c->max_playback_rate, (AVRational) {1, 1}))
1224  avio_printf(out, "\t\t<PlaybackRate min=\"%.2f\" max=\"%.2f\"/>\n",
1226  avio_printf(out, "\t</ServiceDescription>\n");
1227 
1228  if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) {
1229  OutputStream *os = &c->streams[0];
1230  int start_index = FFMAX(os->nb_segments - c->window_size, 0);
1231  int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q);
1232  avio_printf(out, "\t<Period id=\"0\" start=\"");
1233  write_time(out, start_time);
1234  avio_printf(out, "\">\n");
1235  } else {
1236  avio_printf(out, "\t<Period id=\"0\" start=\"PT0.0S\">\n");
1237  }
1238 
1239  for (i = 0; i < c->nb_as; i++) {
1240  if ((ret = write_adaptation_set(s, out, i, final)) < 0)
1241  return ret;
1242  }
1243  avio_printf(out, "\t</Period>\n");
1244 
1245  if (c->utc_timing_url)
1246  avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
1247 
1248  avio_printf(out, "</MPD>\n");
1249  avio_flush(out);
1250  dashenc_io_close(s, &c->mpd_out, temp_filename);
1251 
1252  if (use_rename) {
1253  if ((ret = ff_rename(temp_filename, s->url, s)) < 0)
1254  return ret;
1255  }
1256 
1257  if (c->hls_playlist) {
1258  char filename_hls[1024];
1259  const char *audio_group = "A1";
1260  char audio_codec_str[128] = "\0";
1261  int is_default = 1;
1262  int max_audio_bitrate = 0;
1263 
1264  // Publish master playlist only the configured rate
1267  return 0;
1268 
1269  if (*c->dirname)
1270  snprintf(filename_hls, sizeof(filename_hls), "%s%s", c->dirname, c->hls_master_name);
1271  else
1272  snprintf(filename_hls, sizeof(filename_hls), "%s", c->hls_master_name);
1273 
1274  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", filename_hls);
1275 
1276  set_http_options(&opts, c);
1277  ret = dashenc_io_open(s, &c->m3u8_out, temp_filename, &opts);
1278  av_dict_free(&opts);
1279  if (ret < 0) {
1280  return handle_io_open_error(s, ret, temp_filename);
1281  }
1282 
1284 
1285  for (i = 0; i < s->nb_streams; i++) {
1286  char playlist_file[64];
1287  AVStream *st = s->streams[i];
1288  OutputStream *os = &c->streams[i];
1290  continue;
1291  if (os->segment_type != SEGMENT_TYPE_MP4)
1292  continue;
1293  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1294  ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group,
1295  playlist_file, NULL, i, is_default);
1296  max_audio_bitrate = FFMAX(st->codecpar->bit_rate +
1297  os->muxer_overhead, max_audio_bitrate);
1298  if (!av_strnstr(audio_codec_str, os->codec_str, sizeof(audio_codec_str))) {
1299  if (strlen(audio_codec_str))
1300  av_strlcat(audio_codec_str, ",", sizeof(audio_codec_str));
1301  av_strlcat(audio_codec_str, os->codec_str, sizeof(audio_codec_str));
1302  }
1303  is_default = 0;
1304  }
1305 
1306  for (i = 0; i < s->nb_streams; i++) {
1307  char playlist_file[64];
1308  char codec_str[128];
1309  AVStream *st = s->streams[i];
1310  OutputStream *os = &c->streams[i];
1311  char *agroup = NULL;
1312  char *codec_str_ptr = NULL;
1313  int stream_bitrate = os->muxer_overhead;
1314  if (os->bit_rate > 0)
1315  stream_bitrate += os->bit_rate;
1316  else if (final)
1317  stream_bitrate += os->pos * 8 * AV_TIME_BASE / c->total_duration;
1318  else if (os->first_segment_bit_rate > 0)
1319  stream_bitrate += os->first_segment_bit_rate;
1321  continue;
1322  if (os->segment_type != SEGMENT_TYPE_MP4)
1323  continue;
1324  av_strlcpy(codec_str, os->codec_str, sizeof(codec_str));
1325  if (max_audio_bitrate) {
1326  agroup = (char *)audio_group;
1327  stream_bitrate += max_audio_bitrate;
1328  av_strlcat(codec_str, ",", sizeof(codec_str));
1329  av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
1330  }
1331  if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) {
1332  codec_str_ptr = codec_str;
1333  }
1334  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1335  ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
1336  playlist_file, agroup,
1337  codec_str_ptr, NULL, NULL);
1338  }
1339  dashenc_io_close(s, &c->m3u8_out, temp_filename);
1340  if (use_rename)
1341  if ((ret = ff_rename(temp_filename, filename_hls, s)) < 0)
1342  return ret;
1343  c->master_playlist_created = 1;
1344  }
1345 
1346  return 0;
1347 }
1348 
1349 static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
1350 {
1351  AVDictionaryEntry *entry = av_dict_get(src, key, NULL, 0);
1352  if (entry)
1353  av_dict_set(dst, key, entry->value, AV_DICT_DONT_OVERWRITE);
1354  return 0;
1355 }
1356 
1358 {
1359  DASHContext *c = s->priv_data;
1360  int ret = 0, i;
1361  char *ptr;
1362  char basename[1024];
1363 
1364  c->nr_of_streams_to_flush = 0;
1365  if (c->single_file_name)
1366  c->single_file = 1;
1367  if (c->single_file)
1368  c->use_template = 0;
1369 
1370  if (!c->profile) {
1371  av_log(s, AV_LOG_ERROR, "At least one profile must be enabled.\n");
1372  return AVERROR(EINVAL);
1373  }
1374 #if FF_API_DASH_MIN_SEG_DURATION
1375  if (c->min_seg_duration != 5000000) {
1376  av_log(s, AV_LOG_WARNING, "The min_seg_duration option is deprecated and will be removed. Please use the -seg_duration\n");
1377  c->seg_duration = c->min_seg_duration;
1378  }
1379 #endif
1381  av_log(s, AV_LOG_ERROR,
1382  "LHLS is experimental, Please set -strict experimental in order to enable it.\n");
1383  return AVERROR_EXPERIMENTAL;
1384  }
1385 
1386  if (c->lhls && !c->streaming) {
1387  av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as streaming is not enabled\n");
1388  c->lhls = 0;
1389  }
1390 
1391  if (c->lhls && !c->hls_playlist) {
1392  av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as hls_playlist is not enabled\n");
1393  c->lhls = 0;
1394  }
1395 
1396  if (c->ldash && !c->streaming) {
1397  av_log(s, AV_LOG_WARNING, "LDash option will be ignored as streaming is not enabled\n");
1398  c->ldash = 0;
1399  }
1400 
1401  if (c->target_latency && !c->streaming) {
1402  av_log(s, AV_LOG_WARNING, "Target latency option will be ignored as streaming is not enabled\n");
1403  c->target_latency = 0;
1404  }
1405 
1406  if (c->global_sidx && !c->single_file) {
1407  av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as single_file is not enabled\n");
1408  c->global_sidx = 0;
1409  }
1410 
1411  if (c->global_sidx && c->streaming) {
1412  av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as streaming is enabled\n");
1413  c->global_sidx = 0;
1414  }
1415  if (c->frag_type == FRAG_TYPE_NONE && c->streaming) {
1416  av_log(s, AV_LOG_VERBOSE, "Changing frag_type from none to every_frame as streaming is enabled\n");
1418  }
1419 
1420  if (c->write_prft < 0) {
1421  c->write_prft = c->ldash;
1422  if (c->ldash)
1423  av_log(s, AV_LOG_VERBOSE, "Enabling Producer Reference Time element for Low Latency mode\n");
1424  }
1425 
1426  if (c->write_prft && !c->utc_timing_url) {
1427  av_log(s, AV_LOG_WARNING, "Producer Reference Time element option will be ignored as utc_timing_url is not set\n");
1428  c->write_prft = 0;
1429  }
1430 
1431  if (c->write_prft && !c->streaming) {
1432  av_log(s, AV_LOG_WARNING, "Producer Reference Time element option will be ignored as streaming is not enabled\n");
1433  c->write_prft = 0;
1434  }
1435 
1436  if (c->ldash && !c->write_prft) {
1437  av_log(s, AV_LOG_WARNING, "Low Latency mode enabled without Producer Reference Time element option! Resulting manifest may not be complaint\n");
1438  }
1439 
1440  if (c->target_latency && !c->write_prft) {
1441  av_log(s, AV_LOG_WARNING, "Target latency option will be ignored as Producer Reference Time element will not be written\n");
1442  c->target_latency = 0;
1443  }
1444 
1445  if (av_cmp_q(c->max_playback_rate, c->min_playback_rate) < 0) {
1446  av_log(s, AV_LOG_WARNING, "Minimum playback rate value is higer than the Maximum. Both will be ignored\n");
1447  c->min_playback_rate = c->max_playback_rate = (AVRational) {1, 1};
1448  }
1449 
1450  av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
1451  ptr = strrchr(c->dirname, '/');
1452  if (ptr) {
1453  av_strlcpy(basename, &ptr[1], sizeof(basename));
1454  ptr[1] = '\0';
1455  } else {
1456  c->dirname[0] = '\0';
1457  av_strlcpy(basename, s->url, sizeof(basename));
1458  }
1459 
1460  ptr = strrchr(basename, '.');
1461  if (ptr)
1462  *ptr = '\0';
1463 
1464  c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
1465  if (!c->streams)
1466  return AVERROR(ENOMEM);
1467 
1468  if ((ret = parse_adaptation_sets(s)) < 0)
1469  return ret;
1470 
1471  if ((ret = init_segment_types(s)) < 0)
1472  return ret;
1473 
1474  for (i = 0; i < s->nb_streams; i++) {
1475  OutputStream *os = &c->streams[i];
1476  AdaptationSet *as = &c->as[os->as_idx - 1];
1478  AVStream *st;
1479  AVDictionary *opts = NULL;
1480  char filename[1024];
1481 
1482  os->bit_rate = s->streams[i]->codecpar->bit_rate;
1483  if (!os->bit_rate) {
1486  av_log(s, level, "No bit rate set for stream %d\n", i);
1488  return AVERROR(EINVAL);
1489  }
1490 
1491  // copy AdaptationSet language and role from stream metadata
1492  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "language");
1493  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "role");
1494 
1495  if (c->init_seg_name) {
1496  os->init_seg_name = av_strireplace(c->init_seg_name, "$ext$", os->extension_name);
1497  if (!os->init_seg_name)
1498  return AVERROR(ENOMEM);
1499  }
1500  if (c->media_seg_name) {
1502  if (!os->media_seg_name)
1503  return AVERROR(ENOMEM);
1504  }
1505  if (c->single_file_name) {
1507  if (!os->single_file_name)
1508  return AVERROR(ENOMEM);
1509  }
1510 
1511  if (os->segment_type == SEGMENT_TYPE_WEBM) {
1512  if ((!c->single_file && check_file_extension(os->init_seg_name, os->format_name) != 0) ||
1513  (!c->single_file && check_file_extension(os->media_seg_name, os->format_name) != 0) ||
1516  "One or many segment file names doesn't end with .webm. "
1517  "Override -init_seg_name and/or -media_seg_name and/or "
1518  "-single_file_name to end with the extension .webm\n");
1519  }
1520  if (c->streaming) {
1521  // Streaming not supported as matroskaenc buffers internally before writing the output
1522  av_log(s, AV_LOG_WARNING, "One or more streams in WebM output format. Streaming option will be ignored\n");
1523  c->streaming = 0;
1524  }
1525  }
1526 
1527  os->ctx = ctx = avformat_alloc_context();
1528  if (!ctx)
1529  return AVERROR(ENOMEM);
1530 
1532  if (!ctx->oformat)
1533  return AVERROR_MUXER_NOT_FOUND;
1535  ctx->opaque = s->opaque;
1536  ctx->io_close = s->io_close;
1537  ctx->io_open = s->io_open;
1539 
1540  if (!(st = avformat_new_stream(ctx, NULL)))
1541  return AVERROR(ENOMEM);
1544  st->time_base = s->streams[i]->time_base;
1547  ctx->flags = s->flags;
1548 
1549  os->parser = av_parser_init(st->codecpar->codec_id);
1550  if (os->parser) {
1552  if (!os->parser_avctx)
1553  return AVERROR(ENOMEM);
1555  if (ret < 0)
1556  return ret;
1557  // We only want to parse frame headers
1559  }
1560 
1561  if (c->single_file) {
1562  if (os->single_file_name)
1563  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);
1564  else
1565  snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.%s", basename, i, os->format_name);
1566  } else {
1567  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->init_seg_name, i, 0, os->bit_rate, 0);
1568  }
1569  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
1570  set_http_options(&opts, c);
1571  if (!c->single_file) {
1572  if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0)
1573  return ret;
1574  ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts);
1575  } else {
1576  ctx->url = av_strdup(filename);
1577  ret = avio_open2(&ctx->pb, filename, AVIO_FLAG_WRITE, NULL, &opts);
1578  }
1579  av_dict_free(&opts);
1580  if (ret < 0)
1581  return ret;
1582  os->init_start_pos = 0;
1583 
1584  av_dict_copy(&opts, c->format_options, 0);
1585  if (!as->seg_duration)
1586  as->seg_duration = c->seg_duration;
1587  if (!as->frag_duration)
1588  as->frag_duration = c->frag_duration;
1589  if (as->frag_type < 0)
1590  as->frag_type = c->frag_type;
1591  os->seg_duration = as->seg_duration;
1592  os->frag_duration = as->frag_duration;
1593  os->frag_type = as->frag_type;
1594 
1596 
1597  if (c->profile & MPD_PROFILE_DVB && (os->seg_duration > 15000000 || os->seg_duration < 960000)) {
1598  av_log(s, AV_LOG_ERROR, "Segment duration %"PRId64" is outside the allowed range for DVB-DASH profile\n", os->seg_duration);
1599  return AVERROR(EINVAL);
1600  }
1601 
1602  if (os->frag_type == FRAG_TYPE_DURATION && !os->frag_duration) {
1603  av_log(s, AV_LOG_WARNING, "frag_type set to duration for stream %d but no frag_duration set\n", i);
1605  }
1606  if (os->frag_type == FRAG_TYPE_DURATION && os->frag_duration > os->seg_duration) {
1607  av_log(s, AV_LOG_ERROR, "Fragment duration %"PRId64" is longer than Segment duration %"PRId64"\n", os->frag_duration, os->seg_duration);
1608  return AVERROR(EINVAL);
1609  }
1610  if (os->frag_type == FRAG_TYPE_PFRAMES && (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || !os->parser)) {
1611  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !os->parser)
1612  av_log(s, AV_LOG_WARNING, "frag_type set to P-Frame reordering, but no parser found for stream %d\n", i);
1614  }
1615  if (os->frag_type != FRAG_TYPE_PFRAMES && as->trick_idx < 0)
1616  // Set this now if a parser isn't used
1617  os->coding_dependency = 1;
1618 
1619  if (os->segment_type == SEGMENT_TYPE_MP4) {
1620  if (c->streaming)
1621  // skip_sidx : Reduce bitrate overhead
1622  // skip_trailer : Avoids growing memory usage with time
1623  av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_sidx+skip_trailer", AV_DICT_APPEND);
1624  else {
1625  if (c->global_sidx)
1626  av_dict_set(&opts, "movflags", "+dash+delay_moov+global_sidx+skip_trailer", AV_DICT_APPEND);
1627  else
1628  av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_trailer", AV_DICT_APPEND);
1629  }
1630  if (os->frag_type == FRAG_TYPE_EVERY_FRAME)
1631  av_dict_set(&opts, "movflags", "+frag_every_frame", AV_DICT_APPEND);
1632  else
1633  av_dict_set(&opts, "movflags", "+frag_custom", AV_DICT_APPEND);
1634  if (os->frag_type == FRAG_TYPE_DURATION)
1635  av_dict_set_int(&opts, "frag_duration", os->frag_duration, 0);
1636  if (c->write_prft)
1637  av_dict_set(&opts, "write_prft", "wallclock", 0);
1638  } else {
1639  av_dict_set_int(&opts, "cluster_time_limit", c->seg_duration / 1000, 0);
1640  av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
1641  av_dict_set_int(&opts, "dash", 1, 0);
1642  av_dict_set_int(&opts, "dash_track_number", i + 1, 0);
1643  av_dict_set_int(&opts, "live", 1, 0);
1644  }
1645  ret = avformat_init_output(ctx, &opts);
1646  av_dict_free(&opts);
1647  if (ret < 0)
1648  return ret;
1649  os->ctx_inited = 1;
1650  avio_flush(ctx->pb);
1651 
1652  av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename);
1653 
1654  s->streams[i]->time_base = st->time_base;
1655  // If the muxer wants to shift timestamps, request to have them shifted
1656  // already before being handed to this muxer, so we don't have mismatches
1657  // between the MPD and the actual segments.
1659  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1660  AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
1661  AVRational par;
1662  if (avg_frame_rate.num > 0) {
1663  if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0)
1664  as->min_frame_rate = avg_frame_rate;
1665  if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0)
1666  as->max_frame_rate = avg_frame_rate;
1667  } else {
1668  as->ambiguous_frame_rate = 1;
1669  }
1670 
1671  if (st->codecpar->width > as->max_width)
1672  as->max_width = st->codecpar->width;
1673  if (st->codecpar->height > as->max_height)
1674  as->max_height = st->codecpar->height;
1675 
1676  if (st->sample_aspect_ratio.num)
1677  os->sar = st->sample_aspect_ratio;
1678  else
1679  os->sar = (AVRational){1,1};
1680  av_reduce(&par.num, &par.den,
1681  st->codecpar->width * (int64_t)os->sar.num,
1682  st->codecpar->height * (int64_t)os->sar.den,
1683  1024 * 1024);
1684 
1685  if (as->par.num && av_cmp_q(par, as->par)) {
1686  av_log(s, AV_LOG_ERROR, "Conflicting stream par values in Adaptation Set %d\n", os->as_idx);
1687  return AVERROR(EINVAL);
1688  }
1689  as->par = par;
1690 
1691  c->has_video = 1;
1692  }
1693 
1694  set_codec_str(s, st->codecpar, &st->avg_frame_rate, os->codec_str,
1695  sizeof(os->codec_str));
1696  os->first_pts = AV_NOPTS_VALUE;
1697  os->max_pts = AV_NOPTS_VALUE;
1698  os->last_dts = AV_NOPTS_VALUE;
1699  os->segment_index = 1;
1700 
1703  }
1704 
1705  if (!c->has_video && c->seg_duration <= 0) {
1706  av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");
1707  return AVERROR(EINVAL);
1708  }
1709  if (!c->has_video && c->frag_type == FRAG_TYPE_PFRAMES)
1710  av_log(s, AV_LOG_WARNING, "no video stream and P-frame fragmentation set\n");
1711 
1712  c->nr_of_streams_flushed = 0;
1713  c->target_latency_refid = -1;
1714 
1715  return 0;
1716 }
1717 
1719 {
1720  DASHContext *c = s->priv_data;
1721  int i, ret;
1722  for (i = 0; i < s->nb_streams; i++) {
1723  OutputStream *os = &c->streams[i];
1724  if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
1725  return ret;
1726 
1727  // Flush init segment
1728  // Only for WebM segment, since for mp4 delay_moov is set and
1729  // the init segment is thus flushed after the first packets.
1730  if (os->segment_type == SEGMENT_TYPE_WEBM &&
1731  (ret = flush_init_segment(s, os)) < 0)
1732  return ret;
1733  }
1734  return ret;
1735 }
1736 
1737 static int add_segment(OutputStream *os, const char *file,
1738  int64_t time, int64_t duration,
1739  int64_t start_pos, int64_t range_length,
1740  int64_t index_length, int next_exp_index)
1741 {
1742  int err;
1743  Segment *seg;
1744  if (os->nb_segments >= os->segments_size) {
1745  os->segments_size = (os->segments_size + 1) * 2;
1746  if ((err = av_reallocp_array(&os->segments, sizeof(*os->segments),
1747  os->segments_size)) < 0) {
1748  os->segments_size = 0;
1749  os->nb_segments = 0;
1750  return err;
1751  }
1752  }
1753  seg = av_mallocz(sizeof(*seg));
1754  if (!seg)
1755  return AVERROR(ENOMEM);
1756  av_strlcpy(seg->file, file, sizeof(seg->file));
1757  seg->time = time;
1758  seg->duration = duration;
1759  if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
1760  seg->duration += seg->time;
1761  seg->time = 0;
1762  }
1763  seg->start_pos = start_pos;
1764  seg->range_length = range_length;
1765  seg->index_length = index_length;
1766  os->segments[os->nb_segments++] = seg;
1767  os->segment_index++;
1768  //correcting the segment index if it has fallen behind the expected value
1769  if (os->segment_index < next_exp_index) {
1770  av_log(NULL, AV_LOG_WARNING, "Correcting the segment index after file %s: current=%d corrected=%d\n",
1771  file, os->segment_index, next_exp_index);
1772  os->segment_index = next_exp_index;
1773  }
1774  return 0;
1775 }
1776 
1777 static void write_styp(AVIOContext *pb)
1778 {
1779  avio_wb32(pb, 24);
1780  ffio_wfourcc(pb, "styp");
1781  ffio_wfourcc(pb, "msdh");
1782  avio_wb32(pb, 0); /* minor */
1783  ffio_wfourcc(pb, "msdh");
1784  ffio_wfourcc(pb, "msix");
1785 }
1786 
1787 static void find_index_range(AVFormatContext *s, const char *full_path,
1788  int64_t pos, int *index_length)
1789 {
1790  uint8_t buf[8];
1791  AVIOContext *pb;
1792  int ret;
1793 
1794  ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL);
1795  if (ret < 0)
1796  return;
1797  if (avio_seek(pb, pos, SEEK_SET) != pos) {
1798  ff_format_io_close(s, &pb);
1799  return;
1800  }
1801  ret = avio_read(pb, buf, 8);
1802  ff_format_io_close(s, &pb);
1803  if (ret < 8)
1804  return;
1805  if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
1806  return;
1807  *index_length = AV_RB32(&buf[0]);
1808 }
1809 
1811  AVPacket *pkt, AVRational *frame_rate)
1812 {
1813  AVCodecParameters *par = os->ctx->streams[0]->codecpar;
1814  uint8_t *extradata;
1815  int ret, extradata_size;
1816 
1817  if (par->extradata_size)
1818  return 0;
1819 
1820  extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &extradata_size);
1821  if (!extradata_size)
1822  return 0;
1823 
1824  ret = ff_alloc_extradata(par, extradata_size);
1825  if (ret < 0)
1826  return ret;
1827 
1828  memcpy(par->extradata, extradata, extradata_size);
1829 
1830  set_codec_str(s, par, frame_rate, os->codec_str, sizeof(os->codec_str));
1831 
1832  return 0;
1833 }
1834 
1835 static void dashenc_delete_file(AVFormatContext *s, char *filename) {
1836  DASHContext *c = s->priv_data;
1837  int http_base_proto = ff_is_http_proto(filename);
1838 
1839  if (http_base_proto) {
1840  AVIOContext *out = NULL;
1841  AVDictionary *http_opts = NULL;
1842 
1843  set_http_options(&http_opts, c);
1844  av_dict_set(&http_opts, "method", "DELETE", 0);
1845 
1846  if (dashenc_io_open(s, &out, filename, &http_opts) < 0) {
1847  av_log(s, AV_LOG_ERROR, "failed to delete %s\n", filename);
1848  }
1849 
1850  av_dict_free(&http_opts);
1851  ff_format_io_close(s, &out);
1852  } else {
1853  int res = avpriv_io_delete(filename);
1854  if (res < 0) {
1855  char errbuf[AV_ERROR_MAX_STRING_SIZE];
1856  av_strerror(res, errbuf, sizeof(errbuf));
1857  av_log(s, (res == AVERROR(ENOENT) ? AV_LOG_WARNING : AV_LOG_ERROR), "failed to delete %s: %s\n", filename, errbuf);
1858  }
1859  }
1860 }
1861 
1863 {
1864  DASHContext *c = s->priv_data;
1865  AVBPrint buf;
1866 
1868 
1869  av_bprintf(&buf, "%s%s", c->dirname, file);
1870  if (!av_bprint_is_complete(&buf)) {
1871  av_bprint_finalize(&buf, NULL);
1872  av_log(s, AV_LOG_WARNING, "Out of memory for filename\n");
1873  return AVERROR(ENOMEM);
1874  }
1875 
1876  dashenc_delete_file(s, buf.str);
1877 
1878  av_bprint_finalize(&buf, NULL);
1879  return 0;
1880 }
1881 
1882 static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
1883 {
1884  for (int i = 0; i < remove_count; ++i) {
1886 
1887  // Delete the segment regardless of whether the file was successfully deleted
1888  av_free(os->segments[i]);
1889  }
1890 
1891  os->nb_segments -= remove_count;
1892  memmove(os->segments, os->segments + remove_count, os->nb_segments * sizeof(*os->segments));
1893 }
1894 
1895 static int dash_flush(AVFormatContext *s, int final, int stream)
1896 {
1897  DASHContext *c = s->priv_data;
1898  int i, ret = 0;
1899 
1900  const char *proto = avio_find_protocol_name(s->url);
1901  int use_rename = proto && !strcmp(proto, "file");
1902 
1903  int cur_flush_segment_index = 0, next_exp_index = -1;
1904  if (stream >= 0) {
1905  cur_flush_segment_index = c->streams[stream].segment_index;
1906 
1907  //finding the next segment's expected index, based on the current pts value
1908  if (c->use_template && !c->use_timeline && c->index_correction &&
1909  c->streams[stream].last_pts != AV_NOPTS_VALUE &&
1910  c->streams[stream].first_pts != AV_NOPTS_VALUE) {
1911  int64_t pts_diff = av_rescale_q(c->streams[stream].last_pts -
1912  c->streams[stream].first_pts,
1913  s->streams[stream]->time_base,
1914  AV_TIME_BASE_Q);
1915  next_exp_index = (pts_diff / c->streams[stream].seg_duration) + 1;
1916  }
1917  }
1918 
1919  for (i = 0; i < s->nb_streams; i++) {
1920  OutputStream *os = &c->streams[i];
1921  AVStream *st = s->streams[i];
1922  int range_length, index_length = 0;
1923  int64_t duration;
1924 
1925  if (!os->packets_written)
1926  continue;
1927 
1928  // Flush the single stream that got a keyframe right now.
1929  // Flush all audio streams as well, in sync with video keyframes,
1930  // but not the other video streams.
1931  if (stream >= 0 && i != stream) {
1932  if (s->streams[stream]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
1934  continue;
1936  continue;
1937  // Make sure we don't flush audio streams multiple times, when
1938  // all video streams are flushed one at a time.
1939  if (c->has_video && os->segment_index > cur_flush_segment_index)
1940  continue;
1941  }
1942 
1943  if (c->single_file)
1944  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile);
1945 
1946  ret = flush_dynbuf(c, os, &range_length);
1947  if (ret < 0)
1948  break;
1949  os->packets_written = 0;
1950 
1951  if (c->single_file) {
1952  find_index_range(s, os->full_path, os->pos, &index_length);
1953  } else {
1954  dashenc_io_close(s, &os->out, os->temp_path);
1955 
1956  if (use_rename) {
1957  ret = ff_rename(os->temp_path, os->full_path, os->ctx);
1958  if (ret < 0)
1959  break;
1960  }
1961  }
1962 
1963  duration = av_rescale_q(os->max_pts - os->start_pts, st->time_base, AV_TIME_BASE_Q);
1964  os->last_duration = FFMAX(os->last_duration, duration);
1965 
1966  if (!os->muxer_overhead && os->max_pts > os->start_pts)
1967  os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) *
1968  8 * AV_TIME_BASE) / duration;
1969  os->total_pkt_size = 0;
1970  os->total_pkt_duration = 0;
1971 
1972  if (!os->bit_rate && !os->first_segment_bit_rate) {
1973  os->first_segment_bit_rate = (int64_t) range_length * 8 * AV_TIME_BASE / duration;
1974  }
1975  add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index);
1976  av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path);
1977 
1978  os->pos += range_length;
1979  }
1980 
1981  if (c->window_size) {
1982  for (i = 0; i < s->nb_streams; i++) {
1983  OutputStream *os = &c->streams[i];
1984  int remove_count = os->nb_segments - c->window_size - c->extra_window_size;
1985  if (remove_count > 0)
1986  dashenc_delete_media_segments(s, os, remove_count);
1987  }
1988  }
1989 
1990  if (final) {
1991  for (i = 0; i < s->nb_streams; i++) {
1992  OutputStream *os = &c->streams[i];
1993  if (os->ctx && os->ctx_inited) {
1994  int64_t file_size = avio_tell(os->ctx->pb);
1995  av_write_trailer(os->ctx);
1996  if (c->global_sidx) {
1997  int j, start_index, start_number;
1998  int64_t sidx_size = avio_tell(os->ctx->pb) - file_size;
1999  get_start_index_number(os, c, &start_index, &start_number);
2000  if (start_index >= os->nb_segments ||
2002  continue;
2003  os->init_range_length += sidx_size;
2004  for (j = start_index; j < os->nb_segments; j++) {
2005  Segment *seg = os->segments[j];
2006  seg->start_pos += sidx_size;
2007  }
2008  }
2009 
2010  }
2011  }
2012  }
2013  if (ret >= 0) {
2014  if (c->has_video && !final) {
2015  c->nr_of_streams_flushed++;
2017  return ret;
2018 
2019  c->nr_of_streams_flushed = 0;
2020  }
2021  ret = write_manifest(s, final);
2022  }
2023  return ret;
2024 }
2025 
2027 {
2028  OutputStream *os = &c->streams[pkt->stream_index];
2030  int side_data_size;
2031 
2032  prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &side_data_size);
2033  if (!prft || side_data_size != sizeof(AVProducerReferenceTime) || (prft->flags && prft->flags != 24)) {
2034  // No encoder generated or user provided capture time AVProducerReferenceTime side data. Instead
2035  // of letting the mov muxer generate one, do it here so we can also use it for the manifest.
2037  sizeof(AVProducerReferenceTime));
2038  if (!prft)
2039  return AVERROR(ENOMEM);
2040  prft->wallclock = av_gettime();
2041  prft->flags = 24;
2042  }
2043  if (os->first_pts == AV_NOPTS_VALUE) {
2044  os->producer_reference_time = *prft;
2045  if (c->target_latency_refid < 0)
2047  }
2048 
2049  return 0;
2050 }
2051 
2053 {
2054  DASHContext *c = s->priv_data;
2055  AVStream *st = s->streams[pkt->stream_index];
2056  OutputStream *os = &c->streams[pkt->stream_index];
2057  AdaptationSet *as = &c->as[os->as_idx - 1];
2058  int64_t seg_end_duration, elapsed_duration;
2059  int ret;
2060 
2061  ret = update_stream_extradata(s, os, pkt, &st->avg_frame_rate);
2062  if (ret < 0)
2063  return ret;
2064 
2065  // Fill in a heuristic guess of the packet duration, if none is available.
2066  // The mp4 muxer will do something similar (for the last packet in a fragment)
2067  // if nothing is set (setting it for the other packets doesn't hurt).
2068  // By setting a nonzero duration here, we can be sure that the mp4 muxer won't
2069  // invoke its heuristic (this doesn't have to be identical to that algorithm),
2070  // so that we know the exact timestamps of fragments.
2071  if (!pkt->duration && os->last_dts != AV_NOPTS_VALUE)
2072  pkt->duration = pkt->dts - os->last_dts;
2073  os->last_dts = pkt->dts;
2074 
2075  // If forcing the stream to start at 0, the mp4 muxer will set the start
2076  // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps.
2077  if (os->first_pts == AV_NOPTS_VALUE &&
2079  pkt->pts -= pkt->dts;
2080  pkt->dts = 0;
2081  }
2082 
2083  if (c->write_prft) {
2084  ret = dash_parse_prft(c, pkt);
2085  if (ret < 0)
2086  return ret;
2087  }
2088 
2089  if (os->first_pts == AV_NOPTS_VALUE) {
2090  os->first_pts = pkt->pts;
2091  }
2092  os->last_pts = pkt->pts;
2093 
2094  if (!c->availability_start_time[0]) {
2095  int64_t start_time_us = av_gettime();
2096  c->start_time_s = start_time_us / 1000000;
2098  sizeof(c->availability_start_time), start_time_us);
2099  }
2100 
2101  if (!os->packets_written)
2102  os->availability_time_offset = 0;
2103 
2104  if (!os->availability_time_offset &&
2105  ((os->frag_type == FRAG_TYPE_DURATION && os->seg_duration != os->frag_duration) ||
2106  (os->frag_type == FRAG_TYPE_EVERY_FRAME && pkt->duration))) {
2107  AdaptationSet *as = &c->as[os->as_idx - 1];
2108  int64_t frame_duration = 0;
2109 
2110  switch (os->frag_type) {
2111  case FRAG_TYPE_DURATION:
2112  frame_duration = os->frag_duration;
2113  break;
2114  case FRAG_TYPE_EVERY_FRAME:
2115  frame_duration = av_rescale_q(pkt->duration, st->time_base, AV_TIME_BASE_Q);
2116  break;
2117  }
2118 
2119  os->availability_time_offset = ((double) os->seg_duration -
2120  frame_duration) / AV_TIME_BASE;
2121  as->max_frag_duration = FFMAX(frame_duration, as->max_frag_duration);
2122  }
2123 
2124  if (c->use_template && !c->use_timeline) {
2125  elapsed_duration = pkt->pts - os->first_pts;
2126  seg_end_duration = (int64_t) os->segment_index * os->seg_duration;
2127  } else {
2128  elapsed_duration = pkt->pts - os->start_pts;
2129  seg_end_duration = os->seg_duration;
2130  }
2131 
2132  if (os->parser &&
2133  (os->frag_type == FRAG_TYPE_PFRAMES ||
2134  as->trick_idx >= 0)) {
2135  // Parse the packets only in scenarios where it's needed
2136  uint8_t *data;
2137  int size;
2139  &data, &size, pkt->data, pkt->size,
2140  pkt->pts, pkt->dts, pkt->pos);
2141 
2143  }
2144 
2145  if (pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
2146  av_compare_ts(elapsed_duration, st->time_base,
2147  seg_end_duration, AV_TIME_BASE_Q) >= 0) {
2148  if (!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
2149  c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
2150  st->time_base,
2151  AV_TIME_BASE_Q);
2152  c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
2153  st->time_base,
2154  AV_TIME_BASE_Q);
2155 
2156  if ((!c->use_timeline || !c->use_template) && os->last_duration) {
2157  if (c->last_duration < os->last_duration*9/10 ||
2158  c->last_duration > os->last_duration*11/10) {
2160  "Segment durations differ too much, enable use_timeline "
2161  "and use_template, or keep a stricter keyframe interval\n");
2162  }
2163  }
2164  }
2165 
2168  sizeof(os->producer_reference_time_str),
2170 
2171  if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0)
2172  return ret;
2173  }
2174 
2175  if (!os->packets_written) {
2176  // If we wrote a previous segment, adjust the start time of the segment
2177  // to the end of the previous one (which is the same as the mp4 muxer
2178  // does). This avoids gaps in the timeline.
2179  if (os->max_pts != AV_NOPTS_VALUE)
2180  os->start_pts = os->max_pts;
2181  else
2182  os->start_pts = pkt->pts;
2183  }
2184  if (os->max_pts == AV_NOPTS_VALUE)
2185  os->max_pts = pkt->pts + pkt->duration;
2186  else
2187  os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
2188 
2189  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
2190  os->frag_type == FRAG_TYPE_PFRAMES &&
2191  os->packets_written) {
2192  av_assert0(os->parser);
2193  if ((os->parser->pict_type == AV_PICTURE_TYPE_P &&
2194  st->codecpar->video_delay &&
2195  !(os->last_flags & AV_PKT_FLAG_KEY)) ||
2196  pkt->flags & AV_PKT_FLAG_KEY) {
2197  ret = av_write_frame(os->ctx, NULL);
2198  if (ret < 0)
2199  return ret;
2200 
2201  if (!os->availability_time_offset) {
2202  int64_t frag_duration = av_rescale_q(os->total_pkt_duration, st->time_base,
2203  AV_TIME_BASE_Q);
2204  os->availability_time_offset = ((double) os->seg_duration -
2205  frag_duration) / AV_TIME_BASE;
2206  as->max_frag_duration = FFMAX(frag_duration, as->max_frag_duration);
2207  }
2208  }
2209  }
2210 
2211  if (pkt->flags & AV_PKT_FLAG_KEY && (os->packets_written || os->nb_segments) && !os->gop_size && as->trick_idx < 0) {
2213  c->max_gop_size = FFMAX(c->max_gop_size, os->gop_size);
2214  }
2215 
2216  if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0)
2217  return ret;
2218 
2219  os->packets_written++;
2220  os->total_pkt_size += pkt->size;
2221  os->total_pkt_duration += pkt->duration;
2222  os->last_flags = pkt->flags;
2223 
2224  if (!os->init_range_length)
2225  flush_init_segment(s, os);
2226 
2227  //open the output context when the first frame of a segment is ready
2228  if (!c->single_file && os->packets_written == 1) {
2229  AVDictionary *opts = NULL;
2230  const char *proto = avio_find_protocol_name(s->url);
2231  int use_rename = proto && !strcmp(proto, "file");
2232  if (os->segment_type == SEGMENT_TYPE_MP4)
2233  write_styp(os->ctx->pb);
2234  os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0';
2235  ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename),
2236  os->media_seg_name, pkt->stream_index,
2237  os->segment_index, os->bit_rate, os->start_pts);
2238  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname,
2239  os->filename);
2240  snprintf(os->temp_path, sizeof(os->temp_path),
2241  use_rename ? "%s.tmp" : "%s", os->full_path);
2242  set_http_options(&opts, c);
2243  ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
2244  av_dict_free(&opts);
2245  if (ret < 0) {
2246  return handle_io_open_error(s, ret, os->temp_path);
2247  }
2248  if (c->lhls) {
2249  char *prefetch_url = use_rename ? NULL : os->filename;
2250  write_hls_media_playlist(os, s, pkt->stream_index, 0, prefetch_url);
2251  }
2252  }
2253 
2254  //write out the data immediately in streaming mode
2255  if (c->streaming && os->segment_type == SEGMENT_TYPE_MP4) {
2256  int len = 0;
2257  uint8_t *buf = NULL;
2258  avio_flush(os->ctx->pb);
2259  len = avio_get_dyn_buf (os->ctx->pb, &buf);
2260  if (os->out) {
2261  avio_write(os->out, buf + os->written_len, len - os->written_len);
2262  avio_flush(os->out);
2263  }
2264  os->written_len = len;
2265  }
2266 
2267  return ret;
2268 }
2269 
2271 {
2272  DASHContext *c = s->priv_data;
2273  int i;
2274 
2275  if (s->nb_streams > 0) {
2276  OutputStream *os = &c->streams[0];
2277  // If no segments have been written so far, try to do a crude
2278  // guess of the segment duration
2279  if (!c->last_duration)
2281  s->streams[0]->time_base,
2282  AV_TIME_BASE_Q);
2284  s->streams[0]->time_base,
2285  AV_TIME_BASE_Q);
2286  }
2287  dash_flush(s, 1, -1);
2288 
2289  if (c->remove_at_exit) {
2290  for (i = 0; i < s->nb_streams; ++i) {
2291  OutputStream *os = &c->streams[i];
2294  if (c->hls_playlist && os->segment_type == SEGMENT_TYPE_MP4) {
2295  char filename[1024];
2296  get_hls_playlist_name(filename, sizeof(filename), c->dirname, i);
2297  dashenc_delete_file(s, filename);
2298  }
2299  }
2300  dashenc_delete_file(s, s->url);
2301 
2302  if (c->hls_playlist && c->master_playlist_created) {
2303  char filename[1024];
2304  snprintf(filename, sizeof(filename), "%s%s", c->dirname, c->hls_master_name);
2305  dashenc_delete_file(s, filename);
2306  }
2307  }
2308 
2309  return 0;
2310 }
2311 
2312 static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
2313 {
2314  DASHContext *c = s->priv_data;
2315  OutputStream *os = &c->streams[avpkt->stream_index];
2316  AVFormatContext *oc = os->ctx;
2317  if (oc->oformat->check_bitstream) {
2318  int ret;
2319  AVPacket pkt = *avpkt;
2320  pkt.stream_index = 0;
2321  ret = oc->oformat->check_bitstream(oc, &pkt);
2322  if (ret == 1) {
2323  AVStream *st = s->streams[avpkt->stream_index];
2324  AVStream *ost = oc->streams[0];
2325  st->internal->bsfc = ost->internal->bsfc;
2326  ost->internal->bsfc = NULL;
2327  }
2328  return ret;
2329  }
2330  return 1;
2331 }
2332 
2333 #define OFFSET(x) offsetof(DASHContext, x)
2334 #define E AV_OPT_FLAG_ENCODING_PARAM
2335 static const AVOption options[] = {
2336  { "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 },
2337  { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
2338  { "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 },
2339 #if FF_API_DASH_MIN_SEG_DURATION
2340  { "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 },
2341 #endif
2342  { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E },
2343  { "frag_duration", "fragment duration (in seconds, fractional value can be set)", OFFSET(frag_duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E },
2344  { "frag_type", "set type of interval for fragments", OFFSET(frag_type), AV_OPT_TYPE_INT, {.i64 = FRAG_TYPE_NONE }, 0, FRAG_TYPE_NB - 1, E, "frag_type"},
2345  { "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE }, 0, UINT_MAX, E, "frag_type"},
2346  { "every_frame", "fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_EVERY_FRAME }, 0, UINT_MAX, E, "frag_type"},
2347  { "duration", "fragment at specific time intervals", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_DURATION }, 0, UINT_MAX, E, "frag_type"},
2348  { "pframes", "fragment at keyframes and following P-Frame reordering (Video only, experimental)", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_PFRAMES }, 0, UINT_MAX, E, "frag_type"},
2349  { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2350  { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
2351  { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
2352  { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2353  { "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 },
2354  { "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 },
2355  { "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 },
2356  { "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 },
2357  { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
2358  { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
2359  { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
2360  { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2361  { "hls_master_name", "HLS master playlist name", OFFSET(hls_master_name), AV_OPT_TYPE_STRING, {.str = "master.m3u8"}, 0, 0, E },
2362  { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2363  { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
2364  { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2365  { "format_options","set list of options for the container format (mp4/webm) used for dash", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
2366  { "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 },
2367  { "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"},
2368  { "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX, E, "segment_type"},
2369  { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX, E, "segment_type"},
2370  { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX, E, "segment_type"},
2371  { "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 },
2372  { "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 },
2373  { "ldash", "Enable Low-latency dash. Constrains the value of a few elements", OFFSET(ldash), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2374  { "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},
2375  { "write_prft", "Write producer reference time element", OFFSET(write_prft), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, E},
2376  { "mpd_profile", "Set profiles. Elements and values used in the manifest may be constrained by them", OFFSET(profile), AV_OPT_TYPE_FLAGS, {.i64 = MPD_PROFILE_DASH }, 0, UINT_MAX, E, "mpd_profile"},
2377  { "dash", "MPEG-DASH ISO Base media file format live profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DASH }, 0, UINT_MAX, E, "mpd_profile"},
2378  { "dvb_dash", "DVB-DASH profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DVB }, 0, UINT_MAX, E, "mpd_profile"},
2379  { "http_opts", "HTTP protocol options", OFFSET(http_opts), AV_OPT_TYPE_DICT, { .str = NULL }, 0, 0, E },
2380  { "target_latency", "Set desired target latency for Low-latency dash", OFFSET(target_latency), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E },
2381  { "min_playback_rate", "Set desired minimum playback rate", OFFSET(min_playback_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 1.0 }, 0.5, 1.5, E },
2382  { "max_playback_rate", "Set desired maximum playback rate", OFFSET(max_playback_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 1.0 }, 0.5, 1.5, E },
2383  { NULL },
2384 };
2385 
2386 static const AVClass dash_class = {
2387  .class_name = "dash muxer",
2388  .item_name = av_default_item_name,
2389  .option = options,
2390  .version = LIBAVUTIL_VERSION_INT,
2391 };
2392 
2394  .name = "dash",
2395  .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
2396  .extensions = "mpd",
2397  .priv_data_size = sizeof(DASHContext),
2398  .audio_codec = AV_CODEC_ID_AAC,
2399  .video_codec = AV_CODEC_ID_H264,
2401  .init = dash_init,
2405  .deinit = dash_free,
2407  .priv_class = &dash_class,
2408 };
#define FF_COMPLIANCE_EXPERIMENTAL
Allow nonstandardized experimental things.
Definition: avcodec.h:1594
SegmentType segment_type
Definition: dashenc.c:119
AVRational min_playback_rate
Definition: dashenc.c:199
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:701
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:1933
#define NULL
Definition: coverity.c:32
enum AVFieldOrder field_order
Video only.
Definition: codec_par.h:141
AVBSFContext * bsfc
bitstream filter to run on stream
Definition: internal.h:159
int last_flags
Definition: dashenc.c:116
Bytestream IO Context.
Definition: avio.h:161
Producer Reference Time data corresponding to the AVProducerReferenceTime struct, usually exported by...
Definition: packet.h:268
int use_timeline
Definition: dashenc.c:157
static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
Definition: dashenc.c:1349
static int init_segment_types(AVFormatContext *s)
Definition: dashenc.c:304
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
AVRational av_div_q(AVRational b, AVRational c)
Divide one rational by another.
Definition: rational.c:88
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1629
static void set_http_options(AVDictionary **options, DASHContext *c)
Definition: dashenc.c:485
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1414
AVOption.
Definition: opt.h:248
static int parse_adaptation_sets(AVFormatContext *s)
Definition: dashenc.c:939
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:134
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
static const AVOption options[]
Definition: dashenc.c:2335
AVIOContext * mpd_out
Definition: dashenc.c:178
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:1190
const char * media_seg_name
Definition: dashenc.c:124
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:375
const char * single_file_name
Definition: dashenc.c:122
int64_t frag_duration
Definition: dashenc.c:154
int ambiguous_frame_rate
Definition: dashenc.c:91
#define AV_DICT_DONT_OVERWRITE
Don&#39;t overwrite existing entries.
Definition: dict.h:79
int range_length
Definition: dashenc.c:75
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
Definition: parseutils.c:587
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int64_t frag_duration
Definition: dashenc.c:111
AVCodecParserContext * parser
Definition: dashenc.c:103
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:1305
int nb_segments
Definition: dashenc.c:109
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:938
int num
Numerator.
Definition: rational.h:59
static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
Definition: dashenc.c:244
int size
Definition: packet.h:356
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:253
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
#define AVIO_FLAG_READ
read-only
Definition: avio.h:674
int n
Definition: dashenc.c:79
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:675
uint8_t transfer_characteristics
Definition: av1.h:39
char codec_str[100]
Definition: dashenc.c:126
Convenience header that includes libavutil&#39;s core.
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
GLint GLenum type
Definition: opengl_enc.c:104
char filename[1024]
Definition: dashenc.c:128
const char * str
Definition: dashenc.c:217
int64_t timeout
Definition: dashenc.c:181
const char * key
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
AVFormatContext * ctx
Definition: dashenc.c:100
int single_file
Definition: dashenc.c:158
static AVPacket pkt
static int update_stream_extradata(AVFormatContext *s, OutputStream *os, AVPacket *pkt, AVRational *frame_rate)
Definition: dashenc.c:1810
int ff_is_http_proto(char *filename)
Utility function to check if the file uses http or https protocol.
Definition: utils.c:5692
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:87
int nr_of_streams_to_flush
Definition: dashenc.c:190
int packets_written
Definition: dashenc.c:105
int as_idx
Definition: dashenc.c:101
static void set_codec_str(AVFormatContext *s, AVCodecParameters *par, AVRational *frame_rate, char *str, int size)
Definition: dashenc.c:360
int64_t start_pts
Definition: dashenc.c:114
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1369
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1659
static int dash_init(AVFormatContext *s)
Definition: dashenc.c:1357
uint8_t chroma_sample_position
Definition: av1.h:36
This struct describes the properties of an encoded stream.
Definition: codec_par.h:52
int64_t last_pts
Definition: dashenc.c:115
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:659
uint8_t monochrome
Definition: av1.h:33
static struct codec_string codecs[]
static struct @315 state
int64_t last_dts
Definition: dashenc.c:115
void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, const char *filename, const char *language, int name_id, int is_default)
Definition: hlsplaylist.c:39
uint8_t chroma_subsampling_x
Definition: av1.h:34
Format I/O context.
Definition: avformat.h:1351
int global_sidx
Definition: dashenc.c:184
int frag_type
Definition: dashenc.c:87
#define gmtime_r
Definition: time_internal.h:34
int64_t init_start_pos
Definition: dashenc.c:107
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:1737
int trick_idx
Definition: dashenc.c:96
static int64_t start_time
Definition: ffplay.c:332
int streaming
Definition: dashenc.c:180
char * adaptation_sets
Definition: dashenc.c:145
AdaptationSet * as
Definition: dashenc.c:146
uint8_t
int width
Video only.
Definition: codec_par.h:126
AVRational min_frame_rate
Definition: dashenc.c:90
AVOptions.
miscellaneous OS support macros and functions.
int write_prft
Definition: dashenc.c:193
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:892
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: packet.h:373
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5685
int extra_window_size
Definition: dashenc.c:149
const char * hls_master_name
Definition: dashenc.c:175
static void get_start_index_number(OutputStream *os, DASHContext *c, int *start_index, int *start_number)
Definition: dashenc.c:506
int ctx_inited
Definition: dashenc.c:101
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4519
int frag_type
Definition: dashenc.c:137
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:87
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1419
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par)
Fill the codec context based on the values from the supplied codec parameters.
Definition: utils.c:2148
const char * method
Definition: dashenc.c:171
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:208
int first_segment_bit_rate
Definition: dashenc.c:118
SegmentType
Definition: dashenc.c:54
int64_t wallclock
A UTC timestamp, in microseconds, since Unix epoch (e.g, av_gettime()).
Definition: avcodec.h:502
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
int64_t presentation_time_offset
Definition: dashenc.c:165
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1482
uint8_t * data
Definition: packet.h:355
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
uint32_t tag
Definition: movenc.c:1532
static void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
Definition: dashenc.c:1882
int ignore_io_errors
Definition: dashenc.c:186
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
time_t start_time_s
Definition: dashenc.c:164
static int dashenc_delete_segment_file(AVFormatContext *s, const char *file)
Definition: dashenc.c:1862
AVIOContext * m3u8_out
Definition: dashenc.c:179
int max_height
Definition: dashenc.c:93
ptrdiff_t size
Definition: opengl_enc.c:100
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition: rational.c:35
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:225
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
Definition: avio_internal.h:58
uint64_t availability_start_time
Definition: dashdec.c:139
char initfile[1024]
Definition: dashenc.c:106
int64_t seg_duration
Definition: dashenc.c:153
#define av_log(a,...)
AVDictionary * format_options
Definition: dashenc.c:183
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:278
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:637
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:89
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:388
static void get_hls_playlist_name(char *playlist_name, int string_size, const char *base_url, int id)
Definition: dashenc.c:498
static void write_time(AVIOContext *out, int64_t time)
Definition: dashenc.c:769
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:1143
#define src
Definition: vp8dsp.c:254
#define E
Definition: dashenc.c:2334
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1591
int64_t last_duration
Definition: dashenc.c:112
int hls_playlist
Definition: dashenc.c:174
#define AV_BPRINT_SIZE_UNLIMITED
AVDictionary * metadata
Definition: dashenc.c:89
const char * init_seg_name
Definition: dashenc.c:123
int remove_at_exit
Definition: dashenc.c:155
int bitdepth
Definition: vpcc.h:38
int64_t last_duration
Definition: dashenc.c:161
uint8_t * av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:353
static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: dashenc.c:2052
int nb_as
Definition: dashenc.c:147
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:153
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:635
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:1159
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
char * url
input or output URL.
Definition: avformat.h:1447
int video_delay
Video only.
Definition: codec_par.h:155
unsigned int pos
Definition: spdifenc.c:410
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
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: codec_par.h:56
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:2312
static int flush_init_segment(AVFormatContext *s, OutputStream *os)
Definition: dashenc.c:595
static SegmentType select_segment_type(SegmentType segment_type, enum AVCodecID codec_id)
Definition: dashenc.c:290
int64_t start_pos
Definition: dashenc.c:74
double availability_time_offset
Definition: dashenc.c:131
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:949
#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:1835
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:361
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
Definition: mathematics.c:147
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:78
void * opaque
User data.
Definition: avformat.h:1857
AVOutputFormat ff_dash_muxer
Definition: dashenc.c:2393
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate, or free an array through a pointer to a pointer.
Definition: mem.c:206
int ldash
Definition: dashenc.c:188
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1407
int ff_rename(const char *url_src, const char *url_dst, void *logctx)
Wrap avpriv_io_move and log if error happens.
Definition: avio.c:673
AVDictionary * opts
Definition: movenc.c:50
AVCodecContext * parser_avctx
Definition: dashenc.c:104
const char * media_seg_name
Definition: dashenc.c:169
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:3321
AVProducerReferenceTime producer_reference_time
Definition: dashenc.c:132
#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:505
#define FFMIN(a, b)
Definition: common.h:96
int segment_index
Definition: dashenc.c:109
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition: options.c:172
int av_parser_parse2(AVCodecParserContext *s, AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size, int64_t pts, int64_t dts, int64_t pos)
Parse a packet.
Definition: parser.c:120
AVRational sar
Definition: dashenc.c:139
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:98
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:461
void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type, int iframe_mode)
Definition: hlsplaylist.c:98
const char * name
Definition: avformat.h:500
int master_playlist_created
Definition: dashenc.c:177
AVFormatContext * ctx
Definition: movenc.c:48
void av_parser_close(AVCodecParserContext *s)
Definition: parser.c:224
char full_path[1024]
Definition: dashenc.c:129
char dirname[1024]
Definition: dashenc.c:166
enum AVMediaType media_type
Definition: dashenc.c:88
int64_t frag_duration
Definition: dashenc.c:86
#define s(width, name)
Definition: cbs_vp9.c:257
char * descriptor
Definition: dashenc.c:84
int avoid_negative_ts
Avoid negative timestamps during muxing.
Definition: avformat.h:1682
int index_correction
Definition: dashenc.c:182
uint8_t color_description_present_flag
Definition: av1.h:37
#define AV_DICT_APPEND
If the entry already exists, append to it.
Definition: dict.h:80
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:185
AVDictionary * metadata
Definition: avformat.h:940
static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par, AVRational *frame_rate, char *str, int size)
Definition: dashenc.c:345
enum AVCodecID codec_id
Definition: vaapi_decode.c:369
Usually treated as AVMEDIA_TYPE_DATA.
Definition: avutil.h:200
AVRational par
Definition: dashenc.c:95
int64_t pos
Definition: dashenc.c:107
av_warn_unused_result int avformat_init_output(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and initialize the codec, but do not write the header.
Definition: mux.c:485
int segments_size
Definition: dashenc.c:109
#define AV_ERROR_MAX_STRING_SIZE
Definition: error.h:83
#define OFFSET(x)
Definition: dashenc.c:2333
#define MPD_PROFILE_DASH
Definition: dashenc.c:69
#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:1370
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1444
if(ret)
int target_latency_refid
Definition: dashenc.c:198
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:876
static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length)
Definition: dashenc.c:456
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:76
Segment ** segments
Definition: dashenc.c:113
void ff_hls_write_playlist_version(AVIOContext *out, int version)
Definition: hlsplaylist.c:31
int64_t gop_size
Definition: dashenc.c:138
AVRational max_playback_rate
Definition: dashenc.c:200
int index_length
Definition: dashenc.c:75
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition: packet.h:55
AVCodecParserContext * av_parser_init(int codec_id)
Definition: parser.c:34
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
AVStreamInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1231
const AVCodecTag ff_codec_movaudio_tags[]
Definition: isom.c:321
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer...
Definition: options.c:187
int64_t max_segment_duration
Definition: dashenc.c:195
int frag_type
Definition: dashenc.c:192
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
AVIOContext * pb
I/O context.
Definition: avformat.h:1393
int bit_rate
Definition: dashenc.c:117
int64_t target_latency
Definition: dashenc.c:197
SegmentType segment_type
Definition: dashenc.c:216
main external API structure.
Definition: avcodec.h:526
int nb_streams
Definition: dashenc.c:94
int use_template
Definition: dashenc.c:156
int written_len
Definition: dashenc.c:127
int64_t max_gop_size
Definition: dashenc.c:194
AVRational max_frame_rate
Definition: dashenc.c:90
double prog_date_time
Definition: dashenc.c:77
#define MPD_PROFILE_DVB
Definition: dashenc.c:70
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1939
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
AVDictionary * http_opts
Definition: dashenc.c:173
Describe the class of an AVClass context structure.
Definition: log.h:67
int max_width
Definition: dashenc.c:93
const char * init_seg_name
Definition: dashenc.c:168
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:120
static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index, int final)
Definition: dashenc.c:803
int64_t seg_duration
Definition: dashenc.c:85
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:245
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:263
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:1153
#define FF_COMPLIANCE_STRICT
Strictly conform to all the things in the spec no matter what consequences.
Definition: avcodec.h:1591
#define snprintf
Definition: snprintf.h:34
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4448
static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
Definition: dashenc.c:916
int64_t total_duration
Definition: dashenc.c:162
misc parsing utilities
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, const char *filename, const char *agroup, const char *codecs, const char *ccgroup, const char *sgroup)
Definition: hlsplaylist.c:69
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes...
Definition: avstring.c:93
static void find_index_range(AVFormatContext *s, const char *full_path, int64_t pos, int *index_length)
Definition: dashenc.c:1787
char file[1024]
Definition: dashenc.c:73
mfxU16 profile
Definition: qsvenc.c:45
int coding_dependency
Definition: dashenc.c:140
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:475
static const char * get_extension_str(SegmentType type, int single_file)
Definition: dashenc.c:271
static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, AVDictionary **options)
Definition: dashenc.c:225
URLContext * ffio_geturlcontext(AVIOContext *s)
Return the URLContext associated with the AVIOContext.
Definition: aviobuf.c:983
#define flags(name, subs,...)
Definition: cbs_av1.c:560
uint8_t level
Definition: svq3.c:209
OutputStream * streams
Definition: dashenc.c:159
int init_range_length
Definition: dashenc.c:108
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition: http.c:333
SegmentType segment_type_option
Definition: dashenc.c:185
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: codec_par.h:170
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO
Shift timestamps so that they start at 0.
Definition: avformat.h:1685
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
int64_t seg_duration
Definition: dashenc.c:110
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:458
Utilties for rational number calculation.
const char * user_agent
Definition: dashenc.c:172
const char * single_file_name
Definition: dashenc.c:167
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
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:334
uint8_t level
Definition: av1.h:30
static int handle_io_open_error(AVFormatContext *s, int err, char *url)
Definition: dashenc.c:281
#define PARSER_FLAG_COMPLETE_FRAMES
Definition: avcodec.h:3387
int muxer_overhead
Definition: dashenc.c:136
int64_t max_frag_duration
Definition: dashenc.c:92
int den
Denominator.
Definition: rational.h:60
static void write_styp(AVIOContext *pb)
Definition: dashenc.c:1777
int64_t duration
Definition: dashenc.c:78
static int dash_write_header(AVFormatContext *s)
Definition: dashenc.c:1718
int nr_of_streams_flushed
Definition: dashenc.c:191
uint8_t tier
Definition: av1.h:31
char producer_reference_time_str[100]
Definition: dashenc.c:133
This structure supplies correlation between a packet timestamp and a wall clock production time...
Definition: avcodec.h:498
int profile
Definition: dashenc.c:196
static int check_file_extension(const char *filename, const char *extension)
Definition: dashenc.c:335
static int dash_parse_prft(DASHContext *c, AVPacket *pkt)
Definition: dashenc.c:2026
#define av_free(p)
char * value
Definition: dict.h:87
int len
int lhls
Definition: dashenc.c:187
const char * str
Definition: dashenc.c:205
void * priv_data
Format private data.
Definition: avformat.h:1379
static void format_date(char *buf, int size, int64_t time_us)
Definition: dashenc.c:785
static int check_bitstream(AVFormatContext *s, AVStream *st, AVPacket *pkt)
Definition: mux.c:1075
const char * utc_timing_url
Definition: dashenc.c:170
int profile
Definition: vpcc.h:36
static int dash_write_trailer(AVFormatContext *s)
Definition: dashenc.c:2270
int window_size
Definition: dashenc.c:148
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:346
#define lrint
Definition: tablegen.h:53
static void dash_free(AVFormatContext *s)
Definition: dashenc.c:613
static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s, int representation_id, int final, char *prefetch_url)
Definition: dashenc.c:516
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:74
int64_t total_pkt_duration
Definition: dashenc.c:135
int has_video
Definition: dashenc.c:160
int channels
Audio only.
Definition: codec_par.h:166
int64_t max_pts
Definition: dashenc.c:114
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: packet.h:354
int avpriv_io_delete(const char *url)
Delete a resource.
Definition: avio.c:523
void ff_hls_write_end_list(AVIOContext *out)
Definition: hlsplaylist.c:189
int total_pkt_size
Definition: dashenc.c:134
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1251
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:387
int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, int byterange_mode, double duration, int round_duration, int64_t size, int64_t pos, const char *baseurl, const char *filename, double *prog_date_time, int64_t video_keyframe_size, int64_t video_keyframe_pos, int iframe_mode)
Definition: hlsplaylist.c:132
static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatContext *s, int representation_id, int final)
Definition: dashenc.c:654
FILE * out
Definition: movenc.c:54
const char * extension_name
Definition: dashenc.c:121
#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:189
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1023
static char * xmlescape(const char *str)
Definition: dashenc.c:729
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:64
formats
Definition: signature.h:48
AVIOContext * out
Definition: dashenc.c:102
char temp_path[1024]
Definition: dashenc.c:130
static int dash_flush(AVFormatContext *s, int final, int stream)
Definition: dashenc.c:1895
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int size)
Allocate new information of a packet.
Definition: avpacket.c:332
int stream_index
Definition: packet.h:357
void ff_hls_write_init_file(AVIOContext *out, const char *filename, int byterange_mode, int64_t size, int64_t pos)
Definition: hlsplaylist.c:122
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:905
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
int64_t first_pts
Definition: ffmpeg.h:458
#define MKTAG(a, b, c, d)
Definition: common.h:406
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:477
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2073
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:87
This structure stores compressed data.
Definition: packet.h:332
uint8_t bitdepth
Definition: av1.h:32
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:265
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:348
int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
Definition: avc.c:108
int i
Definition: input.c:406
static const AVClass dash_class
Definition: dashenc.c:2386
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
Predicted.
Definition: avutil.h:275
GLuint buffer
Definition: opengl_enc.c:101
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
int http_persistent
Definition: dashenc.c:176
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1381
static uint8_t tmp[11]
Definition: aes_ctr.c:26
uint8_t profile
Definition: av1.h:29