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
picture->iq_matrix = NULL;
}
+ if (picture->bitplane) {
+ destroy_bitplane(decoder, picture->bitplane);
+ picture->bitplane = NULL;
+ }
+
picture->surface = NULL;
picture->surface_id = VA_INVALID_ID;
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);
}
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;
{
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;
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,
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
void *param;
GPtrArray *slices;
GstVaapiIqMatrix *iq_matrix;
+ GstVaapiBitPlane *bitplane;
GstClockTime pts;
};
void *param;
};
+struct _GstVaapiBitPlane {
+ VABufferID data_id;
+ guint8 *data;
+};
+
struct _GstVaapiDecoderPrivate {
GstVaapiDisplay *display;
VADisplay va_display;
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,
GstVC1SeqHdr seq_hdr;
GstVC1EntryPointHdr entrypoint_hdr;
GstVC1FrameHdr frame_hdr;
+ GstVC1BitPlanes *bitplanes;
GstVaapiPicture *current_picture;
GstVaapiPicture *next_picture;
GstVaapiPicture *prev_picture;
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;
priv->tsb = gst_vaapi_tsb_new();
if (!priv->tsb)
return FALSE;
+
+ priv->bitplanes = gst_vc1_bitplanes_new();
+ if (!priv->bitplanes)
+ return FALSE;
return TRUE;
}
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)
{
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;
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;
}
}
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);