+/* Finds the inter-view reference picture with the supplied view id */
+static GstVaapiPictureH264 *
+find_inter_view_reference(GstVaapiDecoderH264 *decoder, guint16 view_id)
+{
+ GPtrArray * const inter_views = decoder->priv.inter_views;
+ guint i;
+
+ for (i = 0; i < inter_views->len; i++) {
+ GstVaapiPictureH264 * const picture = g_ptr_array_index(inter_views, i);
+ if (picture->base.view_id == view_id)
+ return picture;
+ }
+
+ GST_WARNING("failed to find inter-view reference picture for view_id: %d",
+ 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;
+}
+
+static gboolean
+find_view_id_in_view(guint16 view_id, const GstH264SPSExtMVCView *view,
+ gboolean is_anchor)
+{
+ if (is_anchor)
+ 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));
+}
+
+/* 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);
+ gboolean is_anchor;
+
+ if (!GST_VAAPI_PICTURE_IS_MVC(picture) ||
+ sps->extension_type != GST_H264_NAL_EXTENSION_MVC)
+ return FALSE;
+
+ is_anchor = GST_VAAPI_PICTURE_IS_ANCHOR(picture);
+ return find_view_id_in_view(view_id,
+ &sps->extension.mvc.view[picture->base.voc], is_anchor);
+}
+
+/* Checks whether the supplied inter-view reference picture is used
+ for decoding the next view component pictures */
+static gboolean
+is_inter_view_reference_for_next_pictures(GstVaapiDecoderH264 *decoder,
+ GstVaapiPictureH264 *picture)
+{
+ const GstH264SPS * const sps = get_sps(decoder);
+ gboolean is_anchor;
+ guint i, num_views;
+
+ if (!GST_VAAPI_PICTURE_IS_MVC(picture) ||
+ sps->extension_type != GST_H264_NAL_EXTENSION_MVC)
+ return FALSE;
+
+ is_anchor = GST_VAAPI_PICTURE_IS_ANCHOR(picture);
+ num_views = sps->extension.mvc.num_views_minus1 + 1;
+ for (i = picture->base.voc + 1; i < num_views; i++) {
+ const GstH264SPSExtMVCView * const view = &sps->extension.mvc.view[i];
+ if (find_view_id_in_view(picture->base.view_id, view, is_anchor))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* H.8.2.1 - Initialization process for inter-view prediction references */
+static void
+init_picture_refs_mvc_1(GstVaapiDecoderH264 *decoder,
+ GstVaapiPictureH264 **ref_list, guint *ref_list_count_ptr, guint num_refs,
+ const guint16 *view_ids, guint num_view_ids)
+{
+ guint j, n;
+
+ n = *ref_list_count_ptr;
+ for (j = 0; j < num_view_ids && n < num_refs; j++) {
+ GstVaapiPictureH264 * const pic =
+ find_inter_view_reference(decoder, view_ids[j]);
+ if (pic)
+ ref_list[n++] = pic;
+ }
+ *ref_list_count_ptr = n;
+}
+
+static inline void
+init_picture_refs_mvc(GstVaapiDecoderH264 *decoder,
+ GstVaapiPictureH264 *picture, GstH264SliceHdr *slice_hdr, guint list)
+{
+ GstVaapiDecoderH264Private * const priv = &decoder->priv;
+ const GstH264SPS * const sps = get_sps(decoder);
+ const GstH264SPSExtMVCView *view;
+
+ GST_DEBUG("initialize reference picture list for inter-view prediction");
+
+ if (sps->extension_type != GST_H264_NAL_EXTENSION_MVC)
+ return;
+ view = &sps->extension.mvc.view[picture->base.voc];
+
+#define INVOKE_INIT_PICTURE_REFS_MVC(ref_list, view_list) do { \
+ init_picture_refs_mvc_1(decoder, \
+ priv->RefPicList##ref_list, \
+ &priv->RefPicList##ref_list##_count, \
+ slice_hdr->num_ref_idx_l##ref_list##_active_minus1 + 1, \
+ view->view_list##_l##ref_list, \
+ view->num_##view_list##s_l##ref_list); \
+ } while (0)
+
+ if (list == 0) {
+ if (GST_VAAPI_PICTURE_IS_ANCHOR(picture))
+ INVOKE_INIT_PICTURE_REFS_MVC(0, anchor_ref);
+ else
+ INVOKE_INIT_PICTURE_REFS_MVC(0, non_anchor_ref);
+ }
+ else {
+ if (GST_VAAPI_PICTURE_IS_ANCHOR(picture))
+ INVOKE_INIT_PICTURE_REFS_MVC(1, anchor_ref);
+ else
+ INVOKE_INIT_PICTURE_REFS_MVC(1, non_anchor_ref);
+ }
+
+#undef INVOKE_INIT_PICTURE_REFS_MVC
+}
+