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