]> git.sesse.net Git - vlc/blob - extras/contrib/src/Patches/ffmpeg-libvpx.patch
ffmpeg-libvpx: fixed typo
[vlc] / extras / contrib / src / Patches / ffmpeg-libvpx.patch
1 Index: configure
2 ===================================================================
3 --- configure   (revision 23210)
4 +++ configure   (working copy)
5 @@ -183,6 +183,7 @@ External library support:
6    --enable-libtheora       enable Theora encoding via libtheora [no]
7    --enable-libvorbis       enable Vorbis encoding via libvorbis,
8                             native implementation exists [no]
9 +  --enable-libvpx          enable VP8 support via libvpx [no]
10    --enable-libx264         enable H.264 encoding via x264 [no]
11    --enable-libxvid         enable Xvid encoding via xvidcore,
12                             native MPEG-4/Xvid encoder exists [no]
13 @@ -927,6 +928,7 @@ CONFIG_LIST="
14      libspeex
15      libtheora
16      libvorbis
17 +    libvpx
18      libx264
19      libxvid
20      lpc
21 @@ -1349,6 +1351,8 @@ libschroedinger_encoder_deps="libschroed
22  libspeex_decoder_deps="libspeex"
23  libtheora_encoder_deps="libtheora"
24  libvorbis_encoder_deps="libvorbis"
25 +libvpx_decoder_deps="libvpx"
26 +libvpx_encoder_deps="libvpx"
27  libx264_encoder_deps="libx264"
28  libxvid_encoder_deps="libxvid"
29  
30 @@ -2617,6 +2621,9 @@ enabled libschroedinger && add_cflags $(
31  enabled libspeex   && require  libspeex speex/speex.h speex_decoder_init -lspeex
32  enabled libtheora  && require  libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg
33  enabled libvorbis  && require  libvorbis vorbis/vorbisenc.h vorbis_info_init -lvorbisenc -lvorbis -logg
34 +enabled libvpx     && add_cflags -DHAVE_STDINT_H &&
35 +                      require2 libvpx "vpx_decoder.h vp8dx.h" "vpx_codec_dec_init_ver" -lvpx &&
36 +                      require2 libvpx "vpx_encoder.h vp8cx.h" "vpx_codec_enc_init_ver" -lvpx
37  enabled libx264    && require  libx264 x264.h x264_encoder_encode -lx264 -lm &&
38                        { check_cpp_condition x264.h "X264_BUILD >= 90" ||
39                          die "ERROR: libx264 version must be >= 0.90."; }
40 @@ -2886,6 +2893,7 @@ echo "libschroedinger enabled   ${libsch
41  echo "libspeex enabled          ${libspeex-no}"
42  echo "libtheora enabled         ${libtheora-no}"
43  echo "libvorbis enabled         ${libvorbis-no}"
44 +echo "libvpx enabled            ${libvpx-no}"
45  echo "libx264 enabled           ${libx264-no}"
46  echo "libxvid enabled           ${libxvid-no}"
47  echo "zlib enabled              ${zlib-no}"
48 Index: libavcodec/libvpxdec.c
49 ===================================================================
50 --- libavcodec/libvpxdec.c      (revision 0)
51 +++ libavcodec/libvpxdec.c      (revision 0)
52 @@ -0,0 +1,132 @@
53 +/*
54 + * Copyright (c) 2010, Google, Inc.
55 + *
56 + * This file is part of FFmpeg.
57 + *
58 + * FFmpeg is free software; you can redistribute it and/or
59 + * modify it under the terms of the GNU Lesser General Public
60 + * License as published by the Free Software Foundation; either
61 + * version 2.1 of the License, or (at your option) any later version.
62 + *
63 + * FFmpeg is distributed in the hope that it will be useful,
64 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
65 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
66 + * Lesser General Public License for more details.
67 + *
68 + * You should have received a copy of the GNU Lesser General Public
69 + * License along with FFmpeg; if not, write to the Free Software
70 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
71 + */
72 +
73 +/**
74 + * @file
75 + * VP8 decoder support via libvpx
76 + */
77 +
78 +#ifndef HAVE_STDINT_H
79 +# define HAVE_STDINT_H 1
80 +#endif
81 +
82 +#define VPX_CODEC_DISABLE_COMPAT 1
83 +#include <vpx_decoder.h>
84 +#include <vp8dx.h>
85 +
86 +#include "avcodec.h"
87 +
88 +typedef struct VP8DecoderContext {
89 +    vpx_codec_ctx_t decoder;
90 +} VP8Context;
91 +
92 +static av_cold int vp8_init(AVCodecContext *avctx)
93 +{
94 +    VP8Context *ctx = avctx->priv_data;
95 +    const struct vpx_codec_iface *iface = &vpx_codec_vp8_dx_algo;
96 +    struct vpx_codec_dec_cfg deccfg = {
97 +        /* token partitions+1 would be a decent choice */
98 +        .threads = FFMIN(avctx->thread_count, 16)
99 +    };
100 +
101 +    av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str());
102 +    av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config());
103 +
104 +    if (vpx_codec_dec_init(&ctx->decoder, iface, &deccfg, 0) != VPX_CODEC_OK) {
105 +        const char *error = vpx_codec_error(&ctx->decoder);
106 +        av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n",
107 +               error);
108 +        return AVERROR(EINVAL);
109 +    }
110 +
111 +    avctx->pix_fmt = PIX_FMT_YUV420P;
112 +    return 0;
113 +}
114 +
115 +static int vp8_decode(AVCodecContext *avctx,
116 +                      void *data, int *data_size, AVPacket *avpkt)
117 +{
118 +    VP8Context *ctx = avctx->priv_data;
119 +    AVFrame *picture = data;
120 +    const void *iter = NULL;
121 +    vpx_image_t *img;
122 +
123 +    /* end of stream, vp8 does no buffering */
124 +    if (!avpkt->size)
125 +        return 0;
126 +
127 +    if (vpx_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL, 0) !=
128 +        VPX_CODEC_OK) {
129 +        const char *error  = vpx_codec_error(&ctx->decoder);
130 +        const char *detail = vpx_codec_error_detail(&ctx->decoder);
131 +
132 +        av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error);
133 +        if (detail)
134 +            av_log(avctx, AV_LOG_ERROR, "  Additional information: %s\n",
135 +                   detail);
136 +        return AVERROR_INVALIDDATA;
137 +    }
138 +
139 +    if ((img = vpx_codec_get_frame(&ctx->decoder, &iter))) {
140 +        if (img->fmt != IMG_FMT_I420) {
141 +            av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d)\n",
142 +                   img->fmt);
143 +            return AVERROR_INVALIDDATA;
144 +        }
145 +
146 +        if ((int) img->d_w != avctx->width || (int) img->d_h != avctx->height) {
147 +            av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n",
148 +                   avctx->width, avctx->height, img->d_w, img->d_h);
149 +            if (avcodec_check_dimensions(avctx, img->d_w, img->d_h))
150 +                return AVERROR_INVALIDDATA;
151 +            avcodec_set_dimensions(avctx, img->d_w, img->d_h);
152 +        }
153 +        picture->data[0]     = img->planes[0];
154 +        picture->data[1]     = img->planes[1];
155 +        picture->data[2]     = img->planes[2];
156 +        picture->data[3]     = NULL;
157 +        picture->linesize[0] = img->stride[0];
158 +        picture->linesize[1] = img->stride[1];
159 +        picture->linesize[2] = img->stride[2];
160 +        picture->linesize[3] = 0;
161 +        *data_size           = sizeof(AVPicture);
162 +    }
163 +    return avpkt->size;
164 +}
165 +
166 +static av_cold int vp8_free(AVCodecContext *avctx)
167 +{
168 +    VP8Context *ctx = avctx->priv_data;
169 +    vpx_codec_destroy(&ctx->decoder);
170 +    return 0;
171 +}
172 +
173 +AVCodec libvpx_decoder = {
174 +    "libvpx",
175 +    AVMEDIA_TYPE_VIDEO,
176 +    CODEC_ID_VP8,
177 +    sizeof(VP8Context),
178 +    vp8_init,
179 +    NULL, /* encode */
180 +    vp8_free,
181 +    vp8_decode,
182 +    0, /* capabilities */
183 +    .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"),
184 +};
185 Index: libavcodec/options.c
186 ===================================================================
187 --- libavcodec/options.c        (revision 23210)
188 +++ libavcodec/options.c        (working copy)
189 @@ -414,6 +414,19 @@ static const AVOption options[]={
190  {"intra_refresh", "use periodic insertion of intra blocks instead of keyframes", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_INTRA_REFRESH, INT_MIN, INT_MAX, V|E, "flags2"},
191  {"crf_max", "in crf mode, prevents vbv from lowering quality beyond this point", OFFSET(crf_max), FF_OPT_TYPE_FLOAT, DEFAULT, 0, 51, V|E},
192  {"log_level_offset", "set the log level offset", OFFSET(log_level_offset), FF_OPT_TYPE_INT, 0, INT_MIN, INT_MAX },
193 +{"spatial_rsmpl", "Enable spatial resampling (VP8)", OFFSET(spatial_rsmpl), FF_OPT_TYPE_INT, 0, 0, 1, V|E},
194 +{"spatial_rsmpl_up", "Spatial resampling up watermark, percentage of target data buffer. (VP8)", OFFSET(spatial_rsmpl_up), FF_OPT_TYPE_INT, 60, 0, 100, V|E},
195 +{"spatial_rsmpl_down", "Spatial resampling down watermark, percentage of target data buffer. (VP8)", OFFSET(spatial_rsmpl_down), FF_OPT_TYPE_INT, 30, 0, 100, V|E},
196 +{"vbr_bias", "Two-pass mode CBR/VBR bias, 0-100 (VP8)", OFFSET(vbr_bias), FF_OPT_TYPE_INT, 50, 0, 100, V|E},
197 +{"lag", "Allow lagged encoding, given as frames (VP8)", OFFSET(lag), FF_OPT_TYPE_INT, 0, 0, INT_MAX, V|E},
198 +{"sharpness", "[0-7] (VP8)", OFFSET(sharpness), FF_OPT_TYPE_INT, 0, 0, 7, V|E},
199 +{"altref", "Allow use of alternate reference frame", OFFSET(altref), FF_OPT_TYPE_INT, 0, 0, 1, V|E},
200 +{"ar_max_frames", "Max frames used in creating alt. ref. [0,25]", OFFSET(ar_max_frames), FF_OPT_TYPE_INT, 0, 0, 25, V|E},
201 +{"ar_type", "Filter type used in creating alt. ref.", OFFSET(ar_type), FF_OPT_TYPE_INT, 0, 0, INT_MAX, V|E},
202 +{"ar_strength", "Filter strength used in creating alt. ref. [0,6]", OFFSET(ar_strength), FF_OPT_TYPE_INT, 0, 0, 6, V|E},
203 +{"mb_static_threshold", "", OFFSET(mb_static_threshold), FF_OPT_TYPE_INT, 800, 0, INT_MAX, V|E},
204 +{"rc_opt_occupancy", "number of bits which should be kept in the rc buffer during decoding", OFFSET(rc_optimal_buffer_occupancy), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
205 +{"token_partitions", "Number of sub-streams in bitstream (1,2,4,8). Used for parallelized decoding.", OFFSET(token_partitions), FF_OPT_TYPE_INT, 1, 1, INT_MAX, V|E},
206  {NULL},
207  };
208  
209 Index: libavcodec/allcodecs.c
210 ===================================================================
211 --- libavcodec/allcodecs.c      (revision 23210)
212 +++ libavcodec/allcodecs.c      (working copy)
213 @@ -349,6 +349,7 @@ void avcodec_register_all(void)
214      REGISTER_DECODER (LIBSPEEX, libspeex);
215      REGISTER_ENCODER (LIBTHEORA, libtheora);
216      REGISTER_ENCODER (LIBVORBIS, libvorbis);
217 +    REGISTER_ENCDEC  (LIBVPX, libvpx);
218      REGISTER_ENCODER (LIBX264, libx264);
219      REGISTER_ENCODER (LIBXVID, libxvid);
220  
221 Index: libavcodec/avcodec.h
222 ===================================================================
223 --- libavcodec/avcodec.h        (revision 23210)
224 +++ libavcodec/avcodec.h        (working copy)
225 @@ -30,7 +30,7 @@
226  #include "libavutil/avutil.h"
227  
228  #define LIBAVCODEC_VERSION_MAJOR 52
229 -#define LIBAVCODEC_VERSION_MINOR 68
230 +#define LIBAVCODEC_VERSION_MINOR 69
231  #define LIBAVCODEC_VERSION_MICRO  3
232  
233  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
234 @@ -2659,6 +2659,160 @@ typedef struct AVCodecContext {
235      float crf_max;
236  
237      int log_level_offset;
238 +
239 +    /**
240 +     * Enable spatial resampling
241 +     *
242 +     * Spatial resampling allows the codec to compress a lower resolution
243 +     * version of the frame, which is then upscaled by the encoder to the
244 +     * correct presentation resolution. This increases visual quality at low
245 +     * data rates, at the expense of CPU time on the encoder/decoder.
246 +     * - encoding: Set by user.
247 +     * - decoding: unused
248 +     *
249 +     *  \attention VP8 specific
250 +     */
251 +    int spatial_rsmpl;
252 +
253 +    /**
254 +     * Spatial resampling up watermark.
255 +     *
256 +     * This threshold is described as a percentage of the target data buffer.
257 +     * When the data buffer rises above this percentage of fullness, the
258 +     * encoder will step up to a higher resolution version of the frame.
259 +     * - encoding: Set by user.
260 +     * - decoding: unused
261 +     *
262 +     *  \attention VP8 specific
263 +     */
264 +    int spatial_rsmpl_up;
265 +
266 +    /**
267 +     * Spatial resampling down watermark.
268 +     *
269 +     * This threshold is described as a percentage of the target data buffer.
270 +     * When the data buffer falls below this percentage of fullness, the
271 +     * encoder will step down to a lower resolution version of the frame.
272 +     * - encoding: Set by user.
273 +     * - decoding: unused
274 +     *
275 +     *  \attention VP8 specific
276 +     */
277 +    int spatial_rsmpl_down;
278 +
279 +    /**
280 +     * Two-pass mode CBR/VBR bias.
281 +     *
282 +     * Bias, expressed on a scale of 0 to 100, for determining target size for
283 +     * the current frame. The value 0 indicates the optimal CBR mode value
284 +     * should be used. The value 100 indicates the optimal VBR mode value
285 +     * should be used. Values in between indicate which way the encoder should
286 +     * "lean." RC mode bias between CBR and VBR(0-100: 0->CBR, 100->VBR)
287 +     * - encoding: Set by user.
288 +     * - decoding: unused
289 +     *
290 +     *  \attention VP8 specific
291 +     */
292 +    int vbr_bias;
293 +
294 +    /**
295 +     * Allow lagged encoding.
296 +     *
297 +     * If set, this value allows the encoder to consume a number of input
298 +     * frames before producing output frames. This allows the encoder to base
299 +     * decisions for the current frame on future frames. This does increase the
300 +     * latency of the encoding pipeline, so it is not appropriate in all
301 +     * situations (ex: realtime encoding). Half the output average output
302 +     * framerate is a reasonable default in other cases.
303 +     *
304 +     * Note that this is a maximum value -- the encoder may produce frames
305 +     * sooner than the given limit. Set this value to 0 to disable this
306 +     * feature.
307 +     * - encoding: Set by user.
308 +     * - decoding: unused
309 +     *
310 +     *  \attention VP8 specific
311 +     */
312 +    int lag;
313 +
314 +    /**
315 +     * Control sharpness preprocessing
316 +     *
317 +     * This setting does not impact any other setting and is largely a matter
318 +     * of personal preference.  A low sharpness setting will result in fewer
319 +     * visible artifacts but may blur the image somewhat; a high sharpness will
320 +     * result in a sharper image but may result in more visible artifacts.
321 +     * Valid Range: [0,7]
322 +     * - encoding: Set by user.
323 +     * - decoding: unused
324 +     *
325 +     *  \attention VP8 specific
326 +     */
327 +    int sharpness;
328 +
329 +    /**
330 +     * Allow encoder to automatically set and use alternate reference frame.
331 +     * - encoding: Set by user.
332 +     * - decoding: unused
333 +     *
334 +     *  \attention VP8 specific
335 +     */
336 +    int altref;
337 +
338 +    /**
339 +     * Set the max number of frames blurred creating the alternate reference frame.
340 +     * - encoding: Set by user.
341 +     * - decoding: unused
342 +     *
343 +     *  \attention VP8 specific
344 +     */
345 +    int ar_max_frames;
346 +
347 +    /**
348 +     * Set the type of filter to use for the alternate reference frame.
349 +     * - encoding: Set by user.
350 +     * - decoding: unused
351 +     *
352 +     *  \attention VP8 specific
353 +     */
354 +    int ar_type;
355 +
356 +    /**
357 +     * Set the filter strength for the alternate reference frame.
358 +     * - encoding: Set by user.
359 +     * - decoding: unused
360 +     *
361 +     *  \attention VP8 specific
362 +     */
363 +    int ar_strength;
364 +
365 +    /**
366 +     * Set the threshold for macroblocks treated as static.
367 +     * - encoding: Set by user.
368 +     * - decoding: unused
369 +     *
370 +     *  \attention VP8 specific
371 +     */
372 +    int mb_static_threshold;
373 +
374 +    /**
375 +     * Number of bits which should be maintained in rc buffer during decoding.
376 +     * - encoding: Set by user.
377 +     * - decoding: unused
378 +     *
379 +     *  \attention VP8 specific
380 +     */
381 +    int rc_optimal_buffer_occupancy;
382 +
383 +    /**
384 +     * Number of token partitions.
385 +     * Valid Values: {1,2,4,8}
386 +     * - encoding: Set by user.
387 +     * - decoding: unused
388 +     *
389 +     *  \attention VP8 specific
390 +     */
391 +    int token_partitions;
392  } AVCodecContext;
393  
394  /**
395 Index: libavcodec/Makefile
396 ===================================================================
397 --- libavcodec/Makefile (revision 23210)
398 +++ libavcodec/Makefile (working copy)
399 @@ -512,6 +512,7 @@ OBJS-$(CONFIG_OGG_DEMUXER)             +
400                                            dirac.o mpeg12data.o
401  OBJS-$(CONFIG_OGG_MUXER)               += xiph.o flacdec.o flacdata.o flac.o
402  OBJS-$(CONFIG_RTP_MUXER)               += mpegvideo.o
403 +OBJS-$(CONFIG_WEBM_MUXER)              += xiph.o
404  
405  # external codec libraries
406  OBJS-$(CONFIG_LIBDIRAC_DECODER)           += libdiracdec.o
407 @@ -536,6 +537,8 @@ OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER)  
408  OBJS-$(CONFIG_LIBSPEEX_DECODER)           += libspeexdec.o
409  OBJS-$(CONFIG_LIBTHEORA_ENCODER)          += libtheoraenc.o
410  OBJS-$(CONFIG_LIBVORBIS_ENCODER)          += libvorbis.o
411 +OBJS-$(CONFIG_LIBVPX_DECODER)             += libvpxdec.o
412 +OBJS-$(CONFIG_LIBVPX_ENCODER)             += libvpxenc.o
413  OBJS-$(CONFIG_LIBX264_ENCODER)            += libx264.o
414  OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvidff.o libxvid_rc.o
415  
416 Index: libavcodec/libvpxenc.c
417 ===================================================================
418 --- libavcodec/libvpxenc.c      (revision 0)
419 +++ libavcodec/libvpxenc.c      (revision 0)
420 @@ -0,0 +1,506 @@
421 +/*
422 + * Copyright (c) 2010, Google, Inc.
423 + *
424 + * This file is part of FFmpeg.
425 + *
426 + * FFmpeg is free software; you can redistribute it and/or
427 + * modify it under the terms of the GNU Lesser General Public
428 + * License as published by the Free Software Foundation; either
429 + * version 2.1 of the License, or (at your option) any later version.
430 + *
431 + * FFmpeg is distributed in the hope that it will be useful,
432 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
433 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
434 + * Lesser General Public License for more details.
435 + *
436 + * You should have received a copy of the GNU Lesser General Public
437 + * License along with FFmpeg; if not, write to the Free Software
438 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
439 + */
440 +
441 +/**
442 + * @file
443 + * VP8 encoder support via libvpx
444 + *
445 + * @par VPx SDK param./#AVCodecContext param./Assoc. cli opt {{{
446 + * <table>
447 + * <tr><td>g_threads</td><td>AVCodecContext::thread_count</td><td>-threads</td></tr>
448 + * <tr><td>g_lag_in_frames</td><td>AVCodecContext::lag</td><td>-lag</td></tr>
449 + * <tr><td>rc_target_bitrate</td><td>AVCodecContext::bit_rate/1000</td><td>-vb</td></tr>
450 + * <tr><td>kf_max_dist</td><td>AVCodecContext::gop_size</td><td>-g</td></tr>
451 + * <tr><td>kf_min_dist</td><td>AVCodecContext::keyint_min</td><td>-keyint_min</td></tr>
452 + * <tr><td><code>VPX_KF_FIXED</code></td><td>AVCodecContext::keyint_min == AVCodecContext::gop_size</td><td>-keyint_min -g</td></tr>
453 + * <tr><td>rc_min_quantizer</td><td>((AVCodecContext::qmin*5+1)&gt;&gt;2) - 1</td><td>-qmin</td></tr>
454 + * <tr><td>rc_max_quantizer</td><td>((AVCodecContext::qmax*5+1)&gt;&gt;2) - 1</td><td>-qmax</td></tr>
455 + * <tr><td>rc_buf_sz</td><td>AVCodecContext::rc_buffer_size*1000 / AVCodecContext::bit_rate</td><td>-bufsize -vb</td></tr>
456 + * <tr><td>rc_buf_initial_sz</td><td>AVCodecContext::rc_initial_buffer_occupancy*1000 / AVCodecContext::bit_rate</td><td>-rc_init_occupancy -vb</td></tr>
457 + * <tr><td>rc_buf_optimal_sz</td><td>AVCodecContext::rc_optimal_buffer_occupancy*1000 / AVCodecContext::bit_rate</td><td>-rc_opt_occupancy -vb</td></tr>
458 + * <tr><td>rc_dropframe_thresh</td><td>AVCodecContext::frame_skip_threshold</td><td>-skip_threshold</td></tr>
459 + * <tr><td>rc_undershoot_pct</td><td>AVCodecContext::rc_buffer_aggressivity*100</td><td>-rc_buf_aggressivity</td></tr>
460 + * <tr><td>rc_overshoot_pct</td><td>AVCodecContext::bit_rate_tolerance*100 / AVCodecContext::bit_rate</td><td>-bt -vb</td></tr>
461 + * <tr><td>rc_resize_allowed</td><td>AVCodecContext::spatial_rsmpl</td><td>-spatial_rsmpl</td></tr>
462 + * <tr><td>rc_resize_up_thresh</td><td>AVCodecContext::spatial_rsmpl_up</td><td>-spatial_rsmpl_up</td></tr>
463 + * <tr><td>rc_resize_down_thresh</td><td>AVCodecContext::spatial_rsmpl_down</td><td>-spatial_rsmpl_down</td></tr>
464 + * <tr><td>rc_2pass_vbr_bias_pct</td><td>AVCodecContext::vbr_bias</td><td>-vbr_bias</td></tr>
465 + * <tr><td>rc_2pass_vbr_maxsection_pct</td><td>AVCodecContext::rc_max_rate*100 / AVCodecContext::bit_rate</td><td>-maxrate -vb</td></tr>
466 + * <tr><td>rc_2pass_vbr_minsection_pct</td><td>AVCodecContext::rc_min_rate*100 / AVCodecContext::bit_rate</td><td>-minrate -vb</td></tr>
467 + * <tr><td>VPX_CBR</td><td>AVCodecContext::rc_min_rate == AVCodecContext::rc_max_rate &amp;&amp; AVCodecContext::rc_min_rate == AVCodecContext::bit_rate</td><td>-minrate -maxrate -vb</td></tr>
468 + * <tr><td>g_profile</td><td>AVCodecContext::profile</td><td>-profile</td></tr>
469 + * <tr><td>g_error_resilient</td><td>AVCodecContext::level&lt;0</td><td>-level</td></tr>
470 + * <tr><td><code>VPX_DL_BEST_QUALITY(1)/VPX_DL_GOOD_QUALITY(2)/VPX_DL_REALTIME(3)</code></td><td>#FFABS(AVCodecContext::level)/100</td><td>-level</td></tr>
471 + * <tr><td><code>VP8E_SET_CPUUSED</code></td><td>#FFABS(AVCodecContext::level)%%100-16</td><td>-level</td></tr>
472 + * <tr><td><code>VP8E_SET_NOISE_SENSITIVITY</code></td><td>AVCodecContext::noise_reduction</td><td>-nr</td></tr>
473 + * <tr><td><code>VP8E_SET_SHARPNESS</code></td><td>AVCodecContext::sharpness</td><td>-sharpness</td></tr>
474 + * <tr><td><code>VP8E_SET_ENABLEAUTOALTREF</code></td><td>AVCodecContext::altref</td><td>-altref</td></tr>
475 + * <tr><td><code>VP8E_SET_ARNR_MAXFRAMES</code></td><td>AVCodecContext::ar_max_frames</td><td>-ar_max_frames</td></tr>
476 + * <tr><td><code>VP8E_SET_ARNR_TYPE</code></td><td>AVCodecContext::ar_type</td><td>-ar_type</td></tr>
477 + * <tr><td><code>VP8E_SET_ARNR_STRENGTH</code></td><td>AVCodecContext::ar_strength</td><td>-ar_strength</td></tr>
478 + * <tr><td><code>VP8E_SET_STATIC_THRESHOLD</code></td><td>AVCodecContext::mb_static_threshold</td><td>-mb_static_threshold</td></tr>
479 + * <tr><td><code>VP8E_SET_TOKEN_PARTITIONS</code></td><td>AVCodecContext::token_partitions</td><td>-token_partitions</td></tr>
480 + * </table> }}}
481 + */
482 +
483 +#include "avcodec.h"
484 +#include "libavutil/base64.h"
485 +
486 +#ifndef HAVE_STDINT_H
487 +# define HAVE_STDINT_H 1
488 +#endif
489 +#define VPX_CODEC_DISABLE_COMPAT 1
490 +#include <vpx_encoder.h>
491 +#include <vp8cx.h>
492 +
493 +/**
494 + * Portion of #vpx_codec_cx_pkt_t from vpx_encoder.h.
495 + * One encoded frame returned from the library.
496 + */
497 +struct FrameListData {
498 +  void                    *buf;      /**< compressed data buffer */
499 +  size_t                   sz;       /**< length of compressed data */
500 +  vpx_codec_pts_t          pts;      /**< time stamp to show frame
501 +                                          (in timebase units) */
502 +  unsigned long            duration; /**< duration to show frame
503 +                                          (in timebase units) */
504 +  vpx_codec_frame_flags_t  flags;    /**< flags for this frame */
505 +  struct FrameListData    *next;
506 +};
507 +
508 +typedef struct VP8EncoderContext {
509 +  vpx_codec_ctx_t encoder;
510 +  vpx_image_t rawimg;
511 +  vpx_fixed_buf_t twopass_stats;
512 +  unsigned long deadline; //i.e., RT/GOOD/BEST
513 +  struct FrameListData* coded_frame_list;
514 +} VP8Context;
515 +
516 +static int vp8_free(AVCodecContext *avctx);
517 +static void free_frame_list(struct FrameListData* list);
518 +static void free_coded_frame(struct FrameListData* cx_frame);
519 +static void coded_frame_add(void* list, struct FrameListData* cx_frame);
520 +static void log_encoder_error(AVCodecContext *avctx, const char* desc);
521 +static void dump_enc_cfg(AVCodecContext *avctx, const vpx_codec_enc_cfg_t* cfg);
522 +
523 +static av_cold int vp8_init(AVCodecContext *avctx)
524 +{
525 +  VP8Context* const ctx = avctx->priv_data;
526 +  vpx_codec_iface_t* const iface = &vpx_codec_vp8_cx_algo;
527 +  const int log_field_width = -30;
528 +  const unsigned int usage = 0; //should be 0 for current VP8
529 +  const vpx_codec_flags_t flags = 0;
530 +  int cpuused = 3;
531 +  vpx_codec_enc_cfg_t enccfg;
532 +  vpx_codec_err_t res;
533 +
534 +  av_log(avctx,AV_LOG_INFO,"%s\n",vpx_codec_version_str());
535 +  av_log(avctx,AV_LOG_VERBOSE,"%s\n",vpx_codec_build_config());
536 +
537 +  if((res= vpx_codec_enc_config_default(iface,&enccfg,usage))!=VPX_CODEC_OK) {
538 +    av_log(avctx,AV_LOG_ERROR,"Failed to get config: %s\n",vpx_codec_err_to_string(res));
539 +    return -1;
540 +  }
541 +  dump_enc_cfg(avctx,&enccfg);
542 +
543 +  enccfg.g_w = avctx->width;
544 +  enccfg.g_h = avctx->height;
545 +
546 +  /*With altref set an additional frame at the same pts may be produced.
547 +    Increasing the time_base gives the library a window to place these frames
548 +    ensuring strictly increasing timestamps.*/
549 +  if(avctx->altref) {
550 +    avctx->ticks_per_frame = 2;
551 +    avctx->time_base = av_mul_q(avctx->time_base,(AVRational){1,avctx->ticks_per_frame});
552 +  }
553 +  enccfg.g_timebase.num = avctx->time_base.num;
554 +  enccfg.g_timebase.den = avctx->time_base.den;
555 +
556 +  enccfg.g_threads = FFMIN(avctx->thread_count,64);
557 +  if(avctx->flags&CODEC_FLAG_PASS1) enccfg.g_pass= VPX_RC_FIRST_PASS;
558 +  else if(avctx->flags&CODEC_FLAG_PASS2) enccfg.g_pass= VPX_RC_LAST_PASS;
559 +  else enccfg.g_pass= VPX_RC_ONE_PASS;
560 +
561 +  enccfg.rc_resize_allowed     = avctx->spatial_rsmpl;
562 +  enccfg.rc_resize_up_thresh   = avctx->spatial_rsmpl_up;
563 +  enccfg.rc_resize_down_thresh = avctx->spatial_rsmpl_down;
564 +  enccfg.rc_dropframe_thresh   = avctx->frame_skip_threshold;
565 +
566 +  if(avctx->rc_min_rate==avctx->rc_max_rate && avctx->rc_min_rate==avctx->bit_rate)
567 +    enccfg.rc_end_usage = VPX_CBR;
568 +  enccfg.rc_target_bitrate = (unsigned int)av_rescale_rnd(avctx->bit_rate,1,1000,AV_ROUND_NEAR_INF);
569 +  enccfg.rc_overshoot_pct = avctx->bit_rate_tolerance*100/avctx->bit_rate;
570 +
571 +  //convert [1,51] -> [0,63]
572 +  enccfg.rc_min_quantizer = ((avctx->qmin*5+1)>>2) - 1;
573 +  enccfg.rc_max_quantizer = ((avctx->qmax*5+1)>>2) - 1;
574 +  if(avctx->rc_buffer_size)
575 +    enccfg.rc_buf_sz = avctx->rc_buffer_size*1000/avctx->bit_rate;
576 +  if(avctx->rc_initial_buffer_occupancy)
577 +    enccfg.rc_buf_initial_sz = avctx->rc_initial_buffer_occupancy*1000/avctx->bit_rate;
578 +  if(avctx->rc_optimal_buffer_occupancy)
579 +    enccfg.rc_buf_optimal_sz = avctx->rc_optimal_buffer_occupancy*1000/avctx->bit_rate;
580 +  if(avctx->rc_buffer_aggressivity)
581 +    enccfg.rc_undershoot_pct = (unsigned int)round(avctx->rc_buffer_aggressivity*100);
582 +
583 +  enccfg.rc_2pass_vbr_bias_pct= avctx->vbr_bias;
584 +  if(avctx->rc_min_rate)
585 +    enccfg.rc_2pass_vbr_minsection_pct = avctx->rc_min_rate*100/avctx->bit_rate;
586 +  if(avctx->rc_max_rate)
587 +    enccfg.rc_2pass_vbr_maxsection_pct = avctx->rc_max_rate*100/avctx->bit_rate;
588 +
589 +  if(avctx->keyint_min==avctx->gop_size) enccfg.kf_mode= VPX_KF_FIXED;
590 +  //_enc_init() will balk if kf_min_dist is set in this case
591 +  if(enccfg.kf_mode!=VPX_KF_AUTO) enccfg.kf_min_dist= avctx->keyint_min;
592 +  enccfg.kf_max_dist = avctx->gop_size;
593 +  enccfg.g_lag_in_frames= avctx->lag;
594 +
595 +  if(enccfg.g_pass==VPX_RC_FIRST_PASS) enccfg.g_lag_in_frames= 0;
596 +  if(enccfg.g_pass==VPX_RC_LAST_PASS) {
597 +    int decode_size;
598 +
599 +    if(!avctx->stats_in) {
600 +      av_log(avctx,AV_LOG_ERROR,"No stats file for second pass\n");
601 +      return -1;
602 +    }
603 +
604 +    ctx->twopass_stats.sz  = strlen(avctx->stats_in) * 3/4;
605 +    ctx->twopass_stats.buf = av_malloc(ctx->twopass_stats.sz);
606 +    if(!ctx->twopass_stats.buf) {
607 +      av_log(avctx,AV_LOG_ERROR,"Stat buffer alloc (%zu bytes) failed\n",ctx->twopass_stats.sz);
608 +      return AVERROR(ENOMEM);
609 +    }
610 +    decode_size =
611 +      av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in, ctx->twopass_stats.sz);
612 +    if(decode_size<0) {
613 +      av_log(avctx,AV_LOG_ERROR,"Stat buffer decode failed\n");
614 +      return -1;
615 +    }
616 +
617 +    ctx->twopass_stats.sz      = decode_size;
618 +    enccfg.rc_twopass_stats_in = ctx->twopass_stats;
619 +  }
620 +
621 +  if(avctx->profile!=FF_PROFILE_UNKNOWN) enccfg.g_profile= avctx->profile;
622 +  switch(FFABS(avctx->level)/100) {
623 +  case 1:          ctx->deadline = VPX_DL_BEST_QUALITY; break;
624 +  case 2: default: ctx->deadline = VPX_DL_GOOD_QUALITY; break;
625 +  case 3:          ctx->deadline = VPX_DL_REALTIME; break;
626 +  }
627 +  av_log(avctx,AV_LOG_DEBUG,"Using deadline: %lu\n",ctx->deadline);
628 +
629 +  if(avctx->level!=FF_LEVEL_UNKNOWN) {
630 +    enccfg.g_error_resilient = avctx->level<0;
631 +    cpuused = FFABS(avctx->level)%100-16;
632 +  }
633 +
634 +  dump_enc_cfg(avctx,&enccfg);
635 +  /* Construct Encoder Context */
636 +  res = vpx_codec_enc_init(&ctx->encoder,iface,&enccfg,flags);
637 +  if(res!=VPX_CODEC_OK) { log_encoder_error(avctx,"Failed to initialize encoder"); return -1; }
638 +
639 +  //codec control failures are currently treated only as warnings
640 +  av_log(avctx,AV_LOG_DEBUG,"vpx_codec_control\n");
641 +  #define codecctl(id,val)\
642 +    do if(av_log(avctx,AV_LOG_DEBUG,"%*s%d\n",log_field_width," "#id":",val),\
643 +          (res= vpx_codec_control(&ctx->encoder,id,val))!=VPX_CODEC_OK) {\
644 +      log_encoder_error(avctx,"Failed to set "#id" codec control");\
645 +    } while(0);
646 +  codecctl(VP8E_SET_CPUUSED,cpuused);
647 +  codecctl(VP8E_SET_NOISE_SENSITIVITY,avctx->noise_reduction);
648 +  codecctl(VP8E_SET_SHARPNESS,avctx->sharpness);
649 +  codecctl(VP8E_SET_ENABLEAUTOALTREF,avctx->altref);
650 +  codecctl(VP8E_SET_ARNR_MAXFRAMES,avctx->ar_max_frames);
651 +  codecctl(VP8E_SET_ARNR_TYPE,avctx->ar_type);
652 +  codecctl(VP8E_SET_ARNR_STRENGTH,avctx->ar_strength);
653 +  codecctl(VP8E_SET_STATIC_THRESHOLD,avctx->mb_static_threshold);
654 +  codecctl(VP8E_SET_TOKEN_PARTITIONS,av_log2(avctx->token_partitions));
655 +  #undef codecctl
656 +
657 +  //provide dummy value to initialize wrapper, values will be updated each _encode()
658 +  vpx_img_wrap(&ctx->rawimg,IMG_FMT_I420,avctx->width,avctx->height,1,(unsigned char*)1);
659 +
660 +  avctx->coded_frame = avcodec_alloc_frame();
661 +  if(!avctx->coded_frame) {
662 +    av_log(avctx,AV_LOG_ERROR,"Error allocating coded frame\n");
663 +    vp8_free(avctx);
664 +    return AVERROR(ENOMEM);
665 +  }
666 +  return 0;
667 +}
668 +
669 +static inline void cx_pktcpy(struct FrameListData* dst, const vpx_codec_cx_pkt_t* src)
670 +{
671 +  dst->pts      = src->data.frame.pts;
672 +  dst->duration = src->data.frame.duration;
673 +  dst->flags    = src->data.frame.flags;
674 +  dst->sz       = src->data.frame.sz;
675 +  dst->buf      = src->data.frame.buf;
676 +}
677 +
678 +/**
679 + * Store coded frame information in format suitable for return from encode().
680 + *
681 + * Write buffer information from @a cx_frame to @a buf & @a buf_size.
682 + * Timing/frame details to @a coded_frame.
683 + * @return Frame size written to @a buf on success
684 + * @return -1 on error
685 + */
686 +static int storeframe(AVCodecContext *avctx, struct FrameListData* cx_frame,
687 +                      uint8_t* buf, int buf_size, AVFrame* coded_frame)
688 +{
689 +  if((int)cx_frame->sz<=buf_size) {
690 +    buf_size = cx_frame->sz;
691 +    memcpy(buf,cx_frame->buf,buf_size);
692 +    coded_frame->pts = cx_frame->pts;
693 +    coded_frame->key_frame = !!(cx_frame->flags&VPX_FRAME_IS_KEY);
694 +
695 +    if(coded_frame->key_frame)
696 +      coded_frame->pict_type = FF_I_TYPE;
697 +    else
698 +      coded_frame->pict_type = FF_P_TYPE;
699 +  } else {
700 +    av_log(avctx,AV_LOG_ERROR,
701 +      "Compressed frame larger than storage provided! (%zu/%d)\n",
702 +      cx_frame->sz,buf_size);
703 +    return -1;
704 +  }
705 +  return buf_size;
706 +}
707 +
708 +/**
709 + * Queue multiple output frames from the encoder, returning the front-most.
710 + * In cases where vpx_codec_get_cx_data() returns more than 1 frame append
711 + * the frame queue. Return the head frame if available.
712 + * @return Stored frame size
713 + * @return -1 on error
714 + */
715 +static int queue_frames(AVCodecContext *avctx, uint8_t* buf, int buf_size, AVFrame* coded_frame)
716 +{
717 +  VP8Context* const ctx = avctx->priv_data;
718 +  const vpx_codec_cx_pkt_t* pkt;
719 +  vpx_codec_iter_t iter = NULL;
720 +  int size = 0;
721 +
722 +  if(ctx->coded_frame_list) {
723 +    struct FrameListData* const cx_frame = ctx->coded_frame_list;
724 +    /*return the leading frame if we've already begun queueing*/
725 +    size = storeframe(avctx,cx_frame,buf,buf_size,coded_frame);
726 +    if(size<0)
727 +      return -1;
728 +    ctx->coded_frame_list = cx_frame->next;
729 +    free_coded_frame(cx_frame);
730 +  }
731 +
732 +  /*consume all available output from the encoder before returning. buffers
733 +    are only good through the next vpx_codec call*/
734 +  while( (pkt= vpx_codec_get_cx_data(&ctx->encoder,&iter)) ) {
735 +    switch(pkt->kind) {
736 +    case VPX_CODEC_CX_FRAME_PKT: {
737 +      if(!size) {
738 +        struct FrameListData cx_frame;
739 +
740 +        /*avoid storing the frame when the list is empty and we haven't yet
741 +          provided a frame for output*/
742 +        assert(!ctx->coded_frame_list);
743 +        cx_pktcpy(&cx_frame,pkt);
744 +        size = storeframe(avctx,&cx_frame,buf,buf_size,coded_frame);
745 +        if(size<0)
746 +          return -1;
747 +      } else {
748 +        struct FrameListData* const cx_frame = av_malloc(sizeof(struct FrameListData));
749 +
750 +        if(!cx_frame) {
751 +          av_log(avctx,AV_LOG_ERROR,"Frame queue element alloc failed\n");
752 +          return AVERROR(ENOMEM);
753 +        }
754 +        cx_pktcpy(cx_frame,pkt);
755 +        cx_frame->buf = av_malloc(cx_frame->sz);
756 +
757 +        if(!cx_frame->buf) {
758 +          av_log(avctx,AV_LOG_ERROR,"Data buffer alloc (%zu bytes) failed\n",
759 +            cx_frame->sz);
760 +          return AVERROR(ENOMEM);
761 +        }
762 +        memcpy(cx_frame->buf,pkt->data.frame.buf,pkt->data.frame.sz);
763 +        coded_frame_add(&ctx->coded_frame_list,cx_frame);
764 +      }
765 +      break; }
766 +    case VPX_CODEC_STATS_PKT: {
767 +      vpx_fixed_buf_t* const stats = &ctx->twopass_stats;
768 +      stats->buf = av_realloc(stats->buf,stats->sz+pkt->data.twopass_stats.sz);
769 +      if(!stats->buf) {
770 +        av_log(avctx,AV_LOG_ERROR,"Stat buffer realloc failed\n");
771 +        return AVERROR(ENOMEM);
772 +      }
773 +      memcpy((uint8_t*)stats->buf + stats->sz,
774 +          pkt->data.twopass_stats.buf,
775 +          pkt->data.twopass_stats.sz);
776 +      stats->sz += pkt->data.twopass_stats.sz;
777 +      break; }
778 +    case VPX_CODEC_CUSTOM_PKT:
779 +      //ignore unsupported/unrecognized packet types
780 +      break;
781 +    }
782 +  }
783 +
784 +  return size;
785 +}
786 +
787 +static int vp8_encode(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
788 +{
789 +  VP8Context* const ctx = avctx->priv_data;
790 +  AVFrame* const frame = data;
791 +  vpx_image_t* rawimg = NULL;
792 +  int coded_size;
793 +
794 +  if(frame) {
795 +    rawimg = &ctx->rawimg;
796 +    rawimg->planes[PLANE_Y] = frame->data[0];
797 +    rawimg->planes[PLANE_U] = frame->data[1];
798 +    rawimg->planes[PLANE_V] = frame->data[2];
799 +    rawimg->stride[PLANE_Y] = frame->linesize[0];
800 +    rawimg->stride[PLANE_U] = frame->linesize[1];
801 +    rawimg->stride[PLANE_V] = frame->linesize[2];
802 +  }
803 +
804 +  { vpx_codec_err_t res;
805 +  const vpx_codec_pts_t timestamp = frame?frame->pts:0;
806 +  const unsigned long framedur = avctx->ticks_per_frame;
807 +  const vpx_enc_frame_flags_t flags = 0; //VPX_EFLAG_FORCE_KF
808 +  const unsigned long deadline = ctx->deadline;
809 +
810 +  //FIXME use vpx_codec_set_cx_data_buf?
811 +  res = vpx_codec_encode(&ctx->encoder,rawimg,timestamp,framedur,flags,deadline);
812 +  if(res!=VPX_CODEC_OK) { log_encoder_error(avctx,"Error encoding frame"); return -1; } }
813 +  coded_size = queue_frames(avctx,buf,buf_size,avctx->coded_frame);
814 +
815 +  if(!frame && avctx->flags&CODEC_FLAG_PASS1) {
816 +    const unsigned int b64_size = ((ctx->twopass_stats.sz + 2) / 3) * 4 + 1;
817 +
818 +    avctx->stats_out = av_malloc(b64_size);
819 +    if(!avctx->stats_out) {
820 +      av_log(avctx,AV_LOG_ERROR,"Stat buffer alloc (%d bytes) failed\n",b64_size);
821 +      return AVERROR(ENOMEM);
822 +    }
823 +    av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, ctx->twopass_stats.sz);
824 +  }
825 +  return coded_size;
826 +}
827 +
828 +static av_cold int vp8_free(AVCodecContext *avctx)
829 +{
830 +  VP8Context* const ctx = avctx->priv_data;
831 +
832 +  vpx_codec_destroy(&ctx->encoder);
833 +  av_freep(&ctx->twopass_stats.buf);
834 +  av_freep(&avctx->coded_frame);
835 +  av_freep(&avctx->stats_out);
836 +  free_frame_list(ctx->coded_frame_list);
837 +  return 0;
838 +}
839 +
840 +static av_cold void free_coded_frame(struct FrameListData* cx_frame)
841 +{
842 +  av_freep(&cx_frame->buf);
843 +  av_freep(&cx_frame);
844 +}
845 +
846 +static av_cold void free_frame_list(struct FrameListData* list)
847 +{
848 +  struct FrameListData* p = list;
849 +
850 +  while(p) {
851 +    list = list->next;
852 +    free_coded_frame(p);
853 +    p = list;
854 +  }
855 +}
856 +
857 +static void coded_frame_add(void* list, struct FrameListData* cx_frame)
858 +{
859 +  struct FrameListData** p = list;
860 +
861 +  while(*p!=NULL) p= &(*p)->next;
862 +  *p = cx_frame;
863 +  cx_frame->next = NULL;
864 +}
865 +
866 +static av_cold void log_encoder_error(AVCodecContext *avctx, const char* desc)
867 +{
868 +  VP8Context* const ctx = avctx->priv_data;
869 +  const char* error = vpx_codec_error(&ctx->encoder);
870 +  const char* detail = vpx_codec_error_detail(&ctx->encoder);
871 +
872 +  av_log(avctx,AV_LOG_ERROR,"%s: %s\n",desc,error);
873 +  if(detail) av_log(avctx,AV_LOG_ERROR,"  Additional information: %s\n",detail);
874 +}
875 +
876 +static av_cold void dump_enc_cfg(AVCodecContext *avctx, const vpx_codec_enc_cfg_t* cfg)
877 +{
878 +  const int width = -30;
879 +  const int level = AV_LOG_DEBUG;
880 +
881 +  av_log(avctx,level,"vpx_codec_enc_cfg\n");
882 +  av_log(avctx,level," %*s%u\n",      width, " g_usage:", cfg->g_usage);
883 +  av_log(avctx,level," %*s%u\n",      width, " g_threads:", cfg->g_threads);
884 +  av_log(avctx,level," %*s%u\n",      width, " g_profile:", cfg->g_profile);
885 +  av_log(avctx,level," %*s%u\n",      width, " g_w:", cfg->g_w);
886 +  av_log(avctx,level," %*s%u\n",      width, " g_h:", cfg->g_h);
887 +  av_log(avctx,level," %*s{%u/%u}\n", width, " g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den);
888 +  av_log(avctx,level," %*s%u\n",      width, " g_error_resilient:", cfg->g_error_resilient);
889 +  av_log(avctx,level," %*s%d\n",      width, " g_pass:", cfg->g_pass);
890 +  av_log(avctx,level," %*s%u\n",      width, " g_lag_in_frames:", cfg->g_lag_in_frames);
891 +  av_log(avctx,level," %*s%u\n",      width, " rc_dropframe_thresh:", cfg->rc_dropframe_thresh);
892 +  av_log(avctx,level," %*s%u\n",      width, " rc_resize_allowed:", cfg->rc_resize_allowed);
893 +  av_log(avctx,level," %*s%u\n",      width, " rc_resize_up_thresh:", cfg->rc_resize_up_thresh);
894 +  av_log(avctx,level," %*s%u\n",      width, " rc_resize_down_thresh:", cfg->rc_resize_down_thresh);
895 +  av_log(avctx,level," %*s%d\n",      width, " rc_end_usage:", cfg->rc_end_usage);
896 +  av_log(avctx,level," %*s%p(%zu)\n", width, " rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz);
897 +  av_log(avctx,level," %*s%u\n",      width, " rc_target_bitrate:", cfg->rc_target_bitrate);
898 +  av_log(avctx,level," %*s%u\n",      width, " rc_min_quantizer:", cfg->rc_min_quantizer);
899 +  av_log(avctx,level," %*s%u\n",      width, " rc_max_quantizer:", cfg->rc_max_quantizer);
900 +  av_log(avctx,level," %*s%u\n",      width, " rc_undershoot_pct:", cfg->rc_undershoot_pct);
901 +  av_log(avctx,level," %*s%u\n",      width, " rc_overshoot_pct:", cfg->rc_overshoot_pct);
902 +  av_log(avctx,level," %*s%u\n",      width, " rc_buf_sz:", cfg->rc_buf_sz);
903 +  av_log(avctx,level," %*s%u\n",      width, " rc_buf_initial_sz:", cfg->rc_buf_initial_sz);
904 +  av_log(avctx,level," %*s%u\n",      width, " rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz);
905 +  av_log(avctx,level," %*s%u\n",      width, " rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct);
906 +  av_log(avctx,level," %*s%u\n",      width, " rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct);
907 +  av_log(avctx,level," %*s%u\n",      width, " rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct);
908 +  av_log(avctx,level," %*s%d\n",      width, " kf_mode:", cfg->kf_mode);
909 +  av_log(avctx,level," %*s%u\n",      width, " kf_min_dist:", cfg->kf_min_dist);
910 +  av_log(avctx,level," %*s%u\n",      width, " kf_max_dist:", cfg->kf_max_dist);
911 +  av_log(avctx,level,"\n");
912 +}
913 +
914 +AVCodec libvpx_encoder = {
915 +  "libvpx",
916 +  AVMEDIA_TYPE_VIDEO,
917 +  CODEC_ID_VP8,
918 +  sizeof(VP8Context),
919 +  vp8_init,
920 +  vp8_encode,
921 +  vp8_free,
922 +  NULL,
923 +  CODEC_CAP_DELAY,
924 +  .pix_fmts  = (const enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_NONE },
925 +  .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"),
926 +};
927 Index: ffpresets/libvpx-720p50_60.ffpreset
928 ===================================================================
929 --- ffpresets/libvpx-720p50_60.ffpreset (revision 0)
930 +++ ffpresets/libvpx-720p50_60.ffpreset (revision 0)
931 @@ -0,0 +1,17 @@
932 +vcodec=libvpx
933 +bt=4M
934 +g=120
935 +lag=25
936 +level=216
937 +mb_static_threshold=0
938 +profile=0
939 +qmax=42
940 +qmin=10
941 +rc_buf_aggressivity=0.95
942 +token_partitions=4
943 +vb=2M
944 +
945 +#ignored unless using -pass 2
946 +altref=1
947 +maxrate=24M
948 +minrate=100k
949 Index: ffpresets/libvpx-1080p.ffpreset
950 ===================================================================
951 --- ffpresets/libvpx-1080p.ffpreset     (revision 0)
952 +++ ffpresets/libvpx-1080p.ffpreset     (revision 0)
953 @@ -0,0 +1,17 @@
954 +vcodec=libvpx
955 +bt=4M
956 +g=120
957 +lag=16
958 +level=216
959 +mb_static_threshold=0
960 +profile=1
961 +qmax=42
962 +qmin=10
963 +rc_buf_aggressivity=0.95
964 +token_partitions=4
965 +vb=2M
966 +
967 +#ignored unless using -pass 2
968 +altref=1
969 +maxrate=24M
970 +minrate=100k
971 Index: ffpresets/libvpx-1080p50_60.ffpreset
972 ===================================================================
973 --- ffpresets/libvpx-1080p50_60.ffpreset        (revision 0)
974 +++ ffpresets/libvpx-1080p50_60.ffpreset        (revision 0)
975 @@ -0,0 +1,17 @@
976 +vcodec=libvpx
977 +bt=4M
978 +g=120
979 +lag=25
980 +level=216
981 +mb_static_threshold=0
982 +profile=1
983 +qmax=42
984 +qmin=10
985 +rc_buf_aggressivity=0.95
986 +token_partitions=4
987 +vb=2M
988 +
989 +#ignored unless using -pass 2
990 +altref=1
991 +maxrate=24M
992 +minrate=100k
993 Index: ffpresets/libvpx-360p.ffpreset
994 ===================================================================
995 --- ffpresets/libvpx-360p.ffpreset      (revision 0)
996 +++ ffpresets/libvpx-360p.ffpreset      (revision 0)
997 @@ -0,0 +1,16 @@
998 +vcodec=libvpx
999 +bt=1.5M
1000 +g=120
1001 +lag=16
1002 +level=216
1003 +mb_static_threshold=0
1004 +profile=0
1005 +qmax=51
1006 +qmin=1
1007 +rc_buf_aggressivity=0.95
1008 +vb=768k
1009 +
1010 +#ignored unless using -pass 2
1011 +altref=1
1012 +maxrate=1.5M
1013 +minrate=40k
1014 Index: ffpresets/libvpx-720p.ffpreset
1015 ===================================================================
1016 --- ffpresets/libvpx-720p.ffpreset      (revision 0)
1017 +++ ffpresets/libvpx-720p.ffpreset      (revision 0)
1018 @@ -0,0 +1,17 @@
1019 +vcodec=libvpx
1020 +bt=4M
1021 +g=120
1022 +lag=16
1023 +level=216
1024 +mb_static_threshold=0
1025 +profile=0
1026 +qmax=42
1027 +qmin=10
1028 +rc_buf_aggressivity=0.95
1029 +token_partitions=4
1030 +vb=2M
1031 +
1032 +#ignored unless using -pass 2
1033 +altref=1
1034 +maxrate=24M
1035 +minrate=100k
1036 Index: libavformat/matroskaenc.c
1037 ===================================================================
1038 --- libavformat/matroskaenc.c   (revision 23210)
1039 +++ libavformat/matroskaenc.c   (working copy)
1040 @@ -20,15 +20,21 @@
1041   */
1042  
1043  #include "avformat.h"
1044 +#if CONFIG_MATROSKA_MUXER
1045  #include "riff.h"
1046  #include "isom.h"
1047 +#endif
1048  #include "matroska.h"
1049 +#if CONFIG_MATROSKA_MUXER
1050  #include "avc.h"
1051  #include "flacenc.h"
1052 +#endif
1053  #include "libavutil/intreadwrite.h"
1054  #include "libavutil/md5.h"
1055  #include "libavcodec/xiph.h"
1056 +#if CONFIG_MATROSKA_MUXER
1057  #include "libavcodec/mpeg4audio.h"
1058 +#endif
1059  
1060  typedef struct ebml_master {
1061      int64_t         pos;                ///< absolute offset in the file where the master's elements start
1062 @@ -81,6 +87,12 @@ typedef struct MatroskaMuxContext {
1063      mkv_track       *tracks;
1064  
1065      struct AVMD5    *md5_ctx;
1066 +    int             max_cluster_size;
1067 +    int             max_cluster_pts;
1068 +#if CONFIG_WEBM_MUXER
1069 +    unsigned int    audio_buffer_size;
1070 +    AVPacket        cur_audio_pkt;
1071 +#endif
1072  } MatroskaMuxContext;
1073  
1074  
1075 @@ -429,6 +441,7 @@ static int put_xiph_codecpriv(AVFormatCo
1076      return 0;
1077  }
1078  
1079 +#if CONFIG_MATROSKA_MUXER
1080  static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, int *sample_rate, int *output_sample_rate)
1081  {
1082      int sri;
1083 @@ -455,6 +468,7 @@ static void get_aac_sample_rates(AVForma
1084          *output_sample_rate = ff_mpeg4audio_sample_rates[sri];
1085      }
1086  }
1087 +#endif
1088  
1089  static int mkv_write_codecprivate(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec, int native_id, int qt_id)
1090  {
1091 @@ -469,12 +483,15 @@ static int mkv_write_codecprivate(AVForm
1092      if (native_id) {
1093          if (codec->codec_id == CODEC_ID_VORBIS || codec->codec_id == CODEC_ID_THEORA)
1094              ret = put_xiph_codecpriv(s, dyn_cp, codec);
1095 +#if CONFIG_MATROSKA_MUXER
1096          else if (codec->codec_id == CODEC_ID_FLAC)
1097              ret = ff_flac_write_header(dyn_cp, codec, 1);
1098          else if (codec->codec_id == CODEC_ID_H264)
1099              ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_size);
1100 +#endif
1101          else if (codec->extradata_size)
1102              put_buffer(dyn_cp, codec->extradata, codec->extradata_size);
1103 +#if CONFIG_MATROSKA_MUXER
1104      } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
1105          if (qt_id) {
1106              if (!codec->codec_tag)
1107 @@ -503,6 +520,7 @@ static int mkv_write_codecprivate(AVForm
1108              codec->codec_tag = tag;
1109  
1110          ff_put_wav_header(dyn_cp, codec);
1111 +#endif
1112      }
1113  
1114      codecpriv_size = url_close_dyn_buf(dyn_cp, &codecpriv);
1115 @@ -537,8 +555,10 @@ static int mkv_write_tracks(AVFormatCont
1116          if (!bit_depth)
1117              bit_depth = av_get_bits_per_sample_format(codec->sample_fmt);
1118  
1119 +#if CONFIG_MATROSKA_MUXER
1120          if (codec->codec_id == CODEC_ID_AAC)
1121              get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate);
1122 +#endif
1123  
1124          track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0);
1125          put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER     , i + 1);
1126 @@ -566,8 +586,16 @@ static int mkv_write_tracks(AVFormatCont
1127  
1128          switch (codec->codec_type) {
1129              case AVMEDIA_TYPE_VIDEO:
1130 +#if CONFIG_WEBM_MUXER
1131 +                if (codec->codec_id != CODEC_ID_VP8 &&
1132 +                    !strcmp("webm", s->oformat->name)) {
1133 +                    av_log(s, AV_LOG_INFO, "WebM only supports VP8 video.\n");
1134 +                    return -1;
1135 +                }
1136 +#endif
1137                  put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
1138  
1139 +#if CONFIG_MATROSKA_MUXER
1140                  if (!native_id &&
1141                        ff_codec_get_tag(codec_movvideo_tags, codec->codec_id) &&
1142                      (!ff_codec_get_tag(ff_codec_bmp_tags,   codec->codec_id)
1143 @@ -583,7 +611,7 @@ static int mkv_write_tracks(AVFormatCont
1144                      put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC");
1145                      mkv->tracks[i].write_dts = 1;
1146                  }
1147 -
1148 +#endif
1149                  subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0);
1150                  // XXX: interlace flag?
1151                  put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
1152 @@ -597,6 +625,13 @@ static int mkv_write_tracks(AVFormatCont
1153                  break;
1154  
1155              case AVMEDIA_TYPE_AUDIO:
1156 +#if CONFIG_WEBM_MUXER
1157 +                if (codec->codec_id != CODEC_ID_VORBIS && 
1158 +                    !strcmp("webm", s->oformat->name)) {
1159 +                    av_log(s, AV_LOG_INFO, "WebM only supports Vorbis audio.\n");
1160 +                    return -1;
1161 +                }
1162 +#endif
1163                  put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
1164  
1165                  if (!native_id)
1166 @@ -693,7 +728,7 @@ static int mkv_write_header(AVFormatCont
1167      put_ebml_uint   (pb, EBML_ID_EBMLREADVERSION    ,           1);
1168      put_ebml_uint   (pb, EBML_ID_EBMLMAXIDLENGTH    ,           4);
1169      put_ebml_uint   (pb, EBML_ID_EBMLMAXSIZELENGTH  ,           8);
1170 -    put_ebml_string (pb, EBML_ID_DOCTYPE            ,  "matroska");
1171 +    put_ebml_string (pb, EBML_ID_DOCTYPE            , s->oformat->name);
1172      put_ebml_uint   (pb, EBML_ID_DOCTYPEVERSION     ,           2);
1173      put_ebml_uint   (pb, EBML_ID_DOCTYPEREADVERSION ,           2);
1174      end_ebml_master(pb, ebml_header);
1175 @@ -746,6 +781,20 @@ static int mkv_write_header(AVFormatCont
1176      if (mkv->cues == NULL)
1177          return AVERROR(ENOMEM);
1178  
1179 +#if CONFIG_WEBM_MUXER
1180 +    av_init_packet(&mkv->cur_audio_pkt);
1181 +    mkv->cur_audio_pkt.size = 0;
1182 +    mkv->audio_buffer_size = 0;
1183 +#endif
1184 +
1185 +    if (!strcmp("webm", s->oformat->name)) {
1186 +        mkv->max_cluster_size = 500*1024*1024;   // 500 MB
1187 +        mkv->max_cluster_pts = 30000;            // 30 seconds
1188 +    } else {
1189 +        mkv->max_cluster_size = 5*1024*1024;     // 5 MB
1190 +        mkv->max_cluster_pts = 5000;             // 5 seconds
1191 +    }
1192 +
1193      put_flush_packet(pb);
1194      return 0;
1195  }
1196 @@ -831,10 +880,12 @@ static void mkv_write_block(AVFormatCont
1197      av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, "
1198             "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n",
1199             url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags);
1200 +#if CONFIG_MATROSKA_MUXER
1201      if (codec->codec_id == CODEC_ID_H264 && codec->extradata_size > 0 &&
1202          (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1))
1203          ff_avc_parse_nal_units_buf(pkt->data, &data, &size);
1204      else
1205 +#endif
1206          data = pkt->data;
1207      put_ebml_id(pb, blockid);
1208      put_ebml_num(pb, size+4, 0);
1209 @@ -910,9 +961,10 @@ static int mkv_write_packet(AVFormatCont
1210          if (ret < 0) return ret;
1211      }
1212  
1213 -    // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming
1214 +    // start a new cluster every 32k / 1 sec for streaming
1215      if ((url_is_streamed(s->pb) && (url_ftell(pb) > 32*1024 || ts > mkv->cluster_pts + 1000))
1216 -        ||  url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || ts > mkv->cluster_pts + 5000) {
1217 +        || url_ftell(pb) > mkv->cluster_pos + mkv->max_cluster_size 
1218 +        || ts > mkv->cluster_pts + mkv->max_cluster_pts) {
1219          av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
1220                 " bytes, pts %" PRIu64 "\n", url_ftell(pb), ts);
1221          end_ebml_master(pb, mkv->cluster);
1222 @@ -924,7 +976,59 @@ static int mkv_write_packet(AVFormatCont
1223      mkv->duration = FFMAX(mkv->duration, ts + duration);
1224      return 0;
1225  }
1226 +#if CONFIG_WEBM_MUXER
1227 +static int mkv_copy_packet(MatroskaMuxContext *mkv, const AVPacket *pkt)
1228 +{
1229 +    uint8_t *data = mkv->cur_audio_pkt.data;
1230 +    mkv->cur_audio_pkt = *pkt;
1231 +    mkv->cur_audio_pkt.data = av_fast_realloc(data, &mkv->audio_buffer_size, pkt->size);
1232 +    if (mkv->cur_audio_pkt.data == NULL)
1233 +        return AVERROR(ENOMEM);
1234 +
1235 +    memcpy(mkv->cur_audio_pkt.data, pkt->data, pkt->size);
1236 +    mkv->cur_audio_pkt.size = pkt->size;
1237 +    return 0;
1238 +}
1239 +
1240 +static int mkv_write_packet2(AVFormatContext *s, AVPacket *pkt)
1241 +{
1242 +    MatroskaMuxContext *mkv = s->priv_data;
1243 +    ByteIOContext *pb = s->pb;
1244 +    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
1245 +    int keyframe = !!(pkt->flags & PKT_FLAG_KEY);
1246 +    int ret = 0;
1247 +
1248 +    if (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe && mkv->cluster_pos) {
1249 +        // Start a new cluster when we get a key frame
1250 +        int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
1251  
1252 +        av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
1253 +          " bytes, pts %" PRIu64 "\n", url_ftell(pb), ts);
1254 +
1255 +        end_ebml_master(pb, mkv->cluster);
1256 +        mkv->cluster_pos = 0;
1257 +        if (mkv->dyn_bc)
1258 +            mkv_flush_dynbuf(s);
1259 +    }
1260 +    
1261 +    // Check if we have an audio packet cached
1262 +    if ( (codec->codec_type == AVMEDIA_TYPE_AUDIO || codec->codec_type == AVMEDIA_TYPE_VIDEO)
1263 +      && mkv->cur_audio_pkt.size > 0) {
1264 +        ret = mkv_write_packet(s, &mkv->cur_audio_pkt);
1265 +        mkv->cur_audio_pkt.size = 0;
1266 +        if (ret < 0) {
1267 +            av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
1268 +            return ret;
1269 +        }
1270 +    }
1271 +
1272 +    if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
1273 +        ret = mkv_copy_packet(mkv, pkt);
1274 +    else
1275 +        ret = mkv_write_packet(s, pkt);
1276 +    return ret;
1277 +}
1278 +#endif
1279  static int mkv_write_trailer(AVFormatContext *s)
1280  {
1281      MatroskaMuxContext *mkv = s->priv_data;
1282 @@ -932,6 +1036,18 @@ static int mkv_write_trailer(AVFormatCon
1283      int64_t currentpos, second_seekhead, cuespos;
1284      int ret;
1285  
1286 +#if CONFIG_WEBM_MUXER
1287 +    // Check if we have an audio packet cached
1288 +    if (mkv->cur_audio_pkt.size > 0) {
1289 +        ret = mkv_write_packet(s, &mkv->cur_audio_pkt);
1290 +        mkv->cur_audio_pkt.size = 0;
1291 +        if (ret < 0) {
1292 +            av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
1293 +            return ret;
1294 +        }
1295 +    }
1296 +#endif
1297 +
1298      if (mkv->dyn_bc) {
1299          end_ebml_master(mkv->dyn_bc, mkv->cluster);
1300          mkv_flush_dynbuf(s);
1301 @@ -970,10 +1086,15 @@ static int mkv_write_trailer(AVFormatCon
1302      end_ebml_master(pb, mkv->segment);
1303      av_free(mkv->md5_ctx);
1304      av_free(mkv->tracks);
1305 +#if CONFIG_WEBM_MUXER
1306 +    if (!strcmp("webm", s->oformat->name))
1307 +        av_destruct_packet(&mkv->cur_audio_pkt);
1308 +#endif
1309      put_flush_packet(pb);
1310      return 0;
1311  }
1312  
1313 +#if CONFIG_MATROSKA_MUXER
1314  AVOutputFormat matroska_muxer = {
1315      "matroska",
1316      NULL_IF_CONFIG_SMALL("Matroska file format"),
1317 @@ -989,7 +1110,23 @@ AVOutputFormat matroska_muxer = {
1318      .codec_tag = (const AVCodecTag* const []){ff_codec_bmp_tags, ff_codec_wav_tags, 0},
1319      .subtitle_codec = CODEC_ID_TEXT,
1320  };
1321 -
1322 +#endif
1323 +#if CONFIG_WEBM_MUXER
1324 +AVOutputFormat webm_muxer = {
1325 +    "webm",
1326 +    NULL_IF_CONFIG_SMALL("WebM file format"),
1327 +    "video/webm",
1328 +    "webm",
1329 +    sizeof(MatroskaMuxContext),
1330 +    CODEC_ID_VORBIS,
1331 +    CODEC_ID_VP8,
1332 +    mkv_write_header,
1333 +    mkv_write_packet2,
1334 +    mkv_write_trailer,
1335 +    .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS,
1336 +};
1337 +#endif
1338 +#if CONFIG_MATROSKA_AUDIO_MUXER
1339  AVOutputFormat matroska_audio_muxer = {
1340      "matroska",
1341      NULL_IF_CONFIG_SMALL("Matroska file format"),
1342 @@ -1004,3 +1141,4 @@ AVOutputFormat matroska_audio_muxer = {
1343      .flags = AVFMT_GLOBALHEADER,
1344      .codec_tag = (const AVCodecTag* const []){ff_codec_wav_tags, 0},
1345  };
1346 +#endif
1347 Index: libavformat/Makefile
1348 ===================================================================
1349 --- libavformat/Makefile        (revision 23210)
1350 +++ libavformat/Makefile        (working copy)
1351 @@ -255,6 +255,8 @@ OBJS-$(CONFIG_W64_DEMUXER)              
1352  OBJS-$(CONFIG_WAV_DEMUXER)               += wav.o riff.o raw.o
1353  OBJS-$(CONFIG_WAV_MUXER)                 += wav.o riff.o
1354  OBJS-$(CONFIG_WC3_DEMUXER)               += wc3movie.o
1355 +OBJS-$(CONFIG_WEBM_MUXER)                += matroskaenc.o matroska.o \
1356 +                                            riff.o
1357  OBJS-$(CONFIG_WSAUD_DEMUXER)             += westwood.o
1358  OBJS-$(CONFIG_WSVQA_DEMUXER)             += westwood.o
1359  OBJS-$(CONFIG_WV_DEMUXER)                += wv.o apetag.o id3v1.o
1360 Index: libavformat/allformats.c
1361 ===================================================================
1362 --- libavformat/allformats.c    (revision 23210)
1363 +++ libavformat/allformats.c    (working copy)
1364 @@ -203,6 +203,7 @@ void av_register_all(void)
1365      REGISTER_DEMUXER  (W64, w64);
1366      REGISTER_MUXDEMUX (WAV, wav);
1367      REGISTER_DEMUXER  (WC3, wc3);
1368 +    REGISTER_MUXER    (WEBM, webm);
1369      REGISTER_DEMUXER  (WSAUD, wsaud);
1370      REGISTER_DEMUXER  (WSVQA, wsvqa);
1371      REGISTER_DEMUXER  (WV, wv);