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