[Libva] [PATCH] mpeg2: fix incorrect slice_vertical_position from codec layers.

Gwenole Beauchesne gb.devel at gmail.com
Mon Mar 12 09:33:08 PDT 2012


Correctly emit slice_vertical_position, as per the definition from
the bitstream, to the HW decoder (MFD_MPEG2_BSD_OBJECT).

Add workaround for players that have not fixed their usage of
slice_vertical_position. That field shall represent the slice vertical
position as it comes from the bitstream.

NOTE: I have not tested the ILK code path yet. Only SNB, IVB.

Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
---
 NEWS                     |    1 +
 src/gen6_mfd.c           |   14 +++++++++++---
 src/gen6_mfd.h           |    2 ++
 src/gen7_mfd.c           |   13 ++++++++++---
 src/gen7_mfd.h           |    2 ++
 src/i965_decoder_utils.c |   38 ++++++++++++++++++++++++++++++++++++++
 src/i965_decoder_utils.h |    8 ++++++++
 src/i965_media_mpeg2.c   |   12 ++++++++++--
 src/i965_media_mpeg2.h   |    1 +
 9 files changed, 83 insertions(+), 8 deletions(-)

diff --git a/NEWS b/NEWS
index 2fc1bd8..9b46a06 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ Copyright (C) 2009-2011 Intel Corporation
 
 Version 1.0.16 - DD.Feb.2012
 * Fix rendering of interlaced surfaces
+* Fix MPEG-2 decoding of interlaced streams
 * Fix VC-1 bitplane buffer size (SNB, IVB)
 * Fix VC-1 motion vector modes for Ivy Bridge
 * Fix MFX_QM_STATE for H.264 flat scaling lists (IVB)
diff --git a/src/gen6_mfd.c b/src/gen6_mfd.c
index c47f11b..a959a44 100644
--- a/src/gen6_mfd.c
+++ b/src/gen6_mfd.c
@@ -1222,20 +1222,22 @@ 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;
-    int mb_count, vpos0, hpos0, vpos1, hpos1, is_field_pic = 0;
+    int mb_count, vpos0, hpos0, vpos1, hpos1, is_field_pic_wa, 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;
+    is_field_pic_wa = is_field_pic &&
+        gen6_mfd_context->wa_mpeg2_slice_vertical_position > 0;
 
-    vpos0 = slice_param->slice_vertical_position / (1 + is_field_pic);
+    vpos0 = slice_param->slice_vertical_position / (1 + is_field_pic_wa);
     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);
+        vpos1 = next_slice_param->slice_vertical_position / (1 + is_field_pic_wa);
         hpos1 = next_slice_param->slice_horizontal_position;
     }
 
@@ -1283,6 +1285,10 @@ gen6_mfd_mpeg2_decode_picture(VADriverContextP ctx,
     gen6_mfd_mpeg2_pic_state(ctx, decode_state, gen6_mfd_context);
     gen6_mfd_mpeg2_qm_state(ctx, decode_state, gen6_mfd_context);
 
+    if (gen6_mfd_context->wa_mpeg2_slice_vertical_position < 0)
+        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;
@@ -2019,6 +2025,8 @@ gen6_dec_hw_context_init(VADriverContextP ctx, VAProfile profile)
         gen6_mfd_context->reference_surface[i].surface_id = VA_INVALID_ID;
         gen6_mfd_context->reference_surface[i].frame_store_id = -1;
     }
+
+    gen6_mfd_context->wa_mpeg2_slice_vertical_position = -1;
     
     return (struct hw_context *)gen6_mfd_context;
 }
diff --git a/src/gen6_mfd.h b/src/gen6_mfd.h
index bf06a00..6e20364 100644
--- a/src/gen6_mfd.h
+++ b/src/gen6_mfd.h
@@ -77,6 +77,8 @@ struct gen6_mfd_context
     GenBuffer           bsd_mpc_row_store_scratch_buffer;
     GenBuffer           mpr_row_store_scratch_buffer;
     GenBuffer           bitplane_read_buffer;
+
+    int                 wa_mpeg2_slice_vertical_position;
 };
 
 #endif /* _GEN6_MFD_H_ */
diff --git a/src/gen7_mfd.c b/src/gen7_mfd.c
index f9bf09b..10e36ac 100644
--- a/src/gen7_mfd.c
+++ b/src/gen7_mfd.c
@@ -1189,20 +1189,22 @@ 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;
-    int mb_count, vpos0, hpos0, vpos1, hpos1, is_field_pic = 0;
+    int mb_count, vpos0, hpos0, vpos1, hpos1, is_field_pic_wa, 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;
+    is_field_pic_wa = is_field_pic &&
+        gen7_mfd_context->wa_mpeg2_slice_vertical_position > 0;
 
-    vpos0 = slice_param->slice_vertical_position / (1 + is_field_pic);
+    vpos0 = slice_param->slice_vertical_position / (1 + is_field_pic_wa);
     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);
+        vpos1 = next_slice_param->slice_vertical_position / (1 + is_field_pic_wa);
         hpos1 = next_slice_param->slice_horizontal_position;
     }
 
@@ -1250,6 +1252,10 @@ gen7_mfd_mpeg2_decode_picture(VADriverContextP ctx,
     gen7_mfd_mpeg2_pic_state(ctx, decode_state, gen7_mfd_context);
     gen7_mfd_mpeg2_qm_state(ctx, decode_state, gen7_mfd_context);
 
+    if (gen7_mfd_context->wa_mpeg2_slice_vertical_position < 0)
+        gen7_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;
@@ -2784,6 +2790,7 @@ gen7_dec_hw_context_init(VADriverContextP ctx, VAProfile profile)
     }
 
     gen7_mfd_context->jpeg_wa_surface_id = VA_INVALID_SURFACE;
+    gen7_mfd_context->wa_mpeg2_slice_vertical_position = -1;
 
     switch (profile) {
     case VAProfileH264Baseline:
diff --git a/src/gen7_mfd.h b/src/gen7_mfd.h
index 225a808..08d9e3a 100644
--- a/src/gen7_mfd.h
+++ b/src/gen7_mfd.h
@@ -95,6 +95,8 @@ struct gen7_mfd_context
     
     VASurfaceID jpeg_wa_surface_id;
     dri_bo *jpeg_wa_slice_data_bo;
+
+    int                 wa_mpeg2_slice_vertical_position;
 };
 
 #endif /* _GEN7_MFD_H_ */
diff --git a/src/i965_decoder_utils.c b/src/i965_decoder_utils.c
index 9482ba4..48f01b2 100644
--- a/src/i965_decoder_utils.c
+++ b/src/i965_decoder_utils.c
@@ -27,8 +27,46 @@
 #include <alloca.h>
 #include "intel_batchbuffer.h"
 #include "i965_decoder_utils.h"
+#include "i965_drv_video.h"
 #include "i965_defines.h"
 
+int
+mpeg2_wa_slice_vertical_position(
+    struct decode_state           *decode_state,
+    VAPictureParameterBufferMPEG2 *pic_param
+)
+{
+    unsigned int i, j, mb_height, vpos, last_vpos = 0;
+
+    /* Assume progressive sequence if we got a progressive frame */
+    if (pic_param->picture_coding_extension.bits.progressive_frame)
+        return 0;
+
+    /* Wait for a field coded picture */
+    if (pic_param->picture_coding_extension.bits.picture_structure == MPEG_FRAME)
+        return -1;
+
+    assert(decode_state && decode_state->slice_params);
+
+    mb_height = (pic_param->vertical_size + 31) / 32;
+
+    for (j = 0; j < decode_state->num_slice_params; j++) {
+        struct buffer_store * const buffer_store =
+            decode_state->slice_params[j];
+
+        for (i = 0; i < buffer_store->num_elements; i++) {
+            VASliceParameterBufferMPEG2 * const slice_param =
+                ((VASliceParameterBufferMPEG2 *)buffer_store->buffer) + i;
+
+            vpos = slice_param->slice_vertical_position;
+            if (vpos >= mb_height || vpos == last_vpos + 2)
+                return 1;
+            last_vpos = vpos;
+        }
+    }
+    return 0;
+}
+
 /* Generate flat scaling matrices for H.264 decoding */
 void
 avc_gen_default_iq_matrix(VAIQMatrixBufferH264 *iq_matrix)
diff --git a/src/i965_decoder_utils.h b/src/i965_decoder_utils.h
index 37402b4..1c624c0 100644
--- a/src/i965_decoder_utils.h
+++ b/src/i965_decoder_utils.h
@@ -27,6 +27,14 @@
 #include "i965_decoder.h"
 #include "intel_batchbuffer.h"
 
+struct decode_state;
+
+int
+mpeg2_wa_slice_vertical_position(
+    struct decode_state           *decode_state,
+    VAPictureParameterBufferMPEG2 *pic_param
+);
+
 void
 avc_gen_default_iq_matrix(VAIQMatrixBufferH264 *iq_matrix);
 
diff --git a/src/i965_media_mpeg2.c b/src/i965_media_mpeg2.c
index 9278ab7..55e2109 100644
--- a/src/i965_media_mpeg2.c
+++ b/src/i965_media_mpeg2.c
@@ -36,6 +36,7 @@
 #include "intel_driver.h"
 #include "i965_defines.h"
 #include "i965_drv_video.h"
+#include "i965_decoder_utils.h"
 
 #include "i965_media.h"
 #include "i965_media_mpeg2.h"
@@ -879,6 +880,7 @@ i965_media_mpeg2_objects(VADriverContextP ctx,
                          struct decode_state *decode_state,
                          struct i965_media_context *media_context)
 {
+    struct i965_mpeg2_context * const i965_mpeg2_context = media_context->private_context;
     struct intel_batchbuffer *batch = media_context->base.batch;
     VASliceParameterBufferMPEG2 *slice_param;
     VAPictureParameterBufferMPEG2 *pic_param;
@@ -887,6 +889,10 @@ i965_media_mpeg2_objects(VADriverContextP ctx,
     assert(decode_state->pic_param && decode_state->pic_param->buffer);
     pic_param = (VAPictureParameterBufferMPEG2 *)decode_state->pic_param->buffer;
 
+    if (i965_mpeg2_context->wa_slice_vertical_position < 0)
+        i965_mpeg2_context->wa_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[j] && decode_state->slice_params[j]->buffer);
         assert(decode_state->slice_datas[j] && decode_state->slice_datas[j]->bo);
@@ -895,8 +901,9 @@ i965_media_mpeg2_objects(VADriverContextP ctx,
         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)
+            if (i965_mpeg2_context->wa_slice_vertical_position > 0 &&
+                (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);
@@ -970,6 +977,7 @@ i965_media_mpeg2_dec_context_init(VADriverContextP ctx, struct i965_media_contex
     int i;
 
     i965_mpeg2_context = calloc(1, sizeof(struct i965_mpeg2_context));
+    i965_mpeg2_context->wa_slice_vertical_position = -1;
 
     /* kernel */
     assert(NUM_MPEG2_VLD_KERNELS == (sizeof(mpeg2_vld_kernels_gen4) / 
diff --git a/src/i965_media_mpeg2.h b/src/i965_media_mpeg2.h
index 65e308c..5b8867e 100644
--- a/src/i965_media_mpeg2.h
+++ b/src/i965_media_mpeg2.h
@@ -44,6 +44,7 @@ struct i965_mpeg2_context
 {
     struct i965_kernel vld_kernels[NUM_MPEG2_VLD_KERNELS];
     VAIQMatrixBufferMPEG2 iq_matrix;
+    int wa_slice_vertical_position;
 };
 
 void i965_media_mpeg2_decode_init(VADriverContextP ctx, struct decode_state * decode_state, struct i965_media_context *media_context);
-- 
1.7.5.4



More information about the Libva mailing list