diff options
author | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2012-03-15 14:41:47 +0100 |
---|---|---|
committer | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2012-03-18 09:10:11 +0100 |
commit | 14f70559b516030d141cce09db54cf49d11df9b2 (patch) | |
tree | 0282004db9b50b3e174bd2a7b13e8bca0323c581 | |
parent | 18212d42c5dfee047094ae67914c2b2b630ad99e (diff) |
mpeg2: fix construction of reference frames list (SNB, IVB).
Fix construction of reference frames list for interlaced streams.
In this case, the array is indexed by frame store ID >> 1 where
bit 0 of frame store ID represents top (0) or bottom (1) field.
Besides, current render target can also be used as a reference
while decoding the second field.
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
-rw-r--r-- | src/gen6_mfd.c | 25 | ||||
-rw-r--r-- | src/gen7_mfd.c | 25 | ||||
-rw-r--r-- | src/i965_decoder_utils.c | 86 | ||||
-rw-r--r-- | src/i965_decoder_utils.h | 8 | ||||
-rw-r--r-- | src/i965_defines.h | 4 |
5 files changed, 110 insertions, 38 deletions
diff --git a/src/gen6_mfd.c b/src/gen6_mfd.c index 367294f..51426ba 100644 --- a/src/gen6_mfd.c +++ b/src/gen6_mfd.c @@ -1084,30 +1084,17 @@ gen6_mfd_mpeg2_decode_init(VADriverContextP ctx, VAPictureParameterBufferMPEG2 *pic_param; struct i965_driver_data *i965 = i965_driver_data(ctx); struct object_surface *obj_surface; - int i; dri_bo *bo; assert(decode_state->pic_param && decode_state->pic_param->buffer); pic_param = (VAPictureParameterBufferMPEG2 *)decode_state->pic_param->buffer; - /* reference picture */ - obj_surface = SURFACE(pic_param->forward_reference_picture); - - if (obj_surface && obj_surface->bo) - gen6_mfd_context->reference_surface[0].surface_id = pic_param->forward_reference_picture; - else - gen6_mfd_context->reference_surface[0].surface_id = VA_INVALID_ID; - - obj_surface = SURFACE(pic_param->backward_reference_picture); - - if (obj_surface && obj_surface->bo) - gen6_mfd_context->reference_surface[1].surface_id = pic_param->backward_reference_picture; - else - gen6_mfd_context->reference_surface[1].surface_id = gen6_mfd_context->reference_surface[0].surface_id; - - /* must do so !!! */ - for (i = 2; i < ARRAY_ELEMS(gen6_mfd_context->reference_surface); i++) - gen6_mfd_context->reference_surface[i].surface_id = gen6_mfd_context->reference_surface[i % 2].surface_id; + mpeg2_set_reference_surfaces( + ctx, + gen6_mfd_context->reference_surface, + decode_state, + pic_param + ); /* Current decoded picture */ obj_surface = SURFACE(decode_state->current_render_target); diff --git a/src/gen7_mfd.c b/src/gen7_mfd.c index 6318ab9..6d3e044 100644 --- a/src/gen7_mfd.c +++ b/src/gen7_mfd.c @@ -1032,30 +1032,17 @@ gen7_mfd_mpeg2_decode_init(VADriverContextP ctx, VAPictureParameterBufferMPEG2 *pic_param; struct i965_driver_data *i965 = i965_driver_data(ctx); struct object_surface *obj_surface; - int i; dri_bo *bo; assert(decode_state->pic_param && decode_state->pic_param->buffer); pic_param = (VAPictureParameterBufferMPEG2 *)decode_state->pic_param->buffer; - /* reference picture */ - obj_surface = SURFACE(pic_param->forward_reference_picture); - - if (obj_surface && obj_surface->bo) - gen7_mfd_context->reference_surface[0].surface_id = pic_param->forward_reference_picture; - else - gen7_mfd_context->reference_surface[0].surface_id = VA_INVALID_ID; - - obj_surface = SURFACE(pic_param->backward_reference_picture); - - if (obj_surface && obj_surface->bo) - gen7_mfd_context->reference_surface[1].surface_id = pic_param->backward_reference_picture; - else - gen7_mfd_context->reference_surface[1].surface_id = gen7_mfd_context->reference_surface[0].surface_id; - - /* must do so !!! */ - for (i = 2; i < ARRAY_ELEMS(gen7_mfd_context->reference_surface); i++) - gen7_mfd_context->reference_surface[i].surface_id = gen7_mfd_context->reference_surface[i % 2].surface_id; + mpeg2_set_reference_surfaces( + ctx, + gen7_mfd_context->reference_surface, + decode_state, + pic_param + ); /* Current decoded picture */ obj_surface = SURFACE(decode_state->current_render_target); diff --git a/src/i965_decoder_utils.c b/src/i965_decoder_utils.c index 6985c36..047fa62 100644 --- a/src/i965_decoder_utils.c +++ b/src/i965_decoder_utils.c @@ -30,6 +30,27 @@ #include "i965_drv_video.h" #include "i965_defines.h" +/* Set reference surface if backing store exists */ +static inline int +set_ref_frame( + struct i965_driver_data *i965, + GenFrameStore *ref_frame, + VASurfaceID va_surface +) +{ + struct object_surface *obj_surface; + + if (va_surface == VA_INVALID_ID) + return 0; + + obj_surface = SURFACE(va_surface); + if (!obj_surface || !obj_surface->bo) + return 0; + + ref_frame->surface_id = va_surface; + return 1; +} + /* Check wether codec layer incorrectly fills in slice_vertical_position */ int mpeg2_wa_slice_vertical_position( @@ -70,6 +91,71 @@ mpeg2_wa_slice_vertical_position( return 0; } +/* Build MPEG-2 reference frames array */ +void +mpeg2_set_reference_surfaces( + VADriverContextP ctx, + GenFrameStore ref_frames[MAX_GEN_REFERENCE_FRAMES], + struct decode_state *decode_state, + VAPictureParameterBufferMPEG2 *pic_param +) +{ + struct i965_driver_data * const i965 = i965_driver_data(ctx); + VASurfaceID va_surface; + unsigned pic_structure, is_second_field, n = 0; + + pic_structure = pic_param->picture_coding_extension.bits.picture_structure; + is_second_field = pic_structure != MPEG_FRAME && + !pic_param->picture_coding_extension.bits.is_first_field; + + /* Reference frames are indexed by frame store ID (0:top, 1:bottom) */ + switch (pic_param->picture_coding_type) { + case MPEG_P_PICTURE: + if (is_second_field && pic_structure == MPEG_BOTTOM_FIELD) { + va_surface = decode_state->current_render_target; + n += set_ref_frame(i965, &ref_frames[n], va_surface); + } + va_surface = pic_param->forward_reference_picture; + n += set_ref_frame(i965, &ref_frames[n], va_surface); + break; + + case MPEG_B_PICTURE: + va_surface = pic_param->forward_reference_picture; + n += set_ref_frame(i965, &ref_frames[n], va_surface); + va_surface = pic_param->backward_reference_picture; + n += set_ref_frame(i965, &ref_frames[n], va_surface); + break; + } + + while (n != 2) + ref_frames[n++].surface_id = VA_INVALID_ID; + + if (pic_param->picture_coding_extension.bits.progressive_frame) + return; + + /* Bottom field pictures used as reference */ + switch (pic_param->picture_coding_type) { + case MPEG_P_PICTURE: + if (is_second_field && pic_structure == MPEG_TOP_FIELD) { + va_surface = decode_state->current_render_target; + n += set_ref_frame(i965, &ref_frames[n], va_surface); + } + va_surface = pic_param->forward_reference_picture; + n += set_ref_frame(i965, &ref_frames[n], va_surface); + break; + + case MPEG_B_PICTURE: + va_surface = pic_param->forward_reference_picture; + n += set_ref_frame(i965, &ref_frames[n], va_surface); + va_surface = pic_param->backward_reference_picture; + n += set_ref_frame(i965, &ref_frames[n], va_surface); + break; + } + + while (n != 4) + ref_frames[n++].surface_id = VA_INVALID_ID; +} + /* 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 1c624c0..0d86523 100644 --- a/src/i965_decoder_utils.h +++ b/src/i965_decoder_utils.h @@ -36,6 +36,14 @@ mpeg2_wa_slice_vertical_position( ); void +mpeg2_set_reference_surfaces( + VADriverContextP ctx, + GenFrameStore ref_frames[MAX_GEN_REFERENCE_FRAMES], + struct decode_state *decode_state, + VAPictureParameterBufferMPEG2 *pic_param +); + +void avc_gen_default_iq_matrix(VAIQMatrixBufferH264 *iq_matrix); unsigned int diff --git a/src/i965_defines.h b/src/i965_defines.h index d530a5b..b58260a 100644 --- a/src/i965_defines.h +++ b/src/i965_defines.h @@ -707,6 +707,10 @@ #define MFX_SURFACE_PLANAR_422_8 6 #define MFX_SURFACE_MONOCHROME 12 +#define MPEG_I_PICTURE 1 +#define MPEG_P_PICTURE 2 +#define MPEG_B_PICTURE 3 + #define MPEG_TOP_FIELD 1 #define MPEG_BOTTOM_FIELD 2 #define MPEG_FRAME 3 |