FFmpeg  4.3
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:webm: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 && (!filename)) ||
175  (!w->is_live && (!irange || !cues_start || !cues_end || !filename || !bandwidth))) {
176  return AVERROR_INVALIDDATA;
177  }
178  avio_printf(s->pb, "<Representation id=\"%s\"", id);
179  // if bandwidth for live was not provided, use a default
180  if (w->is_live && !bandwidth) {
181  bandwidth_str = (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ? "128000" : "1000000";
182  } else {
183  bandwidth_str = bandwidth->value;
184  }
185  avio_printf(s->pb, " bandwidth=\"%s\"", bandwidth_str);
186  if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && output_width)
187  avio_printf(s->pb, " width=\"%d\"", stream->codecpar->width);
188  if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && output_height)
189  avio_printf(s->pb, " height=\"%d\"", stream->codecpar->height);
190  if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && output_sample_rate)
191  avio_printf(s->pb, " audioSamplingRate=\"%d\"", stream->codecpar->sample_rate);
192  if (w->is_live) {
193  // For live streams, Codec and Mime Type always go in the Representation tag.
194  avio_printf(s->pb, " codecs=\"%s\"", get_codec_name(stream->codecpar->codec_id));
195  avio_printf(s->pb, " mimeType=\"%s/webm\"",
196  stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
197  // For live streams, subsegments always start with key frames. So this
198  // is always 1.
199  avio_printf(s->pb, " startsWithSAP=\"1\"");
200  avio_printf(s->pb, ">");
201  } else {
202  avio_printf(s->pb, ">\n");
203  avio_printf(s->pb, "<BaseURL>%s</BaseURL>\n", filename->value);
204  avio_printf(s->pb, "<SegmentBase\n");
205  avio_printf(s->pb, " indexRange=\"%s-%s\">\n", cues_start->value, cues_end->value);
206  avio_printf(s->pb, "<Initialization\n");
207  avio_printf(s->pb, " range=\"0-%s\" />\n", irange->value);
208  avio_printf(s->pb, "</SegmentBase>\n");
209  }
210  avio_printf(s->pb, "</Representation>\n");
211  return 0;
212 }
213 
214 /*
215  * Checks if width of all streams are the same. Returns 1 if true, 0 otherwise.
216  */
218  int first_width, i;
219  if (as->nb_streams < 2) return 1;
220  first_width = s->streams[as->streams[0]]->codecpar->width;
221  for (i = 1; i < as->nb_streams; i++)
222  if (first_width != s->streams[as->streams[i]]->codecpar->width)
223  return 0;
224  return 1;
225 }
226 
227 /*
228  * Checks if height of all streams are the same. Returns 1 if true, 0 otherwise.
229  */
231  int first_height, i;
232  if (as->nb_streams < 2) return 1;
233  first_height = s->streams[as->streams[0]]->codecpar->height;
234  for (i = 1; i < as->nb_streams; i++)
235  if (first_height != s->streams[as->streams[i]]->codecpar->height)
236  return 0;
237  return 1;
238 }
239 
240 /*
241  * Checks if sample rate of all streams are the same. Returns 1 if true, 0 otherwise.
242  */
244  int first_sample_rate, i;
245  if (as->nb_streams < 2) return 1;
246  first_sample_rate = s->streams[as->streams[0]]->codecpar->sample_rate;
247  for (i = 1; i < as->nb_streams; i++)
248  if (first_sample_rate != s->streams[as->streams[i]]->codecpar->sample_rate)
249  return 0;
250  return 1;
251 }
252 
254  WebMDashMuxContext *w = s->priv_data;
255  int i;
256  for (i = 0; i < w->nb_as; i++) {
257  av_freep(&w->as[i].streams);
258  }
259  av_freep(&w->as);
260  w->nb_as = 0;
261 }
262 
263 /*
264  * Parses a live header filename and computes the representation id,
265  * initialization pattern and the media pattern. Pass NULL if you don't want to
266  * compute any of those 3. Returns 0 on success and non-zero on failure.
267  *
268  * Name of the header file should conform to the following pattern:
269  * <file_description>_<representation_id>.hdr where <file_description> can be
270  * anything. The chunks should be named according to the following pattern:
271  * <file_description>_<representation_id>_<chunk_number>.chk
272  */
273 static int parse_filename(char *filename, char **representation_id,
274  char **initialization_pattern, char **media_pattern) {
275  char *underscore_pos = NULL;
276  char *period_pos = NULL;
277  char *filename_str = av_strdup(filename);
278  int ret = 0;
279 
280  if (!filename_str) {
281  ret = AVERROR(ENOMEM);
282  goto end;
283  }
284  underscore_pos = strrchr(filename_str, '_');
285  if (!underscore_pos) {
287  goto end;
288  }
289  period_pos = strchr(++underscore_pos, '.');
290  if (!period_pos) {
292  goto end;
293  }
294  *(underscore_pos - 1) = 0;
295  if (representation_id) {
296  *representation_id = av_malloc(period_pos - underscore_pos + 1);
297  if (!(*representation_id)) {
298  ret = AVERROR(ENOMEM);
299  goto end;
300  }
301  av_strlcpy(*representation_id, underscore_pos, period_pos - underscore_pos + 1);
302  }
303  if (initialization_pattern) {
304  *initialization_pattern = av_asprintf("%s_$RepresentationID$.hdr",
305  filename_str);
306  if (!(*initialization_pattern)) {
307  ret = AVERROR(ENOMEM);
308  goto end;
309  }
310  }
311  if (media_pattern) {
312  *media_pattern = av_asprintf("%s_$RepresentationID$_$Number$.chk",
313  filename_str);
314  if (!(*media_pattern)) {
315  ret = AVERROR(ENOMEM);
316  goto end;
317  }
318  }
319 
320 end:
321  av_freep(&filename_str);
322  return ret;
323 }
324 
325 /*
326  * Writes an Adaptation Set. Returns 0 on success and < 0 on failure.
327  */
328 static int write_adaptation_set(AVFormatContext *s, int as_index)
329 {
330  WebMDashMuxContext *w = s->priv_data;
331  AdaptationSet *as = &w->as[as_index];
332  AVCodecParameters *par = s->streams[as->streams[0]]->codecpar;
333  AVDictionaryEntry *lang;
334  int i;
335  static const char boolean[2][6] = { "false", "true" };
336  int subsegmentStartsWithSAP = 1;
337 
338  // Width, Height and Sample Rate will go in the AdaptationSet tag if they
339  // are the same for all contained Representations. otherwise, they will go
340  // on their respective Representation tag. For live streams, they always go
341  // in the Representation tag.
342  int width_in_as = 1, height_in_as = 1, sample_rate_in_as = 1;
343  if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
344  width_in_as = !w->is_live && check_matching_width(s, as);
345  height_in_as = !w->is_live && check_matching_height(s, as);
346  } else {
347  sample_rate_in_as = !w->is_live && check_matching_sample_rate(s, as);
348  }
349 
350  avio_printf(s->pb, "<AdaptationSet id=\"%s\"", as->id);
351  avio_printf(s->pb, " mimeType=\"%s/webm\"",
352  par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
353  avio_printf(s->pb, " codecs=\"%s\"", get_codec_name(par->codec_id));
354 
355  lang = av_dict_get(s->streams[as->streams[0]]->metadata, "language", NULL, 0);
356  if (lang) avio_printf(s->pb, " lang=\"%s\"", lang->value);
357 
358  if (par->codec_type == AVMEDIA_TYPE_VIDEO && width_in_as)
359  avio_printf(s->pb, " width=\"%d\"", par->width);
360  if (par->codec_type == AVMEDIA_TYPE_VIDEO && height_in_as)
361  avio_printf(s->pb, " height=\"%d\"", par->height);
362  if (par->codec_type == AVMEDIA_TYPE_AUDIO && sample_rate_in_as)
363  avio_printf(s->pb, " audioSamplingRate=\"%d\"", par->sample_rate);
364 
365  avio_printf(s->pb, " bitstreamSwitching=\"%s\"",
366  boolean[bitstream_switching(s, as)]);
367  avio_printf(s->pb, " subsegmentAlignment=\"%s\"",
368  boolean[w->is_live || subsegment_alignment(s, as)]);
369 
370  for (i = 0; i < as->nb_streams; i++) {
371  AVDictionaryEntry *kf = av_dict_get(s->streams[as->streams[i]]->metadata,
372  CLUSTER_KEYFRAME, NULL, 0);
373  if (!w->is_live && (!kf || !strncmp(kf->value, "0", 1))) subsegmentStartsWithSAP = 0;
374  }
375  avio_printf(s->pb, " subsegmentStartsWithSAP=\"%d\"", subsegmentStartsWithSAP);
376  avio_printf(s->pb, ">\n");
377 
378  if (w->is_live) {
379  AVDictionaryEntry *filename =
380  av_dict_get(s->streams[as->streams[0]]->metadata, FILENAME, NULL, 0);
381  char *initialization_pattern = NULL;
382  char *media_pattern = NULL;
383  int ret = parse_filename(filename->value, NULL, &initialization_pattern,
384  &media_pattern);
385  if (ret) return ret;
386  avio_printf(s->pb, "<ContentComponent id=\"1\" type=\"%s\"/>\n",
387  par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
388  avio_printf(s->pb, "<SegmentTemplate");
389  avio_printf(s->pb, " timescale=\"1000\"");
390  avio_printf(s->pb, " duration=\"%d\"", w->chunk_duration);
391  avio_printf(s->pb, " media=\"%s\"", media_pattern);
392  avio_printf(s->pb, " startNumber=\"%d\"", w->chunk_start_index);
393  avio_printf(s->pb, " initialization=\"%s\"", initialization_pattern);
394  avio_printf(s->pb, "/>\n");
395  av_free(initialization_pattern);
396  av_free(media_pattern);
397  }
398 
399  for (i = 0; i < as->nb_streams; i++) {
400  char *representation_id = NULL;
401  int ret;
402  if (w->is_live) {
403  AVDictionaryEntry *filename =
404  av_dict_get(s->streams[as->streams[i]]->metadata, FILENAME, NULL, 0);
405  if (!filename)
406  return AVERROR(EINVAL);
407  if (ret = parse_filename(filename->value, &representation_id, NULL, NULL))
408  return ret;
409  } else {
410  representation_id = av_asprintf("%d", w->representation_id++);
411  if (!representation_id) return AVERROR(ENOMEM);
412  }
413  ret = write_representation(s, s->streams[as->streams[i]],
414  representation_id, !width_in_as,
415  !height_in_as, !sample_rate_in_as);
416  av_free(representation_id);
417  if (ret) return ret;
418  }
419  avio_printf(s->pb, "</AdaptationSet>\n");
420  return 0;
421 }
422 
424 {
425  WebMDashMuxContext *w = s->priv_data;
426  char *p = w->adaptation_sets;
427  char *q;
428  enum { new_set, parsed_id, parsing_streams } state;
429  if (!w->adaptation_sets) {
430  av_log(s, AV_LOG_ERROR, "The 'adaptation_sets' option must be set.\n");
431  return AVERROR(EINVAL);
432  }
433  // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
434  state = new_set;
435  while (1) {
436  if (*p == '\0') {
437  if (state == new_set)
438  break;
439  else
440  return AVERROR(EINVAL);
441  } else if (state == new_set && *p == ' ') {
442  p++;
443  continue;
444  } else if (state == new_set && !strncmp(p, "id=", 3)) {
445  void *mem = av_realloc(w->as, sizeof(*w->as) * (w->nb_as + 1));
446  const char *comma;
447  if (mem == NULL)
448  return AVERROR(ENOMEM);
449  w->as = mem;
450  ++w->nb_as;
451  w->as[w->nb_as - 1].nb_streams = 0;
452  w->as[w->nb_as - 1].streams = NULL;
453  p += 3; // consume "id="
454  q = w->as[w->nb_as - 1].id;
455  comma = strchr(p, ',');
456  if (!comma || comma - p >= sizeof(w->as[w->nb_as - 1].id)) {
457  av_log(s, AV_LOG_ERROR, "'id' in 'adaptation_sets' is malformed.\n");
458  return AVERROR(EINVAL);
459  }
460  while (*p != ',') *q++ = *p++;
461  *q = 0;
462  p++;
463  state = parsed_id;
464  } else if (state == parsed_id && !strncmp(p, "streams=", 8)) {
465  p += 8; // consume "streams="
466  state = parsing_streams;
467  } else if (state == parsing_streams) {
468  struct AdaptationSet *as = &w->as[w->nb_as - 1];
469  int64_t num;
470  int ret = av_reallocp_array(&as->streams, ++as->nb_streams,
471  sizeof(*as->streams));
472  if (ret < 0)
473  return ret;
474  num = strtoll(p, &q, 10);
475  if (!av_isdigit(*p) || (*q != ' ' && *q != '\0' && *q != ',') ||
476  num < 0 || num >= s->nb_streams) {
477  av_log(s, AV_LOG_ERROR, "Invalid value for 'streams' in adapation_sets.\n");
478  return AVERROR(EINVAL);
479  }
480  as->streams[as->nb_streams - 1] = num;
481  if (*q == '\0') break;
482  if (*q == ' ') state = new_set;
483  p = ++q;
484  } else {
485  return -1;
486  }
487  }
488  return 0;
489 }
490 
492 {
493  int i;
494  double start = 0.0;
495  int ret;
496  WebMDashMuxContext *w = s->priv_data;
497 
498  for (unsigned i = 0; i < s->nb_streams; i++) {
499  enum AVCodecID codec_id = s->streams[i]->codecpar->codec_id;
502  return AVERROR(EINVAL);
503  }
504 
506  if (ret < 0) {
507  goto fail;
508  }
509  ret = write_header(s);
510  if (ret < 0) {
511  goto fail;
512  }
513  avio_printf(s->pb, "<Period id=\"0\"");
514  avio_printf(s->pb, " start=\"PT%gS\"", start);
515  if (!w->is_live) {
516  avio_printf(s->pb, " duration=\"PT%gS\"", get_duration(s));
517  }
518  avio_printf(s->pb, " >\n");
519 
520  for (i = 0; i < w->nb_as; i++) {
522  if (ret < 0) {
523  goto fail;
524  }
525  }
526 
527  avio_printf(s->pb, "</Period>\n");
528  write_footer(s);
529 fail:
531  return ret < 0 ? ret : 0;
532 }
533 
535 {
536  return AVERROR_EOF;
537 }
538 
539 #define OFFSET(x) offsetof(WebMDashMuxContext, x)
540 static const AVOption options[] = {
541  { "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 },
542  { "live", "create a live stream manifest", OFFSET(is_live), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
543  { "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 },
544  { "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 },
545  { "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 },
546  { "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 },
547  { "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 },
548  { NULL },
549 };
550 
551 static const AVClass webm_dash_class = {
552  .class_name = "WebM DASH Manifest muxer",
553  .item_name = av_default_item_name,
554  .option = options,
555  .version = LIBAVUTIL_VERSION_INT,
556 };
557 
559  .name = "webm_dash_manifest",
560  .long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"),
561  .mime_type = "application/xml",
562  .extensions = "xml",
563  .priv_data_size = sizeof(WebMDashMuxContext),
566  .priv_class = &webm_dash_class,
567 };
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
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
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:253
AVCodecDescriptor::name
const char * name
Name of the codec described by this descriptor.
Definition: codec_desc.h:46
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
check_matching_width
static int check_matching_width(AVFormatContext *s, AdaptationSet *as)
Definition: webmdashenc.c:217
CUES_START
#define CUES_START
Definition: matroska.h:371
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
AdaptationSet::id
int id
Definition: dashenc.c:83
AVOption
AVOption.
Definition: opt.h:246
write_footer
static void write_footer(AVFormatContext *s)
Definition: webmdashenc.c:121
matroska.h
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
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
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:534
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:423
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:491
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:186
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:208
OFFSET
#define OFFSET(x)
Definition: webmdashenc.c:539
write_packet
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:701
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:558
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:328
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
parse_filename
static int parse_filename(char *filename, char **representation_id, char **initialization_pattern, char **media_pattern)
Definition: webmdashenc.c:273
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:540
WebMDashMuxContext::minimum_update_period
int minimum_update_period
Definition: webmdashenc.c:58
w
FFmpeg Automated Testing Environment ************************************Introduction Using FATE from your FFmpeg source directory Submitting the results to the FFmpeg result aggregation server Uploading new samples to the fate suite FATE makefile targets and variables Makefile targets Makefile variables Examples Introduction **************FATE is an extended regression suite on the client side and a means for results aggregation and presentation on the server side The first part of this document explains how you can use FATE from your FFmpeg source directory to test your ffmpeg binary The second part describes how you can run FATE to submit the results to FFmpeg’s FATE server In any way you can have a look at the publicly viewable FATE results by visiting this as it can be seen if some test on some platform broke with their recent contribution This usually happens on the platforms the developers could not test on The second part of this document describes how you can run FATE to submit your results to FFmpeg’s FATE server If you want to submit your results be sure to check that your combination of OS and compiler is not already listed on the above mentioned website In the third part you can find a comprehensive listing of FATE makefile targets and variables Using FATE from your FFmpeg source directory **********************************************If you want to run FATE on your machine you need to have the samples in place You can get the samples via the build target fate rsync Use this command from the top level source this will cause FATE to fail NOTE To use a custom wrapper to run the pass ‘ target exec’ to ‘configure’ or set the TARGET_EXEC Make variable Submitting the results to the FFmpeg result aggregation server ****************************************************************To submit your results to the server you should run fate through the shell script ‘tests fate sh’ from the FFmpeg sources This script needs to be invoked with a configuration file as its first argument tests fate sh path to fate_config A configuration file template with comments describing the individual configuration variables can be found at ‘doc fate_config sh template’ Create a configuration that suits your based on the configuration template The ‘slot’ configuration variable can be any string that is not yet but it is suggested that you name it adhering to the following pattern ‘ARCH OS COMPILER COMPILER VERSION’ The configuration file itself will be sourced in a shell therefore all shell features may be used This enables you to setup the environment as you need it for your build For your first test runs the ‘fate_recv’ variable should be empty or commented out This will run everything as normal except that it will omit the submission of the results to the server The following files should be present in $workdir as specified in the configuration it may help to try out the ‘ssh’ command with one or more ‘ v’ options You should get detailed output concerning your SSH configuration and the authentication process The only thing left is to automate the execution of the fate sh script and the synchronisation of the samples directory Uploading new samples to the fate suite *****************************************If you need a sample uploaded send a mail to samples request This is for developers who have an account on the fate suite server If you upload new please make sure they are as small as space on each network bandwidth and so on benefit from smaller test cases Also keep in mind older checkouts use existing sample that means in practice generally do not remove or overwrite files as it likely would break older checkouts or releases Also all needed samples for a commit should be ideally before the push If you need an account for frequently uploading samples or you wish to help others by doing that send a mail to ffmpeg devel rsync vauL Duo ug o o w
Definition: fate.txt:150
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:551
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:243
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:255
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:230
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
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