From 5975def8ab076e52919c9249c8f47ac3d6300ae4 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Mon, 2 Apr 2012 11:29:53 +0200 Subject: [PATCH] mpeg2: allocate dummy picture for first field based I-frame. In P-pictures, prediction shall be made from the two most recently decoded reference fields. However, when the first I-frame is a field, the next field of the current picture could be a P-picture but only a single field was decoded so far. In this case, create a dummy picture with POC = -1 that will be used as reference. Some VA drivers would error out if P-pictures don't have a forward reference picture. This is true in general but not in this very specific initial case. --- gst-libs/gst/vaapi/gstvaapidecoder_dpb.c | 8 ++++++ gst-libs/gst/vaapi/gstvaapidecoder_dpb.h | 4 +++ gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.c | 33 ++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_dpb.c b/gst-libs/gst/vaapi/gstvaapidecoder_dpb.c index 6ba5834631..da520c48cc 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_dpb.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder_dpb.c @@ -238,6 +238,14 @@ gst_vaapi_dpb_add(GstVaapiDpb *dpb, GstVaapiPicture *picture) return klass->add(dpb, picture); } +guint +gst_vaapi_dpb_size(GstVaapiDpb *dpb) +{ + g_return_val_if_fail(GST_VAAPI_IS_DPB(dpb), 0); + + return dpb->num_pictures; +} + /* ------------------------------------------------------------------------- */ /* --- MPEG-2 Decoded Picture Buffer --- */ /* ------------------------------------------------------------------------- */ diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_dpb.h b/gst-libs/gst/vaapi/gstvaapidecoder_dpb.h index 198ad19521..1a199b8949 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_dpb.h +++ b/gst-libs/gst/vaapi/gstvaapidecoder_dpb.h @@ -103,6 +103,10 @@ gboolean gst_vaapi_dpb_add(GstVaapiDpb *dpb, GstVaapiPicture *picture) attribute_hidden; +guint +gst_vaapi_dpb_size(GstVaapiDpb *dpb) + attribute_hidden; + static inline gpointer gst_vaapi_dpb_ref(gpointer ptr) { diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.c b/gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.c index 0e97d2e13d..3477573134 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.c @@ -700,6 +700,39 @@ decode_picture_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size) picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME; break; } + + /* Allocate dummy picture for first field based I-frame */ + if (picture->type == GST_VAAPI_PICTURE_TYPE_I && + !GST_VAAPI_PICTURE_IS_FRAME(picture) && + gst_vaapi_dpb_size(priv->dpb) == 0) { + GstVaapiPicture *dummy_picture; + gboolean success; + + dummy_picture = GST_VAAPI_PICTURE_NEW(MPEG2, decoder); + if (!dummy_picture) { + GST_ERROR("failed to allocate dummy picture"); + return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; + } + + dummy_picture->type = GST_VAAPI_PICTURE_TYPE_I; + dummy_picture->pts = GST_CLOCK_TIME_NONE; + dummy_picture->poc = -1; + dummy_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME; + + GST_VAAPI_PICTURE_FLAG_SET( + dummy_picture, + (GST_VAAPI_PICTURE_FLAG_SKIPPED | + GST_VAAPI_PICTURE_FLAG_REFERENCE) + ); + + success = gst_vaapi_dpb_add(priv->dpb, dummy_picture); + gst_vaapi_picture_unref(dummy_picture); + if (!success) { + GST_ERROR("failed to add dummy picture into DPB"); + return GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN; + } + GST_INFO("allocated dummy picture for first field based I-frame"); + } return GST_VAAPI_DECODER_STATUS_SUCCESS; }