vc1: port to common GstVaapiDpb interface.
authorSreerenj Balachandran <sreerenj.balachandran@intel.com>
Thu, 2 Aug 2012 14:15:26 +0000 (17:15 +0300)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Mon, 21 Jan 2013 18:08:00 +0000 (19:08 +0100)
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>
gst-libs/gst/vaapi/gstvaapidecoder_vc1.c

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