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