From: Boyuan Zhang <boyuan.zh...@amd.com> Signed-off-by: Boyuan Zhang <boyuan.zh...@amd.com> Reviewed-by: Christian König <christian.koe...@amd.com> --- src/gallium/state_trackers/va/buffer.c | 24 +++++- src/gallium/state_trackers/va/context.c | 7 ++ src/gallium/state_trackers/va/picture.c | 117 +++++++++++++++++------------ src/gallium/state_trackers/va/va_private.h | 3 + 4 files changed, 102 insertions(+), 49 deletions(-)
diff --git a/src/gallium/state_trackers/va/buffer.c b/src/gallium/state_trackers/va/buffer.c index 71a6503..e1f4c31 100644 --- a/src/gallium/state_trackers/va/buffer.c +++ b/src/gallium/state_trackers/va/buffer.c @@ -30,6 +30,7 @@ #include "state_tracker/drm_driver.h" #include "util/u_memory.h" #include "util/u_handle_table.h" +#include "util/u_video.h" #include "util/u_transfer.h" #include "vl/vl_winsys.h" @@ -41,10 +42,20 @@ vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type, VABufferID *buf_id) { vlVaBuffer *buf; + vlVaDriver *drv; + vlVaContext *pContext; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + pContext = handle_table_get(drv->htab, context); + if (!pContext) + return VA_STATUS_ERROR_INVALID_CONTEXT; + buf = CALLOC(1, sizeof(vlVaBuffer)); if (!buf) return VA_STATUS_ERROR_ALLOCATION_FAILED; @@ -59,8 +70,17 @@ vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type, return VA_STATUS_ERROR_ALLOCATION_FAILED; } - if (data) - memcpy(buf->data, data, size * num_elements); + uint8_t* pExternalData = (uint8_t*) data; + if (data) { + if ((u_reduce_video_profile(pContext->desc.base.profile) == PIPE_VIDEO_FORMAT_MPEG4) + && (pContext->mpeg4.vaapi_mpeg4_workaround == true) + && (buf->type == VASliceDataBufferType)) { + memcpy(pContext->mpeg4.extra_data, + pExternalData - VL_VA_MPEG4_BYTES_FOR_LOOKUP, + VL_VA_MPEG4_BYTES_FOR_LOOKUP); + } + memcpy(buf->data, pExternalData, buf->size * buf->num_elements); + } *buf_id = handle_table_add(VL_VA_DRIVER(ctx)->htab, buf); diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c index 845b547..45240f5 100644 --- a/src/gallium/state_trackers/va/context.c +++ b/src/gallium/state_trackers/va/context.c @@ -35,6 +35,8 @@ #include "va_private.h" +DEBUG_GET_ONCE_BOOL_OPTION(mpeg4, "VAAPI_MPEG4_WORKAROUND", FALSE); + #include <va/va_drmcommon.h> static struct VADriverVTable vtable = @@ -275,6 +277,11 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, return VA_STATUS_ERROR_ALLOCATION_FAILED; } } + + if (u_reduce_video_profile(context->decoder->profile) == + PIPE_VIDEO_FORMAT_MPEG4) { + context->mpeg4.vaapi_mpeg4_workaround = debug_get_option_mpeg4(); + } } context->desc.base.profile = config_id; diff --git a/src/gallium/state_trackers/va/picture.c b/src/gallium/state_trackers/va/picture.c index e850689..1f1b427 100644 --- a/src/gallium/state_trackers/va/picture.c +++ b/src/gallium/state_trackers/va/picture.c @@ -584,60 +584,83 @@ vlVaDecoderFixMPEG4Startcode(vlVaContext *context) int mod_time; unsigned int vop_size; unsigned int vop_coding_type = context->desc.mpeg4.vop_coding_type; + bool startcode_available = false; context->mpeg4.start_code_size = 0; memset(context->mpeg4.start_code, 0, sizeof(context->mpeg4.start_code)); - if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_I) { - unsigned int vop_time = context->mpeg4.frame_num/ - context->desc.mpeg4.vop_time_increment_resolution; - unsigned int vop_hour = vop_time / 3600; - unsigned int vop_minute = (vop_time / 60) % 60; - unsigned int vop_second = vop_time % 60; - uint8_t group_of_vop[] = { 0x00, 0x00, 0x01, 0xb3, 0x00, 0x00, 0x00 }; - struct bit_stream bs_gvop = {group_of_vop, sizeof(group_of_vop)*8, 32}; - - write_bits(&bs_gvop, vop_hour, 5); - write_bits(&bs_gvop, vop_minute, 6); - write_bit(&bs_gvop, 1); /* marker_bit */ - write_bits(&bs_gvop, vop_second, 6); - write_bit(&bs_gvop, 0); /* closed_gov */ /* TODO replace magic */ - write_bit(&bs_gvop, 0); /* broken_link */ - write_bit(&bs_gvop, 0); /* padding */ - write_bits(&bs_gvop, 7, 3); /* padding */ - - memcpy(context->mpeg4.start_code, group_of_vop, sizeof(group_of_vop)); - context->mpeg4.start_code_size += sizeof(group_of_vop); + if (context->mpeg4.vaapi_mpeg4_workaround == true) { + uint8_t* p = (uint8_t*) context->mpeg4.extra_data; + const uint8_t start_code[] = { 0x00, 0x00, 0x01, 0xb6 }; + int extraSize = 0; + bool found = false; + for (int i = 0 ; i < VL_VA_MPEG4_BYTES_FOR_LOOKUP ; i++) { + if (memcmp (p, start_code, sizeof(start_code)) == 0) { + found = true; + break; + } + p += 1; + extraSize += 1; + } + if (found) { + startcode_available = true; + vop_size = VL_VA_MPEG4_BYTES_FOR_LOOKUP - extraSize; + for (int i = 0 ; i < vop_size ; i++) + vop[i] = *(p + i); + } } + if (startcode_available == false) { + if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_I) { + unsigned int vop_time = context->mpeg4.frame_num/ + context->desc.mpeg4.vop_time_increment_resolution; + unsigned int vop_hour = vop_time / 3600; + unsigned int vop_minute = (vop_time / 60) % 60; + unsigned int vop_second = vop_time % 60; + uint8_t group_of_vop[] = { 0x00, 0x00, 0x01, 0xb3, 0x00, 0x00, 0x00 }; + struct bit_stream bs_gvop = {group_of_vop, sizeof(group_of_vop)*8, 32}; + + write_bits(&bs_gvop, vop_hour, 5); + write_bits(&bs_gvop, vop_minute, 6); + write_bit(&bs_gvop, 1); /* marker_bit */ + write_bits(&bs_gvop, vop_second, 6); + write_bit(&bs_gvop, 0); /* closed_gov */ /* TODO replace magic */ + write_bit(&bs_gvop, 0); /* broken_link */ + write_bit(&bs_gvop, 0); /* padding */ + write_bits(&bs_gvop, 7, 3); /* padding */ + + memcpy(context->mpeg4.start_code, group_of_vop, sizeof(group_of_vop)); + context->mpeg4.start_code_size += sizeof(group_of_vop); + } - write_bits(&bs_vop, vop_coding_type, 2); - mod_time = context->mpeg4.frame_num % - context->desc.mpeg4.vop_time_increment_resolution == 0 && - vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I; - while (mod_time--) - write_bit(&bs_vop, 1); /* modulo_time_base */ - write_bit(&bs_vop, 0); /* modulo_time_base */ - - write_bit(&bs_vop, 1); /* marker_bit */ - vop_time_inc = context->mpeg4.frame_num % - context->desc.mpeg4.vop_time_increment_resolution; - write_bits(&bs_vop, vop_time_inc, context->mpeg4.vti_bits); - write_bit(&bs_vop, 1); /* marker_bit */ - write_bit(&bs_vop, 1); /* vop_coded */ - if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_P) - write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.vop_rounding_type); - write_bits(&bs_vop, context->mpeg4.pps.vop_fields.bits.intra_dc_vlc_thr, 3); - if (context->mpeg4.pps.vol_fields.bits.interlaced) { - write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.top_field_first); - write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.alternate_vertical_scan_flag); - } + write_bits(&bs_vop, vop_coding_type, 2); + mod_time = context->mpeg4.frame_num % + context->desc.mpeg4.vop_time_increment_resolution == 0 && + vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I; + while (mod_time--) + write_bit(&bs_vop, 1); /* modulo_time_base */ + write_bit(&bs_vop, 0); /* modulo_time_base */ - write_bits(&bs_vop, context->mpeg4.quant_scale, context->mpeg4.pps.quant_precision); - if (vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I) - write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_forward, 3); - if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_B) - write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_backward, 3); + write_bit(&bs_vop, 1); /* marker_bit */ + vop_time_inc = context->mpeg4.frame_num % + context->desc.mpeg4.vop_time_increment_resolution; + write_bits(&bs_vop, vop_time_inc, context->mpeg4.vti_bits); + write_bit(&bs_vop, 1); /* marker_bit */ + write_bit(&bs_vop, 1); /* vop_coded */ + if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_P) + write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.vop_rounding_type); + write_bits(&bs_vop, context->mpeg4.pps.vop_fields.bits.intra_dc_vlc_thr, 3); + if (context->mpeg4.pps.vol_fields.bits.interlaced) { + write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.top_field_first); + write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.alternate_vertical_scan_flag); + } - vop_size = bs_vop.pos/8; + write_bits(&bs_vop, context->mpeg4.quant_scale, context->mpeg4.pps.quant_precision); + if (vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I) + write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_forward, 3); + if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_B) + write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_backward, 3); + + vop_size = bs_vop.pos/8; + } memcpy(context->mpeg4.start_code + context->mpeg4.start_code_size, vop, vop_size); context->mpeg4.start_code_size += vop_size; } diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h index 2b645d0..c954950 100644 --- a/src/gallium/state_trackers/va/va_private.h +++ b/src/gallium/state_trackers/va/va_private.h @@ -49,6 +49,7 @@ #define VL_VA_PSCREEN(ctx) (VL_VA_DRIVER(ctx)->vscreen->pscreen) #define VL_VA_MAX_IMAGE_FORMATS 9 +#define VL_VA_MPEG4_BYTES_FOR_LOOKUP 12 static inline enum pipe_video_chroma_format ChromaToPipe(int format) @@ -226,6 +227,8 @@ typedef struct { unsigned int quant_scale; VAPictureParameterBufferMPEG4 pps; uint8_t start_code[32]; + uint8_t extra_data[VL_VA_MPEG4_BYTES_FOR_LOOKUP]; + bool vaapi_mpeg4_workaround; } mpeg4; } vlVaContext; -- 1.9.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev