vc1: fix bitplanes decoding.

This commit is contained in:
Gwenole Beauchesne 2011-10-04 17:51:51 +02:00
parent e686c440c7
commit 5aea02a66f
3 changed files with 151 additions and 1 deletions

View file

@ -615,6 +615,9 @@ gst_vaapi_decoder_push_surface_proxy(
static void
destroy_iq_matrix(GstVaapiDecoder *decoder, GstVaapiIqMatrix *iq_matrix);
static void
destroy_bitplane(GstVaapiDecoder *decoder, GstVaapiBitPlane *bitplane);
static void
destroy_slice(GstVaapiDecoder *decoder, GstVaapiSlice *slice);
@ -643,6 +646,11 @@ destroy_picture(GstVaapiDecoder *decoder, GstVaapiPicture *picture)
picture->iq_matrix = NULL;
}
if (picture->bitplane) {
destroy_bitplane(decoder, picture->bitplane);
picture->bitplane = NULL;
}
picture->surface = NULL;
picture->surface_id = VA_INVALID_ID;
@ -669,6 +677,7 @@ create_picture(GstVaapiDecoder *decoder)
picture->param = NULL;
picture->slices = NULL;
picture->iq_matrix = NULL;
picture->bitplane = NULL;
picture->pts = GST_CLOCK_TIME_NONE;
picture->surface = gst_vaapi_context_get_surface(priv->context);
@ -752,6 +761,50 @@ gst_vaapi_decoder_new_iq_matrix(GstVaapiDecoder *decoder)
return create_iq_matrix(decoder);
}
static void
destroy_bitplane(GstVaapiDecoder *decoder, GstVaapiBitPlane *bitplane)
{
GstVaapiDecoderPrivate * const priv = decoder->priv;
vaapi_destroy_buffer(priv->va_display, &bitplane->data_id);
bitplane->data = NULL;
g_slice_free(GstVaapiBitPlane, bitplane);
}
static GstVaapiBitPlane *
create_bitplane(GstVaapiDecoder *decoder, guint size)
{
GstVaapiDecoderPrivate * const priv = decoder->priv;
GstVaapiBitPlane *bitplane;
bitplane = g_slice_new(GstVaapiBitPlane);
if (!bitplane)
return NULL;
bitplane->data_id = VA_INVALID_ID;
bitplane->data = vaapi_create_buffer(
priv->va_display,
priv->va_context,
VABitPlaneBufferType,
size,
&bitplane->data_id
);
if (!bitplane->data)
goto error;
return bitplane;
error:
destroy_bitplane(decoder, bitplane);
return NULL;
}
GstVaapiBitPlane *
gst_vaapi_decoder_new_bitplane(GstVaapiDecoder *decoder, guint size)
{
return create_bitplane(decoder, size);
}
static void
destroy_slice(GstVaapiDecoder *decoder, GstVaapiSlice *slice)
{
@ -836,6 +889,7 @@ gst_vaapi_decoder_decode_picture(
{
GstVaapiDecoderPrivate * const priv = decoder->priv;
GstVaapiIqMatrix * const iq_matrix = picture->iq_matrix;
GstVaapiBitPlane * const bitplane = picture->bitplane;
GstVaapiSlice *slice;
VABufferID va_buffers[3];
guint i, n_va_buffers = 0;
@ -851,6 +905,11 @@ gst_vaapi_decoder_decode_picture(
va_buffers[n_va_buffers++] = iq_matrix->param_id;
}
if (bitplane) {
vaapi_unmap_buffer(priv->va_display, bitplane->data_id, (void **)&bitplane->data);
va_buffers[n_va_buffers++] = bitplane->data_id;
}
status = vaBeginPicture(
priv->va_display,
priv->va_context,

View file

@ -113,6 +113,7 @@ typedef struct _GstVaapiCodecInfo GstVaapiCodecInfo;
typedef struct _GstVaapiPicture GstVaapiPicture;
typedef struct _GstVaapiSlice GstVaapiSlice;
typedef struct _GstVaapiIqMatrix GstVaapiIqMatrix;
typedef struct _GstVaapiBitPlane GstVaapiBitPlane;
enum _GstVaapiPictureType {
GST_VAAPI_PICTURE_TYPE_NONE = 0, // Undefined
@ -153,6 +154,7 @@ struct _GstVaapiPicture {
void *param;
GPtrArray *slices;
GstVaapiIqMatrix *iq_matrix;
GstVaapiBitPlane *bitplane;
GstClockTime pts;
};
@ -167,6 +169,11 @@ struct _GstVaapiIqMatrix {
void *param;
};
struct _GstVaapiBitPlane {
VABufferID data_id;
guint8 *data;
};
struct _GstVaapiDecoderPrivate {
GstVaapiDisplay *display;
VADisplay va_display;
@ -250,6 +257,10 @@ GstVaapiIqMatrix *
gst_vaapi_decoder_new_iq_matrix(GstVaapiDecoder *decoder)
attribute_hidden;
GstVaapiBitPlane *
gst_vaapi_decoder_new_bitplane(GstVaapiDecoder *decoder, guint size)
attribute_hidden;
GstVaapiSlice *
gst_vaapi_decoder_new_slice(
GstVaapiDecoder *decoder,

View file

@ -54,6 +54,7 @@ struct _GstVaapiDecoderVC1Private {
GstVC1SeqHdr seq_hdr;
GstVC1EntryPointHdr entrypoint_hdr;
GstVC1FrameHdr frame_hdr;
GstVC1BitPlanes *bitplanes;
GstVaapiPicture *current_picture;
GstVaapiPicture *next_picture;
GstVaapiPicture *prev_picture;
@ -117,6 +118,11 @@ gst_vaapi_decoder_vc1_close(GstVaapiDecoderVC1 *decoder)
priv->sub_buffer = NULL;
}
if (priv->bitplanes) {
gst_vc1_bitplanes_free(priv->bitplanes);
priv->bitplanes = NULL;
}
if (priv->tsb) {
gst_vaapi_tsb_destroy(priv->tsb);
priv->tsb = NULL;
@ -133,6 +139,10 @@ gst_vaapi_decoder_vc1_open(GstVaapiDecoderVC1 *decoder, GstBuffer *buffer)
priv->tsb = gst_vaapi_tsb_new();
if (!priv->tsb)
return FALSE;
priv->bitplanes = gst_vc1_bitplanes_new();
if (!priv->bitplanes)
return FALSE;
return TRUE;
}
@ -584,6 +594,22 @@ has_OVERFLAGS_bitplane(GstVaapiDecoderVC1 *decoder)
pic->condover == GST_VC1_CONDOVER_SELECT);
}
static inline void
pack_bitplanes(GstVaapiBitPlane *bitplane, guint n, const guint8 *bitplanes[3], guint x, guint y, guint stride)
{
const guint dst_index = n / 2;
const guint src_index = y * stride + x;
guint8 v = 0;
if (bitplanes[0])
v |= bitplanes[0][src_index];
if (bitplanes[1])
v |= bitplanes[1][src_index] << 1;
if (bitplanes[2])
v |= bitplanes[2][src_index] << 2;
bitplane->data[dst_index] = (bitplane->data[dst_index] << 4) | v;
}
static gboolean
fill_picture_structc(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
{
@ -701,6 +727,7 @@ fill_picture_advanced(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
static gboolean
fill_picture(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
{
GstVaapiDecoder * const base_decoder = GST_VAAPI_DECODER(decoder);
GstVaapiDecoderVC1Private * const priv = decoder->priv;
VAPictureParameterBufferVC1 * const pic_param = picture->param;
GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
@ -759,6 +786,49 @@ fill_picture(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
default:
break;
}
if (pic_param->bitplane_present.value) {
const guint8 *bitplanes[3];
guint x, y, n;
switch (picture->type) {
case GST_VAAPI_PICTURE_TYPE_P:
bitplanes[0] = pic_param->bitplane_present.flags.bp_direct_mb ? priv->bitplanes->directmb : NULL;
bitplanes[1] = pic_param->bitplane_present.flags.bp_skip_mb ? priv->bitplanes->skipmb : NULL;
bitplanes[2] = pic_param->bitplane_present.flags.bp_mv_type_mb ? priv->bitplanes->mvtypemb : NULL;
break;
case GST_VAAPI_PICTURE_TYPE_B:
bitplanes[0] = pic_param->bitplane_present.flags.bp_direct_mb ? priv->bitplanes->directmb : NULL;
bitplanes[1] = pic_param->bitplane_present.flags.bp_skip_mb ? priv->bitplanes->skipmb : NULL;
bitplanes[2] = NULL; /* XXX: interlaced frame (FORWARD plane) */
break;
case GST_VAAPI_PICTURE_TYPE_BI:
case GST_VAAPI_PICTURE_TYPE_I:
bitplanes[0] = NULL; /* XXX: interlaced frame (FIELDTX plane) */
bitplanes[1] = pic_param->bitplane_present.flags.bp_ac_pred ? priv->bitplanes->acpred : NULL;
bitplanes[2] = pic_param->bitplane_present.flags.bp_overflags ? priv->bitplanes->overflags : NULL;
break;
default:
bitplanes[0] = NULL;
bitplanes[1] = NULL;
bitplanes[2] = NULL;
break;
}
picture->bitplane = gst_vaapi_decoder_new_bitplane(
base_decoder,
(seq_hdr->mb_width * seq_hdr->mb_height + 1) / 2
);
if (!picture->bitplane)
return FALSE;
n = 0;
for (y = 0; y < seq_hdr->mb_height; y++)
for (x = 0; x < seq_hdr->mb_width; x++, n++)
pack_bitplanes(picture->bitplane, n, bitplanes, x, y, seq_hdr->mb_stride);
if (n & 1) /* move last nibble to the high order */
picture->bitplane->data[n/2] <<= 4;
}
return TRUE;
}
@ -794,8 +864,18 @@ decode_frame(GstVaapiDecoderVC1 *decoder, guchar *buf, guint buf_size)
}
picture = priv->current_picture;
if (!gst_vc1_bitplanes_ensure_size(priv->bitplanes, seq_hdr)) {
GST_DEBUG("failed to allocate bitplanes");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
}
memset(frame_hdr, 0, sizeof(*frame_hdr));
result = gst_vc1_parse_frame_header(buf, buf_size, frame_hdr, seq_hdr, NULL);
result = gst_vc1_parse_frame_header(
buf, buf_size,
frame_hdr,
seq_hdr,
priv->bitplanes
);
if (result != GST_VC1_PARSER_OK) {
GST_DEBUG("failed to parse frame layer");
return get_status(result);