From 5aea02a66f9d174d7d57635b85cf809704cc0ae9 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Tue, 4 Oct 2011 17:51:51 +0200 Subject: [PATCH] vc1: fix bitplanes decoding. --- gst-libs/gst/vaapi/gstvaapidecoder.c | 59 ++++++++++++++++++++++ gst-libs/gst/vaapi/gstvaapidecoder_priv.h | 11 +++++ gst-libs/gst/vaapi/gstvaapidecoder_vc1.c | 82 ++++++++++++++++++++++++++++++- 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/vaapi/gstvaapidecoder.c b/gst-libs/gst/vaapi/gstvaapidecoder.c index e1b45df..adb1b18 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder.c @@ -616,6 +616,9 @@ 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); static void @@ -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); @@ -753,6 +762,50 @@ gst_vaapi_decoder_new_iq_matrix(GstVaapiDecoder *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) { GstVaapiDecoderPrivate * const priv = decoder->priv; @@ -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, diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_priv.h b/gst-libs/gst/vaapi/gstvaapidecoder_priv.h index d4cb9bb..478daa8 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_priv.h +++ b/gst-libs/gst/vaapi/gstvaapidecoder_priv.h @@ -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, diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_vc1.c b/gst-libs/gst/vaapi/gstvaapidecoder_vc1.c index a96251d..a344610 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_vc1.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder_vc1.c @@ -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); -- 2.7.4