[Mesa-dev] [PATCH] st/va: add mpeg4 startcode workaround
Leo Liu
leo.liu at amd.com
Thu Nov 5 13:00:21 PST 2015
From: Boyuan Zhang <boyuan.zhang at amd.com>
Signed-off-by: Boyuan Zhang <boyuan.zhang at amd.com>
Reviewed-by: Christian König <christian.koenig at 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
More information about the mesa-dev
mailing list