decoder: h264: reduce ReferenceFrames entries to the essential set.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Tue, 3 Jun 2014 15:36:38 +0000 (17:36 +0200)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Fri, 6 Jun 2014 15:34:02 +0000 (17:34 +0200)
When decoding Multiview High profile streams with a large number of
views, it is not possible to make the VAPictureParameterBufferH264.
ReferenceFrames[] array hold the complete DPB, with all possibly
active pictures to be used for inter-view prediction in the current
access unit.

So reduce the scope of the ReferenceFrames[] array to only include
the set of reference pictures that are going to be used for decoding
the current picture. Basically, this is a union of all RefPicListX[]
array, for all slices constituting the decoded picture.

gst-libs/gst/vaapi/gstvaapidecoder_h264.c

index f5c1c8e..cfe7b02 100644 (file)
@@ -2051,6 +2051,45 @@ find_inter_view_reference(GstVaapiDecoderH264 *decoder, guint16 view_id)
     return NULL;
 }
 
+/* Checks whether the view id exists in the supplied list of view ids */
+static gboolean
+find_view_id(guint16 view_id, const guint16 *view_ids, guint num_view_ids)
+{
+    guint i;
+
+    for (i = 0; i < num_view_ids; i++) {
+        if (view_ids[i] == view_id)
+            return TRUE;
+    }
+    return FALSE;
+}
+
+/* Checks whether the inter-view reference picture with the supplied
+   view id is used for decoding the current view component picture */
+static gboolean
+is_inter_view_reference_for_picture(GstVaapiDecoderH264 *decoder,
+    guint16 view_id, GstVaapiPictureH264 *picture)
+{
+    const GstH264SPS * const sps = get_sps(decoder);
+    const GstH264SPSExtMVCView *view;
+
+    if (!GST_VAAPI_PICTURE_IS_MVC(picture) ||
+        sps->extension_type != GST_H264_NAL_EXTENSION_MVC)
+        return FALSE;
+
+    view = &sps->extension.mvc.view[picture->base.voc];
+    if (GST_VAAPI_PICTURE_IS_ANCHOR(picture))
+        return (find_view_id(view_id, view->anchor_ref_l0,
+                    view->num_anchor_refs_l0) ||
+                find_view_id(view_id, view->anchor_ref_l1,
+                    view->num_anchor_refs_l1));
+
+    return (find_view_id(view_id, view->non_anchor_ref_l0,
+                view->num_non_anchor_refs_l0) ||
+            find_view_id(view_id, view->non_anchor_ref_l1,
+                view->num_non_anchor_refs_l1));
+}
+
 /* H.8.2.1 - Initialization process for inter-view prediction references */
 static void
 init_picture_refs_mvc_1(GstVaapiDecoderH264 *decoder,
@@ -3147,7 +3186,8 @@ fill_picture(GstVaapiDecoderH264 *decoder, GstVaapiPictureH264 *picture)
         GstVaapiFrameStore * const fs = priv->dpb[i];
         if ((gst_vaapi_frame_store_has_reference(fs) &&
              fs->view_id == picture->base.view_id) ||
-            gst_vaapi_frame_store_has_inter_view(fs))
+            (gst_vaapi_frame_store_has_inter_view(fs) &&
+             is_inter_view_reference_for_picture(decoder, fs->view_id, picture)))
             vaapi_fill_picture(&pic_param->ReferenceFrames[n++],
                 fs->buffers[0], fs->structure);
         if (n >= G_N_ELEMENTS(pic_param->ReferenceFrames))