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