dec/mpeg2: ignore slices which aren't in raster scan order on SNB
authorXiang, Haihao <haihao.xiang@intel.com>
Tue, 26 Nov 2013 01:21:11 +0000 (09:21 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Tue, 3 Dec 2013 04:00:19 +0000 (12:00 +0800)
Sometimes codec layer incorrectly fills slice parameters due to
the corrupted video

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71276
Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
src/gen6_mfd.c
src/i965_decoder_utils.c
src/i965_decoder_utils.h

index afbfc4c..f2b0fdf 100755 (executable)
@@ -1167,9 +1167,9 @@ gen6_mfd_mpeg2_decode_picture(VADriverContextP ctx,
 {
     struct intel_batchbuffer *batch = gen6_mfd_context->base.batch;
     VAPictureParameterBufferMPEG2 *pic_param;
-    VASliceParameterBufferMPEG2 *slice_param, *next_slice_param, *next_slice_group_param;
+    VASliceParameterBufferMPEG2 *slice_param, *next_slice_param;
     dri_bo *slice_data_bo;
-    int i, j;
+    int group_idx = 0, pre_group_idx = -1, element_idx = 0;
 
     assert(decode_state->pic_param && decode_state->pic_param->buffer);
     pic_param = (VAPictureParameterBufferMPEG2 *)decode_state->pic_param->buffer;
@@ -1188,28 +1188,18 @@ gen6_mfd_mpeg2_decode_picture(VADriverContextP ctx,
         gen6_mfd_context->wa_mpeg2_slice_vertical_position =
             mpeg2_wa_slice_vertical_position(decode_state, pic_param);
 
-    for (j = 0; j < decode_state->num_slice_params; j++) {
-        assert(decode_state->slice_params && decode_state->slice_params[j]->buffer);
-        slice_param = (VASliceParameterBufferMPEG2 *)decode_state->slice_params[j]->buffer;
-        slice_data_bo = decode_state->slice_datas[j]->bo;
-        gen6_mfd_ind_obj_base_addr_state(ctx, slice_data_bo, MFX_FORMAT_MPEG2, gen6_mfd_context);
-
-        if (j == decode_state->num_slice_params - 1)
-            next_slice_group_param = NULL;
-        else
-            next_slice_group_param = (VASliceParameterBufferMPEG2 *)decode_state->slice_params[j + 1]->buffer;
-
-        for (i = 0; i < decode_state->slice_params[j]->num_elements; i++) {
-            assert(slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_ALL);
+    slice_param = (VASliceParameterBufferMPEG2 *)decode_state->slice_params[group_idx]->buffer;
 
-            if (i < decode_state->slice_params[j]->num_elements - 1)
-                next_slice_param = slice_param + 1;
-            else
-                next_slice_param = next_slice_group_param;
-
-            gen6_mfd_mpeg2_bsd_object(ctx, pic_param, slice_param, next_slice_param, gen6_mfd_context);
-            slice_param++;
+    for (; slice_param;) {
+        if (pre_group_idx != group_idx) {
+            slice_data_bo = decode_state->slice_datas[group_idx]->bo;
+            gen6_mfd_ind_obj_base_addr_state(ctx, slice_data_bo, MFX_FORMAT_MPEG2, gen6_mfd_context);
+            pre_group_idx = group_idx;
         }
+
+        next_slice_param = intel_mpeg2_find_next_slice(decode_state, pic_param, slice_param, &group_idx, &element_idx);
+        gen6_mfd_mpeg2_bsd_object(ctx, pic_param, slice_param, next_slice_param, gen6_mfd_context);
+        slice_param = next_slice_param;
     }
 
     intel_batchbuffer_end_atomic(batch);
index 4ef09b5..41102ba 100644 (file)
@@ -703,3 +703,44 @@ intel_decoder_sanity_check_input(VADriverContextP ctx,
 out:
     return vaStatus;
 }
+
+/*
+ * Return the next slice paramter
+ *
+ * Input:
+ *      slice_param: the current slice
+ *      *group_idx & *element_idx the current slice position in slice groups
+ * Output:
+ *      Return the next slice parameter
+ *      *group_idx & *element_idx the next slice position in slice groups,
+ *      if the next slice is NULL, *group_idx & *element_idx will be ignored
+ */
+VASliceParameterBufferMPEG2 *
+intel_mpeg2_find_next_slice(struct decode_state *decode_state,
+                            VAPictureParameterBufferMPEG2 *pic_param,
+                            VASliceParameterBufferMPEG2 *slice_param,
+                            int *group_idx,
+                            int *element_idx)
+{
+    VASliceParameterBufferMPEG2 *next_slice_param;
+    unsigned int width_in_mbs = ALIGN(pic_param->horizontal_size, 16) / 16;
+    int j = *group_idx, i = *element_idx + 1;
+
+    for (; j < decode_state->num_slice_params; j++) {
+        for (; i < decode_state->slice_params[j]->num_elements; i++) {
+            next_slice_param = ((VASliceParameterBufferMPEG2 *)decode_state->slice_params[j]->buffer) + i;
+
+            if ((next_slice_param->slice_vertical_position * width_in_mbs + next_slice_param->slice_horizontal_position) >=
+                (slice_param->slice_vertical_position * width_in_mbs + slice_param->slice_horizontal_position)) {
+                *group_idx = j;
+                *element_idx = i;
+
+                return next_slice_param;
+            }
+        }
+
+        i = 0;
+    }
+
+    return NULL;
+}
index 2a71f3e..8a9fbe2 100644 (file)
@@ -91,4 +91,12 @@ intel_update_vc1_frame_store_index(VADriverContextP ctx,
                                    struct decode_state *decode_state,
                                    VAPictureParameterBufferVC1 *pic_param,
                                    GenFrameStore frame_store[MAX_GEN_REFERENCE_FRAMES]);
+
+VASliceParameterBufferMPEG2 *
+intel_mpeg2_find_next_slice(struct decode_state *decode_state,
+                            VAPictureParameterBufferMPEG2 *pic_param,
+                            VASliceParameterBufferMPEG2 *slice_param,
+                            int *group_idx,
+                            int *element_idx);
+
 #endif /* I965_DECODER_UTILS_H */