Index: source/libvpx/vp9/vp9_dx_iface.c |
=================================================================== |
--- source/libvpx/vp9/vp9_dx_iface.c (revision 240950) |
+++ source/libvpx/vp9/vp9_dx_iface.c (working copy) |
@@ -59,6 +59,13 @@ |
int img_setup; |
int img_avail; |
int invert_tile_order; |
+ int fb_lru; |
+ |
+ /* External buffer info to save for VP9 common. */ |
+ vpx_codec_frame_buffer_t *fb_list; // External frame buffers |
+ int fb_count; // Total number of frame buffers |
+ vpx_realloc_frame_buffer_cb_fn_t realloc_fb_cb; |
+ void *user_priv; // Private data associated with the external frame buffers. |
}; |
static unsigned long priv_sz(const vpx_codec_dec_cfg_t *si, |
@@ -307,10 +314,32 @@ |
ctx->postproc_cfg.noise_level = 0; |
} |
- if (!optr) |
+ if (!optr) { |
res = VPX_CODEC_ERROR; |
- else |
+ } else { |
+ VP9D_COMP *const pbi = (VP9D_COMP*)optr; |
+ VP9_COMMON *const cm = &pbi->common; |
+ if (ctx->fb_list != NULL && ctx->realloc_fb_cb != NULL && |
+ ctx->fb_count > 0) { |
+ cm->fb_list = ctx->fb_list; |
+ cm->fb_count = ctx->fb_count; |
+ cm->realloc_fb_cb = ctx->realloc_fb_cb; |
+ cm->user_priv = ctx->user_priv; |
+ } else { |
+ cm->fb_count = FRAME_BUFFERS; |
+ } |
+ cm->fb_lru = ctx->fb_lru; |
+ CHECK_MEM_ERROR(cm, cm->yv12_fb, |
+ vpx_calloc(cm->fb_count, sizeof(*cm->yv12_fb))); |
+ CHECK_MEM_ERROR(cm, cm->fb_idx_ref_cnt, |
+ vpx_calloc(cm->fb_count, sizeof(*cm->fb_idx_ref_cnt))); |
+ if (cm->fb_lru) { |
+ CHECK_MEM_ERROR(cm, cm->fb_idx_ref_lru, |
+ vpx_calloc(cm->fb_count, |
+ sizeof(*cm->fb_idx_ref_lru))); |
+ } |
ctx->pbi = optr; |
+ } |
} |
ctx->decoder_init = 1; |
@@ -347,7 +376,7 @@ |
} |
if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) { |
- VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi; |
+ VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi; |
res = update_error_state(ctx, &pbi->common.error); |
} |
@@ -475,6 +504,27 @@ |
return img; |
} |
+static vpx_codec_err_t vp9_set_frame_buffers( |
+ vpx_codec_alg_priv_t *ctx, |
+ vpx_codec_frame_buffer_t *fb_list, int fb_count, |
+ vpx_realloc_frame_buffer_cb_fn_t cb, void *user_priv) { |
+ if (fb_count < REF_FRAMES) { |
+ /* The application must pass in at least REF_FRAMES frame buffers. */ |
+ return VPX_CODEC_INVALID_PARAM; |
+ } else if (!ctx->pbi) { |
+ /* If the decoder has already been initialized, do not accept external |
+ * frame buffers. |
+ */ |
+ ctx->fb_list = fb_list; |
+ ctx->fb_count = fb_count; |
+ ctx->realloc_fb_cb = cb; |
+ ctx->user_priv = user_priv; |
+ return VPX_CODEC_OK; |
+ } |
+ |
+ return VPX_CODEC_ERROR; |
+} |
+ |
static vpx_codec_err_t vp9_xma_get_mmap(const vpx_codec_ctx_t *ctx, |
vpx_codec_mmap_t *mmap, |
vpx_codec_iter_t *iter) { |
@@ -639,7 +689,7 @@ |
int ctrl_id, |
va_list args) { |
int *update_info = va_arg(args, int *); |
- VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi; |
+ VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi; |
if (update_info) { |
*update_info = pbi->refresh_frame_flags; |
@@ -657,7 +707,7 @@ |
int *corrupted = va_arg(args, int *); |
if (corrupted) { |
- VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi; |
+ VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi; |
if (pbi) |
*corrupted = pbi->common.frame_to_show->corrupted; |
else |
@@ -668,6 +718,25 @@ |
} |
} |
+static vpx_codec_err_t get_display_size(vpx_codec_alg_priv_t *ctx, |
+ int ctrl_id, |
+ va_list args) { |
+ int *const display_size = va_arg(args, int *); |
+ |
+ if (display_size) { |
+ const VP9D_COMP *const pbi = (VP9D_COMP*)ctx->pbi; |
+ if (pbi) { |
+ display_size[0] = pbi->common.display_width; |
+ display_size[1] = pbi->common.display_height; |
+ } else { |
+ return VPX_CODEC_ERROR; |
+ } |
+ return VPX_CODEC_OK; |
+ } else { |
+ return VPX_CODEC_INVALID_PARAM; |
+ } |
+} |
+ |
static vpx_codec_err_t set_invert_tile_order(vpx_codec_alg_priv_t *ctx, |
int ctr_id, |
va_list args) { |
@@ -675,6 +744,21 @@ |
return VPX_CODEC_OK; |
} |
+static vpx_codec_err_t set_frame_buffer_lru_cache(vpx_codec_alg_priv_t *ctx, |
+ int ctr_id, |
+ va_list args) { |
+ VP9D_COMP *const pbi = (VP9D_COMP*)ctx->pbi; |
+ |
+ // Save for later to pass into vp9 common. |
+ ctx->fb_lru = va_arg(args, int); |
+ |
+ if (pbi) { |
+ VP9_COMMON *const cm = &pbi->common; |
+ cm->fb_lru = ctx->fb_lru; |
+ } |
+ return VPX_CODEC_OK; |
+} |
+ |
static vpx_codec_ctrl_fn_map_t ctf_maps[] = { |
{VP8_SET_REFERENCE, set_reference}, |
{VP8_COPY_REFERENCE, copy_reference}, |
@@ -686,7 +770,9 @@ |
{VP8D_GET_LAST_REF_UPDATES, get_last_ref_updates}, |
{VP8D_GET_FRAME_CORRUPTED, get_frame_corrupted}, |
{VP9_GET_REFERENCE, get_reference}, |
+ {VP9D_GET_DISPLAY_SIZE, get_display_size}, |
{VP9_INVERT_TILE_DECODE_ORDER, set_invert_tile_order}, |
+ {VP9D_SET_FRAME_BUFFER_LRU_CACHE, set_frame_buffer_lru_cache}, |
{ -1, NULL}, |
}; |
@@ -697,7 +783,8 @@ |
CODEC_INTERFACE(vpx_codec_vp9_dx) = { |
"WebM Project VP9 Decoder" VERSION_STRING, |
VPX_CODEC_INTERNAL_ABI_VERSION, |
- VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC, |
+ VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC | |
+ VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER, |
/* vpx_codec_caps_t caps; */ |
vp9_init, /* vpx_codec_init_fn_t init; */ |
vp9_destroy, /* vpx_codec_destroy_fn_t destroy; */ |
@@ -709,6 +796,7 @@ |
vp9_get_si, /* vpx_codec_get_si_fn_t get_si; */ |
vp9_decode, /* vpx_codec_decode_fn_t decode; */ |
vp9_get_frame, /* vpx_codec_frame_get_fn_t frame_get; */ |
+ vp9_set_frame_buffers, /* vpx_codec_set_frame_buffers_fn_t set_fb; */ |
}, |
{ // NOLINT |
/* encoder functions */ |