Revert "dvdspu: improve negotiation of overlay composition"
authorJan Schmidt <jan@centricular.com>
Sat, 26 Sep 2015 14:24:15 +0000 (00:24 +1000)
committerJan Schmidt <jan@centricular.com>
Sat, 26 Sep 2015 14:24:15 +0000 (00:24 +1000)
This reverts commit 1899e2a099932a7a734e7784c20b624517237e18.

gst/dvdspu/gstdvdspu.c
gst/dvdspu/gstdvdspu.h

index 50edc92..cf0a63b 100644 (file)
@@ -58,23 +58,17 @@ enum
 
 #define VIDEO_FORMATS GST_VIDEO_OVERLAY_COMPOSITION_BLEND_FORMATS
 
-#define DVDSPU_CAPS GST_VIDEO_CAPS_MAKE (VIDEO_FORMATS)
-#define DVDSPU_ALL_CAPS DVDSPU_CAPS ";" \
-    GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("ANY", GST_VIDEO_FORMATS_ALL)
-
-static GstStaticCaps sw_template_caps = GST_STATIC_CAPS (DVDSPU_CAPS);
-
 static GstStaticPadTemplate video_sink_factory =
 GST_STATIC_PAD_TEMPLATE ("video",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (DVDSPU_ALL_CAPS)
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (VIDEO_FORMATS))
     );
 
 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (DVDSPU_ALL_CAPS)
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (VIDEO_FORMATS))
     );
 
 static GstStaticPadTemplate subpic_sink_factory =
@@ -96,10 +90,8 @@ static gboolean gst_dvd_spu_src_event (GstPad * pad, GstObject * parent,
     GstEvent * event);
 static gboolean gst_dvd_spu_src_query (GstPad * pad, GstObject * parent,
     GstQuery * query);
-static GstCaps *gst_dvd_spu_src_get_caps (GstDVDSpu * dvdspu, GstPad * pad,
-    GstCaps * filter);
 
-static GstCaps *gst_dvd_spu_video_get_caps (GstDVDSpu * dvdspu, GstPad * pad,
+static GstCaps *gst_dvd_spu_video_proxy_getcaps (GstPad * pad,
     GstCaps * filter);
 static gboolean gst_dvd_spu_video_set_caps (GstDVDSpu * dvdspu, GstPad * pad,
     GstCaps * caps);
@@ -118,7 +110,7 @@ static gboolean gst_dvd_spu_subpic_event (GstPad * pad, GstObject * parent,
     GstEvent * event);
 static gboolean gst_dvd_spu_subpic_set_caps (GstDVDSpu * dvdspu, GstPad * pad,
     GstCaps * caps);
-static gboolean gst_dvd_spu_negotiate (GstDVDSpu * dvdspu, GstCaps * caps);
+static gboolean gst_dvd_spu_negotiate (GstDVDSpu * dvdspu);
 
 static void gst_dvd_spu_clear (GstDVDSpu * dvdspu);
 static void gst_dvd_spu_flush_spu_info (GstDVDSpu * dvdspu,
@@ -310,7 +302,6 @@ gst_dvd_spu_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 static gboolean
 gst_dvd_spu_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstDVDSpu *dvdspu = GST_DVD_SPU (parent);
   gboolean res = FALSE;
 
   switch (GST_QUERY_TYPE (query)) {
@@ -319,7 +310,7 @@ gst_dvd_spu_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
       GstCaps *filter, *caps;
 
       gst_query_parse_caps (query, &filter);
-      caps = gst_dvd_spu_src_get_caps (dvdspu, pad, filter);
+      caps = gst_dvd_spu_video_proxy_getcaps (pad, filter);
       gst_query_set_caps_result (query, caps);
       gst_caps_unref (caps);
       res = TRUE;
@@ -334,238 +325,53 @@ gst_dvd_spu_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 }
 
 static gboolean
-gst_dvd_spu_can_handle_caps (GstCaps * caps)
-{
-  GstCaps *sw_caps;
-  gboolean ret;
-
-  sw_caps = gst_static_caps_get (&sw_template_caps);
-  ret = gst_caps_is_subset (caps, sw_caps);
-  gst_caps_unref (sw_caps);
-
-  return ret;
-}
-
-static gboolean
 gst_dvd_spu_video_set_caps (GstDVDSpu * dvdspu, GstPad * pad, GstCaps * caps)
 {
+  gboolean res = FALSE;
   GstVideoInfo info;
-  gboolean ret = FALSE;
+  SpuState *state;
 
   if (!gst_video_info_from_caps (&info, caps))
-    goto invalid_caps;
-
-  dvdspu->spu_state.info = info;
-
-  ret = gst_dvd_spu_negotiate (dvdspu, caps);
-
-  DVD_SPU_LOCK (dvdspu);
-  if (!dvdspu->attach_compo_to_buffer && !gst_dvd_spu_can_handle_caps (caps)) {
-    GST_DEBUG_OBJECT (dvdspu, "unsupported caps %" GST_PTR_FORMAT, caps);
-    ret = FALSE;
-  }
-
-  DVD_SPU_UNLOCK (dvdspu);
-
-  return ret;
-
-  /* ERRORS */
-invalid_caps:
-  {
-    GST_DEBUG_OBJECT (dvdspu, "could not parse caps");
-    return FALSE;
-  }
-}
-
-
-/**
- * gst_dvd_spu_add_feature_and_intersect:
- *
- * Creates a new #GstCaps containing the (given caps +
- * given caps feature) + (given caps intersected by the
- * given filter).
- *
- * Returns: the new #GstCaps
- */
-static GstCaps *
-gst_dvd_spu_add_feature_and_intersect (GstCaps * caps,
-    const gchar * feature, GstCaps * filter)
-{
-  int i, caps_size;
-  GstCaps *new_caps;
-
-  new_caps = gst_caps_copy (caps);
-
-  caps_size = gst_caps_get_size (new_caps);
-  for (i = 0; i < caps_size; i++) {
-    GstCapsFeatures *features = gst_caps_get_features (new_caps, i);
-    if (!gst_caps_features_is_any (features)) {
-      gst_caps_features_add (features, feature);
-    }
-  }
-
-  gst_caps_append (new_caps, gst_caps_intersect_full (caps,
-          filter, GST_CAPS_INTERSECT_FIRST));
-
-  return new_caps;
-}
-
-/**
- * gst_dvd_spu_intersect_by_feature:
- *
- * Creates a new #GstCaps based on the following filtering rule.
- *
- * For each individual caps contained in given caps, if the
- * caps uses the given caps feature, keep a version of the caps
- * with the feature and an another one without. Otherwise, intersect
- * the caps with the given filter.
- *
- * Returns: the new #GstCaps
- */
-static GstCaps *
-gst_dvd_spu_intersect_by_feature (GstCaps * caps,
-    const gchar * feature, GstCaps * filter)
-{
-  int i, caps_size;
-  GstCaps *new_caps;
-
-  new_caps = gst_caps_new_empty ();
-
-  caps_size = gst_caps_get_size (caps);
-  for (i = 0; i < caps_size; i++) {
-    GstStructure *caps_structure = gst_caps_get_structure (caps, i);
-    GstCapsFeatures *caps_features =
-        gst_caps_features_copy (gst_caps_get_features (caps, i));
-    GstCaps *filtered_caps;
-    GstCaps *simple_caps =
-        gst_caps_new_full (gst_structure_copy (caps_structure), NULL);
-    gst_caps_set_features (simple_caps, 0, caps_features);
-
-    if (gst_caps_features_contains (caps_features, feature)) {
-      gst_caps_append (new_caps, gst_caps_copy (simple_caps));
-
-      gst_caps_features_remove (caps_features, feature);
-      filtered_caps = gst_caps_ref (simple_caps);
-    } else {
-      filtered_caps = gst_caps_intersect_full (simple_caps, filter,
-          GST_CAPS_INTERSECT_FIRST);
-    }
+    goto done;
 
-    gst_caps_unref (simple_caps);
-    gst_caps_append (new_caps, filtered_caps);
+  res = gst_pad_set_caps (dvdspu->srcpad, caps);
+  if (res) {
+    DVD_SPU_LOCK (dvdspu);
+    state = &dvdspu->spu_state;
+    state->info = info;
+    gst_dvd_spu_negotiate (dvdspu);
+    DVD_SPU_UNLOCK (dvdspu);
   }
 
-  return new_caps;
+done:
+  return res;
 }
 
 static GstCaps *
-gst_dvd_spu_video_get_caps (GstDVDSpu * dvdspu, GstPad * pad, GstCaps * filter)
+gst_dvd_spu_video_proxy_getcaps (GstPad * pad, GstCaps * filter)
 {
-  GstPad *srcpad = dvdspu->srcpad;
-  GstCaps *peer_caps = NULL, *caps = NULL, *dvdspu_filter = NULL;
-
-  if (filter) {
-    /* filter caps + composition feature + filter caps
-     * filtered by the software caps. */
-    GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps);
-    dvdspu_filter = gst_dvd_spu_add_feature_and_intersect (filter,
-        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
-    gst_caps_unref (sw_caps);
-
-    GST_DEBUG_OBJECT (dvdspu, "dvdspu filter %" GST_PTR_FORMAT, dvdspu_filter);
-  }
-
-  peer_caps = gst_pad_peer_query_caps (srcpad, dvdspu_filter);
+  GstDVDSpu *dvdspu = GST_DVD_SPU (gst_pad_get_parent (pad));
+  GstCaps *caps;
+  GstPad *otherpad;
 
-  if (dvdspu_filter)
-    gst_caps_unref (dvdspu_filter);
+  /* Proxy the getcaps between videosink and the srcpad, ignoring the 
+   * subpicture sink pad */
+  otherpad = (pad == dvdspu->srcpad) ? dvdspu->videosinkpad : dvdspu->srcpad;
 
-  if (peer_caps) {
-    GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, peer_caps);
+  caps = gst_pad_peer_query_caps (otherpad, filter);
+  if (caps) {
+    GstCaps *temp, *templ;
 
-    if (gst_caps_is_any (peer_caps)) {
-      /* if peer returns ANY caps, return filtered src pad template caps */
-      caps = gst_caps_copy (gst_pad_get_pad_template_caps (srcpad));
-    } else {
-      /* duplicate caps which contains the composition into one version with
-       * the meta and one without. Filter the other caps by the software caps */
-      GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps);
-      caps = gst_dvd_spu_intersect_by_feature (peer_caps,
-          GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
-      gst_caps_unref (sw_caps);
-    }
-
-    gst_caps_unref (peer_caps);
-
-  } else {
-    /* no peer, our padtemplate is enough then */
-    caps = gst_pad_get_pad_template_caps (pad);
-  }
-
-  if (filter) {
-    GstCaps *intersection = gst_caps_intersect_full (filter, caps,
-        GST_CAPS_INTERSECT_FIRST);
+    templ = gst_pad_get_pad_template_caps (otherpad);
+    temp = gst_caps_intersect (caps, templ);
+    gst_caps_unref (templ);
     gst_caps_unref (caps);
-    caps = intersection;
-  }
-
-  GST_DEBUG_OBJECT (dvdspu, "returning %" GST_PTR_FORMAT, caps);
-
-  return caps;
-}
-
-static GstCaps *
-gst_dvd_spu_src_get_caps (GstDVDSpu * dvdspu, GstPad * pad, GstCaps * filter)
-{
-  GstPad *sinkpad = dvdspu->videosinkpad;
-  GstCaps *peer_caps = NULL, *caps = NULL, *dvdspu_filter = NULL;
-
-  if (filter) {
-    /* duplicate filter caps which contains the composition into one version
-     * with the meta and one without. Filter the other caps by the software
-     * caps */
-    GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps);
-    dvdspu_filter = gst_dvd_spu_intersect_by_feature (filter,
-        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
-    gst_caps_unref (sw_caps);
-  }
-
-  peer_caps = gst_pad_peer_query_caps (sinkpad, dvdspu_filter);
-
-  if (dvdspu_filter)
-    gst_caps_unref (dvdspu_filter);
-
-  if (peer_caps) {
-    GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, peer_caps);
-
-    if (gst_caps_is_any (peer_caps)) {
-      /* if peer returns ANY caps, return filtered sink pad template caps */
-      caps = gst_caps_copy (gst_pad_get_pad_template_caps (sinkpad));
-    } else {
-      /* return upstream caps + composition feature + upstream caps
-       * filtered by the software caps. */
-      GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps);
-      caps = gst_dvd_spu_add_feature_and_intersect (peer_caps,
-          GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps);
-      gst_caps_unref (sw_caps);
-    }
-
-    gst_caps_unref (peer_caps);
-
+    caps = temp;
   } else {
-    /* no peer, our padtemplate is enough then */
     caps = gst_pad_get_pad_template_caps (pad);
   }
 
-  if (filter) {
-    GstCaps *intersection = gst_caps_intersect_full (filter, caps,
-        GST_CAPS_INTERSECT_FIRST);
-    gst_caps_unref (caps);
-    caps = intersection;
-  }
-
-  GST_DEBUG_OBJECT (dvdspu, "returning %" GST_PTR_FORMAT, caps);
-
+  gst_object_unref (dvdspu);
   return caps;
 }
 
@@ -694,16 +500,12 @@ gst_dvd_spu_video_event (GstPad * pad, GstObject * parent, GstEvent * event)
       break;
     }
     case GST_EVENT_FLUSH_START:
-      DVD_SPU_LOCK (dvdspu);
-      dvdspu->video_flushing = TRUE;
-      DVD_SPU_UNLOCK (dvdspu);
       res = gst_pad_event_default (pad, parent, event);
       goto done;
     case GST_EVENT_FLUSH_STOP:
       res = gst_pad_event_default (pad, parent, event);
 
       DVD_SPU_LOCK (dvdspu);
-      dvdspu->video_flushing = FALSE;
       gst_segment_init (&dvdspu->video_seg, GST_FORMAT_UNDEFINED);
       gst_buffer_replace (&dvdspu->ref_frame, NULL);
       gst_buffer_replace (&dvdspu->pending_frame, NULL);
@@ -727,7 +529,6 @@ error:
 static gboolean
 gst_dvd_spu_video_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstDVDSpu *dvdspu = GST_DVD_SPU (parent);
   gboolean res = FALSE;
 
   switch (GST_QUERY_TYPE (query)) {
@@ -736,7 +537,7 @@ gst_dvd_spu_video_query (GstPad * pad, GstObject * parent, GstQuery * query)
       GstCaps *filter, *caps;
 
       gst_query_parse_caps (query, &filter);
-      caps = gst_dvd_spu_video_get_caps (dvdspu, pad, filter);
+      caps = gst_dvd_spu_video_proxy_getcaps (pad, filter);
       gst_query_set_caps_result (query, caps);
       gst_caps_unref (caps);
       res = TRUE;
@@ -759,7 +560,7 @@ gst_dvd_spu_video_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
   g_return_val_if_fail (dvdspu != NULL, GST_FLOW_ERROR);
 
   if (gst_pad_check_reconfigure (dvdspu->srcpad))
-    gst_dvd_spu_negotiate (dvdspu, NULL);
+    gst_dvd_spu_negotiate (dvdspu);
 
   GST_LOG_OBJECT (dvdspu, "video buffer %p with TS %" GST_TIME_FORMAT,
       buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
@@ -1261,134 +1062,40 @@ submit_new_spu_packet (GstDVDSpu * dvdspu, GstBuffer * buf)
 }
 
 static gboolean
-gst_dvd_spu_negotiate (GstDVDSpu * dvdspu, GstCaps * caps)
+gst_dvd_spu_negotiate (GstDVDSpu * dvdspu)
 {
-  gboolean upstream_has_meta = FALSE;
-  gboolean caps_has_meta = FALSE;
-  gboolean alloc_has_meta = FALSE;
-  gboolean attach = FALSE;
-  gboolean ret = TRUE;
-  GstCapsFeatures *f;
-  GstCaps *overlay_caps;
   GstQuery *query;
+  GstCaps *caps;
+  gboolean attach = FALSE;
 
-  GST_DEBUG_OBJECT (dvdspu, "performing negotiation");
-
-  /* Clear the cached composition */
   gst_dvd_spu_reset_composition (dvdspu);
 
-  /* Clear any pending reconfigure to avoid negotiating twice */
-  gst_pad_check_reconfigure (dvdspu->srcpad);
-
-  if (!caps)
-    caps = gst_pad_get_current_caps (dvdspu->videosinkpad);
-  else
-    gst_caps_ref (caps);
+  GST_DEBUG_OBJECT (dvdspu, "performing negotiation");
 
+  caps = gst_pad_get_current_caps (dvdspu->srcpad);
   if (!caps || gst_caps_is_empty (caps))
     goto no_format;
 
-  /* Check if upstream caps have meta */
-  if ((f = gst_caps_get_features (caps, 0))) {
-    upstream_has_meta = gst_caps_features_contains (f,
-        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
-  }
-
-  if (upstream_has_meta) {
-    overlay_caps = gst_caps_ref (caps);
-  } else {
-    GstCaps *peercaps;
-
-    /* BaseTransform requires caps for the allocation query to work */
-    overlay_caps = gst_caps_copy (caps);
-    f = gst_caps_get_features (overlay_caps, 0);
-    gst_caps_features_add (f,
-        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
-
-    /* Then check if downstream accept dvdspu composition in caps */
-    /* FIXME: We should probably check if downstream *prefers* the
-     * dvdspu meta, and only enforce usage of it if we can't handle
-     * the format ourselves and thus would have to drop the overlays.
-     * Otherwise we should prefer what downstream wants here.
-     */
-    peercaps = gst_pad_peer_query_caps (dvdspu->srcpad, NULL);
-    caps_has_meta = gst_caps_can_intersect (peercaps, overlay_caps);
-    gst_caps_unref (peercaps);
-
-    GST_DEBUG ("caps have dvdspu meta %d", caps_has_meta);
-  }
-
-  if (upstream_has_meta || caps_has_meta) {
-    /* Send caps immediatly, it's needed by GstBaseTransform to get a reply
-     * from allocation query */
-    ret = gst_pad_set_caps (dvdspu->srcpad, overlay_caps);
-
-    /* First check if the allocation meta has compositon */
-    query = gst_query_new_allocation (overlay_caps, FALSE);
+  query = gst_query_new_allocation (caps, FALSE);
 
-    if (!gst_pad_peer_query (dvdspu->srcpad, query)) {
-      /* no problem, we use the query defaults */
-      GST_DEBUG_OBJECT (dvdspu, "ALLOCATION query failed");
+  if (!gst_pad_peer_query (dvdspu->srcpad, query))
+    GST_DEBUG_OBJECT (dvdspu, "ALLOCATION query failed");
 
-      /* In case we were flushing, mark reconfigure and fail this method,
-       * will make it retry */
-      if (dvdspu->video_flushing)
-        ret = FALSE;
-    }
-
-    alloc_has_meta = gst_query_find_allocation_meta (query,
-        GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
-
-    GST_DEBUG ("sink alloc has dvdspu meta %d", alloc_has_meta);
-
-    gst_query_unref (query);
-  }
-
-  /* For backward compatbility, we will prefer bliting if downstream
-   * allocation does not support the meta. In other case we will prefer
-   * attaching, and will fail the negotiation in the unlikely case we are
-   * force to blit, but format isn't supported. */
-
-  if (upstream_has_meta) {
+  if (gst_query_find_allocation_meta (query,
+          GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL))
     attach = TRUE;
-  } else if (caps_has_meta) {
-    if (alloc_has_meta) {
-      attach = TRUE;
-    } else {
-      /* Don't attach unless we cannot handle the format */
-      attach = !gst_dvd_spu_can_handle_caps (caps);
-    }
-  } else {
-    ret = gst_dvd_spu_can_handle_caps (caps);
-  }
 
-  /* If we attach, then pick the dvdspu caps */
-  if (attach) {
-    GST_DEBUG_OBJECT (dvdspu, "Using caps %" GST_PTR_FORMAT, overlay_caps);
-    /* Caps where already sent */
-  } else if (ret) {
-    GST_DEBUG_OBJECT (dvdspu, "Using caps %" GST_PTR_FORMAT, caps);
-    ret = gst_pad_set_caps (dvdspu->srcpad, caps);
-  }
+  gst_query_unref (query);
+  gst_caps_unref (caps);
 
   dvdspu->attach_compo_to_buffer = attach;
 
-  if (!ret) {
-    GST_DEBUG_OBJECT (dvdspu, "negotiation failed, schedule reconfigure");
-    gst_pad_mark_reconfigure (dvdspu->srcpad);
-  }
-
-  gst_caps_unref (overlay_caps);
-  gst_caps_unref (caps);
-
-  return ret;
+  return TRUE;
 
 no_format:
-  {
-    if (caps)
-      gst_caps_unref (caps);
-    return FALSE;
-  }
+  if (caps)
+    gst_caps_unref (caps);
+  return FALSE;
 }
 
 static GstFlowReturn
index 61d3e9c..6fa700c 100644 (file)
@@ -94,7 +94,6 @@ struct _GstDVDSpu {
   /* Mutex to protect state we access from different chain funcs */
   GMutex spu_lock;
 
-  gboolean video_flushing;
   GstSegment video_seg;
   GstSegment subp_seg;