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
{
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;
}
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;
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;
}
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_ */
{
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;
}
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;
assert(gen7_mfd_context);
+ gen7_mfd_context->wa_mpeg2_slice_vertical_position = -1;
+
switch (profile) {
case VAProfileMPEG2Simple:
case VAProfileMPEG2Main:
VASurfaceID jpeg_wa_surface_id;
dri_bo *jpeg_wa_slice_data_bo;
+
+ int wa_mpeg2_slice_vertical_position;
};
#endif /* _GEN7_MFD_H_ */
#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)
#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);
#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"
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;
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);
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);
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) /
{
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);