OSDN Git Service

i965_drv_video: fix GPU hang issue when decoding field coded MPEG2 picture.
authorXiang, Haihao <haihao.xiang@intel.com>
Tue, 14 Jun 2011 01:49:44 +0000 (09:49 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Tue, 14 Jun 2011 01:49:44 +0000 (09:49 +0800)
Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
i965_drv_video/gen6_mfd.c
i965_drv_video/gen7_mfd.c
i965_drv_video/i965_defines.h
i965_drv_video/i965_media.h
i965_drv_video/i965_media_mpeg2.c

index e6abb32..9a5ab56 100644 (file)
@@ -1303,15 +1303,24 @@ gen6_mfd_mpeg2_bsd_object(VADriverContextP ctx,
 {
     struct intel_batchbuffer *batch = gen6_mfd_context->base.batch;
     unsigned int width_in_mbs = ALIGN(pic_param->horizontal_size, 16) / 16;
-    unsigned int height_in_mbs = ALIGN(pic_param->vertical_size, 16) / 16;
-    int mb_count;
+    int mb_count, vpos0, hpos0, vpos1, hpos1, is_field_pic = 0;
 
-    if (next_slice_param == NULL)
-        mb_count = width_in_mbs * height_in_mbs - 
-            (slice_param->slice_vertical_position * width_in_mbs + slice_param->slice_horizontal_position);
-    else
-        mb_count = (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);
+    if (pic_param->picture_coding_extension.bits.picture_structure == MPEG_TOP_FIELD ||
+        pic_param->picture_coding_extension.bits.picture_structure == MPEG_BOTTOM_FIELD)
+        is_field_pic = 1;
+
+    vpos0 = slice_param->slice_vertical_position / (1 + is_field_pic);
+    hpos0 = slice_param->slice_horizontal_position;
+
+    if (next_slice_param == NULL) {
+        vpos1 = ALIGN(pic_param->vertical_size, 16) / 16 / (1 + is_field_pic);
+        hpos1 = 0;
+    } else {
+        vpos1 = next_slice_param->slice_vertical_position / (1 + is_field_pic);
+        hpos1 = next_slice_param->slice_horizontal_position;
+    }
+
+    mb_count = (vpos1 * width_in_mbs + hpos1) - (vpos0 * width_in_mbs + hpos0);
 
     BEGIN_BCS_BATCH(batch, 5);
     OUT_BCS_BATCH(batch, MFD_MPEG2_BSD_OBJECT | (5 - 2));
@@ -1320,8 +1329,8 @@ gen6_mfd_mpeg2_bsd_object(VADriverContextP ctx,
     OUT_BCS_BATCH(batch, 
                   slice_param->slice_data_offset + (slice_param->macroblock_offset >> 3));
     OUT_BCS_BATCH(batch,
-                  slice_param->slice_horizontal_position << 24 |
-                  slice_param->slice_vertical_position << 16 |
+                  hpos0 << 24 |
+                  vpos0 << 16 |
                   mb_count << 8 |
                   (next_slice_param == NULL) << 5 |
                   (next_slice_param == NULL) << 3 |
index d2933a2..1fa6c2f 100644 (file)
@@ -1258,15 +1258,24 @@ gen7_mfd_mpeg2_bsd_object(VADriverContextP ctx,
 {
     struct intel_batchbuffer *batch = gen7_mfd_context->base.batch;
     unsigned int width_in_mbs = ALIGN(pic_param->horizontal_size, 16) / 16;
-    unsigned int height_in_mbs = ALIGN(pic_param->vertical_size, 16) / 16;
-    int mb_count;
+    int mb_count, vpos0, hpos0, vpos1, hpos1, is_field_pic = 0;
 
-    if (next_slice_param == NULL)
-        mb_count = width_in_mbs * height_in_mbs - 
-            (slice_param->slice_vertical_position * width_in_mbs + slice_param->slice_horizontal_position);
-    else
-        mb_count = (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);
+    if (pic_param->picture_coding_extension.bits.picture_structure == MPEG_TOP_FIELD ||
+        pic_param->picture_coding_extension.bits.picture_structure == MPEG_BOTTOM_FIELD)
+        is_field_pic = 1;
+
+    vpos0 = slice_param->slice_vertical_position / (1 + is_field_pic);
+    hpos0 = slice_param->slice_horizontal_position;
+
+    if (next_slice_param == NULL) {
+        vpos1 = ALIGN(pic_param->vertical_size, 16) / 16 / (1 + is_field_pic);
+        hpos1 = 0;
+    } else {
+        vpos1 = next_slice_param->slice_vertical_position / (1 + is_field_pic);
+        hpos1 = next_slice_param->slice_horizontal_position;
+    }
+
+    mb_count = (vpos1 * width_in_mbs + hpos1) - (vpos0 * width_in_mbs + hpos0);
 
     BEGIN_BCS_BATCH(batch, 5);
     OUT_BCS_BATCH(batch, MFD_MPEG2_BSD_OBJECT | (5 - 2));
@@ -1275,8 +1284,8 @@ gen7_mfd_mpeg2_bsd_object(VADriverContextP ctx,
     OUT_BCS_BATCH(batch, 
                   slice_param->slice_data_offset + (slice_param->macroblock_offset >> 3));
     OUT_BCS_BATCH(batch,
-                  slice_param->slice_horizontal_position << 24 |
-                  slice_param->slice_vertical_position << 16 |
+                  hpos0 << 24 |
+                  vpos0 << 16 |
                   mb_count << 8 |
                   (next_slice_param == NULL) << 5 |
                   (next_slice_param == NULL) << 3 |
index a14e111..509ae9e 100644 (file)
 #define MFX_SURFACE_PLANAR_420_8        4
 #define MFX_SURFACE_MONOCHROME          12
 
+#define MPEG_TOP_FIELD         1
+#define MPEG_BOTTOM_FIELD      2
+#define MPEG_FRAME             3
+
 #define URB_SIZE(intel)         (IS_GEN7(intel->device_id) ? 4096 :     \
                                  IS_GEN6(intel->device_id) ? 1024 :     \
                                  IS_IRONLAKE(intel->device_id) ? 1024 : \
index 2bb6bb2..e309d5b 100644 (file)
 #define MAX_INTERFACE_DESC      16
 #define MAX_MEDIA_SURFACES      34
 
-#define MPEG_TOP_FIELD         1
-#define MPEG_BOTTOM_FIELD      2
-#define MPEG_FRAME             3
-
 struct decode_state;
 
 struct i965_media_context
index d2a51aa..bc3e048 100644 (file)
@@ -877,15 +877,27 @@ i965_media_mpeg2_objects(VADriverContextP ctx,
 {
     struct intel_batchbuffer *batch = media_context->base.batch;
     VASliceParameterBufferMPEG2 *slice_param;
+    VAPictureParameterBufferMPEG2 *pic_param;
     int i, j;
 
+    assert(decode_state->pic_param && decode_state->pic_param->buffer);
+    pic_param = (VAPictureParameterBufferMPEG2 *)decode_state->pic_param->buffer;
+
     for (j = 0; j < decode_state->num_slice_params; j++) {
         assert(decode_state->slice_params[j] && decode_state->slice_params[j]->buffer);
         assert(decode_state->slice_datas[j] && decode_state->slice_datas[j]->bo);
         slice_param = (VASliceParameterBufferMPEG2 *)decode_state->slice_params[j]->buffer;
 
         for (i = 0; i < decode_state->slice_params[j]->num_elements; i++) {
+            int vpos, hpos, is_field_pic = 0;
+
+            if (pic_param->picture_coding_extension.bits.picture_structure == MPEG_TOP_FIELD ||
+                pic_param->picture_coding_extension.bits.picture_structure == MPEG_BOTTOM_FIELD)
+                is_field_pic = 1;
+
             assert(slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_ALL);
+            vpos = slice_param->slice_vertical_position / (1 + is_field_pic);
+            hpos = slice_param->slice_horizontal_position;
 
             BEGIN_BATCH(batch, 6);
             OUT_BATCH(batch, CMD_MEDIA_OBJECT | 4);
@@ -895,8 +907,8 @@ i965_media_mpeg2_objects(VADriverContextP ctx,
                       I915_GEM_DOMAIN_SAMPLER, 0, 
                       slice_param->slice_data_offset + (slice_param->macroblock_offset >> 3));
             OUT_BATCH(batch, 
-                      ((slice_param->slice_horizontal_position << 24) |     
-                       (slice_param->slice_vertical_position << 16) |
+                      ((hpos << 24) |     
+                       (vpos << 16) |
                        (127 << 8) | 
                        (slice_param->macroblock_offset & 0x7)));
             OUT_BATCH(batch, slice_param->quantiser_scale_code << 24);