vc1: port to common GstVaapiDpb interface.

Use GstVaapiDpb interface instead of maintaining our own prev and next
picture pointers. While doing so, try to derive a sensible POC value.

Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
Sreerenj Balachandran 2012-08-02 17:15:26 +03:00 committed by Gwenole Beauchesne
parent 142e13f637
commit 472f3473e0

View file

@ -29,6 +29,7 @@
#include <gst/codecparsers/gstvc1parser.h> #include <gst/codecparsers/gstvc1parser.h>
#include "gstvaapidecoder_vc1.h" #include "gstvaapidecoder_vc1.h"
#include "gstvaapidecoder_objects.h" #include "gstvaapidecoder_objects.h"
#include "gstvaapidecoder_dpb.h"
#include "gstvaapidecoder_unit.h" #include "gstvaapidecoder_unit.h"
#include "gstvaapidecoder_priv.h" #include "gstvaapidecoder_priv.h"
#include "gstvaapidisplay_priv.h" #include "gstvaapidisplay_priv.h"
@ -55,8 +56,9 @@ struct _GstVaapiDecoderVC1Private {
GstVC1FrameHdr frame_hdr; GstVC1FrameHdr frame_hdr;
GstVC1BitPlanes *bitplanes; GstVC1BitPlanes *bitplanes;
GstVaapiPicture *current_picture; GstVaapiPicture *current_picture;
GstVaapiPicture *next_picture; GstVaapiPicture *last_non_b_picture;
GstVaapiPicture *prev_picture; GstVaapiDpb *dpb;
gint32 next_poc;
guint8 *rbdu_buffer; guint8 *rbdu_buffer;
guint rbdu_buffer_size; guint rbdu_buffer_size;
guint is_constructed : 1; guint is_constructed : 1;
@ -97,9 +99,9 @@ gst_vaapi_decoder_vc1_close(GstVaapiDecoderVC1 *decoder)
{ {
GstVaapiDecoderVC1Private * const priv = decoder->priv; GstVaapiDecoderVC1Private * const priv = decoder->priv;
gst_vaapi_picture_replace(&priv->last_non_b_picture, NULL);
gst_vaapi_picture_replace(&priv->current_picture, NULL); gst_vaapi_picture_replace(&priv->current_picture, NULL);
gst_vaapi_picture_replace(&priv->next_picture, NULL); gst_vaapi_dpb_replace(&priv->dpb, NULL);
gst_vaapi_picture_replace(&priv->prev_picture, NULL);
if (priv->bitplanes) { if (priv->bitplanes) {
gst_vc1_bitplanes_free(priv->bitplanes); gst_vc1_bitplanes_free(priv->bitplanes);
@ -114,6 +116,10 @@ gst_vaapi_decoder_vc1_open(GstVaapiDecoderVC1 *decoder)
gst_vaapi_decoder_vc1_close(decoder); gst_vaapi_decoder_vc1_close(decoder);
priv->dpb = gst_vaapi_dpb_new(2);
if (!priv->dpb)
return FALSE;
priv->bitplanes = gst_vc1_bitplanes_new(); priv->bitplanes = gst_vc1_bitplanes_new();
if (!priv->bitplanes) if (!priv->bitplanes)
return FALSE; return FALSE;
@ -194,31 +200,28 @@ ensure_context(GstVaapiDecoderVC1 *decoder)
return GST_VAAPI_DECODER_STATUS_SUCCESS; return GST_VAAPI_DECODER_STATUS_SUCCESS;
} }
static inline GstVaapiDecoderStatus
render_picture(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
{
if (!gst_vaapi_picture_output(picture))
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
static GstVaapiDecoderStatus static GstVaapiDecoderStatus
decode_current_picture(GstVaapiDecoderVC1 *decoder) decode_current_picture(GstVaapiDecoderVC1 *decoder)
{ {
GstVaapiDecoderVC1Private * const priv = decoder->priv; GstVaapiDecoderVC1Private * const priv = decoder->priv;
GstVaapiPicture * const picture = priv->current_picture; GstVaapiPicture * const picture = priv->current_picture;
GstVaapiDecoderStatus status = GST_VAAPI_DECODER_STATUS_SUCCESS;
if (picture) { if (!picture)
if (!gst_vaapi_picture_decode(picture)) return GST_VAAPI_DECODER_STATUS_SUCCESS;
status = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
if (!GST_VAAPI_PICTURE_IS_REFERENCE(picture)) { if (!gst_vaapi_picture_decode(picture))
if (priv->prev_picture && priv->next_picture) goto error;
status = render_picture(decoder, picture); if (GST_VAAPI_PICTURE_IS_COMPLETE(picture)) {
} if (!gst_vaapi_dpb_add(priv->dpb, picture))
goto error;
gst_vaapi_picture_replace(&priv->current_picture, NULL); gst_vaapi_picture_replace(&priv->current_picture, NULL);
} }
return status; return GST_VAAPI_DECODER_STATUS_SUCCESS;
error:
/* XXX: fix for cases where first field failed to be decoded */
gst_vaapi_picture_replace(&priv->current_picture, NULL);
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
} }
static GstVaapiDecoderStatus static GstVaapiDecoderStatus
@ -337,20 +340,11 @@ decode_sequence_end(GstVaapiDecoderVC1 *decoder)
GstVaapiDecoderVC1Private * const priv = decoder->priv; GstVaapiDecoderVC1Private * const priv = decoder->priv;
GstVaapiDecoderStatus status; GstVaapiDecoderStatus status;
if (priv->current_picture) { status = decode_current_picture(decoder);
status = decode_current_picture(decoder); if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) return status;
return status;
status = render_picture(decoder, priv->current_picture);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
}
if (priv->next_picture) { gst_vaapi_dpb_flush(priv->dpb);
status = render_picture(decoder, priv->next_picture);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
}
return GST_VAAPI_DECODER_STATUS_SUCCESS; return GST_VAAPI_DECODER_STATUS_SUCCESS;
} }
@ -733,6 +727,7 @@ fill_picture(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
VAPictureParameterBufferVC1 * const pic_param = picture->param; VAPictureParameterBufferVC1 * const pic_param = picture->param;
GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr; GstVC1SeqHdr * const seq_hdr = &priv->seq_hdr;
GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr; GstVC1FrameHdr * const frame_hdr = &priv->frame_hdr;
GstVaapiPicture *prev_picture, *next_picture;
/* Fill in VAPictureParameterBufferVC1 (common fields) */ /* Fill in VAPictureParameterBufferVC1 (common fields) */
pic_param->forward_reference_picture = VA_INVALID_ID; pic_param->forward_reference_picture = VA_INVALID_ID;
@ -777,14 +772,17 @@ fill_picture(GstVaapiDecoderVC1 *decoder, GstVaapiPicture *picture)
return FALSE; return FALSE;
} }
gst_vaapi_dpb_get_neighbours(priv->dpb, picture,
&prev_picture, &next_picture);
switch (picture->type) { switch (picture->type) {
case GST_VAAPI_PICTURE_TYPE_B: case GST_VAAPI_PICTURE_TYPE_B:
if (priv->next_picture) if (next_picture)
pic_param->backward_reference_picture = priv->next_picture->surface_id; pic_param->backward_reference_picture = next_picture->surface_id;
// fall-through // fall-through
case GST_VAAPI_PICTURE_TYPE_P: case GST_VAAPI_PICTURE_TYPE_P:
if (priv->prev_picture) if (prev_picture)
pic_param->forward_reference_picture = priv->prev_picture->surface_id; pic_param->forward_reference_picture = prev_picture->surface_id;
break; break;
default: default:
break; break;
@ -859,12 +857,13 @@ decode_frame(GstVaapiDecoderVC1 *decoder, GstVC1BDU *rbdu, GstVC1BDU *ebdu)
return status; return status;
} }
priv->current_picture = GST_VAAPI_PICTURE_NEW(VC1, decoder); picture = GST_VAAPI_PICTURE_NEW(VC1, decoder);
if (!priv->current_picture) { if (!picture) {
GST_DEBUG("failed to allocate picture"); GST_DEBUG("failed to allocate picture");
return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
} }
picture = priv->current_picture; gst_vaapi_picture_replace(&priv->current_picture, picture);
gst_vaapi_picture_unref(picture);
if (!gst_vc1_bitplanes_ensure_size(priv->bitplanes, seq_hdr)) { if (!gst_vc1_bitplanes_ensure_size(priv->bitplanes, seq_hdr)) {
GST_DEBUG("failed to allocate bitplanes"); GST_DEBUG("failed to allocate bitplanes");
@ -906,15 +905,19 @@ decode_frame(GstVaapiDecoderVC1 *decoder, GstVC1BDU *rbdu, GstVC1BDU *ebdu)
} }
/* Update presentation time */ /* Update presentation time */
picture->pts = GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts;
/* Update reference pictures */
if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) { if (GST_VAAPI_PICTURE_IS_REFERENCE(picture)) {
if (priv->next_picture) picture->poc = priv->last_non_b_picture ?
status = render_picture(decoder, priv->next_picture); (priv->last_non_b_picture->poc + 1) : priv->next_poc;
gst_vaapi_picture_replace(&priv->prev_picture, priv->next_picture); priv->next_poc = picture->poc + 1;
gst_vaapi_picture_replace(&priv->next_picture, picture); gst_vaapi_picture_replace(&priv->last_non_b_picture, picture);
} }
else if (!priv->last_non_b_picture)
picture->poc = priv->next_poc++;
else { /* B or BI */
picture->poc = priv->last_non_b_picture->poc++;
priv->next_poc = priv->last_non_b_picture->poc + 1;
}
picture->pts = GST_VAAPI_DECODER_CODEC_FRAME(decoder)->pts;
if (!fill_picture(decoder, picture)) if (!fill_picture(decoder, picture))
return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
@ -936,8 +939,7 @@ decode_frame(GstVaapiDecoderVC1 *decoder, GstVC1BDU *rbdu, GstVC1BDU *ebdu)
slice_param->macroblock_offset = 8 * (ebdu->offset - ebdu->sc_offset) + frame_hdr->header_size; slice_param->macroblock_offset = 8 * (ebdu->offset - ebdu->sc_offset) + frame_hdr->header_size;
slice_param->slice_vertical_position = 0; slice_param->slice_vertical_position = 0;
/* Decode picture right away, we got the full frame */ return GST_VAAPI_DECODER_STATUS_SUCCESS;
return decode_current_picture(decoder);
} }
static gboolean static gboolean
@ -1304,8 +1306,6 @@ gst_vaapi_decoder_vc1_init(GstVaapiDecoderVC1 *decoder)
priv->height = 0; priv->height = 0;
priv->profile = (GstVaapiProfile)0; priv->profile = (GstVaapiProfile)0;
priv->current_picture = NULL; priv->current_picture = NULL;
priv->next_picture = NULL;
priv->prev_picture = NULL;
priv->rbdu_buffer = NULL; priv->rbdu_buffer = NULL;
priv->rbdu_buffer_size = 0; priv->rbdu_buffer_size = 0;
priv->is_constructed = FALSE; priv->is_constructed = FALSE;