Skip blocks in B-frames reuse motion vectors from next reference frame.
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 26 Apr 2008 13:09:36 +0000 (13:09 +0000)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 26 Apr 2008 13:09:36 +0000 (13:09 +0000)
So if referenced blocks is 16x8, 8x16 or 8x8 partitions, skip block
will have them too.

Originally committed as revision 12987 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/rv34.c

index 7749637..68aaded 100644 (file)
@@ -667,6 +667,22 @@ static void rv34_mc_2mv(RV34DecContext *r, const int block_type)
             r->s.dsp.avg_h264_chroma_pixels_tab);
 }
 
+static void rv34_mc_2mv_skip(RV34DecContext *r)
+{
+    int i, j, k;
+    for(j = 0; j < 2; j++)
+        for(i = 0; i < 2; i++){
+             rv34_mc(r, RV34_MB_P_8x8, i*8, j*8, i+j*r->s.b8_stride, 1, 1, 0, r->rv30,
+                    r->rv30 ? r->s.dsp.put_rv30_tpel_pixels_tab
+                            : r->s.dsp.put_h264_qpel_pixels_tab,
+                    r->s.dsp.put_h264_chroma_pixels_tab);
+             rv34_mc(r, RV34_MB_P_8x8, i*8, j*8, i+j*r->s.b8_stride, 1, 1, 1, r->rv30,
+                    r->rv30 ? r->s.dsp.avg_rv30_tpel_pixels_tab
+                            : r->s.dsp.avg_h264_qpel_pixels_tab,
+                    r->s.dsp.avg_h264_chroma_pixels_tab);
+        }
+}
+
 /** number of motion vectors in each macroblock type */
 static const int num_mvs[RV34_MB_TYPES] = { 0, 0, 1, 4, 1, 1, 0, 0, 2, 2, 2, 1 };
 
@@ -678,7 +694,9 @@ static int rv34_decode_mv(RV34DecContext *r, int block_type)
 {
     MpegEncContext *s = &r->s;
     GetBitContext *gb = &s->gb;
-    int i;
+    int i, j, k;
+    int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride;
+    int next_bt;
 
     memset(r->dmv, 0, sizeof(r->dmv));
     for(i = 0; i < num_mvs[block_type]; i++){
@@ -697,9 +715,19 @@ static int rv34_decode_mv(RV34DecContext *r, int block_type)
             break;
         }
     case RV34_MB_B_DIRECT:
-        rv34_pred_mv_b  (r, RV34_MB_B_DIRECT, 0);
-        rv34_pred_mv_b  (r, RV34_MB_B_DIRECT, 1);
-        rv34_mc_2mv     (r, RV34_MB_B_DIRECT);
+        //surprisingly, it uses motion scheme from next reference frame
+        next_bt = s->next_picture_ptr->mb_type[s->mb_x + s->mb_y * s->mb_stride];
+        for(j = 0; j < 2; j++)
+            for(i = 0; i < 2; i++)
+                for(k = 0; k < 2; k++){
+                    s->current_picture_ptr->motion_val[0][mv_pos + i + j*s->b8_stride][k] =  (s->next_picture_ptr->motion_val[0][mv_pos + i + j*s->b8_stride][k] + 1) >> 1;
+                    s->current_picture_ptr->motion_val[1][mv_pos + i + j*s->b8_stride][k] = -(s->next_picture_ptr->motion_val[0][mv_pos + i + j*s->b8_stride][k] >> 1);
+                }
+        if(IS_16X16(next_bt)) //we can use whole macroblock MC
+            rv34_mc_2mv(r, block_type);
+        else
+            rv34_mc_2mv_skip(r);
+        fill_rectangle(s->current_picture_ptr->motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], 2, 2, s->b8_stride, 0, 4);
         break;
     case RV34_MB_P_16x16:
     case RV34_MB_P_MIX16x16: