mpeg2: calculate the slice data length on IVB
authorXiang, Haihao <haihao.xiang@intel.com>
Mon, 26 May 2014 02:14:53 +0000 (10:14 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Fri, 6 Jun 2014 04:46:06 +0000 (12:46 +0800)
Sometimes pending datas are added in slice data buffer, however
HW requires slice data length excludes pending datas, otherwise
the behavior is undefined

https://bugs.freedesktop.org/show_bug.cgi?id=77041

Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
(cherry picked from commit a9004e6c5c7f33cd1e33e4dab92a5a0017714bbd)

src/gen7_mfd.c

index f9114e7..91036be 100755 (executable)
@@ -1034,10 +1034,35 @@ gen7_mfd_mpeg2_qm_state(VADriverContextP ctx,
     }
 }
 
+uint32_t mpeg2_get_slice_data_length(dri_bo *slice_data_bo, VASliceParameterBufferMPEG2 *slice_param)
+{
+    uint8_t *buf;
+    uint32_t buf_offset = slice_param->slice_data_offset + (slice_param->macroblock_offset >> 3);
+    uint32_t buf_size = slice_param->slice_data_size - (slice_param->macroblock_offset >> 3);
+    uint32_t i;
+
+    dri_bo_map(slice_data_bo, 0);
+    buf = (uint8_t *)slice_data_bo->virtual + buf_offset;
+
+    for (i = 3; i < buf_size; i++) {
+        if (buf[i - 3] &&
+            !buf[i - 2] &&
+            !buf[i - 1] &&
+            !buf[i]) {
+            dri_bo_unmap(slice_data_bo);
+            return i - 3 + 1;
+        }
+    }
+
+    dri_bo_unmap(slice_data_bo);
+    return buf_size;
+}
+
 static void
 gen7_mfd_mpeg2_bsd_object(VADriverContextP ctx,
                           VAPictureParameterBufferMPEG2 *pic_param,
                           VASliceParameterBufferMPEG2 *slice_param,
+                          dri_bo *slice_data_bo,
                           VASliceParameterBufferMPEG2 *next_slice_param,
                           struct gen7_mfd_context *gen7_mfd_context)
 {
@@ -1068,7 +1093,7 @@ gen7_mfd_mpeg2_bsd_object(VADriverContextP ctx,
     BEGIN_BCS_BATCH(batch, 5);
     OUT_BCS_BATCH(batch, MFD_MPEG2_BSD_OBJECT | (5 - 2));
     OUT_BCS_BATCH(batch, 
-                  slice_param->slice_data_size - (slice_param->macroblock_offset >> 3));
+                  mpeg2_get_slice_data_length(slice_data_bo, slice_param));
     OUT_BCS_BATCH(batch, 
                   slice_param->slice_data_offset + (slice_param->macroblock_offset >> 3));
     OUT_BCS_BATCH(batch,
@@ -1131,7 +1156,7 @@ gen7_mfd_mpeg2_decode_picture(VADriverContextP ctx,
             else
                 next_slice_param = next_slice_group_param;
 
-            gen7_mfd_mpeg2_bsd_object(ctx, pic_param, slice_param, next_slice_param, gen7_mfd_context);
+            gen7_mfd_mpeg2_bsd_object(ctx, pic_param, slice_param, slice_data_bo, next_slice_param, gen7_mfd_context);
             slice_param++;
         }
     }