From 470491faed80883d9e5d50715947a880f040c5be Mon Sep 17 00:00:00 2001 From: James Zern Date: Sat, 22 May 2010 01:41:32 +0000 Subject: [PATCH] matroskadec: Support webm doctype Patch by James Zern Originally committed as revision 23245 to svn://svn.ffmpeg.org/ffmpeg/trunk --- Changelog | 1 + doc/general.texi | 1 + libavformat/avformat.h | 2 +- libavformat/matroskadec.c | 29 +++++++++++++++++++++-------- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Changelog b/Changelog index b5c578207b..c3ea45b434 100644 --- a/Changelog +++ b/Changelog @@ -71,6 +71,7 @@ version : - spectral extension support in the E-AC-3 decoder - unsharp video filter - RTP hinting in the mov/3gp/mp4 muxer +- WebM support in Matroska demuxer diff --git a/doc/general.texi b/doc/general.texi index 1bfde02bc2..bb199f6501 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -234,6 +234,7 @@ library: @item VC-1 test bitstream @tab X @tab X @item WAV @tab X @tab X @item WavPack @tab @tab X +@item WebM @tab @tab X @item Wing Commander III movie @tab @tab X @tab Multimedia format used in Origin's Wing Commander III computer game. @item Westwood Studios audio @tab @tab X diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 88cabc5468..91d69117f7 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -22,7 +22,7 @@ #define AVFORMAT_AVFORMAT_H #define LIBAVFORMAT_VERSION_MAJOR 52 -#define LIBAVFORMAT_VERSION_MINOR 63 +#define LIBAVFORMAT_VERSION_MINOR 64 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 1bde1af8c4..e5d34d7b41 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -505,6 +505,8 @@ static EbmlSyntax matroska_clusters[] = { { 0 } }; +static const char *matroska_doctypes[] = { "matroska", "webm" }; + /* * Return: Whether we reached the end of a level in the hierarchy or not. */ @@ -825,8 +827,7 @@ static void ebml_free(EbmlSyntax *syntax, void *data) static int matroska_probe(AVProbeData *p) { uint64_t total = 0; - int len_mask = 0x80, size = 1, n = 1; - static const char probe_data[] = "matroska"; + int len_mask = 0x80, size = 1, n = 1, i; /* EBML header? */ if (AV_RB32(p->buf) != EBML_ID_HEADER) @@ -848,13 +849,16 @@ static int matroska_probe(AVProbeData *p) if (p->buf_size < 4 + size + total) return 0; - /* The header must contain the document type 'matroska'. For now, + /* The header should contain a known document type. For now, * we don't parse the whole header but simply check for the * availability of that array of characters inside the header. * Not fully fool-proof, but good enough. */ - for (n = 4+size; n <= 4+size+total-(sizeof(probe_data)-1); n++) - if (!memcmp(p->buf+n, probe_data, sizeof(probe_data)-1)) - return AVPROBE_SCORE_MAX; + for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++) { + int probelen = strlen(matroska_doctypes[i]); + for (n = 4+size; n <= 4+size+total-probelen; n++) + if (!memcmp(p->buf+n, matroska_doctypes[i], probelen)) + return AVPROBE_SCORE_MAX; + } return 0; } @@ -1141,14 +1145,23 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) /* First read the EBML header. */ if (ebml_parse(matroska, ebml_syntax, &ebml) || ebml.version > EBML_VERSION || ebml.max_size > sizeof(uint64_t) - || ebml.id_length > sizeof(uint32_t) || strcmp(ebml.doctype, "matroska") - || ebml.doctype_version > 2) { + || ebml.id_length > sizeof(uint32_t) || ebml.doctype_version > 2) { av_log(matroska->ctx, AV_LOG_ERROR, "EBML header using unsupported features\n" "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", ebml.version, ebml.doctype, ebml.doctype_version); + ebml_free(ebml_syntax, &ebml); + return AVERROR_PATCHWELCOME; + } + for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++) + if (!strcmp(ebml.doctype, matroska_doctypes[i])) + break; + if (i >= FF_ARRAY_ELEMS(matroska_doctypes)) { + av_log(s, AV_LOG_ERROR, "Unknown EBML doctype '%s'\n", ebml.doctype); + ebml_free(ebml_syntax, &ebml); return AVERROR_PATCHWELCOME; } + av_metadata_set2(&s->metadata, "doctype", ebml.doctype, 0); ebml_free(ebml_syntax, &ebml); /* The next thing is a segment. */