diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h index 79d060945bbbb1befcdf3805a4d45bde7a065bc5..55bcccb0eee4a7629773373bd13ce7c6a72f12ee 100644 --- a/vp9/common/vp9_onyx.h +++ b/vp9/common/vp9_onyx.h @@ -211,8 +211,10 @@ extern "C" int vp9_update_reference(VP9_PTR comp, int ref_frame_flags); - int vp9_get_reference_enc(VP9_PTR comp, VP9_REFFRAME ref_frame_flag, - YV12_BUFFER_CONFIG *sd); + int vp9_copy_reference_enc(VP9_PTR comp, VP9_REFFRAME ref_frame_flag, + YV12_BUFFER_CONFIG *sd); + + int vp9_get_reference_enc(VP9_PTR ptr, int index, YV12_BUFFER_CONFIG **fb); int vp9_set_reference_enc(VP9_PTR comp, VP9_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd); diff --git a/vp9/decoder/vp9_onyxd.h b/vp9/decoder/vp9_onyxd.h index 748fc7ea3e5194258fa6f2252ac17d7fcdda3cd5..cd71166e45ceb81517a6418f0024950ba24ae09f 100644 --- a/vp9/decoder/vp9_onyxd.h +++ b/vp9/decoder/vp9_onyxd.h @@ -46,14 +46,16 @@ extern "C" { int64_t *time_stamp, int64_t *time_end_stamp, vp9_ppflags_t *flags); - vpx_codec_err_t vp9_get_reference_dec(VP9D_PTR comp, - VP9_REFFRAME ref_frame_flag, - YV12_BUFFER_CONFIG *sd); + vpx_codec_err_t vp9_copy_reference_dec(VP9D_PTR comp, + VP9_REFFRAME ref_frame_flag, + YV12_BUFFER_CONFIG *sd); vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR comp, VP9_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd); + int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb); + VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf); void vp9_remove_decompressor(VP9D_PTR comp); diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c index 63895800dabde63c524c77a6893879a6c5130225..5cb2a095b016db031414554261ebc5ca0213eac5 100644 --- a/vp9/decoder/vp9_onyxd_if.c +++ b/vp9/decoder/vp9_onyxd_if.c @@ -164,8 +164,9 @@ void vp9_remove_decompressor(VP9D_PTR ptr) { } -vpx_codec_err_t vp9_get_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, - YV12_BUFFER_CONFIG *sd) { +vpx_codec_err_t vp9_copy_reference_dec(VP9D_PTR ptr, + VP9_REFFRAME ref_frame_flag, + YV12_BUFFER_CONFIG *sd) { VP9D_COMP *pbi = (VP9D_COMP *) ptr; VP9_COMMON *cm = &pbi->common; int ref_fb_idx; @@ -242,6 +243,17 @@ vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag, } +int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) { + VP9D_COMP *pbi = (VP9D_COMP *) ptr; + VP9_COMMON *cm = &pbi->common; + + if (index < 0 || index >= NUM_REF_FRAMES) + return -1; + + *fb = &cm->yv12_fb[cm->ref_frame_map[index]]; + return 0; +} + /* If any buffer updating is signalled it should be done here. */ static void swap_frame_buffers(VP9D_COMP *pbi) { int ref_index = 0, mask; diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index c3353cee93e4837427058c049d3f704719fe76ce..19456e44fee6366ea62c93cfa7f3d95c8cc0dd25 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -2103,8 +2103,8 @@ int vp9_update_reference(VP9_PTR ptr, int ref_frame_flags) { return 0; } -int vp9_get_reference_enc(VP9_PTR ptr, VP9_REFFRAME ref_frame_flag, - YV12_BUFFER_CONFIG *sd) { +int vp9_copy_reference_enc(VP9_PTR ptr, VP9_REFFRAME ref_frame_flag, + YV12_BUFFER_CONFIG *sd) { VP9_COMP *cpi = (VP9_COMP *)(ptr); VP9_COMMON *cm = &cpi->common; int ref_fb_idx; @@ -2123,6 +2123,17 @@ int vp9_get_reference_enc(VP9_PTR ptr, VP9_REFFRAME ref_frame_flag, return 0; } +int vp9_get_reference_enc(VP9_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) { + VP9_COMP *cpi = (VP9_COMP *)(ptr); + VP9_COMMON *cm = &cpi->common; + + if (index < 0 || index >= NUM_REF_FRAMES) + return -1; + + *fb = &cm->yv12_fb[cm->ref_frame_map[index]]; + return 0; +} + int vp9_set_reference_enc(VP9_PTR ptr, VP9_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd) { VP9_COMP *cpi = (VP9_COMP *)(ptr); diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk index f330b464a4f2ac4456047ed8d7a1a7d360adf4e8..f1b1573171b130c5d203b0a71ae3657c916dcfe1 100644 --- a/vp9/vp9_common.mk +++ b/vp9/vp9_common.mk @@ -9,6 +9,7 @@ ## VP9_COMMON_SRCS-yes += vp9_common.mk +VP9_COMMON_SRCS-yes += vp9_iface_common.h VP9_COMMON_SRCS-yes += common/vp9_pragmas.h VP9_COMMON_SRCS-yes += common/vp9_ppflags.h VP9_COMMON_SRCS-yes += common/vp9_onyx.h diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 708cec60280285cffb578c29b094a29ba30bcac9..c0828acdb214cfbef4c8179c4d36425118c73479 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -16,6 +16,7 @@ #include "vpx/vp8cx.h" #include "vp9/encoder/vp9_firstpass.h" #include "vp9/common/vp9_onyx.h" +#include "vp9/vp9_iface_common.h" #include <stdlib.h> #include <string.h> @@ -867,9 +868,9 @@ static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx, } -static vpx_codec_err_t vp8e_get_reference(vpx_codec_alg_priv_t *ctx, - int ctr_id, - va_list args) { +static vpx_codec_err_t vp8e_copy_reference(vpx_codec_alg_priv_t *ctx, + int ctr_id, + va_list args) { vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); @@ -878,12 +879,28 @@ static vpx_codec_err_t vp8e_get_reference(vpx_codec_alg_priv_t *ctx, YV12_BUFFER_CONFIG sd; image2yuvconfig(&frame->img, &sd); - vp9_get_reference_enc(ctx->cpi, frame->frame_type, &sd); + vp9_copy_reference_enc(ctx->cpi, frame->frame_type, &sd); return VPX_CODEC_OK; } else return VPX_CODEC_INVALID_PARAM; } +static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx, + int ctr_id, + va_list args) { + vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *); + + if (data) { + YV12_BUFFER_CONFIG* fb; + + vp9_get_reference_enc(ctx->cpi, data->idx, &fb); + yuvconfig2image(&data->img, fb, NULL); + return VPX_CODEC_OK; + } else { + return VPX_CODEC_INVALID_PARAM; + } +} + static vpx_codec_err_t vp8e_set_previewpp(vpx_codec_alg_priv_t *ctx, int ctr_id, va_list args) { @@ -1038,7 +1055,7 @@ static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx, static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] = { {VP8_SET_REFERENCE, vp8e_set_reference}, - {VP8_COPY_REFERENCE, vp8e_get_reference}, + {VP8_COPY_REFERENCE, vp8e_copy_reference}, {VP8_SET_POSTPROC, vp8e_set_previewpp}, {VP8E_UPD_ENTROPY, vp8e_update_entropy}, {VP8E_UPD_REFERENCE, vp8e_update_reference}, @@ -1062,6 +1079,7 @@ static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] = { {VP8E_SET_CQ_LEVEL, set_param}, {VP8E_SET_MAX_INTRA_BITRATE_PCT, set_param}, {VP9E_SET_LOSSLESS, set_param}, + {VP9_GET_REFERENCE, get_reference}, { -1, NULL}, }; diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index eabdb85564523ac59afd627b57ce43dffe997062..655d25b69820232cf73d912b0eeb3ad10bdea2ff 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -17,6 +17,7 @@ #include "vpx_version.h" #include "decoder/vp9_onyxd.h" #include "decoder/vp9_onyxd_int.h" +#include "vp9/vp9_iface_common.h" #define VP8_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0) typedef vpx_codec_stream_info_t vp8_stream_info_t; @@ -273,36 +274,6 @@ update_error_state(vpx_codec_alg_priv_t *ctx, return res; } -static void yuvconfig2image(vpx_image_t *img, - const YV12_BUFFER_CONFIG *yv12, - void *user_priv) { - /** vpx_img_wrap() doesn't allow specifying independent strides for - * the Y, U, and V planes, nor other alignment adjustments that - * might be representable by a YV12_BUFFER_CONFIG, so we just - * initialize all the fields.*/ - img->fmt = yv12->clrtype == REG_YUV ? - VPX_IMG_FMT_I420 : VPX_IMG_FMT_VPXI420; - img->w = yv12->y_stride; - img->h = (yv12->y_height + 2 * VP9BORDERINPIXELS + 15) & ~15; - img->d_w = yv12->y_width; - img->d_h = yv12->y_height; - img->x_chroma_shift = 1; - img->y_chroma_shift = 1; - img->planes[VPX_PLANE_Y] = yv12->y_buffer; - img->planes[VPX_PLANE_U] = yv12->u_buffer; - img->planes[VPX_PLANE_V] = yv12->v_buffer; - img->planes[VPX_PLANE_ALPHA] = NULL; - img->stride[VPX_PLANE_Y] = yv12->y_stride; - img->stride[VPX_PLANE_U] = yv12->uv_stride; - img->stride[VPX_PLANE_V] = yv12->uv_stride; - img->stride[VPX_PLANE_ALPHA] = yv12->y_stride; - img->bps = 12; - img->user_priv = user_priv; - img->img_data = yv12->buffer_alloc; - img->img_data_owner = 0; - img->self_allocd = 0; -} - static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, const uint8_t **data, unsigned int data_sz, @@ -648,9 +619,9 @@ static vpx_codec_err_t vp9_set_reference(vpx_codec_alg_priv_t *ctx, } -static vpx_codec_err_t vp9_get_reference(vpx_codec_alg_priv_t *ctx, - int ctr_id, - va_list args) { +static vpx_codec_err_t vp9_copy_reference(vpx_codec_alg_priv_t *ctx, + int ctr_id, + va_list args) { vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); @@ -660,13 +631,29 @@ static vpx_codec_err_t vp9_get_reference(vpx_codec_alg_priv_t *ctx, image2yuvconfig(&frame->img, &sd); - return vp9_get_reference_dec(ctx->pbi, - (VP9_REFFRAME)frame->frame_type, &sd); + return vp9_copy_reference_dec(ctx->pbi, + (VP9_REFFRAME)frame->frame_type, &sd); } else return VPX_CODEC_INVALID_PARAM; } +static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx, + int ctr_id, + va_list args) { + vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *); + + if (data) { + YV12_BUFFER_CONFIG* fb; + + vp9_get_reference_dec(ctx->pbi, data->idx, &fb); + yuvconfig2image(&data->img, fb, NULL); + return VPX_CODEC_OK; + } else { + return VPX_CODEC_INVALID_PARAM; + } +} + static vpx_codec_err_t vp8_set_postproc(vpx_codec_alg_priv_t *ctx, int ctr_id, va_list args) { @@ -739,7 +726,7 @@ static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, static vpx_codec_ctrl_fn_map_t ctf_maps[] = { {VP8_SET_REFERENCE, vp9_set_reference}, - {VP8_COPY_REFERENCE, vp9_get_reference}, + {VP8_COPY_REFERENCE, vp9_copy_reference}, {VP8_SET_POSTPROC, vp8_set_postproc}, {VP8_SET_DBG_COLOR_REF_FRAME, vp8_set_dbg_options}, {VP8_SET_DBG_COLOR_MB_MODES, vp8_set_dbg_options}, @@ -747,6 +734,7 @@ static vpx_codec_ctrl_fn_map_t ctf_maps[] = { {VP8_SET_DBG_DISPLAY_MV, vp8_set_dbg_options}, {VP8D_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates}, {VP8D_GET_FRAME_CORRUPTED, vp8_get_frame_corrupted}, + {VP9_GET_REFERENCE, get_reference}, { -1, NULL}, }; diff --git a/vp9/vp9_iface_common.h b/vp9/vp9_iface_common.h new file mode 100644 index 0000000000000000000000000000000000000000..450be7dfda09f655eaa10598d68a28e11caecb31 --- /dev/null +++ b/vp9/vp9_iface_common.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef VP9_VP9_IFACE_COMMON_H_ +#define VP9_VP9_IFACE_COMMON_H_ + +static void yuvconfig2image(vpx_image_t *img, + const YV12_BUFFER_CONFIG *yv12, + void *user_priv) { + /** vpx_img_wrap() doesn't allow specifying independent strides for + * the Y, U, and V planes, nor other alignment adjustments that + * might be representable by a YV12_BUFFER_CONFIG, so we just + * initialize all the fields.*/ + img->fmt = yv12->clrtype == REG_YUV ? + VPX_IMG_FMT_I420 : VPX_IMG_FMT_VPXI420; + img->w = yv12->y_stride; + img->h = (yv12->y_height + 2 * VP9BORDERINPIXELS + 15) & ~15; + img->d_w = yv12->y_width; + img->d_h = yv12->y_height; + img->x_chroma_shift = 1; + img->y_chroma_shift = 1; + img->planes[VPX_PLANE_Y] = yv12->y_buffer; + img->planes[VPX_PLANE_U] = yv12->u_buffer; + img->planes[VPX_PLANE_V] = yv12->v_buffer; + img->planes[VPX_PLANE_ALPHA] = NULL; + img->stride[VPX_PLANE_Y] = yv12->y_stride; + img->stride[VPX_PLANE_U] = yv12->uv_stride; + img->stride[VPX_PLANE_V] = yv12->uv_stride; + img->stride[VPX_PLANE_ALPHA] = yv12->y_stride; + img->bps = 12; + img->user_priv = user_priv; + img->img_data = yv12->buffer_alloc; + img->img_data_owner = 0; + img->self_allocd = 0; +} + +#endif diff --git a/vpx/vp8.h b/vpx/vp8.h index 3c313632b9e7aab35818219ccfc853277fabf35e..0b4cb1b9e6d24b9d51a25e229c29d27273f4f932 100644 --- a/vpx/vp8.h +++ b/vpx/vp8.h @@ -44,6 +44,12 @@ enum vp8_com_control_id { VP8_SET_DBG_COLOR_MB_MODES = 5, /**< set which macro block modes to color */ VP8_SET_DBG_COLOR_B_MODES = 6, /**< set which blocks modes to color */ VP8_SET_DBG_DISPLAY_MV = 7, /**< set which motion vector modes to draw */ + + /* TODO(jkoleszar): The encoder incorrectly reuses some of these values (5+) + * for its control ids. These should be migrated to something like the + * VP8_DECODER_CTRL_ID_START range next time we're ready to break the ABI. + */ + VP9_GET_REFERENCE = 128, /**< get a pointer to a reference frame */ VP8_COMMON_CTRL_ID_MAX, VP8_DECODER_CTRL_ID_START = 256 }; @@ -97,6 +103,10 @@ typedef struct vpx_ref_frame { vpx_image_t img; /**< reference frame data in image format */ } vpx_ref_frame_t; +typedef struct vp9_ref_frame { + int idx; /**< frame index to get (input) */ + vpx_image_t img; /**< img structure to populate (output) */ +} vp9_ref_frame_t; /*!\brief vp8 decoder control function parameter type * @@ -110,6 +120,7 @@ VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_REF_FRAME, int) VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_MB_MODES, int) VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_B_MODES, int) VPX_CTRL_USE_TYPE(VP8_SET_DBG_DISPLAY_MV, int) +VPX_CTRL_USE_TYPE(VP9_GET_REFERENCE, vp9_ref_frame_t *) /*! @} - end defgroup vp8 */ diff --git a/vpxenc.c b/vpxenc.c index 19e10820c79b54e61ff29403c080c7a24aee146f..e915efdfac622124499a0545e17a6dc4dc619ea3 100644 --- a/vpxenc.c +++ b/vpxenc.c @@ -1645,8 +1645,6 @@ struct stream_state { stats_io_t stats; struct vpx_image *img; vpx_codec_ctx_t decoder; - vpx_ref_frame_t ref_enc; - vpx_ref_frame_t ref_dec; int mismatch_seen; }; @@ -2235,16 +2233,7 @@ static void initialize_encoder(struct stream_state *stream, #if CONFIG_DECODERS if (global->test_decode != TEST_DECODE_OFF) { - int width, height; - vpx_codec_dec_init(&stream->decoder, global->codec->dx_iface(), NULL, 0); - - width = (stream->config.cfg.g_w + 15) & ~15; - height = (stream->config.cfg.g_h + 15) & ~15; - vpx_img_alloc(&stream->ref_enc.img, VPX_IMG_FMT_I420, width, height, 1); - vpx_img_alloc(&stream->ref_dec.img, VPX_IMG_FMT_I420, width, height, 1); - stream->ref_enc.frame_type = VP8_LAST_FRAME; - stream->ref_dec.frame_type = VP8_LAST_FRAME; } #endif } @@ -2429,19 +2418,44 @@ static float usec_to_fps(uint64_t usec, unsigned int frames) { static void test_decode(struct stream_state *stream, - enum TestDecodeFatality fatal) { + enum TestDecodeFatality fatal, + const struct codec_item *codec) { + vpx_image_t enc_img, dec_img; + if (stream->mismatch_seen) return; - vpx_codec_control(&stream->encoder, VP8_COPY_REFERENCE, &stream->ref_enc); + /* Get the internal reference frame */ + if (codec->fourcc == VP8_FOURCC) { + struct vpx_ref_frame ref_enc, ref_dec; + int width, height; + + width = (stream->config.cfg.g_w + 15) & ~15; + height = (stream->config.cfg.g_h + 15) & ~15; + vpx_img_alloc(&ref_enc.img, VPX_IMG_FMT_I420, width, height, 1); + enc_img = ref_enc.img; + vpx_img_alloc(&ref_dec.img, VPX_IMG_FMT_I420, width, height, 1); + dec_img = ref_dec.img; + + ref_enc.frame_type = VP8_LAST_FRAME; + ref_dec.frame_type = VP8_LAST_FRAME; + vpx_codec_control(&stream->encoder, VP8_COPY_REFERENCE, &ref_enc); + vpx_codec_control(&stream->decoder, VP8_COPY_REFERENCE, &ref_dec); + } else { + struct vp9_ref_frame ref; + + ref.idx = 0; + vpx_codec_control(&stream->encoder, VP9_GET_REFERENCE, &ref); + enc_img = ref.img; + vpx_codec_control(&stream->decoder, VP9_GET_REFERENCE, &ref); + dec_img = ref.img; + } ctx_exit_on_error(&stream->encoder, "Failed to get encoder reference frame"); - vpx_codec_control(&stream->decoder, VP8_COPY_REFERENCE, &stream->ref_dec); ctx_exit_on_error(&stream->decoder, "Failed to get decoder reference frame"); - if (!compare_img(&stream->ref_enc.img, &stream->ref_dec.img)) { + if (!compare_img(&enc_img, &dec_img)) { int y[2], u[2], v[2]; - find_mismatch(&stream->ref_enc.img, &stream->ref_dec.img, - y, u, v); + find_mismatch(&enc_img, &dec_img, y, u, v); stream->decoder.err = 1; warn_or_exit_on_error(&stream->decoder, fatal == TEST_DECODE_FATAL, "Stream %d: Encode/decode mismatch on frame %d" @@ -2450,6 +2464,9 @@ static void test_decode(struct stream_state *stream, y[0], y[1], u[0], u[1], v[0], v[1]); stream->mismatch_seen = stream->frames_out; } + + vpx_img_free(&enc_img); + vpx_img_free(&dec_img); } @@ -2671,7 +2688,7 @@ int main(int argc, const char **argv_) { } if (got_data && global.test_decode != TEST_DECODE_OFF) - FOREACH_STREAM(test_decode(stream, global.test_decode)); + FOREACH_STREAM(test_decode(stream, global.test_decode, global.codec)); } fflush(stdout); @@ -2703,8 +2720,6 @@ int main(int argc, const char **argv_) { if (global.test_decode != TEST_DECODE_OFF) { FOREACH_STREAM(vpx_codec_destroy(&stream->decoder)); - FOREACH_STREAM(vpx_img_free(&stream->ref_enc.img)); - FOREACH_STREAM(vpx_img_free(&stream->ref_dec.img)); } close_input_file(&input);