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