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);
592  for (j = 0; j < os->nb_segments; j++)
593  av_free(os->segments[j]);
594  av_free(os->segments);
596  av_freep(&os->init_seg_name);
597  av_freep(&os->media_seg_name);
598  }
599  av_freep(&c->streams);
600 
601  ff_format_io_close(s, &c->mpd_out);
603 }
604 
606  int representation_id, int final)
607 {
608  DASHContext *c = s->priv_data;
609  int i, start_index, start_number;
610  get_start_index_number(os, c, &start_index, &start_number);
611 
612  if (c->use_template) {
613  int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE;
614  avio_printf(out, "\t\t\t\t<SegmentTemplate timescale=\"%d\" ", timescale);
615  if (!c->use_timeline) {
616  avio_printf(out, "duration=\"%"PRId64"\" ", c->seg_duration);
617  if (c->streaming && os->availability_time_offset)
618  avio_printf(out, "availabilityTimeOffset=\"%.3f\" ",
620  }
621  avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\">\n", os->init_seg_name, os->media_seg_name, c->use_timeline ? start_number : 1);
622  if (c->use_timeline) {
623  int64_t cur_time = 0;
624  avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
625  for (i = start_index; i < os->nb_segments; ) {
626  Segment *seg = os->segments[i];
627  int repeat = 0;
628  avio_printf(out, "\t\t\t\t\t\t<S ");
629  if (i == start_index || seg->time != cur_time) {
630  cur_time = seg->time;
631  avio_printf(out, "t=\"%"PRId64"\" ", seg->time);
632  }
633  avio_printf(out, "d=\"%"PRId64"\" ", seg->duration);
634  while (i + repeat + 1 < os->nb_segments &&
635  os->segments[i + repeat + 1]->duration == seg->duration &&
636  os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration)
637  repeat++;
638  if (repeat > 0)
639  avio_printf(out, "r=\"%d\" ", repeat);
640  avio_printf(out, "/>\n");
641  i += 1 + repeat;
642  cur_time += (1 + repeat) * seg->duration;
643  }
644  avio_printf(out, "\t\t\t\t\t</SegmentTimeline>\n");
645  }
646  avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
647  } else if (c->single_file) {
648  avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
649  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
650  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);
651  for (i = start_index; i < os->nb_segments; i++) {
652  Segment *seg = os->segments[i];
653  avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
654  if (seg->index_length)
655  avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
656  avio_printf(out, "/>\n");
657  }
658  avio_printf(out, "\t\t\t\t</SegmentList>\n");
659  } else {
660  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
661  avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
662  for (i = start_index; i < os->nb_segments; i++) {
663  Segment *seg = os->segments[i];
664  avio_printf(out, "\t\t\t\t\t<SegmentURL media=\"%s\" />\n", seg->file);
665  }
666  avio_printf(out, "\t\t\t\t</SegmentList>\n");
667  }
668  if (!c->lhls || final) {
669  write_hls_media_playlist(os, s, representation_id, final, NULL);
670  }
671 
672 }
673 
674 static char *xmlescape(const char *str) {
675  int outlen = strlen(str)*3/2 + 6;
676  char *out = av_realloc(NULL, outlen + 1);
677  int pos = 0;
678  if (!out)
679  return NULL;
680  for (; *str; str++) {
681  if (pos + 6 > outlen) {
682  char *tmp;
683  outlen = 2 * outlen + 6;
684  tmp = av_realloc(out, outlen + 1);
685  if (!tmp) {
686  av_free(out);
687  return NULL;
688  }
689  out = tmp;
690  }
691  if (*str == '&') {
692  memcpy(&out[pos], "&amp;", 5);
693  pos += 5;
694  } else if (*str == '<') {
695  memcpy(&out[pos], "&lt;", 4);
696  pos += 4;
697  } else if (*str == '>') {
698  memcpy(&out[pos], "&gt;", 4);
699  pos += 4;
700  } else if (*str == '\'') {
701  memcpy(&out[pos], "&apos;", 6);
702  pos += 6;
703  } else if (*str == '\"') {
704  memcpy(&out[pos], "&quot;", 6);
705  pos += 6;
706  } else {
707  out[pos++] = *str;
708  }
709  }
710  out[pos] = '\0';
711  return out;
712 }
713 
714 static void write_time(AVIOContext *out, int64_t time)
715 {
716  int seconds = time / AV_TIME_BASE;
717  int fractions = time % AV_TIME_BASE;
718  int minutes = seconds / 60;
719  int hours = minutes / 60;
720  seconds %= 60;
721  minutes %= 60;
722  avio_printf(out, "PT");
723  if (hours)
724  avio_printf(out, "%dH", hours);
725  if (hours || minutes)
726  avio_printf(out, "%dM", minutes);
727  avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
728 }
729 
730 static void format_date_now(char *buf, int size)
731 {
732  struct tm *ptm, tmbuf;
733  int64_t time_us = av_gettime();
734  int64_t time_ms = time_us / 1000;
735  const time_t time_s = time_ms / 1000;
736  int millisec = time_ms - (time_s * 1000);
737  ptm = gmtime_r(&time_s, &tmbuf);
738  if (ptm) {
739  int len;
740  if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%S", ptm)) {
741  buf[0] = '\0';
742  return;
743  }
744  len = strlen(buf);
745  snprintf(buf + len, size - len, ".%03dZ", millisec);
746  }
747 }
748 
750  int final)
751 {
752  DASHContext *c = s->priv_data;
753  AdaptationSet *as = &c->as[as_index];
754  AVDictionaryEntry *lang, *role;
755  int i;
756 
757  avio_printf(out, "\t\t<AdaptationSet id=\"%s\" contentType=\"%s\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
758  as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
760  avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
761  lang = av_dict_get(as->metadata, "language", NULL, 0);
762  if (lang)
763  avio_printf(out, " lang=\"%s\"", lang->value);
764  avio_printf(out, ">\n");
765 
766  role = av_dict_get(as->metadata, "role", NULL, 0);
767  if (role)
768  avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
769  if (as->descriptor)
770  avio_printf(out, "\t\t\t%s\n", as->descriptor);
771  for (i = 0; i < s->nb_streams; i++) {
772  OutputStream *os = &c->streams[i];
773  char bandwidth_str[64] = {'\0'};
774 
775  if (os->as_idx - 1 != as_index)
776  continue;
777 
778  if (os->bit_rate > 0)
779  snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"",
780  os->bit_rate);
781 
782  if (as->media_type == AVMEDIA_TYPE_VIDEO) {
783  AVStream *st = s->streams[i];
784  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
785  i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
786  if (st->avg_frame_rate.num)
787  avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
788  avio_printf(out, ">\n");
789  } else {
790  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
791  i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->sample_rate);
792  avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
793  s->streams[i]->codecpar->channels);
794  }
795  output_segment_list(os, out, s, i, final);
796  avio_printf(out, "\t\t\t</Representation>\n");
797  }
798  avio_printf(out, "\t\t</AdaptationSet>\n");
799 
800  return 0;
801 }
802 
804 {
805  DASHContext *c = s->priv_data;
806 
807  void *mem = av_realloc(c->as, sizeof(*c->as) * (c->nb_as + 1));
808  if (!mem)
809  return AVERROR(ENOMEM);
810  c->as = mem;
811  ++c->nb_as;
812 
813  *as = &c->as[c->nb_as - 1];
814  memset(*as, 0, sizeof(**as));
815  (*as)->media_type = type;
816 
817  return 0;
818 }
819 
820 static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
821 {
822  DASHContext *c = s->priv_data;
823  AdaptationSet *as = &c->as[as_idx - 1];
824  OutputStream *os = &c->streams[i];
825 
826  if (as->media_type != s->streams[i]->codecpar->codec_type) {
827  av_log(s, AV_LOG_ERROR, "Codec type of stream %d doesn't match AdaptationSet's media type\n", i);
828  return AVERROR(EINVAL);
829  } else if (os->as_idx) {
830  av_log(s, AV_LOG_ERROR, "Stream %d is already assigned to an AdaptationSet\n", i);
831  return AVERROR(EINVAL);
832  }
833  os->as_idx = as_idx;
834 
835  return 0;
836 }
837 
839 {
840  DASHContext *c = s->priv_data;
841  const char *p = c->adaptation_sets;
842  enum { new_set, parse_id, parsing_streams, parse_descriptor } state;
843  AdaptationSet *as;
844  int i, n, ret;
845 
846  // default: one AdaptationSet for each stream
847  if (!p) {
848  for (i = 0; i < s->nb_streams; i++) {
849  if ((ret = add_adaptation_set(s, &as, s->streams[i]->codecpar->codec_type)) < 0)
850  return ret;
851  snprintf(as->id, sizeof(as->id), "%d", i);
852 
853  c->streams[i].as_idx = c->nb_as;
854  }
855  goto end;
856  }
857 
858  // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
859  // option id=0,descriptor=descriptor_str,streams=0,1,2 and so on
860  // descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015
861  // descriptor_str should be a self-closing xml tag.
862  state = new_set;
863  while (*p) {
864  if (*p == ' ') {
865  p++;
866  continue;
867  } else if (state == new_set && av_strstart(p, "id=", &p)) {
868 
869  if ((ret = add_adaptation_set(s, &as, AVMEDIA_TYPE_UNKNOWN)) < 0)
870  return ret;
871 
872  n = strcspn(p, ",");
873  snprintf(as->id, sizeof(as->id), "%.*s", n, p);
874 
875  p += n;
876  if (*p)
877  p++;
878  state = parse_id;
879  } else if (state == parse_id && av_strstart(p, "descriptor=", &p)) {
880  n = strcspn(p, ">") + 1; //followed by one comma, so plus 1
881  if (n < strlen(p)) {
882  as->descriptor = av_strndup(p, n);
883  } else {
884  av_log(s, AV_LOG_ERROR, "Parse error, descriptor string should be a self-closing xml tag\n");
885  return AVERROR(EINVAL);
886  }
887  p += n;
888  if (*p)
889  p++;
890  state = parse_descriptor;
891  } else if ((state == parse_id || state == parse_descriptor) && av_strstart(p, "streams=", &p)) { //descriptor is optional
892  state = parsing_streams;
893  } else if (state == parsing_streams) {
894  AdaptationSet *as = &c->as[c->nb_as - 1];
895  char idx_str[8], *end_str;
896 
897  n = strcspn(p, " ,");
898  snprintf(idx_str, sizeof(idx_str), "%.*s", n, p);
899  p += n;
900 
901  // if value is "a" or "v", map all streams of that type
902  if (as->media_type == AVMEDIA_TYPE_UNKNOWN && (idx_str[0] == 'v' || idx_str[0] == 'a')) {
903  enum AVMediaType type = (idx_str[0] == 'v') ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
904  av_log(s, AV_LOG_DEBUG, "Map all streams of type %s\n", idx_str);
905 
906  for (i = 0; i < s->nb_streams; i++) {
907  if (s->streams[i]->codecpar->codec_type != type)
908  continue;
909 
910  as->media_type = s->streams[i]->codecpar->codec_type;
911 
912  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
913  return ret;
914  }
915  } else { // select single stream
916  i = strtol(idx_str, &end_str, 10);
917  if (idx_str == end_str || i < 0 || i >= s->nb_streams) {
918  av_log(s, AV_LOG_ERROR, "Selected stream \"%s\" not found!\n", idx_str);
919  return AVERROR(EINVAL);
920  }
921  av_log(s, AV_LOG_DEBUG, "Map stream %d\n", i);
922 
923  if (as->media_type == AVMEDIA_TYPE_UNKNOWN) {
924  as->media_type = s->streams[i]->codecpar->codec_type;
925  }
926 
927  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
928  return ret;
929  }
930 
931  if (*p == ' ')
932  state = new_set;
933  if (*p)
934  p++;
935  } else {
936  return AVERROR(EINVAL);
937  }
938  }
939 
940 end:
941  // check for unassigned streams
942  for (i = 0; i < s->nb_streams; i++) {
943  OutputStream *os = &c->streams[i];
944  if (!os->as_idx) {
945  av_log(s, AV_LOG_ERROR, "Stream %d is not mapped to an AdaptationSet\n", i);
946  return AVERROR(EINVAL);
947  }
948  }
949  return 0;
950 }
951 
952 static int write_manifest(AVFormatContext *s, int final)
953 {
954  DASHContext *c = s->priv_data;
955  AVIOContext *out;
956  char temp_filename[1024];
957  int ret, i;
958  const char *proto = avio_find_protocol_name(s->url);
959  int use_rename = proto && !strcmp(proto, "file");
960  static unsigned int warned_non_file = 0;
961  AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
963 
964  if (!use_rename && !warned_non_file++)
965  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
966 
967  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url);
968  set_http_options(&opts, c);
969  ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts);
970  av_dict_free(&opts);
971  if (ret < 0) {
972  return handle_io_open_error(s, ret, temp_filename);
973  }
974  out = c->mpd_out;
975  avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
976  avio_printf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
977  "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
978  "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
979  "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
980  "\tprofiles=\"urn:mpeg:dash:profile:isoff-live:2011\"\n"
981  "\ttype=\"%s\"\n", final ? "static" : "dynamic");
982  if (final) {
983  avio_printf(out, "\tmediaPresentationDuration=\"");
984  write_time(out, c->total_duration);
985  avio_printf(out, "\"\n");
986  } else {
987  int64_t update_period = c->last_duration / AV_TIME_BASE;
988  char now_str[100];
989  if (c->use_template && !c->use_timeline)
990  update_period = 500;
991  avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period);
992  avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE);
993  if (c->availability_start_time[0])
994  avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time);
995  format_date_now(now_str, sizeof(now_str));
996  if (now_str[0])
997  avio_printf(out, "\tpublishTime=\"%s\"\n", now_str);
998  if (c->window_size && c->use_template) {
999  avio_printf(out, "\ttimeShiftBufferDepth=\"");
1000  write_time(out, c->last_duration * c->window_size);
1001  avio_printf(out, "\"\n");
1002  }
1003  }
1004  avio_printf(out, "\tminBufferTime=\"");
1005  write_time(out, c->last_duration * 2);
1006  avio_printf(out, "\">\n");
1007  avio_printf(out, "\t<ProgramInformation>\n");
1008  if (title) {
1009  char *escaped = xmlescape(title->value);
1010  avio_printf(out, "\t\t<Title>%s</Title>\n", escaped);
1011  av_free(escaped);
1012  }
1013  avio_printf(out, "\t</ProgramInformation>\n");
1014 
1015  if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) {
1016  OutputStream *os = &c->streams[0];
1017  int start_index = FFMAX(os->nb_segments - c->window_size, 0);
1018  int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q);
1019  avio_printf(out, "\t<Period id=\"0\" start=\"");
1020  write_time(out, start_time);
1021  avio_printf(out, "\">\n");
1022  } else {
1023  avio_printf(out, "\t<Period id=\"0\" start=\"PT0.0S\">\n");
1024  }
1025 
1026  for (i = 0; i < c->nb_as; i++) {
1027  if ((ret = write_adaptation_set(s, out, i, final)) < 0)
1028  return ret;
1029  }
1030  avio_printf(out, "\t</Period>\n");
1031 
1032  if (c->utc_timing_url)
1033  avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
1034 
1035  avio_printf(out, "</MPD>\n");
1036  avio_flush(out);
1037  dashenc_io_close(s, &c->mpd_out, temp_filename);
1038 
1039  if (use_rename) {
1040  if ((ret = avpriv_io_move(temp_filename, s->url)) < 0)
1041  return ret;
1042  }
1043 
1044  if (c->hls_playlist) {
1045  char filename_hls[1024];
1046  const char *audio_group = "A1";
1047  char audio_codec_str[128] = "\0";
1048  int is_default = 1;
1049  int max_audio_bitrate = 0;
1050 
1051  // Publish master playlist only the configured rate
1054  return 0;
1055 
1056  if (*c->dirname)
1057  snprintf(filename_hls, sizeof(filename_hls), "%smaster.m3u8", c->dirname);
1058  else
1059  snprintf(filename_hls, sizeof(filename_hls), "master.m3u8");
1060 
1061  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", filename_hls);
1062 
1063  set_http_options(&opts, c);
1064  ret = dashenc_io_open(s, &c->m3u8_out, temp_filename, &opts);
1065  av_dict_free(&opts);
1066  if (ret < 0) {
1067  return handle_io_open_error(s, ret, temp_filename);
1068  }
1069 
1071 
1072  for (i = 0; i < s->nb_streams; i++) {
1073  char playlist_file[64];
1074  AVStream *st = s->streams[i];
1075  OutputStream *os = &c->streams[i];
1077  continue;
1078  if (os->segment_type != SEGMENT_TYPE_MP4)
1079  continue;
1080  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1081  ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group,
1082  playlist_file, NULL, i, is_default);
1083  max_audio_bitrate = FFMAX(st->codecpar->bit_rate +
1084  os->muxer_overhead, max_audio_bitrate);
1085  if (!av_strnstr(audio_codec_str, os->codec_str, sizeof(audio_codec_str))) {
1086  if (strlen(audio_codec_str))
1087  av_strlcat(audio_codec_str, ",", sizeof(audio_codec_str));
1088  av_strlcat(audio_codec_str, os->codec_str, sizeof(audio_codec_str));
1089  }
1090  is_default = 0;
1091  }
1092 
1093  for (i = 0; i < s->nb_streams; i++) {
1094  char playlist_file[64];
1095  char codec_str[128];
1096  AVStream *st = s->streams[i];
1097  OutputStream *os = &c->streams[i];
1098  char *agroup = NULL;
1099  char *codec_str_ptr = NULL;
1100  int stream_bitrate = st->codecpar->bit_rate + os->muxer_overhead;
1102  continue;
1103  if (os->segment_type != SEGMENT_TYPE_MP4)
1104  continue;
1105  av_strlcpy(codec_str, os->codec_str, sizeof(codec_str));
1106  if (max_audio_bitrate) {
1107  agroup = (char *)audio_group;
1108  stream_bitrate += max_audio_bitrate;
1109  av_strlcat(codec_str, ",", sizeof(codec_str));
1110  av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
1111  }
1112  if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) {
1113  codec_str_ptr = codec_str;
1114  }
1115  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1116  ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
1117  playlist_file, agroup,
1118  codec_str_ptr, NULL);
1119  }
1120  dashenc_io_close(s, &c->m3u8_out, temp_filename);
1121  if (use_rename)
1122  if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0)
1123  return ret;
1124  c->master_playlist_created = 1;
1125  }
1126 
1127  return 0;
1128 }
1129 
1130 static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
1131 {
1132  AVDictionaryEntry *entry = av_dict_get(src, key, NULL, 0);
1133  if (entry)
1134  av_dict_set(dst, key, entry->value, AV_DICT_DONT_OVERWRITE);
1135  return 0;
1136 }
1137 
1139 {
1140  DASHContext *c = s->priv_data;
1141  int ret = 0, i;
1142  char *ptr;
1143  char basename[1024];
1144 
1145  c->nr_of_streams_to_flush = 0;
1146  if (c->single_file_name)
1147  c->single_file = 1;
1148  if (c->single_file)
1149  c->use_template = 0;
1150 
1151 #if FF_API_DASH_MIN_SEG_DURATION
1152  if (c->min_seg_duration != 5000000) {
1153  av_log(s, AV_LOG_WARNING, "The min_seg_duration option is deprecated and will be removed. Please use the -seg_duration\n");
1154  c->seg_duration = c->min_seg_duration;
1155  }
1156 #endif
1158  av_log(s, AV_LOG_ERROR,
1159  "LHLS is experimental, Please set -strict experimental in order to enable it.\n");
1160  return AVERROR_EXPERIMENTAL;
1161  }
1162 
1163  if (c->lhls && !c->streaming) {
1164  av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as streaming is not enabled\n");
1165  c->lhls = 0;
1166  }
1167 
1168  if (c->lhls && !c->hls_playlist) {
1169  av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as hls_playlist is not enabled\n");
1170  c->lhls = 0;
1171  }
1172 
1173  if (c->global_sidx && !c->single_file) {
1174  av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as single_file is not enabled\n");
1175  c->global_sidx = 0;
1176  }
1177 
1178  if (c->global_sidx && c->streaming) {
1179  av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as streaming is enabled\n");
1180  c->global_sidx = 0;
1181  }
1182 
1183  av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
1184  ptr = strrchr(c->dirname, '/');
1185  if (ptr) {
1186  av_strlcpy(basename, &ptr[1], sizeof(basename));
1187  ptr[1] = '\0';
1188  } else {
1189  c->dirname[0] = '\0';
1190  av_strlcpy(basename, s->url, sizeof(basename));
1191  }
1192 
1193  ptr = strrchr(basename, '.');
1194  if (ptr)
1195  *ptr = '\0';
1196 
1197  c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
1198  if (!c->streams)
1199  return AVERROR(ENOMEM);
1200 
1201  if ((ret = parse_adaptation_sets(s)) < 0)
1202  return ret;
1203 
1204  if ((ret = init_segment_types(s)) < 0)
1205  return ret;
1206 
1207  for (i = 0; i < s->nb_streams; i++) {
1208  OutputStream *os = &c->streams[i];
1209  AdaptationSet *as = &c->as[os->as_idx - 1];
1211  AVStream *st;
1212  AVDictionary *opts = NULL;
1213  char filename[1024];
1214 
1215  os->bit_rate = s->streams[i]->codecpar->bit_rate;
1216  if (!os->bit_rate) {
1219  av_log(s, level, "No bit rate set for stream %d\n", i);
1221  return AVERROR(EINVAL);
1222  }
1223 
1224  // copy AdaptationSet language and role from stream metadata
1225  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "language");
1226  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "role");
1227 
1228  ctx = avformat_alloc_context();
1229  if (!ctx)
1230  return AVERROR(ENOMEM);
1231 
1232  if (c->init_seg_name) {
1233  os->init_seg_name = av_strireplace(c->init_seg_name, "$ext$", os->extension_name);
1234  if (!os->init_seg_name)
1235  return AVERROR(ENOMEM);
1236  }
1237  if (c->media_seg_name) {
1239  if (!os->media_seg_name)
1240  return AVERROR(ENOMEM);
1241  }
1242  if (c->single_file_name) {
1244  if (!os->single_file_name)
1245  return AVERROR(ENOMEM);
1246  }
1247 
1248  if (os->segment_type == SEGMENT_TYPE_WEBM) {
1249  if ((!c->single_file && check_file_extension(os->init_seg_name, os->format_name) != 0) ||
1250  (!c->single_file && check_file_extension(os->media_seg_name, os->format_name) != 0) ||
1253  "One or many segment file names doesn't end with .webm. "
1254  "Override -init_seg_name and/or -media_seg_name and/or "
1255  "-single_file_name to end with the extension .webm\n");
1256  }
1257  if (c->streaming) {
1258  // Streaming not supported as matroskaenc buffers internally before writing the output
1259  av_log(s, AV_LOG_WARNING, "One or more streams in WebM output format. Streaming option will be ignored\n");
1260  c->streaming = 0;
1261  }
1262  }
1263 
1265  if (!ctx->oformat)
1266  return AVERROR_MUXER_NOT_FOUND;
1267  os->ctx = ctx;
1269  ctx->opaque = s->opaque;
1270  ctx->io_close = s->io_close;
1271  ctx->io_open = s->io_open;
1273 
1274  if (!(st = avformat_new_stream(ctx, NULL)))
1275  return AVERROR(ENOMEM);
1278  st->time_base = s->streams[i]->time_base;
1281  ctx->flags = s->flags;
1282 
1283  if (c->single_file) {
1284  if (os->single_file_name)
1285  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);
1286  else
1287  snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.%s", basename, i, os->format_name);
1288  } else {
1289  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->init_seg_name, i, 0, os->bit_rate, 0);
1290  }
1291  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
1292  set_http_options(&opts, c);
1293  if (!c->single_file) {
1294  if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0)
1295  return ret;
1296  ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts);
1297  } else {
1298  ctx->url = av_strdup(filename);
1299  ret = avio_open2(&ctx->pb, filename, AVIO_FLAG_WRITE, NULL, &opts);
1300  }
1301  av_dict_free(&opts);
1302  if (ret < 0)
1303  return ret;
1304  os->init_start_pos = 0;
1305 
1306  if (c->format_options_str) {
1307  ret = av_dict_parse_string(&opts, c->format_options_str, "=", ":", 0);
1308  if (ret < 0)
1309  return ret;
1310  }
1311 
1312  if (os->segment_type == SEGMENT_TYPE_MP4) {
1313  if (c->streaming)
1314  // frag_every_frame : Allows lower latency streaming
1315  // skip_sidx : Reduce bitrate overhead
1316  // skip_trailer : Avoids growing memory usage with time
1317  av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov+skip_sidx+skip_trailer", 0);
1318  else {
1319  if (c->global_sidx)
1320  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+global_sidx+skip_trailer", 0);
1321  else
1322  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+skip_trailer", 0);
1323  }
1324  } else {
1325  av_dict_set_int(&opts, "cluster_time_limit", c->seg_duration / 1000, 0);
1326  av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
1327  av_dict_set_int(&opts, "dash", 1, 0);
1328  av_dict_set_int(&opts, "dash_track_number", i + 1, 0);
1329  av_dict_set_int(&opts, "live", 1, 0);
1330  }
1331  ret = avformat_init_output(ctx, &opts);
1332  av_dict_free(&opts);
1333  if (ret < 0)
1334  return ret;
1335  os->ctx_inited = 1;
1336  avio_flush(ctx->pb);
1337 
1338  av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename);
1339 
1340  s->streams[i]->time_base = st->time_base;
1341  // If the muxer wants to shift timestamps, request to have them shifted
1342  // already before being handed to this muxer, so we don't have mismatches
1343  // between the MPD and the actual segments.
1345  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1346  AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
1347  if (avg_frame_rate.num > 0) {
1348  if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0)
1349  as->min_frame_rate = avg_frame_rate;
1350  if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0)
1351  as->max_frame_rate = avg_frame_rate;
1352  } else {
1353  as->ambiguous_frame_rate = 1;
1354  }
1355  c->has_video = 1;
1356  }
1357 
1358  set_codec_str(s, st->codecpar, &st->avg_frame_rate, os->codec_str,
1359  sizeof(os->codec_str));
1360  os->first_pts = AV_NOPTS_VALUE;
1361  os->max_pts = AV_NOPTS_VALUE;
1362  os->last_dts = AV_NOPTS_VALUE;
1363  os->segment_index = 1;
1364 
1367  }
1368 
1369  if (!c->has_video && c->seg_duration <= 0) {
1370  av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");
1371  return AVERROR(EINVAL);
1372  }
1373 
1374  c->nr_of_streams_flushed = 0;
1375 
1376  return 0;
1377 }
1378 
1380 {
1381  DASHContext *c = s->priv_data;
1382  int i, ret;
1383  for (i = 0; i < s->nb_streams; i++) {
1384  OutputStream *os = &c->streams[i];
1385  if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
1386  return ret;
1387 
1388  // Flush init segment
1389  // Only for WebM segment, since for mp4 delay_moov is set and
1390  // the init segment is thus flushed after the first packets.
1391  if (os->segment_type == SEGMENT_TYPE_WEBM &&
1392  (ret = flush_init_segment(s, os)) < 0)
1393  return ret;
1394  }
1395  return ret;
1396 }
1397 
1398 static int add_segment(OutputStream *os, const char *file,
1399  int64_t time, int64_t duration,
1400  int64_t start_pos, int64_t range_length,
1401  int64_t index_length, int next_exp_index)
1402 {
1403  int err;
1404  Segment *seg;
1405  if (os->nb_segments >= os->segments_size) {
1406  os->segments_size = (os->segments_size + 1) * 2;
1407  if ((err = av_reallocp(&os->segments, sizeof(*os->segments) *
1408  os->segments_size)) < 0) {
1409  os->segments_size = 0;
1410  os->nb_segments = 0;
1411  return err;
1412  }
1413  }
1414  seg = av_mallocz(sizeof(*seg));
1415  if (!seg)
1416  return AVERROR(ENOMEM);
1417  av_strlcpy(seg->file, file, sizeof(seg->file));
1418  seg->time = time;
1419  seg->duration = duration;
1420  if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
1421  seg->duration += seg->time;
1422  seg->time = 0;
1423  }
1424  seg->start_pos = start_pos;
1425  seg->range_length = range_length;
1426  seg->index_length = index_length;
1427  os->segments[os->nb_segments++] = seg;
1428  os->segment_index++;
1429  //correcting the segment index if it has fallen behind the expected value
1430  if (os->segment_index < next_exp_index) {
1431  av_log(NULL, AV_LOG_WARNING, "Correcting the segment index after file %s: current=%d corrected=%d\n",
1432  file, os->segment_index, next_exp_index);
1433  os->segment_index = next_exp_index;
1434  }
1435  return 0;
1436 }
1437 
1438 static void write_styp(AVIOContext *pb)
1439 {
1440  avio_wb32(pb, 24);
1441  ffio_wfourcc(pb, "styp");
1442  ffio_wfourcc(pb, "msdh");
1443  avio_wb32(pb, 0); /* minor */
1444  ffio_wfourcc(pb, "msdh");
1445  ffio_wfourcc(pb, "msix");
1446 }
1447 
1448 static void find_index_range(AVFormatContext *s, const char *full_path,
1449  int64_t pos, int *index_length)
1450 {
1451  uint8_t buf[8];
1452  AVIOContext *pb;
1453  int ret;
1454 
1455  ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL);
1456  if (ret < 0)
1457  return;
1458  if (avio_seek(pb, pos, SEEK_SET) != pos) {
1459  ff_format_io_close(s, &pb);
1460  return;
1461  }
1462  ret = avio_read(pb, buf, 8);
1463  ff_format_io_close(s, &pb);
1464  if (ret < 8)
1465  return;
1466  if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
1467  return;
1468  *index_length = AV_RB32(&buf[0]);
1469 }
1470 
1472  AVPacket *pkt, AVRational *frame_rate)
1473 {
1474  AVCodecParameters *par = os->ctx->streams[0]->codecpar;
1475  uint8_t *extradata;
1476  int ret, extradata_size;
1477 
1478  if (par->extradata_size)
1479  return 0;
1480 
1481  extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &extradata_size);
1482  if (!extradata_size)
1483  return 0;
1484 
1485  ret = ff_alloc_extradata(par, extradata_size);
1486  if (ret < 0)
1487  return ret;
1488 
1489  memcpy(par->extradata, extradata, extradata_size);
1490 
1491  set_codec_str(s, par, frame_rate, os->codec_str, sizeof(os->codec_str));
1492 
1493  return 0;
1494 }
1495 
1496 static void dashenc_delete_file(AVFormatContext *s, char *filename) {
1497  DASHContext *c = s->priv_data;
1498  int http_base_proto = ff_is_http_proto(filename);
1499 
1500  if (http_base_proto) {
1501  AVIOContext *out = NULL;
1502  AVDictionary *http_opts = NULL;
1503 
1504  set_http_options(&http_opts, c);
1505  av_dict_set(&http_opts, "method", "DELETE", 0);
1506 
1507  if (dashenc_io_open(s, &out, filename, &http_opts) < 0) {
1508  av_log(s, AV_LOG_ERROR, "failed to delete %s\n", filename);
1509  }
1510 
1511  av_dict_free(&http_opts);
1512  ff_format_io_close(s, &out);
1513  } else {
1514  int res = avpriv_io_delete(filename);
1515  if (res < 0) {
1516  char errbuf[AV_ERROR_MAX_STRING_SIZE];
1517  av_strerror(res, errbuf, sizeof(errbuf));
1518  av_log(s, (res == AVERROR(ENOENT) ? AV_LOG_WARNING : AV_LOG_ERROR), "failed to delete %s: %s\n", filename, errbuf);
1519  }
1520  }
1521 }
1522 
1524 {
1525  DASHContext *c = s->priv_data;
1526  size_t dirname_len, file_len;
1527  char filename[1024];
1528 
1529  dirname_len = strlen(c->dirname);
1530  if (dirname_len >= sizeof(filename)) {
1531  av_log(s, AV_LOG_WARNING, "Cannot delete segments as the directory path is too long: %"PRIu64" characters: %s\n",
1532  (uint64_t)dirname_len, c->dirname);
1533  return AVERROR(ENAMETOOLONG);
1534  }
1535 
1536  memcpy(filename, c->dirname, dirname_len);
1537 
1538  file_len = strlen(file);
1539  if ((dirname_len + file_len) >= sizeof(filename)) {
1540  av_log(s, AV_LOG_WARNING, "Cannot delete segments as the path is too long: %"PRIu64" characters: %s%s\n",
1541  (uint64_t)(dirname_len + file_len), c->dirname, file);
1542  return AVERROR(ENAMETOOLONG);
1543  }
1544 
1545  memcpy(filename + dirname_len, file, file_len + 1); // include the terminating zero
1546  dashenc_delete_file(s, filename);
1547 
1548  return 0;
1549 }
1550 
1551 static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
1552 {
1553  for (int i = 0; i < remove_count; ++i) {
1555 
1556  // Delete the segment regardless of whether the file was successfully deleted
1557  av_free(os->segments[i]);
1558  }
1559 
1560  os->nb_segments -= remove_count;
1561  memmove(os->segments, os->segments + remove_count, os->nb_segments * sizeof(*os->segments));
1562 }
1563 
1564 static int dash_flush(AVFormatContext *s, int final, int stream)
1565 {
1566  DASHContext *c = s->priv_data;
1567  int i, ret = 0;
1568 
1569  const char *proto = avio_find_protocol_name(s->url);
1570  int use_rename = proto && !strcmp(proto, "file");
1571 
1572  int cur_flush_segment_index = 0, next_exp_index = -1;
1573  if (stream >= 0) {
1574  cur_flush_segment_index = c->streams[stream].segment_index;
1575 
1576  //finding the next segment's expected index, based on the current pts value
1577  if (c->use_template && !c->use_timeline && c->index_correction &&
1578  c->streams[stream].last_pts != AV_NOPTS_VALUE &&
1579  c->streams[stream].first_pts != AV_NOPTS_VALUE) {
1580  int64_t pts_diff = av_rescale_q(c->streams[stream].last_pts -
1581  c->streams[stream].first_pts,
1582  s->streams[stream]->time_base,
1583  AV_TIME_BASE_Q);
1584  next_exp_index = (pts_diff / c->seg_duration) + 1;
1585  }
1586  }
1587 
1588  for (i = 0; i < s->nb_streams; i++) {
1589  OutputStream *os = &c->streams[i];
1590  AVStream *st = s->streams[i];
1591  int range_length, index_length = 0;
1592 
1593  if (!os->packets_written)
1594  continue;
1595 
1596  // Flush the single stream that got a keyframe right now.
1597  // Flush all audio streams as well, in sync with video keyframes,
1598  // but not the other video streams.
1599  if (stream >= 0 && i != stream) {
1601  continue;
1602  // Make sure we don't flush audio streams multiple times, when
1603  // all video streams are flushed one at a time.
1604  if (c->has_video && os->segment_index > cur_flush_segment_index)
1605  continue;
1606  }
1607 
1608  if (!c->single_file) {
1609  if (os->segment_type == SEGMENT_TYPE_MP4 && !os->written_len)
1610  write_styp(os->ctx->pb);
1611  } else {
1612  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile);
1613  }
1614 
1615  ret = flush_dynbuf(c, os, &range_length);
1616  if (ret < 0)
1617  break;
1618  os->packets_written = 0;
1619 
1620  if (c->single_file) {
1621  find_index_range(s, os->full_path, os->pos, &index_length);
1622  } else {
1623  dashenc_io_close(s, &os->out, os->temp_path);
1624 
1625  if (use_rename) {
1626  ret = avpriv_io_move(os->temp_path, os->full_path);
1627  if (ret < 0)
1628  break;
1629  }
1630  }
1631 
1632  if (!os->muxer_overhead)
1633  os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) *
1634  8 * AV_TIME_BASE) /
1635  av_rescale_q(os->max_pts - os->start_pts,
1636  st->time_base, AV_TIME_BASE_Q);
1637  os->total_pkt_size = 0;
1638 
1639  if (!os->bit_rate) {
1640  // calculate average bitrate of first segment
1641  int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / av_rescale_q(os->max_pts - os->start_pts,
1642  st->time_base,
1643  AV_TIME_BASE_Q);
1644  if (bitrate >= 0)
1645  os->bit_rate = bitrate;
1646  }
1647  add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index);
1648  av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path);
1649 
1650  os->pos += range_length;
1651  }
1652 
1653  if (c->window_size) {
1654  for (i = 0; i < s->nb_streams; i++) {
1655  OutputStream *os = &c->streams[i];
1656  int remove_count = os->nb_segments - c->window_size - c->extra_window_size;
1657  if (remove_count > 0)
1658  dashenc_delete_media_segments(s, os, remove_count);
1659  }
1660  }
1661 
1662  if (final) {
1663  for (i = 0; i < s->nb_streams; i++) {
1664  OutputStream *os = &c->streams[i];
1665  if (os->ctx && os->ctx_inited) {
1666  int64_t file_size = avio_tell(os->ctx->pb);
1667  av_write_trailer(os->ctx);
1668  if (c->global_sidx) {
1669  int j, start_index, start_number;
1670  int64_t sidx_size = avio_tell(os->ctx->pb) - file_size;
1671  get_start_index_number(os, c, &start_index, &start_number);
1672  if (start_index >= os->nb_segments ||
1674  continue;
1675  os->init_range_length += sidx_size;
1676  for (j = start_index; j < os->nb_segments; j++) {
1677  Segment *seg = os->segments[j];
1678  seg->start_pos += sidx_size;
1679  }
1680  }
1681 
1682  }
1683  }
1684  }
1685  if (ret >= 0) {
1686  if (c->has_video && !final) {
1687  c->nr_of_streams_flushed++;
1689  return ret;
1690 
1691  c->nr_of_streams_flushed = 0;
1692  }
1693  ret = write_manifest(s, final);
1694  }
1695  return ret;
1696 }
1697 
1699 {
1700  DASHContext *c = s->priv_data;
1701  AVStream *st = s->streams[pkt->stream_index];
1702  OutputStream *os = &c->streams[pkt->stream_index];
1703  int64_t seg_end_duration, elapsed_duration;
1704  int ret;
1705 
1706  ret = update_stream_extradata(s, os, pkt, &st->avg_frame_rate);
1707  if (ret < 0)
1708  return ret;
1709 
1710  // Fill in a heuristic guess of the packet duration, if none is available.
1711  // The mp4 muxer will do something similar (for the last packet in a fragment)
1712  // if nothing is set (setting it for the other packets doesn't hurt).
1713  // By setting a nonzero duration here, we can be sure that the mp4 muxer won't
1714  // invoke its heuristic (this doesn't have to be identical to that algorithm),
1715  // so that we know the exact timestamps of fragments.
1716  if (!pkt->duration && os->last_dts != AV_NOPTS_VALUE)
1717  pkt->duration = pkt->dts - os->last_dts;
1718  os->last_dts = pkt->dts;
1719 
1720  // If forcing the stream to start at 0, the mp4 muxer will set the start
1721  // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps.
1722  if (os->first_pts == AV_NOPTS_VALUE &&
1724  pkt->pts -= pkt->dts;
1725  pkt->dts = 0;
1726  }
1727 
1728  if (os->first_pts == AV_NOPTS_VALUE)
1729  os->first_pts = pkt->pts;
1730  os->last_pts = pkt->pts;
1731 
1732  if (!c->availability_start_time[0]) {
1733  int64_t start_time_us = av_gettime();
1734  c->start_time_s = start_time_us / 1000000;
1736  sizeof(c->availability_start_time));
1737  }
1738 
1739  if (!os->availability_time_offset && pkt->duration) {
1740  int64_t frame_duration = av_rescale_q(pkt->duration, st->time_base,
1741  AV_TIME_BASE_Q);
1742  os->availability_time_offset = ((double) c->seg_duration -
1743  frame_duration) / AV_TIME_BASE;
1744  }
1745 
1746  if (c->use_template && !c->use_timeline) {
1747  elapsed_duration = pkt->pts - os->first_pts;
1748  seg_end_duration = (int64_t) os->segment_index * c->seg_duration;
1749  } else {
1750  elapsed_duration = pkt->pts - os->start_pts;
1751  seg_end_duration = c->seg_duration;
1752  }
1753 
1754  if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
1755  pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
1756  av_compare_ts(elapsed_duration, st->time_base,
1757  seg_end_duration, AV_TIME_BASE_Q) >= 0) {
1758  int64_t prev_duration = c->last_duration;
1759 
1760  c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
1761  st->time_base,
1762  AV_TIME_BASE_Q);
1763  c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
1764  st->time_base,
1765  AV_TIME_BASE_Q);
1766 
1767  if ((!c->use_timeline || !c->use_template) && prev_duration) {
1768  if (c->last_duration < prev_duration*9/10 ||
1769  c->last_duration > prev_duration*11/10) {
1771  "Segment durations differ too much, enable use_timeline "
1772  "and use_template, or keep a stricter keyframe interval\n");
1773  }
1774  }
1775 
1776  if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0)
1777  return ret;
1778  }
1779 
1780  if (!os->packets_written) {
1781  // If we wrote a previous segment, adjust the start time of the segment
1782  // to the end of the previous one (which is the same as the mp4 muxer
1783  // does). This avoids gaps in the timeline.
1784  if (os->max_pts != AV_NOPTS_VALUE)
1785  os->start_pts = os->max_pts;
1786  else
1787  os->start_pts = pkt->pts;
1788  }
1789  if (os->max_pts == AV_NOPTS_VALUE)
1790  os->max_pts = pkt->pts + pkt->duration;
1791  else
1792  os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
1793  os->packets_written++;
1794  os->total_pkt_size += pkt->size;
1795  if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0)
1796  return ret;
1797 
1798  if (!os->init_range_length)
1799  flush_init_segment(s, os);
1800 
1801  //open the output context when the first frame of a segment is ready
1802  if (!c->single_file && os->packets_written == 1) {
1803  AVDictionary *opts = NULL;
1804  const char *proto = avio_find_protocol_name(s->url);
1805  int use_rename = proto && !strcmp(proto, "file");
1806  os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0';
1807  ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename),
1808  os->media_seg_name, pkt->stream_index,
1809  os->segment_index, os->bit_rate, os->start_pts);
1810  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname,
1811  os->filename);
1812  snprintf(os->temp_path, sizeof(os->temp_path),
1813  use_rename ? "%s.tmp" : "%s", os->full_path);
1814  set_http_options(&opts, c);
1815  ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
1816  av_dict_free(&opts);
1817  if (ret < 0) {
1818  return handle_io_open_error(s, ret, os->temp_path);
1819  }
1820  if (c->lhls) {
1821  char *prefetch_url = use_rename ? NULL : os->filename;
1822  write_hls_media_playlist(os, s, pkt->stream_index, 0, prefetch_url);
1823  }
1824  }
1825 
1826  //write out the data immediately in streaming mode
1827  if (c->streaming && os->segment_type == SEGMENT_TYPE_MP4) {
1828  int len = 0;
1829  uint8_t *buf = NULL;
1830  if (!os->written_len)
1831  write_styp(os->ctx->pb);
1832  avio_flush(os->ctx->pb);
1833  len = avio_get_dyn_buf (os->ctx->pb, &buf);
1834  if (os->out) {
1835  avio_write(os->out, buf + os->written_len, len - os->written_len);
1836  avio_flush(os->out);
1837  }
1838  os->written_len = len;
1839  }
1840 
1841  return ret;
1842 }
1843 
1845 {
1846  DASHContext *c = s->priv_data;
1847  int i;
1848 
1849  if (s->nb_streams > 0) {
1850  OutputStream *os = &c->streams[0];
1851  // If no segments have been written so far, try to do a crude
1852  // guess of the segment duration
1853  if (!c->last_duration)
1855  s->streams[0]->time_base,
1856  AV_TIME_BASE_Q);
1858  s->streams[0]->time_base,
1859  AV_TIME_BASE_Q);
1860  }
1861  dash_flush(s, 1, -1);
1862 
1863  if (c->remove_at_exit) {
1864  for (i = 0; i < s->nb_streams; ++i) {
1865  OutputStream *os = &c->streams[i];
1868  if (c->hls_playlist && os->segment_type == SEGMENT_TYPE_MP4) {
1869  char filename[1024];
1870  get_hls_playlist_name(filename, sizeof(filename), c->dirname, i);
1871  dashenc_delete_file(s, filename);
1872  }
1873  }
1874  dashenc_delete_file(s, s->url);
1875 
1876  if (c->hls_playlist && c->master_playlist_created) {
1877  char filename[1024];
1878  snprintf(filename, sizeof(filename), "%smaster.m3u8", c->dirname);
1879  dashenc_delete_file(s, filename);
1880  }
1881  }
1882 
1883  return 0;
1884 }
1885 
1886 static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
1887 {
1888  DASHContext *c = s->priv_data;
1889  OutputStream *os = &c->streams[avpkt->stream_index];
1890  AVFormatContext *oc = os->ctx;
1891  if (oc->oformat->check_bitstream) {
1892  int ret;
1893  AVPacket pkt = *avpkt;
1894  pkt.stream_index = 0;
1895  ret = oc->oformat->check_bitstream(oc, &pkt);
1896  if (ret == 1) {
1897  AVStream *st = s->streams[avpkt->stream_index];
1898  AVStream *ost = oc->streams[0];
1899  st->internal->bsfcs = ost->internal->bsfcs;
1900  st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
1901  ost->internal->bsfcs = NULL;
1902  ost->internal->nb_bsfcs = 0;
1903  }
1904  return ret;
1905  }
1906  return 1;
1907 }
1908 
1909 #define OFFSET(x) offsetof(DASHContext, x)
1910 #define E AV_OPT_FLAG_ENCODING_PARAM
1911 static const AVOption options[] = {
1912  { "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 },
1913  { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
1914  { "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 },
1915 #if FF_API_DASH_MIN_SEG_DURATION
1916  { "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 },
1917 #endif
1918  { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E },
1919  { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1920  { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1921  { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1922  { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1923  { "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 },
1924  { "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 },
1925  { "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 },
1926  { "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 },
1927  { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1928  { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1929  { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1930  { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1931  { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1932  { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
1933  { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1934  { "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},
1935  { "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 },
1936  { "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"},
1937  { "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX, E, "segment_type"},
1938  { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX, E, "segment_type"},
1939  { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX, E, "segment_type"},
1940  { "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 },
1941  { "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 },
1942  { "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},
1943  { NULL },
1944 };
1945 
1946 static const AVClass dash_class = {
1947  .class_name = "dash muxer",
1948  .item_name = av_default_item_name,
1949  .option = options,
1950  .version = LIBAVUTIL_VERSION_INT,
1951 };
1952 
1954  .name = "dash",
1955  .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
1956  .extensions = "mpd",
1957  .priv_data_size = sizeof(DASHContext),
1958  .audio_codec = AV_CODEC_ID_AAC,
1959  .video_codec = AV_CODEC_ID_H264,
1961  .init = dash_init,
1965  .deinit = dash_free,
1966  .check_bitstream = dash_check_bitstream,
1967  .priv_class = &dash_class,
1968 };
#define FF_COMPLIANCE_EXPERIMENTAL
Allow nonstandardized experimental things.
Definition: avcodec.h:2638
SegmentType segment_type
Definition: dashenc.c:92
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:690
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
Definition: avformat.h:1940
#define NULL
Definition: coverity.c:32
char * format_options_str
Definition: dashenc.c: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:1130
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:1464
AVOption.
Definition: opt.h:246
static int parse_adaptation_sets(AVFormatContext *s)
Definition: dashenc.c:838
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, const char *filename, char *agroup, char *codecs, char *ccgroup)
Definition: hlsplaylist.c:51
static const AVOption options[]
Definition: dashenc.c:1911
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:885
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:1321
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:3970
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:1483
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:1471
int ff_is_http_proto(char *filename)
Utility function to check if the file uses http or https protocol.
Definition: utils.c:5691
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:1138
uint8_t chroma_sample_position
Definition: av1.h:36
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3962
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:655
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:497
static struct codec_string codecs[]
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:1398
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:4036
AVRational min_frame_rate
Definition: dashenc.c:75
AVOptions.
miscellaneous OS support macros and functions.
void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, const char *filename, char *language, int name_id, int is_default)
Definition: hlsplaylist.c:38
const AVCodecTag ff_codec_movvideo_tags[]
Definition: isom.c:75
static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type)
Definition: dashenc.c:803
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:1500
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:5684
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:4502
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:1531
static void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
Definition: dashenc.c:1551
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:1523
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:730
static struct @321 state
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
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: avcodec.h:3999
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1514
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:714
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:952
#define E
Definition: dashenc.c:1910
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2040
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1598
int hls_playlist
Definition: dashenc.c: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:1698
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:3966
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:1886
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:1496
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1488
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:3988
void * opaque
User data.
Definition: avformat.h:1864
AVOutputFormat ff_dash_muxer
Definition: dashenc.c:1953
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:159
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:3321
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: mux.c:516
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:496
int segments_size
Definition: dashenc.c:87
#define AV_ERROR_MAX_STRING_SIZE
Definition: error.h:83
#define OFFSET(x)
Definition: dashenc.c:1909
#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:1494
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:1204
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:749
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:2635
#define snprintf
Definition: snprintf.h:34
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4433
static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
Definition: dashenc.c:820
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:1448
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:471
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
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:323
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:4080
#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:293
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:1438
int64_t duration
Definition: dashenc.c:66
static int dash_write_header(AVFormatContext *s)
Definition: dashenc.c:1379
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:1844
int window_size
Definition: dashenc.c:114
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:349
#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:3984
int has_video
Definition: dashenc.c:125
int channels
Audio only.
Definition: avcodec.h:4076
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:1481
int avpriv_io_delete(const char *url)
Delete a resource.
Definition: avio.c:519
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:1261
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:605
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:674
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: avcodec.h:3974
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:1564
int stream_index
Definition: avcodec.h:1484
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:1459
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:1475
int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
Definition: avc.c:109
static const AVClass dash_class
Definition: dashenc.c:1946
#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