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="
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"
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)
54 + * Copyright (c) 2010, Google, Inc.
56 + * This file is part of FFmpeg.
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.
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.
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
75 + * VP8 decoder support via libvpx
78 +#ifndef HAVE_STDINT_H
79 +# define HAVE_STDINT_H 1
82 +#define VPX_CODEC_DISABLE_COMPAT 1
83 +#include <vpx_decoder.h>
88 +typedef struct VP8DecoderContext {
89 + vpx_codec_ctx_t decoder;
92 +static av_cold int vp8_init(AVCodecContext *avctx)
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)
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());
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",
108 + return AVERROR(EINVAL);
111 + avctx->pix_fmt = PIX_FMT_YUV420P;
115 +static int vp8_decode(AVCodecContext *avctx,
116 + void *data, int *data_size, AVPacket *avpkt)
118 + VP8Context *ctx = avctx->priv_data;
119 + AVFrame *picture = data;
120 + const void *iter = NULL;
123 + /* end of stream, vp8 does no buffering */
127 + if (vpx_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL, 0) !=
129 + const char *error = vpx_codec_error(&ctx->decoder);
130 + const char *detail = vpx_codec_error_detail(&ctx->decoder);
132 + av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error);
134 + av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n",
136 + return AVERROR_INVALIDDATA;
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",
143 + return AVERROR_INVALIDDATA;
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);
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);
163 + return avpkt->size;
166 +static av_cold int vp8_free(AVCodecContext *avctx)
168 + VP8Context *ctx = avctx->priv_data;
169 + vpx_codec_destroy(&ctx->decoder);
173 +AVCodec libvpx_decoder = {
175 + AVMEDIA_TYPE_VIDEO,
177 + sizeof(VP8Context),
182 + 0, /* capabilities */
183 + .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"),
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},
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);
221 Index: libavcodec/avcodec.h
222 ===================================================================
223 --- libavcodec/avcodec.h (revision 23210)
224 +++ libavcodec/avcodec.h (working copy)
226 #include "libavutil/avutil.h"
228 #define LIBAVCODEC_VERSION_MAJOR 52
229 -#define LIBAVCODEC_VERSION_MINOR 68
230 +#define LIBAVCODEC_VERSION_MINOR 69
231 #define LIBAVCODEC_VERSION_MICRO 3
233 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
234 @@ -2659,6 +2659,160 @@ typedef struct AVCodecContext {
237 int log_level_offset;
240 + * Enable spatial resampling
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
249 + * \attention VP8 specific
254 + * Spatial resampling up watermark.
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
262 + * \attention VP8 specific
264 + int spatial_rsmpl_up;
267 + * Spatial resampling down watermark.
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
275 + * \attention VP8 specific
277 + int spatial_rsmpl_down;
280 + * Two-pass mode CBR/VBR bias.
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
290 + * \attention VP8 specific
295 + * Allow lagged encoding.
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.
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
307 + * - encoding: Set by user.
308 + * - decoding: unused
310 + * \attention VP8 specific
315 + * Control sharpness preprocessing
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
325 + * \attention VP8 specific
330 + * Allow encoder to automatically set and use alternate reference frame.
331 + * - encoding: Set by user.
332 + * - decoding: unused
334 + * \attention VP8 specific
339 + * Set the max number of frames blurred creating the alternate reference frame.
340 + * - encoding: Set by user.
341 + * - decoding: unused
343 + * \attention VP8 specific
348 + * Set the type of filter to use for the alternate reference frame.
349 + * - encoding: Set by user.
350 + * - decoding: unused
352 + * \attention VP8 specific
357 + * Set the filter strength for the alternate reference frame.
358 + * - encoding: Set by user.
359 + * - decoding: unused
361 + * \attention VP8 specific
366 + * Set the threshold for macroblocks treated as static.
367 + * - encoding: Set by user.
368 + * - decoding: unused
370 + * \attention VP8 specific
372 + int mb_static_threshold;
375 + * Number of bits which should be maintained in rc buffer during decoding.
376 + * - encoding: Set by user.
377 + * - decoding: unused
379 + * \attention VP8 specific
381 + int rc_optimal_buffer_occupancy;
384 + * Number of token partitions.
385 + * Valid Values: {1,2,4,8}
386 + * - encoding: Set by user.
387 + * - decoding: unused
389 + * \attention VP8 specific
391 + int token_partitions;
395 Index: libavcodec/Makefile
396 ===================================================================
397 --- libavcodec/Makefile (revision 23210)
398 +++ libavcodec/Makefile (working copy)
399 @@ -512,6 +512,7 @@ OBJS-$(CONFIG_OGG_DEMUXER) +
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
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
416 Index: libavcodec/libvpxenc.c
417 ===================================================================
418 --- libavcodec/libvpxenc.c (revision 0)
419 +++ libavcodec/libvpxenc.c (revision 0)
422 + * Copyright (c) 2010, Google, Inc.
424 + * This file is part of FFmpeg.
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.
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.
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
443 + * VP8 encoder support via libvpx
445 + * @par VPx SDK param./#AVCodecContext param./Assoc. cli opt {{{
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)>>2) - 1</td><td>-qmin</td></tr>
454 + * <tr><td>rc_max_quantizer</td><td>((AVCodecContext::qmax*5+1)>>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 && 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<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>
483 +#include "avcodec.h"
484 +#include "libavutil/base64.h"
486 +#ifndef HAVE_STDINT_H
487 +# define HAVE_STDINT_H 1
489 +#define VPX_CODEC_DISABLE_COMPAT 1
490 +#include <vpx_encoder.h>
494 + * Portion of #vpx_codec_cx_pkt_t from vpx_encoder.h.
495 + * One encoded frame returned from the library.
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;
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;
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);
523 +static av_cold int vp8_init(AVCodecContext *avctx)
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;
531 + vpx_codec_enc_cfg_t enccfg;
532 + vpx_codec_err_t res;
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());
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));
541 + dump_enc_cfg(avctx,&enccfg);
543 + enccfg.g_w = avctx->width;
544 + enccfg.g_h = avctx->height;
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});
553 + enccfg.g_timebase.num = avctx->time_base.num;
554 + enccfg.g_timebase.den = avctx->time_base.den;
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;
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;
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;
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);
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;
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;
595 + if(enccfg.g_pass==VPX_RC_FIRST_PASS) enccfg.g_lag_in_frames= 0;
596 + if(enccfg.g_pass==VPX_RC_LAST_PASS) {
599 + if(!avctx->stats_in) {
600 + av_log(avctx,AV_LOG_ERROR,"No stats file for second pass\n");
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);
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");
617 + ctx->twopass_stats.sz = decode_size;
618 + enccfg.rc_twopass_stats_in = ctx->twopass_stats;
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;
627 + av_log(avctx,AV_LOG_DEBUG,"Using deadline: %lu\n",ctx->deadline);
629 + if(avctx->level!=FF_LEVEL_UNKNOWN) {
630 + enccfg.g_error_resilient = avctx->level<0;
631 + cpuused = FFABS(avctx->level)%100-16;
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; }
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");\
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));
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);
660 + avctx->coded_frame = avcodec_alloc_frame();
661 + if(!avctx->coded_frame) {
662 + av_log(avctx,AV_LOG_ERROR,"Error allocating coded frame\n");
664 + return AVERROR(ENOMEM);
669 +static inline void cx_pktcpy(struct FrameListData* dst, const vpx_codec_cx_pkt_t* src)
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;
679 + * Store coded frame information in format suitable for return from encode().
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
686 +static int storeframe(AVCodecContext *avctx, struct FrameListData* cx_frame,
687 + uint8_t* buf, int buf_size, AVFrame* coded_frame)
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);
695 + if(coded_frame->key_frame)
696 + coded_frame->pict_type = FF_I_TYPE;
698 + coded_frame->pict_type = FF_P_TYPE;
700 + av_log(avctx,AV_LOG_ERROR,
701 + "Compressed frame larger than storage provided! (%zu/%d)\n",
702 + cx_frame->sz,buf_size);
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
715 +static int queue_frames(AVCodecContext *avctx, uint8_t* buf, int buf_size, AVFrame* coded_frame)
717 + VP8Context* const ctx = avctx->priv_data;
718 + const vpx_codec_cx_pkt_t* pkt;
719 + vpx_codec_iter_t iter = NULL;
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);
728 + ctx->coded_frame_list = cx_frame->next;
729 + free_coded_frame(cx_frame);
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: {
738 + struct FrameListData cx_frame;
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);
748 + struct FrameListData* const cx_frame = av_malloc(sizeof(struct FrameListData));
751 + av_log(avctx,AV_LOG_ERROR,"Frame queue element alloc failed\n");
752 + return AVERROR(ENOMEM);
754 + cx_pktcpy(cx_frame,pkt);
755 + cx_frame->buf = av_malloc(cx_frame->sz);
757 + if(!cx_frame->buf) {
758 + av_log(avctx,AV_LOG_ERROR,"Data buffer alloc (%zu bytes) failed\n",
760 + return AVERROR(ENOMEM);
762 + memcpy(cx_frame->buf,pkt->data.frame.buf,pkt->data.frame.sz);
763 + coded_frame_add(&ctx->coded_frame_list,cx_frame);
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);
770 + av_log(avctx,AV_LOG_ERROR,"Stat buffer realloc failed\n");
771 + return AVERROR(ENOMEM);
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;
778 + case VPX_CODEC_CUSTOM_PKT:
779 + //ignore unsupported/unrecognized packet types
787 +static int vp8_encode(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
789 + VP8Context* const ctx = avctx->priv_data;
790 + AVFrame* const frame = data;
791 + vpx_image_t* rawimg = NULL;
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];
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;
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);
815 + if(!frame && avctx->flags&CODEC_FLAG_PASS1) {
816 + const unsigned int b64_size = ((ctx->twopass_stats.sz + 2) / 3) * 4 + 1;
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);
823 + av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, ctx->twopass_stats.sz);
828 +static av_cold int vp8_free(AVCodecContext *avctx)
830 + VP8Context* const ctx = avctx->priv_data;
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);
840 +static av_cold void free_coded_frame(struct FrameListData* cx_frame)
842 + av_freep(&cx_frame->buf);
843 + av_freep(&cx_frame);
846 +static av_cold void free_frame_list(struct FrameListData* list)
848 + struct FrameListData* p = list;
852 + free_coded_frame(p);
857 +static void coded_frame_add(void* list, struct FrameListData* cx_frame)
859 + struct FrameListData** p = list;
861 + while(*p!=NULL) p= &(*p)->next;
863 + cx_frame->next = NULL;
866 +static av_cold void log_encoder_error(AVCodecContext *avctx, const char* desc)
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);
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);
876 +static av_cold void dump_enc_cfg(AVCodecContext *avctx, const vpx_codec_enc_cfg_t* cfg)
878 + const int width = -30;
879 + const int level = AV_LOG_DEBUG;
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");
914 +AVCodec libvpx_encoder = {
916 + AVMEDIA_TYPE_VIDEO,
918 + sizeof(VP8Context),
924 + .pix_fmts = (const enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_NONE },
925 + .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"),
927 Index: ffpresets/libvpx-720p50_60.ffpreset
928 ===================================================================
929 --- ffpresets/libvpx-720p50_60.ffpreset (revision 0)
930 +++ ffpresets/libvpx-720p50_60.ffpreset (revision 0)
937 +mb_static_threshold=0
941 +rc_buf_aggressivity=0.95
945 +#ignored unless using -pass 2
949 Index: ffpresets/libvpx-1080p.ffpreset
950 ===================================================================
951 --- ffpresets/libvpx-1080p.ffpreset (revision 0)
952 +++ ffpresets/libvpx-1080p.ffpreset (revision 0)
959 +mb_static_threshold=0
963 +rc_buf_aggressivity=0.95
967 +#ignored unless using -pass 2
971 Index: ffpresets/libvpx-1080p50_60.ffpreset
972 ===================================================================
973 --- ffpresets/libvpx-1080p50_60.ffpreset (revision 0)
974 +++ ffpresets/libvpx-1080p50_60.ffpreset (revision 0)
981 +mb_static_threshold=0
985 +rc_buf_aggressivity=0.95
989 +#ignored unless using -pass 2
993 Index: ffpresets/libvpx-360p.ffpreset
994 ===================================================================
995 --- ffpresets/libvpx-360p.ffpreset (revision 0)
996 +++ ffpresets/libvpx-360p.ffpreset (revision 0)
1003 +mb_static_threshold=0
1007 +rc_buf_aggressivity=0.95
1010 +#ignored unless using -pass 2
1014 Index: ffpresets/libvpx-720p.ffpreset
1015 ===================================================================
1016 --- ffpresets/libvpx-720p.ffpreset (revision 0)
1017 +++ ffpresets/libvpx-720p.ffpreset (revision 0)
1024 +mb_static_threshold=0
1028 +rc_buf_aggressivity=0.95
1032 +#ignored unless using -pass 2
1036 Index: libavformat/matroskaenc.c
1037 ===================================================================
1038 --- libavformat/matroskaenc.c (revision 23210)
1039 +++ libavformat/matroskaenc.c (working copy)
1043 #include "avformat.h"
1044 +#if CONFIG_MATROSKA_MUXER
1048 #include "matroska.h"
1049 +#if CONFIG_MATROSKA_MUXER
1051 #include "flacenc.h"
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"
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 {
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;
1072 } MatroskaMuxContext;
1075 @@ -429,6 +441,7 @@ static int put_xiph_codecpriv(AVFormatCo
1079 +#if CONFIG_MATROSKA_MUXER
1080 static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, int *sample_rate, int *output_sample_rate)
1083 @@ -455,6 +468,7 @@ static void get_aac_sample_rates(AVForma
1084 *output_sample_rate = ff_mpeg4audio_sample_rates[sri];
1089 static int mkv_write_codecprivate(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec, int native_id, int qt_id)
1091 @@ -469,12 +483,15 @@ static int mkv_write_codecprivate(AVForm
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);
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) {
1106 if (!codec->codec_tag)
1107 @@ -503,6 +520,7 @@ static int mkv_write_codecprivate(AVForm
1108 codec->codec_tag = tag;
1110 ff_put_wav_header(dyn_cp, codec);
1114 codecpriv_size = url_close_dyn_buf(dyn_cp, &codecpriv);
1115 @@ -537,8 +555,10 @@ static int mkv_write_tracks(AVFormatCont
1117 bit_depth = av_get_bits_per_sample_format(codec->sample_fmt);
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);
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
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");
1137 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
1139 +#if CONFIG_MATROSKA_MUXER
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;
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
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");
1163 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
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);
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;
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
1189 + mkv->max_cluster_size = 5*1024*1024; // 5 MB
1190 + mkv->max_cluster_pts = 5000; // 5 seconds
1193 put_flush_packet(pb);
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);
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;
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);
1226 +#if CONFIG_WEBM_MUXER
1227 +static int mkv_copy_packet(MatroskaMuxContext *mkv, const AVPacket *pkt)
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);
1235 + memcpy(mkv->cur_audio_pkt.data, pkt->data, pkt->size);
1236 + mkv->cur_audio_pkt.size = pkt->size;
1240 +static int mkv_write_packet2(AVFormatContext *s, AVPacket *pkt)
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);
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;
1252 + av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
1253 + " bytes, pts %" PRIu64 "\n", url_ftell(pb), ts);
1255 + end_ebml_master(pb, mkv->cluster);
1256 + mkv->cluster_pos = 0;
1258 + mkv_flush_dynbuf(s);
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;
1267 + av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
1272 + if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
1273 + ret = mkv_copy_packet(mkv, pkt);
1275 + ret = mkv_write_packet(s, pkt);
1279 static int mkv_write_trailer(AVFormatContext *s)
1281 MatroskaMuxContext *mkv = s->priv_data;
1282 @@ -932,6 +1036,18 @@ static int mkv_write_trailer(AVFormatCon
1283 int64_t currentpos, second_seekhead, cuespos;
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;
1292 + av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
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);
1309 put_flush_packet(pb);
1313 +#if CONFIG_MATROSKA_MUXER
1314 AVOutputFormat matroska_muxer = {
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,
1323 +#if CONFIG_WEBM_MUXER
1324 +AVOutputFormat webm_muxer = {
1326 + NULL_IF_CONFIG_SMALL("WebM file format"),
1329 + sizeof(MatroskaMuxContext),
1333 + mkv_write_packet2,
1334 + mkv_write_trailer,
1335 + .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS,
1338 +#if CONFIG_MATROSKA_AUDIO_MUXER
1339 AVOutputFormat matroska_audio_muxer = {
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},
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 \
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);