]> granicus.if.org Git - libvpx/commitdiff
Move frame allocations out of vp8_decode_frame()
authorScott LaVarnway <slavarnway@google.com>
Mon, 24 Sep 2012 19:44:45 +0000 (12:44 -0700)
committerScott LaVarnway <slavarnway@google.com>
Mon, 24 Sep 2012 19:44:45 +0000 (12:44 -0700)
in order to make it easier to implement the frame-base multithreading.

Change-Id: Iea2fd05be34fa704848fdc7669bf167f2ed229c5

vp8/decoder/decodframe.c
vp8/decoder/onyxd_if.c
vp8/decoder/onyxd_int.h
vp8/decoder/threading.c
vp8/vp8_dx_iface.c

index 877eb7738680f00cc43606d53d9693566d0712ca..dbd450542229a2afbb0fd6121ddc7e189353cd6a 100644 (file)
@@ -515,37 +515,36 @@ static void decode_mb_rows(VP8D_COMP *pbi)
     int recon_yoffset, recon_uvoffset;
     int mb_row, mb_col;
     int mb_idx = 0;
-    int dst_fb_idx = pc->new_fb_idx;
-    int recon_y_stride = pc->yv12_fb[dst_fb_idx].y_stride;
-    int recon_uv_stride = pc->yv12_fb[dst_fb_idx].uv_stride;
+
+    YV12_BUFFER_CONFIG *yv12_fb_new = pbi->dec_fb_ref[INTRA_FRAME];
+
+    int recon_y_stride = yv12_fb_new->y_stride;
+    int recon_uv_stride = yv12_fb_new->uv_stride;
 
     unsigned char *ref_buffer[MAX_REF_FRAMES][3];
     unsigned char *dst_buffer[3];
     unsigned char *lf_dst[3];
     unsigned char *eb_dst[3];
     int i;
-    int ref_fb_index[MAX_REF_FRAMES];
     int ref_fb_corrupted[MAX_REF_FRAMES];
 
     ref_fb_corrupted[INTRA_FRAME] = 0;
 
-    ref_fb_index[LAST_FRAME]    = pc->lst_fb_idx;
-    ref_fb_index[GOLDEN_FRAME]  = pc->gld_fb_idx;
-    ref_fb_index[ALTREF_FRAME]  = pc->alt_fb_idx;
-
     for(i = 1; i < MAX_REF_FRAMES; i++)
     {
-        ref_buffer[i][0] = pc->yv12_fb[ref_fb_index[i]].y_buffer;
-        ref_buffer[i][1] = pc->yv12_fb[ref_fb_index[i]].u_buffer;
-        ref_buffer[i][2] = pc->yv12_fb[ref_fb_index[i]].v_buffer;
+        YV12_BUFFER_CONFIG *this_fb = pbi->dec_fb_ref[i];
 
-        ref_fb_corrupted[i] = pc->yv12_fb[ref_fb_index[i]].corrupted;
+        ref_buffer[i][0] = this_fb->y_buffer;
+        ref_buffer[i][1] = this_fb->u_buffer;
+        ref_buffer[i][2] = this_fb->v_buffer;
+
+        ref_fb_corrupted[i] = this_fb->corrupted;
     }
 
     /* Set up the buffer pointers */
-    eb_dst[0] = lf_dst[0] = dst_buffer[0] = pc->yv12_fb[dst_fb_idx].y_buffer;
-    eb_dst[1] = lf_dst[1] = dst_buffer[1] = pc->yv12_fb[dst_fb_idx].u_buffer;
-    eb_dst[2] = lf_dst[2] = dst_buffer[2] = pc->yv12_fb[dst_fb_idx].v_buffer;
+    eb_dst[0] = lf_dst[0] = dst_buffer[0] = yv12_fb_new->y_buffer;
+    eb_dst[1] = lf_dst[1] = dst_buffer[1] = yv12_fb_new->u_buffer;
+    eb_dst[2] = lf_dst[2] = dst_buffer[2] = yv12_fb_new->v_buffer;
 
     xd->up_available = 0;
 
@@ -553,7 +552,7 @@ static void decode_mb_rows(VP8D_COMP *pbi)
     if(pc->filter_level)
         vp8_loop_filter_frame_init(pc, xd, pc->filter_level);
 
-    vp8_setup_intra_recon_top_line(&pc->yv12_fb[dst_fb_idx]);
+    vp8_setup_intra_recon_top_line(yv12_fb_new);
 
     /* Decode the individual macro block */
     for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
@@ -669,7 +668,7 @@ static void decode_mb_rows(VP8D_COMP *pbi)
         }
 
         /* adjust to the next row of mbs */
-        vp8_extend_mb_row(&pc->yv12_fb[dst_fb_idx], xd->dst.y_buffer + 16,
+        vp8_extend_mb_row(yv12_fb_new, xd->dst.y_buffer + 16,
                           xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
 
         ++xd->mode_info_context;      /* skip prediction column */
@@ -690,7 +689,7 @@ static void decode_mb_rows(VP8D_COMP *pbi)
 
                 if(mb_row > 1)
                 {
-                    yv12_extend_frame_left_right_c(&pc->yv12_fb[dst_fb_idx],
+                    yv12_extend_frame_left_right_c(yv12_fb_new,
                                                    eb_dst[0],
                                                    eb_dst[1],
                                                    eb_dst[2]);
@@ -700,7 +699,7 @@ static void decode_mb_rows(VP8D_COMP *pbi)
                     eb_dst[2] += recon_uv_stride *  8;
 
                     if(mb_row == 2)
-                        yv12_extend_frame_top_c(&pc->yv12_fb[dst_fb_idx]);
+                        yv12_extend_frame_top_c(yv12_fb_new);
 
                 }
 
@@ -716,7 +715,7 @@ static void decode_mb_rows(VP8D_COMP *pbi)
             if(mb_row > 0)
             {
                 /**/
-                yv12_extend_frame_left_right_c(&pc->yv12_fb[dst_fb_idx],
+                yv12_extend_frame_left_right_c(yv12_fb_new,
                                                eb_dst[0],
                                                eb_dst[1],
                                                eb_dst[2]);
@@ -726,7 +725,7 @@ static void decode_mb_rows(VP8D_COMP *pbi)
                 eb_dst[2] += recon_uv_stride *  8;
 
                 if(mb_row == 1)
-                    yv12_extend_frame_top_c(&pc->yv12_fb[dst_fb_idx]);
+                    yv12_extend_frame_top_c(yv12_fb_new);
             }
         }
     }
@@ -742,7 +741,7 @@ static void decode_mb_rows(VP8D_COMP *pbi)
                                        recon_uv_stride, lf_dst[0], lf_dst[1],
                                        lf_dst[2]);
 
-        yv12_extend_frame_left_right_c(&pc->yv12_fb[dst_fb_idx],
+        yv12_extend_frame_left_right_c(yv12_fb_new,
                                        eb_dst[0],
                                        eb_dst[1],
                                        eb_dst[2]);
@@ -750,12 +749,13 @@ static void decode_mb_rows(VP8D_COMP *pbi)
         eb_dst[1] += recon_uv_stride *  8;
         eb_dst[2] += recon_uv_stride *  8;
     }
-    yv12_extend_frame_left_right_c(&pc->yv12_fb[dst_fb_idx],
+    yv12_extend_frame_left_right_c(yv12_fb_new,
                                    eb_dst[0],
                                    eb_dst[1],
                                    eb_dst[2]);
 
-    yv12_extend_frame_bottom_c(&pc->yv12_fb[dst_fb_idx]);
+    yv12_extend_frame_bottom_c(yv12_fb_new);
+
 }
 
 static unsigned int read_partition_size(const unsigned char *cx_size)
@@ -995,9 +995,11 @@ int vp8_decode_frame(VP8D_COMP *pbi)
     int corrupt_tokens = 0;
     int prev_independent_partitions = pbi->independent_partitions;
 
+    YV12_BUFFER_CONFIG *yv12_fb_new = pbi->dec_fb_ref[INTRA_FRAME];
+
     /* start with no corruption of current frame */
     xd->corrupted = 0;
-    pc->yv12_fb[pc->new_fb_idx].corrupted = 0;
+    yv12_fb_new->corrupted = 0;
 
     if (data_end - data < 3)
     {
@@ -1035,9 +1037,6 @@ int vp8_decode_frame(VP8D_COMP *pbi)
 
         if (pc->frame_type == KEY_FRAME)
         {
-            const int Width = pc->Width;
-            const int Height = pc->Height;
-
             /* vet via sync code */
             /* When error concealment is enabled we should only check the sync
              * code if we have enough bits available
@@ -1062,85 +1061,14 @@ int vp8_decode_frame(VP8D_COMP *pbi)
             }
             data += 7;
 
-            if (Width != pc->Width  ||  Height != pc->Height)
-            {
-                int prev_mb_rows = pc->mb_rows;
-
-                if (pc->Width <= 0)
-                {
-                    pc->Width = Width;
-                    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
-                                       "Invalid frame width");
-                }
-
-                if (pc->Height <= 0)
-                {
-                    pc->Height = Height;
-                    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
-                                       "Invalid frame height");
-                }
-
-                if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height))
-                    vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
-                                       "Failed to allocate frame buffers");
-
-                vpx_memcpy(&xd->pre, &pc->yv12_fb[pc->lst_fb_idx], sizeof(YV12_BUFFER_CONFIG));
-                vpx_memcpy(&xd->dst, &pc->yv12_fb[pc->new_fb_idx], sizeof(YV12_BUFFER_CONFIG));
-
-#if CONFIG_MULTITHREAD
-                for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
-                {
-                    pbi->mb_row_di[i].mbd.dst = pc->yv12_fb[pc->new_fb_idx];
-                    vp8_build_block_doffsets(&pbi->mb_row_di[i].mbd);
-                }
-#endif
-                vp8_build_block_doffsets(&pbi->mb);
-
-                /* allocate memory for last frame MODE_INFO array */
-#if CONFIG_ERROR_CONCEALMENT
-
-                if (pbi->ec_enabled)
-                {
-                    /* old prev_mip was released by vp8_de_alloc_frame_buffers()
-                     * called in vp8_alloc_frame_buffers() */
-                    pc->prev_mip = vpx_calloc(
-                                       (pc->mb_cols + 1) * (pc->mb_rows + 1),
-                                       sizeof(MODE_INFO));
-
-                    if (!pc->prev_mip)
-                    {
-                        vp8_de_alloc_frame_buffers(pc);
-                        vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
-                                           "Failed to allocate"
-                                           "last frame MODE_INFO array");
-                    }
-
-                    pc->prev_mi = pc->prev_mip + pc->mode_info_stride + 1;
-
-                    if (vp8_alloc_overlap_lists(pbi))
-                        vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
-                                           "Failed to allocate overlap lists "
-                                           "for error concealment");
-                }
-
-#endif
-
-#if CONFIG_MULTITHREAD
-                if (pbi->b_multithreaded_rd)
-                    vp8mt_alloc_temp_buffers(pbi, pc->Width, prev_mb_rows);
-#else
-                (void)prev_mb_rows;
-#endif
-            }
         }
         else
         {
-          vpx_memcpy(&xd->pre, &pc->yv12_fb[pc->lst_fb_idx], sizeof(YV12_BUFFER_CONFIG));
-          vpx_memcpy(&xd->dst, &pc->yv12_fb[pc->new_fb_idx], sizeof(YV12_BUFFER_CONFIG));
+          vpx_memcpy(&xd->pre, yv12_fb_new, sizeof(YV12_BUFFER_CONFIG));
+          vpx_memcpy(&xd->dst, yv12_fb_new, sizeof(YV12_BUFFER_CONFIG));
         }
     }
-    if ((!pbi->decoded_key_frame && pc->frame_type != KEY_FRAME) ||
-        pc->Width == 0 || pc->Height == 0)
+    if ((!pbi->decoded_key_frame && pc->frame_type != KEY_FRAME))
     {
         return -1;
     }
@@ -1412,7 +1340,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
     {
         unsigned int i;
         vp8mt_decode_mb_rows(pbi, xd);
-        vp8_yv12_extend_frame_borders(&pc->yv12_fb[pc->new_fb_idx]);    /*cm->frame_to_show);*/
+        vp8_yv12_extend_frame_borders(yv12_fb_new);
         for (i = 0; i < pbi->decoding_thread_count; ++i)
             corrupt_tokens |= pbi->mb_row_di[i].mbd.corrupted;
     }
@@ -1425,14 +1353,14 @@ int vp8_decode_frame(VP8D_COMP *pbi)
 
     /* Collect information about decoder corruption. */
     /* 1. Check first boolean decoder for errors. */
-    pc->yv12_fb[pc->new_fb_idx].corrupted = vp8dx_bool_error(bc);
+    yv12_fb_new->corrupted = vp8dx_bool_error(bc);
     /* 2. Check the macroblock information */
-    pc->yv12_fb[pc->new_fb_idx].corrupted |= corrupt_tokens;
+    yv12_fb_new->corrupted |= corrupt_tokens;
 
     if (!pbi->decoded_key_frame)
     {
         if (pc->frame_type == KEY_FRAME &&
-            !pc->yv12_fb[pc->new_fb_idx].corrupted)
+            !yv12_fb_new->corrupted)
             pbi->decoded_key_frame = 1;
         else
             vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
index 95293f4214765018a11965e11b7730391ebda9bb..2985d760390bf4ce0dcb49d939dfa95e7b77f064 100644 (file)
@@ -289,14 +289,6 @@ int vp8dx_receive_compressed_data(VP8D_COMP *pbi, unsigned long size, const unsi
     VP8_COMMON *cm = &pbi->common;
     int retcode = 0;
 
-    /*if(pbi->ready_for_new_data == 0)
-        return -1;*/
-
-    if (pbi == 0)
-    {
-        return -1;
-    }
-
     pbi->common.error.error_code = VPX_CODEC_OK;
 
     if (pbi->num_fragments == 0)
@@ -383,6 +375,12 @@ int vp8dx_receive_compressed_data(VP8D_COMP *pbi, unsigned long size, const unsi
 
     cm->new_fb_idx = get_free_fb (cm);
 
+    /* setup reference frames for vp8_decode_frame */
+    pbi->dec_fb_ref[INTRA_FRAME]  = &cm->yv12_fb[cm->new_fb_idx];
+    pbi->dec_fb_ref[LAST_FRAME]   = &cm->yv12_fb[cm->lst_fb_idx];
+    pbi->dec_fb_ref[GOLDEN_FRAME] = &cm->yv12_fb[cm->gld_fb_idx];
+    pbi->dec_fb_ref[ALTREF_FRAME] = &cm->yv12_fb[cm->alt_fb_idx];
+
     if (setjmp(pbi->common.error.jmp))
     {
 #if HAVE_NEON
index e6c814accd7417181fc7d2484338beef6c70d021..022c6985be778cb44bbffa6d06f464d25b35cdd6 100644 (file)
@@ -37,6 +37,8 @@ typedef struct VP8D_COMP
 {
     DECLARE_ALIGNED(16, MACROBLOCKD, mb);
 
+    YV12_BUFFER_CONFIG *dec_fb_ref[NUM_YV12_BUFFERS];
+
     DECLARE_ALIGNED(16, VP8_COMMON, common);
 
     vp8_reader bc, bc2;
index de14789cbd50c64a664066bced0024c25560d53d..a91281b4c744661d82248eb0a72cf51b6026324d 100644 (file)
@@ -48,8 +48,8 @@ static void setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_D
         mbd->mode_info_stride  = pc->mode_info_stride;
 
         mbd->frame_type = pc->frame_type;
-        mbd->pre = pc->yv12_fb[pc->lst_fb_idx];
-        mbd->dst = pc->yv12_fb[pc->new_fb_idx];
+        mbd->pre = xd->pre;
+        mbd->dst = xd->dst;
 
         mbd->segmentation_enabled    = xd->segmentation_enabled;
         mbd->mb_segement_abs_delta     = xd->mb_segement_abs_delta;
@@ -304,31 +304,33 @@ static void mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd, int start_mb_row)
     int num_part = 1 << pbi->common.multi_token_partition;
     int last_mb_row = start_mb_row;
 
-    int dst_fb_idx = pc->new_fb_idx;
+    YV12_BUFFER_CONFIG *yv12_fb_new = pbi->dec_fb_ref[INTRA_FRAME];
+    YV12_BUFFER_CONFIG *yv12_fb_lst = pbi->dec_fb_ref[LAST_FRAME];
+
+    int recon_y_stride = yv12_fb_new->y_stride;
+    int recon_uv_stride = yv12_fb_new->uv_stride;
+
     unsigned char *ref_buffer[MAX_REF_FRAMES][3];
     unsigned char *dst_buffer[3];
     int i;
-    int ref_fb_index[MAX_REF_FRAMES];
     int ref_fb_corrupted[MAX_REF_FRAMES];
 
     ref_fb_corrupted[INTRA_FRAME] = 0;
 
-    ref_fb_index[LAST_FRAME]    = pc->lst_fb_idx;
-    ref_fb_index[GOLDEN_FRAME]  = pc->gld_fb_idx;
-    ref_fb_index[ALTREF_FRAME]  = pc->alt_fb_idx;
-
     for(i = 1; i < MAX_REF_FRAMES; i++)
     {
-        ref_buffer[i][0] = pc->yv12_fb[ref_fb_index[i]].y_buffer;
-        ref_buffer[i][1] = pc->yv12_fb[ref_fb_index[i]].u_buffer;
-        ref_buffer[i][2] = pc->yv12_fb[ref_fb_index[i]].v_buffer;
+        YV12_BUFFER_CONFIG *this_fb = pbi->dec_fb_ref[i];
 
-        ref_fb_corrupted[i] = pc->yv12_fb[ref_fb_index[i]].corrupted;
+        ref_buffer[i][0] = this_fb->y_buffer;
+        ref_buffer[i][1] = this_fb->u_buffer;
+        ref_buffer[i][2] = this_fb->v_buffer;
+
+        ref_fb_corrupted[i] = this_fb->corrupted;
     }
 
-    dst_buffer[0] = pc->yv12_fb[dst_fb_idx].y_buffer;
-    dst_buffer[1] = pc->yv12_fb[dst_fb_idx].u_buffer;
-    dst_buffer[2] = pc->yv12_fb[dst_fb_idx].v_buffer;
+    dst_buffer[0] = yv12_fb_new->y_buffer;
+    dst_buffer[1] = yv12_fb_new->u_buffer;
+    dst_buffer[2] = yv12_fb_new->v_buffer;
 
     xd->up_available = (start_mb_row != 0);
 
@@ -337,11 +339,6 @@ static void mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd, int start_mb_row)
        int i;
        int recon_yoffset, recon_uvoffset;
        int mb_col;
-       int ref_fb_idx = pc->lst_fb_idx;
-       int dst_fb_idx = pc->new_fb_idx;
-       int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
-       int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
-
        int filter_level;
        loop_filter_info_n *lfi_n = &pc->lf_info;
 
@@ -589,8 +586,8 @@ static void mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd, int start_mb_row)
        {
            if(mb_row != pc->mb_rows-1)
            {
-               int lasty = pc->yv12_fb[ref_fb_idx].y_width + VP8BORDERINPIXELS;
-               int lastuv = (pc->yv12_fb[ref_fb_idx].y_width>>1) + (VP8BORDERINPIXELS>>1);
+               int lasty = yv12_fb_lst->y_width + VP8BORDERINPIXELS;
+               int lastuv = (yv12_fb_lst->y_width>>1) + (VP8BORDERINPIXELS>>1);
 
                for (i = 0; i < 4; i++)
                {
@@ -601,7 +598,7 @@ static void mt_decode_mb_rows(VP8D_COMP *pbi, MACROBLOCKD *xd, int start_mb_row)
            }
        }
        else
-           vp8_extend_mb_row(&pc->yv12_fb[dst_fb_idx], xd->dst.y_buffer + 16,
+           vp8_extend_mb_row(yv12_fb_new, xd->dst.y_buffer + 16,
                              xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
 
        /* last MB of row is ready just after extension is done */
@@ -874,13 +871,14 @@ void vp8mt_decode_mb_rows( VP8D_COMP *pbi, MACROBLOCKD *xd)
     int j;
 
     int filter_level = pc->filter_level;
+    YV12_BUFFER_CONFIG *yv12_fb_new = pbi->dec_fb_ref[INTRA_FRAME];
 
     if (filter_level)
     {
         /* Set above_row buffer to 127 for decoding first MB row */
-        vpx_memset(pbi->mt_yabove_row[0] + VP8BORDERINPIXELS-1, 127, pc->yv12_fb[pc->new_fb_idx].y_width + 5);
-        vpx_memset(pbi->mt_uabove_row[0] + (VP8BORDERINPIXELS>>1)-1, 127, (pc->yv12_fb[pc->new_fb_idx].y_width>>1) +5);
-        vpx_memset(pbi->mt_vabove_row[0] + (VP8BORDERINPIXELS>>1)-1, 127, (pc->yv12_fb[pc->new_fb_idx].y_width>>1) +5);
+        vpx_memset(pbi->mt_yabove_row[0] + VP8BORDERINPIXELS-1, 127, yv12_fb_new->y_width + 5);
+        vpx_memset(pbi->mt_uabove_row[0] + (VP8BORDERINPIXELS>>1)-1, 127, (yv12_fb_new->y_width>>1) +5);
+        vpx_memset(pbi->mt_vabove_row[0] + (VP8BORDERINPIXELS>>1)-1, 127, (yv12_fb_new->y_width>>1) +5);
 
         for (j=1; j<pc->mb_rows; j++)
         {
@@ -901,7 +899,7 @@ void vp8mt_decode_mb_rows( VP8D_COMP *pbi, MACROBLOCKD *xd)
         vp8_loop_filter_frame_init(pc, &pbi->mb, filter_level);
     }
     else
-        vp8_setup_intra_recon_top_line(&pc->yv12_fb[pc->new_fb_idx]);
+        vp8_setup_intra_recon_top_line(yv12_fb_new);
 
     setup_decoding_thread_data(pbi, xd, pbi->mb_row_di, pbi->decoding_thread_count);
 
index 3290de9fa8a4577e3a870f4a843d5ab912446b8a..c13d69783119546d559f12890e5b072fb5f6251a 100644 (file)
 #include "vpx_version.h"
 #include "common/onyxd.h"
 #include "decoder/onyxd_int.h"
+#include "common/alloccommon.h"
+#include "vpx_mem/vpx_mem.h"
+#if CONFIG_ERROR_CONCEALMENT
+#include "decoder/error_concealment.h"
+#endif
+#include "decoder/decoderthreading.h"
 
 #define VP8_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
 #define VP8_CAP_ERROR_CONCEALMENT (CONFIG_ERROR_CONCEALMENT ? \
@@ -344,14 +350,30 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t  *ctx,
                                   long                    deadline)
 {
     vpx_codec_err_t res = VPX_CODEC_OK;
+    unsigned int resolution_change = 0;
+    unsigned int w, h;
 
     /* Determine the stream parameters. Note that we rely on peek_si to
      * validate that we have a buffer that does not wrap around the top
      * of the heap.
      */
-    if (!ctx->si.h)
-        res = ctx->base.iface->dec.peek_si(data, data_sz, &ctx->si);
+    w = ctx->si.w;
+    h = ctx->si.h;
+
+    res = ctx->base.iface->dec.peek_si(data, data_sz, &ctx->si);
+
+    if((res == VPX_CODEC_UNSUP_BITSTREAM) && !ctx->si.is_kf)
+    {
+        /* the peek function returns an error for non keyframes, however for
+         * this case, it is not an error */
+        res = VPX_CODEC_OK;
+    }
 
+    if(!ctx->decoder_init && !ctx->si.is_kf)
+        res = VPX_CODEC_UNSUP_BITSTREAM;
+
+    if ((ctx->si.h != h) || (ctx->si.w != w))
+        resolution_change = 1;
 
     /* Perform deferred allocations, if required */
     if (!res && ctx->defer_alloc)
@@ -427,6 +449,101 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t  *ctx,
 
     if (!res && ctx->pbi)
     {
+        if(resolution_change)
+        {
+            VP8D_COMP *pbi = ctx->pbi;
+            VP8_COMMON *const pc = & pbi->common;
+            MACROBLOCKD *const xd  = & pbi->mb;
+#if CONFIG_MULTITHREAD
+            int i;
+#endif
+            pc->Width = ctx->si.w;
+            pc->Height = ctx->si.h;
+            {
+                int prev_mb_rows = pc->mb_rows;
+
+                if (setjmp(pbi->common.error.jmp))
+                {
+                    pbi->common.error.setjmp = 0;
+                    /* same return value as used in vp8dx_receive_compressed_data */
+                    return -1;
+                }
+
+                pbi->common.error.setjmp = 1;
+
+                if (pc->Width <= 0)
+                {
+                    pc->Width = w;
+                    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                                       "Invalid frame width");
+                }
+
+                if (pc->Height <= 0)
+                {
+                    pc->Height = h;
+                    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                                       "Invalid frame height");
+                }
+
+                if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height))
+                    vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+                                       "Failed to allocate frame buffers");
+
+                xd->pre = pc->yv12_fb[pc->lst_fb_idx];
+                xd->dst = pc->yv12_fb[pc->new_fb_idx];
+
+#if CONFIG_MULTITHREAD
+                for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
+                {
+                    pbi->mb_row_di[i].mbd.dst = pc->yv12_fb[pc->new_fb_idx];
+                    vp8_build_block_doffsets(&pbi->mb_row_di[i].mbd);
+                }
+#endif
+                vp8_build_block_doffsets(&pbi->mb);
+
+                /* allocate memory for last frame MODE_INFO array */
+#if CONFIG_ERROR_CONCEALMENT
+
+                if (pbi->ec_enabled)
+                {
+                    /* old prev_mip was released by vp8_de_alloc_frame_buffers()
+                     * called in vp8_alloc_frame_buffers() */
+                    pc->prev_mip = vpx_calloc(
+                                       (pc->mb_cols + 1) * (pc->mb_rows + 1),
+                                       sizeof(MODE_INFO));
+
+                    if (!pc->prev_mip)
+                    {
+                        vp8_de_alloc_frame_buffers(pc);
+                        vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+                                           "Failed to allocate"
+                                           "last frame MODE_INFO array");
+                    }
+
+                    pc->prev_mi = pc->prev_mip + pc->mode_info_stride + 1;
+
+                    if (vp8_alloc_overlap_lists(pbi))
+                        vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+                                           "Failed to allocate overlap lists "
+                                           "for error concealment");
+                }
+
+#endif
+
+#if CONFIG_MULTITHREAD
+                if (pbi->b_multithreaded_rd)
+                    vp8mt_alloc_temp_buffers(pbi, pc->Width, prev_mb_rows);
+#else
+                (void)prev_mb_rows;
+#endif
+            }
+
+            pbi->common.error.setjmp = 0;
+
+            /* required to get past the first get_free_fb() call */
+            ctx->pbi->common.fb_idx_ref_cnt[0] = 0;
+        }
+
         ctx->user_priv = user_priv;
         if (vp8dx_receive_compressed_data(ctx->pbi, data_sz, data, deadline))
         {