WIP: Multiple decoder instances support
authorScott LaVarnway <slavarnway@google.com>
Wed, 3 Oct 2012 17:07:13 +0000 (10:07 -0700)
committerScott LaVarnway <slavarnway@google.com>
Wed, 30 Jan 2013 18:27:26 +0000 (10:27 -0800)
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

vp8/common/onyxd.h
vp8/decoder/onyxd_if.c
vp8/decoder/onyxd_int.h
vp8/vp8_dx_iface.c
vpx/vpx_decoder.h

index c67910e..97c81c1 100644 (file)
@@ -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
index 6f473de..019c255 100644 (file)
@@ -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;
+}
index 290c212..fb2dde8 100644 (file)
@@ -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); \
index 598abbd..1db61f1 100644 (file)
@@ -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;
index dbe6aaa..e7701e5 100644 (file)
@@ -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
    *