mpeg2: allocate dummy picture for first field based I-frame.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Mon, 2 Apr 2012 09:29:53 +0000 (11:29 +0200)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Mon, 2 Apr 2012 09:36:56 +0000 (11:36 +0200)
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
gst-libs/gst/vaapi/gstvaapidecoder_dpb.h
gst-libs/gst/vaapi/gstvaapidecoder_mpeg2.c

index 6ba5834..da520c4 100644 (file)
@@ -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                                     --- */
 /* ------------------------------------------------------------------------- */
index 198ad19..1a199b8 100644 (file)
@@ -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)
 {
index 0e97d2e..3477573 100644 (file)
@@ -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;
 }