mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-23 15:48:23 +00:00
vc1: fix bitplanes decoding.
This commit is contained in:
parent
e686c440c7
commit
5aea02a66f
3 changed files with 151 additions and 1 deletions
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue