diff options
author | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2012-03-12 16:40:59 +0100 |
---|---|---|
committer | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2012-03-18 09:10:11 +0100 |
commit | 298dc939835e3080c9330b4e52e8dfac25bf3060 (patch) | |
tree | a985f174ab987722f1ed56febe9889094feda33f | |
parent | 2447c981a84cd9dc1eddf8e4258cef555503024f (diff) |
mpeg2: fix incorrect slice_vertical_position from codec layers.
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.
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | src/gen6_mfd.c | 14 | ||||
-rw-r--r-- | src/gen6_mfd.h | 2 | ||||
-rw-r--r-- | src/gen7_mfd.c | 14 | ||||
-rw-r--r-- | src/gen7_mfd.h | 2 | ||||
-rw-r--r-- | src/i965_decoder_utils.c | 41 | ||||
-rw-r--r-- | src/i965_decoder_utils.h | 8 | ||||
-rw-r--r-- | src/i965_media_mpeg2.c | 12 | ||||
-rw-r--r-- | src/i965_media_mpeg2.h | 1 |
9 files changed, 87 insertions, 8 deletions
@@ -2,6 +2,7 @@ libva-driver-intel NEWS -- summary of changes. 2012-02-DD Copyright (C) 2009-2011 Intel Corporation Version 1.0.16 - DD.Feb.2012 +* Fix MPEG-2 decoding of interlaced streams (SNB, IVB) * Fix rendering of interlaced surfaces * Fix VC-1 bitplane buffer size (SNB, IVB) * Fix VC-1 motion vector modes for Ivy Bridge diff --git a/src/gen6_mfd.c b/src/gen6_mfd.c index 82cf544..5d52d76 100644 --- a/src/gen6_mfd.c +++ b/src/gen6_mfd.c @@ -1232,20 +1232,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; } @@ -1293,6 +1295,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; @@ -2029,6 +2035,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..804c756 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; @@ -2705,6 +2711,8 @@ gen7_mfd_decode_picture(VADriverContextP ctx, assert(gen7_mfd_context); + gen7_mfd_context->wa_mpeg2_slice_vertical_position = -1; + switch (profile) { case VAProfileMPEG2Simple: case VAProfileMPEG2Main: 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 7b47d86..6985c36 100644 --- a/src/i965_decoder_utils.c +++ b/src/i965_decoder_utils.c @@ -27,8 +27,49 @@ #include <alloca.h> #include "intel_batchbuffer.h" #include "i965_decoder_utils.h" +#include "i965_drv_video.h" #include "i965_defines.h" +/* Check wether codec layer incorrectly fills in slice_vertical_position */ +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) { + WARN_ONCE("codec layer incorrectly fills in MPEG-2 slice_vertical_position. Workaround applied\n"); + 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); |