Browse code

Add WebM muxer

Patch by James Zern <jzern at google>

Originally committed as revision 23474 to svn://svn.ffmpeg.org/ffmpeg/trunk

James Zern authored on 2010/06/05 07:40:54
Showing 7 changed files
... ...
@@ -4,7 +4,7 @@ releases are sorted from youngest to oldest.
4 4
 
5 5
 version <next>:
6 6
 
7
-- WebM support in Matroska demuxer
7
+- WebM support in Matroska de/muxer
8 8
 - low overhead Ogg muxing
9 9
 - MMS-TCP support
10 10
 - VP8 de/encoding via libvpx
... ...
@@ -236,7 +236,7 @@ library:
236 236
 @item VC-1 test bitstream       @tab X @tab X
237 237
 @item WAV                       @tab X @tab X
238 238
 @item WavPack                   @tab   @tab X
239
-@item WebM                      @tab   @tab X
239
+@item WebM                      @tab X @tab X
240 240
 @item Wing Commander III movie  @tab   @tab X
241 241
     @tab Multimedia format used in Origin's Wing Commander III computer game.
242 242
 @item Westwood Studios audio    @tab   @tab X
... ...
@@ -512,6 +512,8 @@ OBJS-$(CONFIG_OGG_DEMUXER)             += flacdec.o flacdata.o flac.o \
512 512
                                           dirac.o mpeg12data.o
513 513
 OBJS-$(CONFIG_OGG_MUXER)               += xiph.o flacdec.o flacdata.o flac.o
514 514
 OBJS-$(CONFIG_RTP_MUXER)               += mpegvideo.o
515
+OBJS-$(CONFIG_WEBM_MUXER)              += xiph.o mpeg4audio.o \
516
+                                          flacdec.o flacdata.o flac.o
515 517
 
516 518
 # external codec libraries
517 519
 OBJS-$(CONFIG_LIBDIRAC_DECODER)           += libdiracdec.o
... ...
@@ -258,6 +258,9 @@ OBJS-$(CONFIG_W64_DEMUXER)               += wav.o riff.o raw.o
258 258
 OBJS-$(CONFIG_WAV_DEMUXER)               += wav.o riff.o raw.o
259 259
 OBJS-$(CONFIG_WAV_MUXER)                 += wav.o riff.o
260 260
 OBJS-$(CONFIG_WC3_DEMUXER)               += wc3movie.o
261
+OBJS-$(CONFIG_WEBM_MUXER)                += matroskaenc.o matroska.o \
262
+                                            riff.o isom.o avc.o \
263
+                                            flacenc_header.o
261 264
 OBJS-$(CONFIG_WSAUD_DEMUXER)             += westwood.o
262 265
 OBJS-$(CONFIG_WSVQA_DEMUXER)             += westwood.o
263 266
 OBJS-$(CONFIG_WV_DEMUXER)                += wv.o apetag.o id3v1.o
... ...
@@ -206,6 +206,7 @@ void av_register_all(void)
206 206
     REGISTER_DEMUXER  (W64, w64);
207 207
     REGISTER_MUXDEMUX (WAV, wav);
208 208
     REGISTER_DEMUXER  (WC3, wc3);
209
+    REGISTER_MUXER    (WEBM, webm);
209 210
     REGISTER_DEMUXER  (WSAUD, wsaud);
210 211
     REGISTER_DEMUXER  (WSVQA, wsvqa);
211 212
     REGISTER_DEMUXER  (WV, wv);
... ...
@@ -22,7 +22,7 @@
22 22
 #define AVFORMAT_AVFORMAT_H
23 23
 
24 24
 #define LIBAVFORMAT_VERSION_MAJOR 52
25
-#define LIBAVFORMAT_VERSION_MINOR 67
25
+#define LIBAVFORMAT_VERSION_MINOR 68
26 26
 #define LIBAVFORMAT_VERSION_MICRO  0
27 27
 
28 28
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
... ...
@@ -65,7 +65,11 @@ typedef struct {
65 65
     int             write_dts;
66 66
 } mkv_track;
67 67
 
68
+#define MODE_MATROSKAv2 0x01
69
+#define MODE_WEBM       0x02
70
+
68 71
 typedef struct MatroskaMuxContext {
72
+    int             mode;
69 73
     ByteIOContext   *dyn_bc;
70 74
     ebml_master     segment;
71 75
     int64_t         segment_offset;
... ...
@@ -565,6 +569,13 @@ static int mkv_write_tracks(AVFormatContext *s)
565 565
             }
566 566
         }
567 567
 
568
+        if (mkv->mode == MODE_WEBM && !(codec->codec_id == CODEC_ID_VP8 ||
569
+                                        codec->codec_id == CODEC_ID_VORBIS)) {
570
+            av_log(s, AV_LOG_ERROR,
571
+                   "Only VP8 video and Vorbis audio are supported for WebM.\n");
572
+            return AVERROR(EINVAL);
573
+        }
574
+
568 575
         switch (codec->codec_type) {
569 576
             case AVMEDIA_TYPE_VIDEO:
570 577
                 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
... ...
@@ -686,6 +697,9 @@ static int mkv_write_header(AVFormatContext *s)
686 686
     AVMetadataTag *tag;
687 687
     int ret;
688 688
 
689
+    if (!strcmp(s->oformat->name, "webm")) mkv->mode = MODE_WEBM;
690
+    else                                   mkv->mode = MODE_MATROSKAv2;
691
+
689 692
     mkv->md5_ctx = av_mallocz(av_md5_size);
690 693
     av_md5_init(mkv->md5_ctx);
691 694
     mkv->tracks = av_mallocz(s->nb_streams * sizeof(*mkv->tracks));
... ...
@@ -695,7 +709,7 @@ static int mkv_write_header(AVFormatContext *s)
695 695
     put_ebml_uint   (pb, EBML_ID_EBMLREADVERSION    ,           1);
696 696
     put_ebml_uint   (pb, EBML_ID_EBMLMAXIDLENGTH    ,           4);
697 697
     put_ebml_uint   (pb, EBML_ID_EBMLMAXSIZELENGTH  ,           8);
698
-    put_ebml_string (pb, EBML_ID_DOCTYPE            ,  "matroska");
698
+    put_ebml_string (pb, EBML_ID_DOCTYPE            , s->oformat->name);
699 699
     put_ebml_uint   (pb, EBML_ID_DOCTYPEVERSION     ,           2);
700 700
     put_ebml_uint   (pb, EBML_ID_DOCTYPEREADVERSION ,           2);
701 701
     end_ebml_master(pb, ebml_header);
... ...
@@ -738,8 +752,10 @@ static int mkv_write_header(AVFormatContext *s)
738 738
     ret = mkv_write_tracks(s);
739 739
     if (ret < 0) return ret;
740 740
 
741
-    ret = mkv_write_chapters(s);
742
-    if (ret < 0) return ret;
741
+    if (mkv->mode != MODE_WEBM) {
742
+        ret = mkv_write_chapters(s);
743
+        if (ret < 0) return ret;
744
+    }
743 745
 
744 746
     if (url_is_streamed(s->pb))
745 747
         mkv_write_seekhead(pb, mkv->main_seekhead);
... ...
@@ -1035,6 +1051,7 @@ static int mkv_write_trailer(AVFormatContext *s)
1035 1035
     return 0;
1036 1036
 }
1037 1037
 
1038
+#if CONFIG_MATROSKA_MUXER
1038 1039
 AVOutputFormat matroska_muxer = {
1039 1040
     "matroska",
1040 1041
     NULL_IF_CONFIG_SMALL("Matroska file format"),
... ...
@@ -1050,7 +1067,25 @@ AVOutputFormat matroska_muxer = {
1050 1050
     .codec_tag = (const AVCodecTag* const []){ff_codec_bmp_tags, ff_codec_wav_tags, 0},
1051 1051
     .subtitle_codec = CODEC_ID_TEXT,
1052 1052
 };
1053
+#endif
1054
+
1055
+#if CONFIG_WEBM_MUXER
1056
+AVOutputFormat webm_muxer = {
1057
+    "webm",
1058
+    NULL_IF_CONFIG_SMALL("WebM file format"),
1059
+    "video/webm",
1060
+    "webm",
1061
+    sizeof(MatroskaMuxContext),
1062
+    CODEC_ID_VORBIS,
1063
+    CODEC_ID_VP8,
1064
+    mkv_write_header,
1065
+    mkv_write_packet,
1066
+    mkv_write_trailer,
1067
+    .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS,
1068
+};
1069
+#endif
1053 1070
 
1071
+#if CONFIG_MATROSKA_AUDIO_MUXER
1054 1072
 AVOutputFormat matroska_audio_muxer = {
1055 1073
     "matroska",
1056 1074
     NULL_IF_CONFIG_SMALL("Matroska file format"),
... ...
@@ -1065,3 +1100,4 @@ AVOutputFormat matroska_audio_muxer = {
1065 1065
     .flags = AVFMT_GLOBALHEADER,
1066 1066
     .codec_tag = (const AVCodecTag* const []){ff_codec_wav_tags, 0},
1067 1067
 };
1068
+#endif