From 316d6c153caffaa9886968783e8d00aa9aca2640 Mon Sep 17 00:00:00 2001 From: James Zern Date: Fri, 4 Jun 2010 22:40:54 +0000 Subject: [PATCH] Add WebM muxer Patch by James Zern Originally committed as revision 23474 to svn://svn.ffmpeg.org/ffmpeg/trunk --- Changelog | 2 +- doc/general.texi | 2 +- libavcodec/Makefile | 2 ++ libavformat/Makefile | 3 +++ libavformat/allformats.c | 1 + libavformat/avformat.h | 2 +- libavformat/matroskaenc.c | 42 ++++++++++++++++++++++++++++++++++++--- 7 files changed, 48 insertions(+), 6 deletions(-) diff --git a/Changelog b/Changelog index 9ec089dc57..d3f32481ae 100644 --- a/Changelog +++ b/Changelog @@ -4,7 +4,7 @@ releases are sorted from youngest to oldest. version : -- WebM support in Matroska demuxer +- WebM support in Matroska de/muxer - low overhead Ogg muxing - MMS-TCP support - VP8 de/encoding via libvpx diff --git a/doc/general.texi b/doc/general.texi index 30d2cd2413..a9208a671d 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -236,7 +236,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 WebM @tab X @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/libavcodec/Makefile b/libavcodec/Makefile index c4e7bedf70..268e13f65f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -512,6 +512,8 @@ OBJS-$(CONFIG_OGG_DEMUXER) += flacdec.o flacdata.o flac.o \ dirac.o mpeg12data.o OBJS-$(CONFIG_OGG_MUXER) += xiph.o flacdec.o flacdata.o flac.o OBJS-$(CONFIG_RTP_MUXER) += mpegvideo.o +OBJS-$(CONFIG_WEBM_MUXER) += xiph.o mpeg4audio.o \ + flacdec.o flacdata.o flac.o # external codec libraries OBJS-$(CONFIG_LIBDIRAC_DECODER) += libdiracdec.o diff --git a/libavformat/Makefile b/libavformat/Makefile index ac812cca6c..4b8103fed2 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -258,6 +258,9 @@ OBJS-$(CONFIG_W64_DEMUXER) += wav.o riff.o raw.o OBJS-$(CONFIG_WAV_DEMUXER) += wav.o riff.o raw.o OBJS-$(CONFIG_WAV_MUXER) += wav.o riff.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o +OBJS-$(CONFIG_WEBM_MUXER) += matroskaenc.o matroska.o \ + riff.o isom.o avc.o \ + flacenc_header.o OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood.o OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood.o OBJS-$(CONFIG_WV_DEMUXER) += wv.o apetag.o id3v1.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index b2f1194f69..2fd2b4cac3 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -206,6 +206,7 @@ void av_register_all(void) REGISTER_DEMUXER (W64, w64); REGISTER_MUXDEMUX (WAV, wav); REGISTER_DEMUXER (WC3, wc3); + REGISTER_MUXER (WEBM, webm); REGISTER_DEMUXER (WSAUD, wsaud); REGISTER_DEMUXER (WSVQA, wsvqa); REGISTER_DEMUXER (WV, wv); diff --git a/libavformat/avformat.h b/libavformat/avformat.h index bd965e36f6..57a6bcec4a 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 67 +#define LIBAVFORMAT_VERSION_MINOR 68 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 2b2a4650da..9e765448c9 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -65,7 +65,11 @@ typedef struct { int write_dts; } mkv_track; +#define MODE_MATROSKAv2 0x01 +#define MODE_WEBM 0x02 + typedef struct MatroskaMuxContext { + int mode; ByteIOContext *dyn_bc; ebml_master segment; int64_t segment_offset; @@ -565,6 +569,13 @@ static int mkv_write_tracks(AVFormatContext *s) } } + if (mkv->mode == MODE_WEBM && !(codec->codec_id == CODEC_ID_VP8 || + codec->codec_id == CODEC_ID_VORBIS)) { + av_log(s, AV_LOG_ERROR, + "Only VP8 video and Vorbis audio are supported for WebM.\n"); + return AVERROR(EINVAL); + } + switch (codec->codec_type) { case AVMEDIA_TYPE_VIDEO: put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO); @@ -686,6 +697,9 @@ static int mkv_write_header(AVFormatContext *s) AVMetadataTag *tag; int ret; + if (!strcmp(s->oformat->name, "webm")) mkv->mode = MODE_WEBM; + else mkv->mode = MODE_MATROSKAv2; + mkv->md5_ctx = av_mallocz(av_md5_size); av_md5_init(mkv->md5_ctx); mkv->tracks = av_mallocz(s->nb_streams * sizeof(*mkv->tracks)); @@ -695,7 +709,7 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4); put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8); - put_ebml_string (pb, EBML_ID_DOCTYPE , "matroska"); + put_ebml_string (pb, EBML_ID_DOCTYPE , s->oformat->name); put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 2); put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 2); end_ebml_master(pb, ebml_header); @@ -738,8 +752,10 @@ static int mkv_write_header(AVFormatContext *s) ret = mkv_write_tracks(s); if (ret < 0) return ret; - ret = mkv_write_chapters(s); - if (ret < 0) return ret; + if (mkv->mode != MODE_WEBM) { + ret = mkv_write_chapters(s); + if (ret < 0) return ret; + } if (url_is_streamed(s->pb)) mkv_write_seekhead(pb, mkv->main_seekhead); @@ -1035,6 +1051,7 @@ static int mkv_write_trailer(AVFormatContext *s) return 0; } +#if CONFIG_MATROSKA_MUXER AVOutputFormat matroska_muxer = { "matroska", NULL_IF_CONFIG_SMALL("Matroska file format"), @@ -1050,7 +1067,25 @@ AVOutputFormat matroska_muxer = { .codec_tag = (const AVCodecTag* const []){ff_codec_bmp_tags, ff_codec_wav_tags, 0}, .subtitle_codec = CODEC_ID_TEXT, }; +#endif +#if CONFIG_WEBM_MUXER +AVOutputFormat webm_muxer = { + "webm", + NULL_IF_CONFIG_SMALL("WebM file format"), + "video/webm", + "webm", + sizeof(MatroskaMuxContext), + CODEC_ID_VORBIS, + CODEC_ID_VP8, + mkv_write_header, + mkv_write_packet, + mkv_write_trailer, + .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, +}; +#endif + +#if CONFIG_MATROSKA_AUDIO_MUXER AVOutputFormat matroska_audio_muxer = { "matroska", NULL_IF_CONFIG_SMALL("Matroska file format"), @@ -1065,3 +1100,4 @@ AVOutputFormat matroska_audio_muxer = { .flags = AVFMT_GLOBALHEADER, .codec_tag = (const AVCodecTag* const []){ff_codec_wav_tags, 0}, }; +#endif