diff --git a/vp8/common/onyxd.h b/vp8/common/onyxd.h index c67910e091c0fb82b15f534e5a452398a83950d3..97c81c130a0adc3443ec945a32fc38a36d9e9d4b 100644 --- a/vp8/common/onyxd.h +++ b/vp8/common/onyxd.h @@ -55,10 +55,6 @@ extern "C" vpx_codec_err_t vp8dx_get_reference(struct VP8D_COMP* comp, enum vpx_ref_frame_type ref_frame_flag, YV12_BUFFER_CONFIG *sd); vpx_codec_err_t vp8dx_set_reference(struct VP8D_COMP* comp, enum vpx_ref_frame_type ref_frame_flag, YV12_BUFFER_CONFIG *sd); - struct VP8D_COMP* vp8dx_create_decompressor(VP8D_CONFIG *oxcf); - - void vp8dx_remove_decompressor(struct VP8D_COMP* comp); - #ifdef __cplusplus } #endif diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c index 6f473de2048d2dff42b34d3bd1a3732f32a7bc98..019c255f698dbcd62a2db5a009194c79695179b7 100644 --- a/vp8/decoder/onyxd_if.c +++ b/vp8/decoder/onyxd_if.c @@ -42,7 +42,16 @@ extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi); static int get_free_fb (VP8_COMMON *cm); static void ref_cnt_fb (int *buf, int *idx, int new_idx); -struct VP8D_COMP * vp8dx_create_decompressor(VP8D_CONFIG *oxcf) +static void remove_decompressor(VP8D_COMP *pbi) +{ +#if CONFIG_ERROR_CONCEALMENT + vp8_de_alloc_overlap_lists(pbi); +#endif + vp8_remove_common(&pbi->common); + vpx_free(pbi); +} + +static struct VP8D_COMP * create_decompressor(VP8D_CONFIG *oxcf) { VP8D_COMP *pbi = vpx_memalign(32, sizeof(VP8D_COMP)); @@ -54,7 +63,7 @@ struct VP8D_COMP * vp8dx_create_decompressor(VP8D_CONFIG *oxcf) if (setjmp(pbi->common.error.jmp)) { pbi->common.error.setjmp = 0; - vp8dx_remove_decompressor(pbi); + remove_decompressor(pbi); return 0; } @@ -65,11 +74,6 @@ struct VP8D_COMP * vp8dx_create_decompressor(VP8D_CONFIG *oxcf) pbi->common.current_video_frame = 0; pbi->ready_for_new_data = 1; -#if CONFIG_MULTITHREAD - pbi->max_threads = oxcf->max_threads; - vp8_decoder_create_threads(pbi); -#endif - /* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid * unnecessary calling of vp8cx_init_de_quantizer() for every frame. */ @@ -103,25 +107,6 @@ struct VP8D_COMP * vp8dx_create_decompressor(VP8D_CONFIG *oxcf) return pbi; } - -void vp8dx_remove_decompressor(VP8D_COMP *pbi) -{ - if (!pbi) - return; - -#if CONFIG_MULTITHREAD - if (pbi->b_multithreaded_rd) - vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows); - vp8_decoder_remove_threads(pbi); -#endif -#if CONFIG_ERROR_CONCEALMENT - vp8_de_alloc_overlap_lists(pbi); -#endif - vp8_remove_common(&pbi->common); - vpx_free(pbi); -} - - vpx_codec_err_t vp8dx_get_reference(VP8D_COMP *pbi, enum vpx_ref_frame_type ref_frame_flag, YV12_BUFFER_CONFIG *sd) { VP8_COMMON *cm = &pbi->common; @@ -490,3 +475,54 @@ int vp8dx_references_buffer( VP8_COMMON *oci, int ref_frame ) return 0; } + +int vp8_create_decoder_instances(struct frame_buffers *fb, VP8D_CONFIG *oxcf) +{ + if(!fb->use_frame_threads) + { + /* decoder instance for single thread mode */ + fb->pbi[0] = create_decompressor(oxcf); + if(!fb->pbi[0]) + return VPX_CODEC_ERROR; + +#if CONFIG_MULTITHREAD + /* enable row-based threading only when use_frame_threads + * is disabled */ + fb->pbi[0]->max_threads = oxcf->max_threads; + vp8_decoder_create_threads(fb->pbi[0]); +#endif + } + else + { + /* TODO : create frame threads and decoder instances for each + * thread here */ + } + + return VPX_CODEC_OK; +} + +int vp8_remove_decoder_instances(struct frame_buffers *fb) +{ + if(!fb->use_frame_threads) + { + VP8D_COMP *pbi = fb->pbi[0]; + + if (!pbi) + return VPX_CODEC_ERROR; +#if CONFIG_MULTITHREAD + if (pbi->b_multithreaded_rd) + vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows); + vp8_decoder_remove_threads(pbi); +#endif + + /* decoder instance for single thread mode */ + remove_decompressor(pbi); + } + else + { + /* TODO : remove frame threads and decoder instances for each + * thread here */ + } + + return VPX_CODEC_OK; +} diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h index 290c212179dbdc626df0416d66662b9275c3b333..fb2dde8527f7a5895916471c32ee1928d0b895a1 100644 --- a/vp8/decoder/onyxd_int.h +++ b/vp8/decoder/onyxd_int.h @@ -33,6 +33,7 @@ typedef struct MACROBLOCKD mbd; } MB_ROW_DEC; + typedef struct { int enabled; @@ -41,6 +42,22 @@ typedef struct unsigned int sizes[MAX_PARTITIONS]; } FRAGMENT_DATA; +#define MAX_FB_MT_DEC 32 + +struct frame_buffers +{ + /* + * this struct will be populated with frame buffer management + * info in future commits. */ + + /* enable/disable frame-based threading */ + int use_frame_threads; + + /* decoder instances */ + struct VP8D_COMP *pbi[MAX_FB_MT_DEC]; + +}; + typedef struct VP8D_COMP { DECLARE_ALIGNED(16, MACROBLOCKD, mb); @@ -108,6 +125,9 @@ typedef struct VP8D_COMP int vp8_decode_frame(VP8D_COMP *cpi); +int vp8_create_decoder_instances(struct frame_buffers *fb, VP8D_CONFIG *oxcf); +int vp8_remove_decoder_instances(struct frame_buffers *fb); + #if CONFIG_DEBUG #define CHECK_MEM_ERROR(lval,expr) do {\ lval = (expr); \ diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c index 598abbd29977dd96883d30482d0933c166a45be9..1db61f1614c7a4943ca09e1d4bc73f24f496c468 100644 --- a/vp8/vp8_dx_iface.c +++ b/vp8/vp8_dx_iface.c @@ -64,7 +64,6 @@ struct vpx_codec_alg_priv vp8_stream_info_t si; int defer_alloc; int decoder_init; - struct VP8D_COMP *pbi; int postproc_cfg_set; vp8_postproc_cfg_t postproc_cfg; #if CONFIG_POSTPROC_VISUALIZER @@ -76,6 +75,7 @@ struct vpx_codec_alg_priv #endif vpx_image_t img; int img_setup; + struct frame_buffers yv12_frame_buffers; void *user_priv; FRAGMENT_DATA fragments; }; @@ -228,6 +228,24 @@ static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx, } } + ctx->priv->alg_priv->yv12_frame_buffers.use_frame_threads = + (ctx->priv->alg_priv->base.init_flags & + VPX_CODEC_USE_FRAME_THREADING); + + /* for now, disable frame threading */ + ctx->priv->alg_priv->yv12_frame_buffers.use_frame_threads = 0; + + if(ctx->priv->alg_priv->yv12_frame_buffers.use_frame_threads && + (( ctx->priv->alg_priv->base.init_flags & + VPX_CODEC_USE_ERROR_CONCEALMENT) + || ( ctx->priv->alg_priv->base.init_flags & + VPX_CODEC_USE_INPUT_FRAGMENTS) ) ) + { + /* row-based threading, error concealment, and input fragments will + * not be supported when using frame-based threading */ + res = VPX_CODEC_INVALID_PARAM; + } + return res; } @@ -235,7 +253,7 @@ static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx) { int i; - vp8dx_remove_decompressor(ctx->pbi); + vp8_remove_decoder_instances(&ctx->yv12_frame_buffers); for (i = NELEMENTS(ctx->mmaps) - 1; i >= 0; i--) { @@ -467,7 +485,6 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, if (!res) { VP8D_CONFIG oxcf; - struct VP8D_COMP* optr; oxcf.Width = ctx->si.w; oxcf.Height = ctx->si.h; @@ -477,8 +494,6 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, oxcf.error_concealment = (ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT); - optr = vp8dx_create_decompressor(&oxcf); - /* If postprocessing was enabled by the application and a * configuration has not been provided, default it. */ @@ -491,20 +506,17 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, ctx->postproc_cfg.noise_level = 0; } - if (!optr) - res = VPX_CODEC_ERROR; - else - ctx->pbi = optr; + res = vp8_create_decoder_instances(&ctx->yv12_frame_buffers, &oxcf); } ctx->decoder_init = 1; } - if (!res && ctx->pbi) + if (!res) { + VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0]; if(resolution_change) { - VP8D_COMP *pbi = ctx->pbi; VP8_COMMON *const pc = & pbi->common; MACROBLOCKD *const xd = & pbi->mb; #if CONFIG_MULTITHREAD @@ -594,16 +606,15 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, pbi->common.error.setjmp = 0; /* required to get past the first get_free_fb() call */ - ctx->pbi->common.fb_idx_ref_cnt[0] = 0; + pbi->common.fb_idx_ref_cnt[0] = 0; } /* update the pbi fragment data */ - ctx->pbi->fragments = ctx->fragments; + pbi->fragments = ctx->fragments; ctx->user_priv = user_priv; - if (vp8dx_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) + if (vp8dx_receive_compressed_data(pbi, data_sz, data, deadline)) { - VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi; res = update_error_state(ctx, &pbi->common.error); } @@ -649,7 +660,8 @@ static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t *ctx, #endif } - if (0 == vp8dx_get_raw_frame(ctx->pbi, &sd, &time_stamp, &time_end_stamp, &flags)) + if (0 == vp8dx_get_raw_frame(ctx->yv12_frame_buffers.pbi[0], &sd, + &time_stamp, &time_end_stamp, &flags)) { yuvconfig2image(&ctx->img, &sd, ctx->user_priv); @@ -774,14 +786,15 @@ static vpx_codec_err_t vp8_set_reference(vpx_codec_alg_priv_t *ctx, vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); - if (data) + if (data && !ctx->yv12_frame_buffers.use_frame_threads) { vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; YV12_BUFFER_CONFIG sd; image2yuvconfig(&frame->img, &sd); - return vp8dx_set_reference(ctx->pbi, frame->frame_type, &sd); + return vp8dx_set_reference(ctx->yv12_frame_buffers.pbi[0], + frame->frame_type, &sd); } else return VPX_CODEC_INVALID_PARAM; @@ -795,14 +808,15 @@ static vpx_codec_err_t vp8_get_reference(vpx_codec_alg_priv_t *ctx, vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); - if (data) + if (data && !ctx->yv12_frame_buffers.use_frame_threads) { vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; YV12_BUFFER_CONFIG sd; image2yuvconfig(&frame->img, &sd); - return vp8dx_get_reference(ctx->pbi, frame->frame_type, &sd); + return vp8dx_get_reference(ctx->yv12_frame_buffers.pbi[0], + frame->frame_type, &sd); } else return VPX_CODEC_INVALID_PARAM; @@ -858,10 +872,11 @@ static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx, va_list args) { int *update_info = va_arg(args, int *); - VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi; - if (update_info) + if (update_info && !ctx->yv12_frame_buffers.use_frame_threads) { + VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; + *update_info = pbi->common.refresh_alt_ref_frame * (int) VP8_ALTR_FRAME + pbi->common.refresh_golden_frame * (int) VP8_GOLD_FRAME + pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME; @@ -878,11 +893,11 @@ static vpx_codec_err_t vp8_get_last_ref_frame(vpx_codec_alg_priv_t *ctx, va_list args) { int *ref_info = va_arg(args, int *); - VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi; - VP8_COMMON *oci = &pbi->common; - if (ref_info) + if (ref_info && !ctx->yv12_frame_buffers.use_frame_threads) { + VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; + VP8_COMMON *oci = &pbi->common; *ref_info = (vp8dx_references_buffer( oci, ALTREF_FRAME )?VP8_ALTR_FRAME:0) | (vp8dx_references_buffer( oci, GOLDEN_FRAME )?VP8_GOLD_FRAME:0) | @@ -903,7 +918,7 @@ static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, if (corrupted) { - VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi; + VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; *corrupted = pbi->common.frame_to_show->corrupted; return VPX_CODEC_OK; diff --git a/vpx/vpx_decoder.h b/vpx/vpx_decoder.h index dbe6aaaaa319c5a89f7fc4e112ca333a34d5075a..e7701e5123411531bb7df5916914b493221540b6 100644 --- a/vpx/vpx_decoder.h +++ b/vpx/vpx_decoder.h @@ -65,12 +65,17 @@ extern "C" { * * The available flags are specified by VPX_CODEC_USE_* defines. */ +#define VPX_CODEC_CAP_FRAME_THREADING 0x200000 /**< Can support frame-based + multi-threading */ + #define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */ #define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded frames */ #define VPX_CODEC_USE_INPUT_FRAGMENTS 0x40000 /**< The input frame should be passed to the decoder one fragment at a time */ +#define VPX_CODEC_USE_FRAME_THREADING 0x80000 /**< Enable frame-based + multi-threading */ /*!\brief Stream properties *