diff --git a/test/encode_test_driver.cc b/test/encode_test_driver.cc index b2b6e0d6d40bbda3f9cc11bf06bad51075a8636c..39d154b139b75a728918aa9820f5f747d9445bfd 100644 --- a/test/encode_test_driver.cc +++ b/test/encode_test_driver.cc @@ -201,6 +201,8 @@ void EncoderTest::RunLoop(VideoSource *video) { MismatchHook(img_enc, img_dec); } } + if (img_dec) + DecompressedFrameHook(*img_dec, video->pts()); } if (!Continue()) break; diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h index 0944dc2c65fd473f2d94352f385e9c34b8b1810a..35082a7fdac2e42729595e0ca317eb8ecb496a7b 100644 --- a/test/encode_test_driver.h +++ b/test/encode_test_driver.h @@ -117,6 +117,11 @@ class Encoder { ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); } + void Control(int ctrl_id, struct vpx_scaling_mode *arg) { + const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } + void set_deadline(unsigned long deadline) { deadline_ = deadline; } @@ -194,6 +199,10 @@ class EncoderTest { virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2); + // Hook to be called on every decompressed frame. + virtual void DecompressedFrameHook(const vpx_image_t& img, + vpx_codec_pts_t pts) {} + bool abort_; vpx_codec_enc_cfg_t cfg_; unsigned int passes_; diff --git a/test/resize_test.cc b/test/resize_test.cc index 0ce8940a373b656ae419769ef320e15fbcb3ba4a..5e9234c38f4ff7fe4388b11e23bb0311e46c4d4b 100644 --- a/test/resize_test.cc +++ b/test/resize_test.cc @@ -12,6 +12,7 @@ #include "third_party/googletest/src/include/gtest/gtest.h" #include "test/codec_factory.h" #include "test/encode_test_driver.h" +#include "test/i420_video_source.h" #include "test/video_source.h" #include "test/util.h" @@ -73,15 +74,9 @@ class ResizeTest : public ::libvpx_test::EncoderTest, return !HasFatalFailure() && !abort_; } - virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) { - if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { - const unsigned char *buf = - reinterpret_cast<const unsigned char *>(pkt->data.frame.buf); - const unsigned int w = (buf[6] | (buf[7] << 8)) & 0x3fff; - const unsigned int h = (buf[8] | (buf[9] << 8)) & 0x3fff; - - frame_info_list_.push_back(FrameInfo(pkt->data.frame.pts, w, h)); - } + virtual void DecompressedFrameHook(const vpx_image_t &img, + vpx_codec_pts_t pts) { + frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h)); } std::vector< FrameInfo > frame_info_list_; @@ -104,5 +99,38 @@ TEST_P(ResizeTest, TestExternalResizeWorks) { } } +class ResizeInternalTest : public ResizeTest { + protected: + ResizeInternalTest() : ResizeTest() {} + + virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video, + libvpx_test::Encoder *encoder) { + if (video->frame() == 3) { + struct vpx_scaling_mode mode = {VP8E_FOURFIVE, VP8E_THREEFIVE}; + encoder->Control(VP8E_SET_SCALEMODE, &mode); + } + } +}; + +TEST_P(ResizeInternalTest, TestInternalResizeWorks) { + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 5); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + + for (std::vector<FrameInfo>::iterator info = frame_info_list_.begin(); + info != frame_info_list_.end(); ++info) { + const vpx_codec_pts_t pts = info->pts; + if (pts >= 3) { + ASSERT_EQ(282U, info->w) << "Frame " << pts << " had unexpected width"; + ASSERT_EQ(173U, info->h) << "Frame " << pts << " had unexpected height"; + } else { + EXPECT_EQ(352U, info->w) << "Frame " << pts << " had unexpected width"; + EXPECT_EQ(288U, info->h) << "Frame " << pts << " had unexpected height"; + } + } +} + VP8_INSTANTIATE_TEST_CASE(ResizeTest, ONE_PASS_TEST_MODES); +VP9_INSTANTIATE_TEST_CASE(ResizeInternalTest, + ::testing::Values(::libvpx_test::kOnePassBest)); } // namespace diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 384033fbcfb5ded4ae3859cdda90f11b3009a02c..3324186efd37ea13c4b7857a4e53de88b3630d7f 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -1367,9 +1367,6 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { vp9_setup_version(pc); if (pc->frame_type == KEY_FRAME) { - const int Width = pc->Width; - const int Height = pc->Height; - /* vet via sync code */ /* When error concealment is enabled we should only check the sync * code if we have enough bits available @@ -1379,18 +1376,23 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM, "Invalid frame sync code"); } + data += 3; + } + { + const int Width = pc->Width; + const int Height = pc->Height; /* If error concealment is enabled we should only parse the new size * if we have enough data. Otherwise we will end up with the wrong * size. */ - if (data + 6 < data_end) { - pc->Width = (data[3] | (data[4] << 8)) & 0x3fff; - pc->horiz_scale = data[4] >> 6; - pc->Height = (data[5] | (data[6] << 8)) & 0x3fff; - pc->vert_scale = data[6] >> 6; + if (data + 4 < data_end) { + pc->Width = (data[0] | (data[1] << 8)) & 0x3fff; + pc->horiz_scale = data[1] >> 6; + pc->Height = (data[2] | (data[3] << 8)) & 0x3fff; + pc->vert_scale = data[3] >> 6; } - data += 7; + data += 4; if (Width != pc->Width || Height != pc->Height) { if (pc->Width <= 0) { @@ -1423,10 +1425,8 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { (unsigned int)first_partition_length_in_bytes)) vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, "Failed to allocate bool decoder 0"); - if (pc->frame_type == KEY_FRAME) { - pc->clr_type = (YUV_TYPE)vp9_read_bit(&header_bc); - pc->clamp_type = (CLAMP_TYPE)vp9_read_bit(&header_bc); - } + pc->clr_type = (YUV_TYPE)vp9_read_bit(&header_bc); + pc->clamp_type = (CLAMP_TYPE)vp9_read_bit(&header_bc); pc->error_resilient_mode = vp9_read_bit(&header_bc); /* Is segmentation enabled */ diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 71109f8f4d9571895603dc8dab5dfc9ce878bc85..eec83a0a8a86dc63dd042fc3c0daa2b78dc9f7c2 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -1532,33 +1532,34 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, * and color type. */ if (oh.type == KEY_FRAME) { - int v; - // Start / synch code cx_data[0] = 0x9D; cx_data[1] = 0x01; cx_data[2] = 0x2a; + extra_bytes_packed = 3; + cx_data += extra_bytes_packed; + } + { + int v; + /* TODO(jkoleszar): support arbitrary resolutions */ v = (pc->horiz_scale << 14) | pc->Width; - cx_data[3] = v; - cx_data[4] = v >> 8; + cx_data[0] = v; + cx_data[1] = v >> 8; v = (pc->vert_scale << 14) | pc->Height; - cx_data[5] = v; - cx_data[6] = v >> 8; + cx_data[2] = v; + cx_data[3] = v >> 8; - extra_bytes_packed = 7; - cx_data += extra_bytes_packed; - - vp9_start_encode(&header_bc, cx_data); + extra_bytes_packed += 4; + cx_data += 4; + } - // signal clr type - vp9_write_bit(&header_bc, pc->clr_type); - vp9_write_bit(&header_bc, pc->clamp_type); + vp9_start_encode(&header_bc, cx_data); - } else { - vp9_start_encode(&header_bc, cx_data); - } + // TODO(jkoleszar): remove these two unused bits? + vp9_write_bit(&header_bc, pc->clr_type); + vp9_write_bit(&header_bc, pc->clamp_type); // error resilient mode vp9_write_bit(&header_bc, pc->error_resilient_mode); diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 280a3224dcd84f74e037eebe72f98c70a283a416..3bbe9761c74f89a533ffd104afc917bb1f7320cc 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -1005,6 +1005,38 @@ void vp9_alloc_compressor_data(VP9_COMP *cpi) { } +static void update_frame_size(VP9_COMP *cpi) { + VP9_COMMON *cm = &cpi->common; + + /* our internal buffers are always multiples of 16 */ + int width = (cm->Width + 15) & ~15; + int height = (cm->Height + 15) & ~15; + + cm->mb_rows = height >> 4; + cm->mb_cols = width >> 4; + cm->MBs = cm->mb_rows * cm->mb_cols; + cm->mode_info_stride = cm->mb_cols + 1; + memset(cm->mip, 0, + (cm->mb_cols + 1) * (cm->mb_rows + 1) * sizeof(MODE_INFO)); + vp9_update_mode_info_border(cm, cm->mip); + + cm->mi = cm->mip + cm->mode_info_stride + 1; + cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1; + vp9_update_mode_info_in_image(cm, cm->mi); + + /* Update size of buffers local to this frame */ + if (vp8_yv12_realloc_frame_buffer(&cpi->last_frame_uf, + width, height, VP9BORDERINPIXELS)) + vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, + "Failed to reallocate last frame buffer"); + + if (vp8_yv12_realloc_frame_buffer(&cpi->scaled_source, + width, height, VP9BORDERINPIXELS)) + vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, + "Failed to reallocate scaled source buffer"); +} + + // TODO perhaps change number of steps expose to outside world when setting // max and min limits. Also this will likely want refining for the extended Q // range. @@ -1302,14 +1334,18 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) { cm->Height = (vs - 1 + cpi->oxcf.Height * vr) / vs; } - if (((cm->Width + 15) & 0xfffffff0) != - cm->yv12_fb[cm->active_ref_idx[cpi->lst_fb_idx]].y_width || - ((cm->Height + 15) & 0xfffffff0) != - cm->yv12_fb[cm->active_ref_idx[cpi->lst_fb_idx]].y_height || - cm->yv12_fb[cm->active_ref_idx[cpi->lst_fb_idx]].y_width == 0) { + // Increasing the size of the frame beyond the first seen frame, or some + // otherwise signalled maximum size, is not supported. + // TODO(jkoleszar): exit gracefully. + if (!cpi->initial_width) { alloc_raw_frame_buffers(cpi); vp9_alloc_compressor_data(cpi); + cpi->initial_width = cm->Width; + cpi->initial_height = cm->Height; } + assert(cm->Width <= cpi->initial_width); + assert(cm->Height <= cpi->initial_height); + update_frame_size(cpi); if (cpi->oxcf.fixed_q >= 0) { cpi->last_q[0] = cpi->oxcf.fixed_q; @@ -3776,6 +3812,28 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, cm->fb_idx_ref_cnt[cm->new_fb_idx]--; cm->new_fb_idx = get_free_fb(cm); + /* Reset the frame pointers to the current frame size */ + vp8_yv12_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx], + cm->mb_cols * 16, cm->mb_rows * 16, + VP9BORDERINPIXELS); + + /* Disable any references that have different size */ + if ((cm->yv12_fb[cm->active_ref_idx[cpi->lst_fb_idx]].y_width != + cm->yv12_fb[cm->new_fb_idx].y_width) || + (cm->yv12_fb[cm->active_ref_idx[cpi->lst_fb_idx]].y_height != + cm->yv12_fb[cm->new_fb_idx].y_height)) + cpi->ref_frame_flags &= ~VP9_LAST_FLAG; + if ((cm->yv12_fb[cm->active_ref_idx[cpi->gld_fb_idx]].y_width != + cm->yv12_fb[cm->new_fb_idx].y_width) || + (cm->yv12_fb[cm->active_ref_idx[cpi->gld_fb_idx]].y_height != + cm->yv12_fb[cm->new_fb_idx].y_height)) + cpi->ref_frame_flags &= ~VP9_GOLD_FLAG; + if ((cm->yv12_fb[cm->active_ref_idx[cpi->alt_fb_idx]].y_width != + cm->yv12_fb[cm->new_fb_idx].y_width) || + (cm->yv12_fb[cm->active_ref_idx[cpi->alt_fb_idx]].y_height != + cm->yv12_fb[cm->new_fb_idx].y_height)) + cpi->ref_frame_flags &= ~VP9_ALT_FLAG; + vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm); if (cpi->pass == 1) { Pass1Encode(cpi, size, dest, frame_flags); @@ -4027,15 +4085,16 @@ int vp9_set_internal_size(VP9_PTR comp, VP9_COMP *cpi = (VP9_COMP *) comp; if (horiz_mode <= ONETWO) - cpi->common.horiz_scale = horiz_mode; + cpi->horiz_scale = horiz_mode; else return -1; if (vert_mode <= ONETWO) - cpi->common.vert_scale = vert_mode; + cpi->vert_scale = vert_mode; else return -1; + vp9_change_config(comp, &cpi->oxcf); return 0; } diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index b7cb558d029efb36784e2b9f19e859dd545831b5..156f86f985cf7b50be25f6661f5df2455b7280b8 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -678,6 +678,8 @@ typedef struct VP9_COMP { unsigned int mb_mv_ref_count[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES]; #endif + int initial_width; + int initial_height; } VP9_COMP; void vp9_encode_frame(VP9_COMP *cpi); diff --git a/vp9/encoder/vp9_picklpf.c b/vp9/encoder/vp9_picklpf.c index b443ede6fae6a121e19b3bba247a41ebdb716d89..6f93335214b3ca33b2e58fa2cf487b751daf8e24 100644 --- a/vp9/encoder/vp9_picklpf.c +++ b/vp9/encoder/vp9_picklpf.c @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ - +#include <assert.h> #include "vp9/common/vp9_onyxc_int.h" #include "vp9/encoder/vp9_onyx_int.h" #include "vp9/encoder/vp9_picklpf.h" @@ -27,6 +27,7 @@ void vp9_yv12_copy_partial_frame_c(YV12_BUFFER_CONFIG *src_ybc, int yoffset; int linestocopy; + assert(src_ybc->y_stride == dst_ybc->y_stride); yheight = src_ybc->y_height; ystride = src_ybc->y_stride; diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index c50c55ff9f304251b51ce3a93dfd75373914bdf0..370374164cfd9fccd646a5d4f475057719e2eb85 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -3517,6 +3517,8 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int64_t *returnintra) { + static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG, + VP9_ALT_FLAG }; VP9_COMMON *cm = &cpi->common; MACROBLOCKD *xd = &x->e_mbd; union b_mode_info best_bmodes[16]; @@ -3684,6 +3686,16 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, if (best_rd <= cpi->rd_threshes[mode_index]) continue; + // Ensure that the references used by this mode are available. + if (mbmi->ref_frame && + !(cpi->ref_frame_flags & flag_list[mbmi->ref_frame])) + continue; + + if (mbmi->second_ref_frame > 0 && + !(cpi->ref_frame_flags & flag_list[mbmi->second_ref_frame])) + continue; + + // current coding mode under rate-distortion optimization test loop #if CONFIG_COMP_INTERINTRA_PRED mbmi->interintra_mode = (MB_PREDICTION_MODE)(DC_PRED - 1); diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index a6b74bc37913e09de9983d2d4d6861ab41e88352..0b8677285f7adc127c0012f2385c3215474608fd 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -80,7 +80,6 @@ struct vpx_codec_alg_priv { unsigned char *pending_cx_data; unsigned int pending_cx_data_sz; vpx_image_t preview_img; - unsigned int next_frame_flag; vp8_postproc_cfg_t preview_ppcfg; vpx_codec_pkt_list_decl(64) pkt_list; // changed to accomendate the maximum number of lagged frames allowed unsigned int fixed_kf_cntr; @@ -678,14 +677,11 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx, if (img != NULL) { res = image2yuvconfig(img, &sd); - if (vp9_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags, + if (vp9_receive_raw_frame(ctx->cpi, lib_flags, &sd, dst_time_stamp, dst_end_time_stamp)) { VP9_COMP *cpi = (VP9_COMP *)ctx->cpi; res = update_error_state(ctx, &cpi->common.error); } - - /* reset for next frame */ - ctx->next_frame_flag = 0; } cx_data = ctx->cx_data; @@ -987,8 +983,6 @@ static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx, scalemode.v_scaling_mode); if (!res) { - /*force next frame a key frame to effect scaling mode */ - ctx->next_frame_flag |= FRAMEFLAGS_KEY; return VPX_CODEC_OK; } else return VPX_CODEC_INVALID_PARAM; diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c index 4cb2a41904c87d41d99f3bc66f843fe2a0436664..267d55f40aba8e23a07ed0b12345c126591c0356 100644 --- a/vpx_scale/generic/yv12config.c +++ b/vpx_scale/generic/yv12config.c @@ -35,13 +35,8 @@ vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) { return 0; } -/**************************************************************************** - * - ****************************************************************************/ -int -vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int border) { - /*NOTE:*/ - +int vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, + int width, int height, int border) { if (ybf) { int y_stride = ((width + 2 * border) + 31) & ~31; int yplane_size = (height + 2 * border) * y_stride; @@ -51,8 +46,15 @@ vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int * uv_stride == y_stride/2, so enforce this here. */ int uv_stride = y_stride >> 1; int uvplane_size = (uv_height + border) * uv_stride; + const int frame_size = yplane_size + 2 * uvplane_size; - vp8_yv12_de_alloc_frame_buffer(ybf); + if (!ybf->buffer_alloc) { + ybf->buffer_alloc = vpx_memalign(32, frame_size); + ybf->buffer_alloc_sz = frame_size; + } + + if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size) + return -1; /** Only support allocating buffers that have a height and width that * are multiples of 16, and a border that's a multiple of 32. @@ -72,21 +74,23 @@ vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int ybf->uv_stride = uv_stride; ybf->border = border; - ybf->frame_size = yplane_size + 2 * uvplane_size; - - ybf->buffer_alloc = (unsigned char *) vpx_memalign(32, ybf->frame_size); - - if (ybf->buffer_alloc == NULL) - return -1; + ybf->frame_size = frame_size; ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border; ybf->u_buffer = ybf->buffer_alloc + yplane_size + (border / 2 * uv_stride) + border / 2; ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + (border / 2 * uv_stride) + border / 2; ybf->corrupted = 0; /* assume not currupted by errors */ - } else { - return -2; + return 0; } + return -2; +} - return 0; +int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, + int width, int height, int border) { + if (ybf) { + vp8_yv12_de_alloc_frame_buffer(ybf); + return vp8_yv12_realloc_frame_buffer(ybf, width, height, border); + } + return -2; } diff --git a/vpx_scale/generic/yv12extend.c b/vpx_scale/generic/yv12extend.c index 5a427356b846eaabb9ac3bb4221faa35ec919dc4..d733bd49d87b1b83e79d4a48dda1489d95c14832 100644 --- a/vpx_scale/generic/yv12extend.c +++ b/vpx_scale/generic/yv12extend.c @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ - +#include <assert.h> #include "vpx_scale/yv12config.h" #include "vpx_mem/vpx_mem.h" #include "vpx_scale/vpx_scale.h" @@ -216,6 +216,9 @@ vp8_yv12_copy_frame_c(YV12_BUFFER_CONFIG *src_ybc, int row; unsigned char *source, *dest; + assert(src_ybc->y_width == dst_ybc->y_width); + assert(src_ybc->y_height == dst_ybc->y_height); + source = src_ybc->y_buffer; dest = dst_ybc->y_buffer; diff --git a/vpx_scale/yv12config.h b/vpx_scale/yv12config.h index 23be8f3dd78a8d6f017a82bdaa2ee9121bcf74be..45e57f40140e1474669289b612a1699708a2106e 100644 --- a/vpx_scale/yv12config.h +++ b/vpx_scale/yv12config.h @@ -55,6 +55,7 @@ extern "C" { uint8_t *v_buffer; uint8_t *buffer_alloc; + int buffer_alloc_sz; int border; int frame_size; YUV_TYPE clrtype; @@ -65,6 +66,8 @@ extern "C" { int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int border); + int vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, + int width, int height, int border); int vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf); #ifdef __cplusplus