FFmpeg
webmdashenc.c
Go to the documentation of this file.
1 /*
2  * WebM DASH Manifest XML muxer
3  * Copyright (c) 2014 Vignesh Venkatasubramanian
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /*
23  * WebM DASH Specification:
24  * https://sites.google.com/a/webmproject.org/wiki/adaptive-streaming/webm-dash-specification
25  * ISO DASH Specification:
26  * http://standards.iso.org/ittf/PubliclyAvailableStandards/c065274_ISO_IEC_23009-1_2014.zip
27  */
28 
29 #include <float.h>
30 #include <stdint.h>
31 #include <string.h>
32 #include <time.h>
33 
34 #include "avformat.h"
35 #include "matroska.h"
36 #include "mux.h"
37 
38 #include "libavutil/avstring.h"
39 #include "libavutil/dict.h"
40 #include "libavutil/mem.h"
41 #include "libavutil/opt.h"
43 
44 #include "libavcodec/codec_desc.h"
45 
46 typedef struct AdaptationSet {
47  char id[10];
48  int *streams;
49  int nb_streams;
51 
52 typedef struct WebMDashMuxContext {
53  const AVClass *class;
56  int nb_as;
58  int is_live;
65 
66 static const char *get_codec_name(int codec_id)
67 {
69 }
70 
72 {
73  int i = 0;
74  double max = 0.0;
75  for (i = 0; i < s->nb_streams; i++) {
76  AVDictionaryEntry *duration = av_dict_get(s->streams[i]->metadata,
77  DURATION, NULL, 0);
78  if (!duration || atof(duration->value) < 0) continue;
79  if (atof(duration->value) > max) max = atof(duration->value);
80  }
81  return max / 1000;
82 }
83 
85 {
86  WebMDashMuxContext *w = s->priv_data;
87  AVIOContext *pb = s->pb;
88  double min_buffer_time = 1.0;
89  avio_printf(pb, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
90  avio_printf(pb, "<MPD\n");
91  avio_printf(pb, " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
92  avio_printf(pb, " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\"\n");
93  avio_printf(pb, " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011\"\n");
94  avio_printf(pb, " type=\"%s\"\n", w->is_live ? "dynamic" : "static");
95  if (!w->is_live) {
96  avio_printf(pb, " mediaPresentationDuration=\"PT%gS\"\n",
97  get_duration(s));
98  }
99  avio_printf(pb, " minBufferTime=\"PT%gS\"\n", min_buffer_time);
100  avio_printf(pb, " profiles=\"%s\"%s",
101  w->is_live ? "urn:mpeg:dash:profile:isoff-live:2011" : "urn:mpeg:dash:profile:webm-on-demand:2012",
102  w->is_live ? "\n" : ">\n");
103  if (w->is_live) {
104  time_t local_time = time(NULL);
105  struct tm gmt_buffer;
106  struct tm *gmt = gmtime_r(&local_time, &gmt_buffer);
107  char gmt_iso[21];
108  if (!strftime(gmt_iso, 21, "%Y-%m-%dT%H:%M:%SZ", gmt)) {
109  return AVERROR_UNKNOWN;
110  }
111  if (s->flags & AVFMT_FLAG_BITEXACT) {
112  av_strlcpy(gmt_iso, "", 1);
113  }
114  avio_printf(pb, " availabilityStartTime=\"%s\"\n", gmt_iso);
115  avio_printf(pb, " timeShiftBufferDepth=\"PT%gS\"\n", w->time_shift_buffer_depth);
116  avio_printf(pb, " minimumUpdatePeriod=\"PT%dS\"", w->minimum_update_period);
117  avio_printf(pb, ">\n");
118  if (w->utc_timing_url) {
119  avio_printf(pb, "<UTCTiming\n");
120  avio_printf(pb, " schemeIdUri=\"urn:mpeg:dash:utc:http-iso:2014\"\n");
121  avio_printf(pb, " value=\"%s\"/>\n", w->utc_timing_url);
122  }
123  }
124  return 0;
125 }
126 
128 {
129  avio_printf(s->pb, "</MPD>\n");
130 }
131 
133 {
134  int i;
135  AVDictionaryEntry *gold = av_dict_get(s->streams[as->streams[0]]->metadata,
136  CUE_TIMESTAMPS, NULL, 0);
137  if (!gold) return 0;
138  for (i = 1; i < as->nb_streams; i++) {
139  AVDictionaryEntry *ts = av_dict_get(s->streams[as->streams[i]]->metadata,
140  CUE_TIMESTAMPS, NULL, 0);
141  if (!ts || !av_strstart(ts->value, gold->value, NULL)) return 0;
142  }
143  return 1;
144 }
145 
147 {
148  int i;
149  const AVStream *gold_st = s->streams[as->streams[0]];
150  AVDictionaryEntry *gold_track_num = av_dict_get(gold_st->metadata,
151  TRACK_NUMBER, NULL, 0);
152  AVCodecParameters *gold_par = gold_st->codecpar;
153  if (!gold_track_num) return 0;
154  for (i = 1; i < as->nb_streams; i++) {
155  const AVStream *st = s->streams[as->streams[i]];
156  AVDictionaryEntry *track_num = av_dict_get(st->metadata,
157  TRACK_NUMBER, NULL, 0);
158  AVCodecParameters *par = st->codecpar;
159  if (!track_num ||
160  !av_strstart(track_num->value, gold_track_num->value, NULL) ||
161  gold_par->codec_id != par->codec_id ||
162  gold_par->extradata_size != par->extradata_size ||
163  (par->extradata_size > 0 &&
164  memcmp(gold_par->extradata, par->extradata, par->extradata_size))) {
165  return 0;
166  }
167  }
168  return 1;
169 }
170 
171 /*
172  * Writes a Representation within an Adaptation Set. Returns 0 on success and
173  * < 0 on failure.
174  */
175 static int write_representation(AVFormatContext *s, AVStream *st, char *id,
176  int output_width, int output_height,
177  int output_sample_rate)
178 {
179  WebMDashMuxContext *w = s->priv_data;
180  AVIOContext *pb = s->pb;
181  const AVCodecParameters *par = st->codecpar;
182  AVDictionaryEntry *bandwidth = av_dict_get(st->metadata, BANDWIDTH, NULL, 0);
183  const char *bandwidth_str;
184  avio_printf(pb, "<Representation id=\"%s\"", id);
185  if (bandwidth) {
186  bandwidth_str = bandwidth->value;
187  } else if (w->is_live) {
188  // if bandwidth for live was not provided, use a default
189  bandwidth_str = (par->codec_type == AVMEDIA_TYPE_AUDIO) ? "128000" : "1000000";
190  } else {
191  return AVERROR(EINVAL);
192  }
193  avio_printf(pb, " bandwidth=\"%s\"", bandwidth_str);
194  if (par->codec_type == AVMEDIA_TYPE_VIDEO && output_width)
195  avio_printf(pb, " width=\"%d\"", par->width);
196  if (par->codec_type == AVMEDIA_TYPE_VIDEO && output_height)
197  avio_printf(pb, " height=\"%d\"", par->height);
198  if (par->codec_type == AVMEDIA_TYPE_AUDIO && output_sample_rate)
199  avio_printf(pb, " audioSamplingRate=\"%d\"", par->sample_rate);
200  if (w->is_live) {
201  // For live streams, Codec and Mime Type always go in the Representation tag.
202  avio_printf(pb, " codecs=\"%s\"", get_codec_name(par->codec_id));
203  avio_printf(pb, " mimeType=\"%s/webm\"",
204  par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
205  // For live streams, subsegments always start with key frames. So this
206  // is always 1.
207  avio_printf(pb, " startsWithSAP=\"1\"");
208  avio_printf(pb, ">");
209  } else {
211  AVDictionaryEntry *cues_start = av_dict_get(st->metadata, CUES_START, NULL, 0);
212  AVDictionaryEntry *cues_end = av_dict_get(st->metadata, CUES_END, NULL, 0);
213  AVDictionaryEntry *filename = av_dict_get(st->metadata, FILENAME, NULL, 0);
214  if (!irange || !cues_start || !cues_end || !filename)
215  return AVERROR(EINVAL);
216 
217  avio_printf(pb, ">\n");
218  avio_printf(pb, "<BaseURL>%s</BaseURL>\n", filename->value);
219  avio_printf(pb, "<SegmentBase\n");
220  avio_printf(pb, " indexRange=\"%s-%s\">\n", cues_start->value, cues_end->value);
221  avio_printf(pb, "<Initialization\n");
222  avio_printf(pb, " range=\"0-%s\" />\n", irange->value);
223  avio_printf(pb, "</SegmentBase>\n");
224  }
225  avio_printf(pb, "</Representation>\n");
226  return 0;
227 }
228 
229 /*
230  * Checks if width of all streams are the same. Returns 1 if true, 0 otherwise.
231  */
233 {
234  int first_width, i;
235  if (as->nb_streams < 2) return 1;
236  first_width = s->streams[as->streams[0]]->codecpar->width;
237  for (i = 1; i < as->nb_streams; i++)
238  if (first_width != s->streams[as->streams[i]]->codecpar->width)
239  return 0;
240  return 1;
241 }
242 
243 /*
244  * Checks if height of all streams are the same. Returns 1 if true, 0 otherwise.
245  */
247 {
248  int first_height, i;
249  if (as->nb_streams < 2) return 1;
250  first_height = s->streams[as->streams[0]]->codecpar->height;
251  for (i = 1; i < as->nb_streams; i++)
252  if (first_height != s->streams[as->streams[i]]->codecpar->height)
253  return 0;
254  return 1;
255 }
256 
257 /*
258  * Checks if sample rate of all streams are the same. Returns 1 if true, 0 otherwise.
259  */
261 {
262  int first_sample_rate, i;
263  if (as->nb_streams < 2) return 1;
264  first_sample_rate = s->streams[as->streams[0]]->codecpar->sample_rate;
265  for (i = 1; i < as->nb_streams; i++)
266  if (first_sample_rate != s->streams[as->streams[i]]->codecpar->sample_rate)
267  return 0;
268  return 1;
269 }
270 
272 {
273  WebMDashMuxContext *w = s->priv_data;
274  int i;
275  for (i = 0; i < w->nb_as; i++) {
276  av_freep(&w->as[i].streams);
277  }
278  av_freep(&w->as);
279  w->nb_as = 0;
280 }
281 
282 /*
283  * Parses a live header filename and returns the position of the '_' and '.'
284  * delimiting <file_description> and <representation_id>.
285  *
286  * Name of the header file should conform to the following pattern:
287  * <file_description>_<representation_id>.hdr where <file_description> can be
288  * anything. The chunks should be named according to the following pattern:
289  * <file_description>_<representation_id>_<chunk_number>.chk
290  */
291 static int split_filename(char *filename, char **underscore_pos,
292  char **period_pos)
293 {
294  *underscore_pos = strrchr(filename, '_');
295  if (!*underscore_pos)
296  return AVERROR(EINVAL);
297  *period_pos = strchr(*underscore_pos, '.');
298  if (!*period_pos)
299  return AVERROR(EINVAL);
300  return 0;
301 }
302 
303 /*
304  * Writes an Adaptation Set. Returns 0 on success and < 0 on failure.
305  */
306 static int write_adaptation_set(AVFormatContext *s, int as_index)
307 {
308  WebMDashMuxContext *w = s->priv_data;
309  AdaptationSet *as = &w->as[as_index];
310  const AVStream *st = s->streams[as->streams[0]];
311  AVCodecParameters *par = st->codecpar;
312  AVDictionaryEntry *lang;
313  AVIOContext *pb = s->pb;
314  int i;
315  static const char boolean[2][6] = { "false", "true" };
316  int subsegmentStartsWithSAP = 1;
317 
318  // Width, Height and Sample Rate will go in the AdaptationSet tag if they
319  // are the same for all contained Representations. otherwise, they will go
320  // on their respective Representation tag. For live streams, they always go
321  // in the Representation tag.
322  int width_in_as = 1, height_in_as = 1, sample_rate_in_as = 1;
323  if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
324  width_in_as = !w->is_live && check_matching_width (s, as);
325  height_in_as = !w->is_live && check_matching_height(s, as);
326  } else {
327  sample_rate_in_as = !w->is_live && check_matching_sample_rate(s, as);
328  }
329 
330  avio_printf(pb, "<AdaptationSet id=\"%s\"", as->id);
331  avio_printf(pb, " mimeType=\"%s/webm\"",
332  par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
333  avio_printf(pb, " codecs=\"%s\"", get_codec_name(par->codec_id));
334 
335  lang = av_dict_get(st->metadata, "language", NULL, 0);
336  if (lang)
337  avio_printf(pb, " lang=\"%s\"", lang->value);
338 
339  if (par->codec_type == AVMEDIA_TYPE_VIDEO && width_in_as)
340  avio_printf(pb, " width=\"%d\"", par->width);
341  if (par->codec_type == AVMEDIA_TYPE_VIDEO && height_in_as)
342  avio_printf(pb, " height=\"%d\"", par->height);
343  if (par->codec_type == AVMEDIA_TYPE_AUDIO && sample_rate_in_as)
344  avio_printf(pb, " audioSamplingRate=\"%d\"", par->sample_rate);
345 
346  avio_printf(pb, " bitstreamSwitching=\"%s\"",
347  boolean[bitstream_switching(s, as)]);
348  avio_printf(pb, " subsegmentAlignment=\"%s\"",
349  boolean[w->is_live || subsegment_alignment(s, as)]);
350 
351  for (i = 0; i < as->nb_streams; i++) {
352  AVDictionaryEntry *kf = av_dict_get(s->streams[as->streams[i]]->metadata,
353  CLUSTER_KEYFRAME, NULL, 0);
354  if (!w->is_live && (!kf || !strncmp(kf->value, "0", 1))) subsegmentStartsWithSAP = 0;
355  }
356  avio_printf(pb, " subsegmentStartsWithSAP=\"%d\"", subsegmentStartsWithSAP);
357  avio_printf(pb, ">\n");
358 
359  if (w->is_live) {
360  AVDictionaryEntry *filename =
361  av_dict_get(st->metadata, FILENAME, NULL, 0);
362  char *underscore_pos, *period_pos;
363  int ret;
364  if (!filename)
365  return AVERROR(EINVAL);
366  ret = split_filename(filename->value, &underscore_pos, &period_pos);
367  if (ret) return ret;
368  *underscore_pos = '\0';
369  avio_printf(pb, "<ContentComponent id=\"1\" type=\"%s\"/>\n",
370  par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
371  avio_printf(pb, "<SegmentTemplate");
372  avio_printf(pb, " timescale=\"1000\"");
373  avio_printf(pb, " duration=\"%d\"", w->chunk_duration);
374  avio_printf(pb, " media=\"%s_$RepresentationID$_$Number$.chk\"",
375  filename->value);
376  avio_printf(pb, " startNumber=\"%d\"", w->chunk_start_index);
377  avio_printf(pb, " initialization=\"%s_$RepresentationID$.hdr\"",
378  filename->value);
379  avio_printf(pb, "/>\n");
380  *underscore_pos = '_';
381  }
382 
383  for (i = 0; i < as->nb_streams; i++) {
384  char buf[25], *representation_id = buf, *underscore_pos, *period_pos;
385  AVStream *st = s->streams[as->streams[i]];
386  int ret;
387  if (w->is_live) {
388  AVDictionaryEntry *filename =
389  av_dict_get(st->metadata, FILENAME, NULL, 0);
390  if (!filename)
391  return AVERROR(EINVAL);
392  ret = split_filename(filename->value, &underscore_pos, &period_pos);
393  if (ret < 0)
394  return ret;
395  representation_id = underscore_pos + 1;
396  *period_pos = '\0';
397  } else {
398  snprintf(buf, sizeof(buf), "%d", w->representation_id++);
399  }
400  ret = write_representation(s, st, representation_id, !width_in_as,
401  !height_in_as, !sample_rate_in_as);
402  if (ret) return ret;
403  if (w->is_live)
404  *period_pos = '.';
405  }
406  avio_printf(s->pb, "</AdaptationSet>\n");
407  return 0;
408 }
409 
411 {
412  WebMDashMuxContext *w = s->priv_data;
413  char *p = w->adaptation_sets;
414  char *q;
415  enum { new_set, parsed_id, parsing_streams } state;
416  if (!w->adaptation_sets) {
417  av_log(s, AV_LOG_ERROR, "The 'adaptation_sets' option must be set.\n");
418  return AVERROR(EINVAL);
419  }
420  // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
421  state = new_set;
422  while (1) {
423  if (*p == '\0') {
424  if (state == new_set)
425  break;
426  else
427  return AVERROR(EINVAL);
428  } else if (state == new_set && *p == ' ') {
429  p++;
430  continue;
431  } else if (state == new_set && !strncmp(p, "id=", 3)) {
432  void *mem = av_realloc(w->as, sizeof(*w->as) * (w->nb_as + 1));
433  const char *comma;
434  if (mem == NULL)
435  return AVERROR(ENOMEM);
436  w->as = mem;
437  ++w->nb_as;
438  w->as[w->nb_as - 1].nb_streams = 0;
439  w->as[w->nb_as - 1].streams = NULL;
440  p += 3; // consume "id="
441  q = w->as[w->nb_as - 1].id;
442  comma = strchr(p, ',');
443  if (!comma || comma - p >= sizeof(w->as[w->nb_as - 1].id)) {
444  av_log(s, AV_LOG_ERROR, "'id' in 'adaptation_sets' is malformed.\n");
445  return AVERROR(EINVAL);
446  }
447  while (*p != ',') *q++ = *p++;
448  *q = 0;
449  p++;
450  state = parsed_id;
451  } else if (state == parsed_id && !strncmp(p, "streams=", 8)) {
452  p += 8; // consume "streams="
453  state = parsing_streams;
454  } else if (state == parsing_streams) {
455  struct AdaptationSet *as = &w->as[w->nb_as - 1];
456  int64_t num;
457  int ret = av_reallocp_array(&as->streams, ++as->nb_streams,
458  sizeof(*as->streams));
459  if (ret < 0)
460  return ret;
461  num = strtoll(p, &q, 10);
462  if (!av_isdigit(*p) || (*q != ' ' && *q != '\0' && *q != ',') ||
463  num < 0 || num >= s->nb_streams) {
464  av_log(s, AV_LOG_ERROR, "Invalid value for 'streams' in adapation_sets.\n");
465  return AVERROR(EINVAL);
466  }
467  as->streams[as->nb_streams - 1] = num;
468  if (*q == '\0') break;
469  if (*q == ' ') state = new_set;
470  p = ++q;
471  } else {
472  return -1;
473  }
474  }
475  return 0;
476 }
477 
479 {
480  int i;
481  double start = 0.0;
482  int ret;
483  WebMDashMuxContext *w = s->priv_data;
484 
485  for (unsigned i = 0; i < s->nb_streams; i++) {
486  enum AVCodecID codec_id = s->streams[i]->codecpar->codec_id;
490  return AVERROR(EINVAL);
491  }
492 
494  if (ret < 0) {
495  goto fail;
496  }
497  ret = write_header(s);
498  if (ret < 0) {
499  goto fail;
500  }
501  avio_printf(s->pb, "<Period id=\"0\"");
502  avio_printf(s->pb, " start=\"PT%gS\"", start);
503  if (!w->is_live) {
504  avio_printf(s->pb, " duration=\"PT%gS\"", get_duration(s));
505  }
506  avio_printf(s->pb, " >\n");
507 
508  for (i = 0; i < w->nb_as; i++) {
510  if (ret < 0) {
511  goto fail;
512  }
513  }
514 
515  avio_printf(s->pb, "</Period>\n");
516  write_footer(s);
517 fail:
519  return ret < 0 ? ret : 0;
520 }
521 
523 {
524  return AVERROR_EOF;
525 }
526 
527 #define OFFSET(x) offsetof(WebMDashMuxContext, x)
528 static const AVOption options[] = {
529  { "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 },
530  { "live", "create a live stream manifest", OFFSET(is_live), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
531  { "chunk_start_index", "start index of the chunk", OFFSET(chunk_start_index), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
532  { "chunk_duration_ms", "duration of each chunk (in milliseconds)", OFFSET(chunk_duration), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
533  { "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, AV_OPT_FLAG_ENCODING_PARAM },
534  { "time_shift_buffer_depth", "Smallest time (in seconds) shifting buffer for which any Representation is guaranteed to be available.", OFFSET(time_shift_buffer_depth), AV_OPT_TYPE_DOUBLE, { .dbl = 60.0 }, 1.0, DBL_MAX, AV_OPT_FLAG_ENCODING_PARAM },
535  { "minimum_update_period", "Minimum Update Period (in seconds) of the manifest.", OFFSET(minimum_update_period), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
536  { NULL },
537 };
538 
539 static const AVClass webm_dash_class = {
540  .class_name = "WebM DASH Manifest muxer",
541  .item_name = av_default_item_name,
542  .option = options,
543  .version = LIBAVUTIL_VERSION_INT,
544 };
545 
547  .p.name = "webm_dash_manifest",
548  .p.long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"),
549  .p.mime_type = "application/xml",
550  .p.extensions = "xml",
551  .priv_data_size = sizeof(WebMDashMuxContext),
554  .p.priv_class = &webm_dash_class,
555 };
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:69
AVOutputFormat::name
const char * name
Definition: avformat.h:510
AVERROR
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
opt.h
check_matching_width
static int check_matching_width(AVFormatContext *s, const AdaptationSet *as)
Definition: webmdashenc.c:232
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:51
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: codec_par.h:47
bitstream_switching
static int bitstream_switching(AVFormatContext *s, const AdaptationSet *as)
Definition: webmdashenc.c:146
check_matching_sample_rate
static int check_matching_sample_rate(AVFormatContext *s, const AdaptationSet *as)
Definition: webmdashenc.c:260
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
free_adaptation_sets
static void free_adaptation_sets(AVFormatContext *s)
Definition: webmdashenc.c:271
AVCodecDescriptor::name
const char * name
Name of the codec described by this descriptor.
Definition: codec_desc.h:46
CUES_START
#define CUES_START
Definition: matroska.h:429
AdaptationSet::id
int id
Definition: dashenc.c:90
w
uint8_t w
Definition: llviddspenc.c:38
AVOption
AVOption.
Definition: opt.h:346
write_footer
static void write_footer(AVFormatContext *s)
Definition: webmdashenc.c:127
matroska.h
split_filename
static int split_filename(char *filename, char **underscore_pos, char **period_pos)
Definition: webmdashenc.c:291
float.h
max
#define max(a, b)
Definition: cuda_runtime.h:33
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
FFOutputFormat::p
AVOutputFormat p
The public AVOutputFormat.
Definition: mux.h:65
AdaptationSet::nb_streams
int nb_streams
Definition: dashenc.c:101
fail
#define fail()
Definition: checkasm.h:179
gmtime_r
#define gmtime_r
Definition: time_internal.h:34
write_representation
static int write_representation(AVFormatContext *s, AVStream *st, char *id, int output_width, int output_height, int output_sample_rate)
Definition: webmdashenc.c:175
AdaptationSet::streams
int * streams
Definition: webmdashenc.c:48
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
duration
int64_t duration
Definition: movenc.c:65
av_dict_get
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:62
webm_dash_manifest_write_packet
static int webm_dash_manifest_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: webmdashenc.c:522
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_OPT_TYPE_DOUBLE
@ AV_OPT_TYPE_DOUBLE
Definition: opt.h:237
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
AV_CODEC_ID_VP9
@ AV_CODEC_ID_VP9
Definition: codec_id.h:220
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:134
TRACK_NUMBER
#define TRACK_NUMBER
Definition: matroska.h:436
WebMDashMuxContext::representation_id
int representation_id
Definition: webmdashenc.c:57
get_duration
static double get_duration(AVFormatContext *s)
Definition: webmdashenc.c:71
CLUSTER_KEYFRAME
#define CLUSTER_KEYFRAME
Definition: matroska.h:434
ff_webm_dash_manifest_muxer
const FFOutputFormat ff_webm_dash_manifest_muxer
Definition: webmdashenc.c:546
codec_id
enum AVCodecID codec_id
Definition: vaapi_decode.c:387
write_header
static int write_header(AVFormatContext *s)
Definition: webmdashenc.c:84
get_codec_name
static const char * get_codec_name(int codec_id)
Definition: webmdashenc.c:66
time_internal.h
WebMDashMuxContext::is_live
int is_live
Definition: webmdashenc.c:58
AVFormatContext
Format I/O context.
Definition: avformat.h:1255
parse_adaptation_sets
static int parse_adaptation_sets(AVFormatContext *s)
Definition: webmdashenc.c:410
subsegment_alignment
static int subsegment_alignment(AVFormatContext *s, const AdaptationSet *as)
Definition: webmdashenc.c:132
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:766
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
WebMDashMuxContext::chunk_duration
int chunk_duration
Definition: webmdashenc.c:60
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
AV_CODEC_ID_AV1
@ AV_CODEC_ID_AV1
Definition: codec_id.h:280
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
WebMDashMuxContext::adaptation_sets
char * adaptation_sets
Definition: webmdashenc.c:54
AVStream::metadata
AVDictionary * metadata
Definition: avformat.h:823
FFOutputFormat
Definition: mux.h:61
time.h
WebMDashMuxContext
Definition: webmdashenc.c:52
CUES_END
#define CUES_END
Definition: matroska.h:430
AV_OPT_FLAG_ENCODING_PARAM
#define AV_OPT_FLAG_ENCODING_PARAM
A generic parameter which can be set by the user for muxing or encoding.
Definition: opt.h:269
AVCodecParameters::sample_rate
int sample_rate
Audio only.
Definition: codec_par.h:184
webm_dash_manifest_write_header
static int webm_dash_manifest_write_header(AVFormatContext *s)
Definition: webmdashenc.c:478
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
AVCodecParameters::extradata_size
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:73
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
WebMDashMuxContext::nb_as
int nb_as
Definition: webmdashenc.c:56
AV_CODEC_ID_OPUS
@ AV_CODEC_ID_OPUS
Definition: codec_id.h:500
INITIALIZATION_RANGE
#define INITIALIZATION_RANGE
Definition: matroska.h:428
av_isdigit
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition: avstring.h:202
av_reallocp_array
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate an array through a pointer to a pointer.
Definition: mem.c:225
OFFSET
#define OFFSET(x)
Definition: webmdashenc.c:527
av_strstart
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:36
check_matching_height
static int check_matching_height(AVFormatContext *s, const AdaptationSet *as)
Definition: webmdashenc.c:246
FILENAME
#define FILENAME
Definition: matroska.h:431
WebMDashMuxContext::chunk_start_index
int chunk_start_index
Definition: webmdashenc.c:59
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
BANDWIDTH
#define BANDWIDTH
Definition: matroska.h:432
AVCodecParameters::height
int height
Definition: codec_par.h:135
DURATION
#define DURATION
Definition: matroska.h:433
AdaptationSet
Definition: dashenc.c:89
CUE_TIMESTAMPS
#define CUE_TIMESTAMPS
Definition: matroska.h:435
write_packet
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
Definition: ffmpeg_mux.c:209
write_adaptation_set
static int write_adaptation_set(AVFormatContext *s, int as_index)
Definition: webmdashenc.c:306
ret
ret
Definition: filter_design.txt:187
AVFMT_FLAG_BITEXACT
#define AVFMT_FLAG_BITEXACT
When muxing, try to avoid writing any random/volatile data to the output.
Definition: avformat.h:1423
AVStream
Stream structure.
Definition: avformat.h:743
AVClass::class_name
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:71
options
static const AVOption options[]
Definition: webmdashenc.c:528
WebMDashMuxContext::minimum_update_period
int minimum_update_period
Definition: webmdashenc.c:63
avformat.h
dict.h
avio_printf
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
webm_dash_class
static const AVClass webm_dash_class
Definition: webmdashenc.c:539
state
static struct @399 state
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:235
WebMDashMuxContext::time_shift_buffer_depth
double time_shift_buffer_depth
Definition: webmdashenc.c:62
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
AVDictionaryEntry
Definition: dict.h:89
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
AVPacket
This structure stores compressed data.
Definition: packet.h:501
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:251
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AV_CODEC_ID_VP8
@ AV_CODEC_ID_VP8
Definition: codec_id.h:192
av_strlcpy
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:85
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
avcodec_descriptor_get
const AVCodecDescriptor * avcodec_descriptor_get(enum AVCodecID id)
Definition: codec_desc.c:3734
AV_CODEC_ID_VORBIS
@ AV_CODEC_ID_VORBIS
Definition: codec_id.h:445
AVDictionaryEntry::value
char * value
Definition: dict.h:91
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:239
WebMDashMuxContext::as
AdaptationSet * as
Definition: webmdashenc.c:55
codec_desc.h
WebMDashMuxContext::utc_timing_url
char * utc_timing_url
Definition: webmdashenc.c:61
snprintf
#define snprintf
Definition: snprintf.h:34
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:155
mux.h