Commit 75f647fe authored by Scott LaVarnway's avatar Scott LaVarnway
Browse files

WIP: Multiple decoder instances support

Started adding support for multiple internal decoder instances.  Also added
code to limit the vp8 config options available when using frame-based
multithreading.

Change-Id: I0f1ee7abcfcff59204f50162e28254b8dd6972eb
parent 8b22a9d3
......@@ -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
......
......@@ -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;
}
......@@ -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); \
......
......@@ -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;
......
......@@ -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
*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment