Fix caps negotiation in _getcaps and _link functions. Should be completely symmetric...
authorDavid Schleef <ds@schleef.org>
Tue, 11 Nov 2003 05:35:31 +0000 (05:35 +0000)
committerDavid Schleef <ds@schleef.org>
Tue, 11 Nov 2003 05:35:31 +0000 (05:35 +0000)
Original commit message from CVS:
Fix caps negotiation in _getcaps and _link functions.  Should be
completely symmetric now.

gst/videoscale/gstvideoscale.c
gst/videoscale/videoscale.c

index 9cdc3d4..6584e5c 100644 (file)
@@ -139,7 +139,7 @@ gst_videoscale_sink_template_factory(void)
     caps2 = caps;
     caps = gst_caps_append(caps1, caps2);
 
-    templ = GST_PAD_TEMPLATE_NEW("src", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
+    templ = GST_PAD_TEMPLATE_NEW("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
   }
   return templ;
 }
@@ -213,167 +213,167 @@ static GstCaps *
 gst_videoscale_getcaps (GstPad *pad, GstCaps *caps)
 {
   GstVideoscale *videoscale;
-  GstCaps *capslist = NULL;
+  //GstCaps *capslist = NULL;
   GstCaps *peercaps;
-  GstCaps *sizecaps1, *sizecaps2;
-  int i;
+  //GstCaps *sizecaps1, *sizecaps2;
+  //GstCaps *sizecaps;
+  GstCaps *handled_caps;
+  GstCaps *icaps;
+  GstPad *otherpad;
 
-  GST_DEBUG ("gst_videoscale_src_link");
+  GST_DEBUG ("gst_videoscale_getcaps");
   videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
   
   /* get list of peer's caps */
   if(pad == videoscale->srcpad){
-    peercaps = gst_pad_get_allowed_caps (videoscale->sinkpad);
+    GST_DEBUG("getting caps of srcpad");
+    otherpad = videoscale->sinkpad;
   }else{
-    peercaps = gst_pad_get_allowed_caps (videoscale->srcpad);
+    GST_DEBUG("getting caps of sinkpad");
+    otherpad = videoscale->srcpad;
   }
-
-  /* FIXME videoscale doesn't allow passthru of video formats it
-   * doesn't understand. */
-  /* Look through our list of caps and find those that match with
-   * the peer's formats.  Create a list of them. */
-  for(i=0;i<videoscale_n_formats;i++){
-    GstCaps *fromcaps = videoscale_get_caps(videoscale_formats + i);
-    if(gst_caps_is_always_compatible(fromcaps, peercaps)){
-      capslist = gst_caps_append(capslist, fromcaps);
-    }
-    gst_caps_unref (fromcaps);
+  if (!GST_PAD_IS_LINKED (otherpad)){
+    GST_DEBUG ("otherpad not linked");
+    return GST_PAD_LINK_DELAYED;
   }
-  gst_caps_unref (peercaps);
+  peercaps = gst_pad_get_allowed_caps (GST_PAD_PEER(otherpad));
+
+  GST_DEBUG("othercaps are %s", gst_caps_to_string(peercaps));
 
-  sizecaps1 = GST_CAPS_NEW("src","video/x-raw-yuv",
+  {
+    GstCaps *caps1 = GST_CAPS_NEW("src","video/x-raw-yuv",
                "width", GST_PROPS_INT_RANGE (0, G_MAXINT),
                "height", GST_PROPS_INT_RANGE (0, G_MAXINT),
                 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT));
-  sizecaps2 = GST_CAPS_NEW("src","video/x-raw-rgb",
+    GstCaps *caps2 = GST_CAPS_NEW("src","video/x-raw-rgb",
                "width", GST_PROPS_INT_RANGE (0, G_MAXINT),
                "height", GST_PROPS_INT_RANGE (0, G_MAXINT),
                 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT));
 
-  caps = gst_caps_intersect(sizecaps1, gst_videoscale_get_capslist ());
-  gst_caps_unref (sizecaps1);
-  sizecaps1 = caps;
-  caps = gst_caps_intersect(sizecaps2, gst_videoscale_get_capslist ());
-  gst_caps_unref (sizecaps2);
-  sizecaps2 = caps;
-  caps = gst_caps_append(sizecaps1, sizecaps2);
+    caps = gst_caps_intersect(caps1, gst_videoscale_get_capslist ());
+    gst_caps_unref (caps1);
+    caps1 = caps;
+    caps = gst_caps_intersect(caps2, gst_videoscale_get_capslist ());
+    gst_caps_unref (caps2);
+    caps2 = caps;
+    handled_caps = gst_caps_append(caps1, caps2);
+  }
+
+  icaps = gst_caps_intersect (handled_caps, gst_caps_copy(peercaps));
 
-  return caps;
+  GST_DEBUG("returning caps %s", gst_caps_to_string (icaps));
+
+  return icaps;
 }
 
 
 static GstPadLinkReturn
-gst_videoscale_src_link (GstPad *pad, GstCaps *caps)
+gst_videoscale_link (GstPad *pad, GstCaps *caps)
 {
   GstVideoscale *videoscale;
   GstPadLinkReturn ret;
-  GstCaps *peercaps;
+  GstCaps *othercaps;
+  GstPad *otherpad;
+  GstCaps *icaps;
 
-  GST_DEBUG ("gst_videoscale_src_link");
+  GST_DEBUG ("gst_videoscale_link");
   videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
 
   if (!GST_CAPS_IS_FIXED (caps)) {
     return GST_PAD_LINK_DELAYED;
   }
 
-  gst_caps_debug(caps,"ack");
-
-  videoscale->format = videoscale_find_by_caps (caps);
-  g_return_val_if_fail(videoscale->format, GST_PAD_LINK_REFUSED);
-
-  gst_caps_get_int (caps, "width", &videoscale->to_width);
-  gst_caps_get_int (caps, "height", &videoscale->to_height);
-
-  GST_DEBUG ("width %d height %d",videoscale->to_width,videoscale->to_height);
-
-  peercaps = gst_caps_copy(caps);
+  if (pad == videoscale->srcpad) {
+    otherpad = videoscale->sinkpad;
+  } else {
+    otherpad = videoscale->srcpad;
+  }
+  if (otherpad == NULL) {
+    return GST_PAD_LINK_DELAYED;
+  }
 
-  gst_caps_set(peercaps, "width", GST_PROPS_INT_RANGE (0, G_MAXINT));
-  gst_caps_set(peercaps, "height", GST_PROPS_INT_RANGE (0, G_MAXINT));
+  othercaps = GST_PAD_CAPS (otherpad);
 
-  g_print("setting caps to %s\n", gst_caps_to_string(peercaps));
+  if (othercaps) {
+    GstCaps *othercaps_wh;
 
-  ret = gst_pad_try_set_caps (videoscale->srcpad, peercaps);
+    GST_DEBUG ("otherpad caps are already set");
+    GST_DEBUG ("otherpad caps are %s", gst_caps_to_string(othercaps));
 
-  gst_caps_unref(peercaps);
+    othercaps_wh = gst_caps_copy (othercaps);
+    gst_caps_set(othercaps_wh, "width", GST_PROPS_INT_RANGE (1, G_MAXINT),
+        "height", GST_PROPS_INT_RANGE (1, G_MAXINT), NULL);
 
-  if(ret==GST_PAD_LINK_OK){
-    caps = gst_pad_get_caps (videoscale->srcpad);
+#if 1
+    icaps = othercaps;
+#else
+    /* FIXME this is disabled because videotestsrc ! videoscale ! ximagesink
+     * doesn't negotiate caps correctly the first time, so we pretend it's
+     * still ok here. */
+    icaps = gst_caps_intersect (othercaps_wh, caps);
 
-    gst_caps_get_int (caps, "width", &videoscale->from_width);
-    gst_caps_get_int (caps, "height", &videoscale->from_height);
-    gst_videoscale_setup(videoscale);
-  }
+    GST_DEBUG ("intersected caps are %s", gst_caps_to_string(icaps));
 
-  return ret;
-}
+    if (icaps == NULL) {
+      /* the new caps are not compatible with the existing, set caps */
+      /* currently, we don't force renegotiation */
+      return GST_PAD_LINK_REFUSED;
+    }
+#endif
 
-static GstPadLinkReturn
-gst_videoscale_sink_link (GstPad *pad, GstCaps *caps)
-{
-  GstVideoscale *videoscale;
-  GstPadLinkReturn ret;
-  GstCaps *peercaps;
-  GstCaps *srccaps;
-  GstCaps *caps1;
+    if (!GST_CAPS_IS_FIXED (icaps)) {
+      return GST_PAD_LINK_REFUSED;
+    }
 
-  GST_DEBUG ("gst_videoscale_sink_link");
-  videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
+    /* ok, we have a candidate caps */
+  } else {
+    GstCaps *othercaps_wh;
 
-  if (!GST_CAPS_IS_FIXED (caps)) {
-    return GST_PAD_LINK_DELAYED;
-  }
+    GST_DEBUG ("otherpad caps are unset");
 
-  videoscale->format = videoscale_find_by_caps (caps);
-  g_return_val_if_fail(videoscale->format, GST_PAD_LINK_REFUSED);
+    othercaps = gst_pad_get_allowed_caps (pad);
 
-  ret = gst_pad_try_set_caps (videoscale->srcpad, gst_caps_copy(caps));
-  if (ret == GST_PAD_LINK_OK || ret == GST_PAD_LINK_DONE) {
-    videoscale->passthru = TRUE;
-    videoscale->inited = TRUE;
-    return ret;
-  }
+    othercaps_wh = gst_caps_copy (othercaps);
+    gst_caps_set(othercaps_wh, "width", GST_PROPS_INT_RANGE (1, G_MAXINT),
+        "height", GST_PROPS_INT_RANGE (1, G_MAXINT), NULL);
 
-  videoscale->passthru = FALSE;
+    icaps = gst_caps_intersect (othercaps_wh, caps);
 
-  srccaps = gst_caps_copy(caps);
-  gst_caps_set(srccaps, "width", GST_PROPS_INT_RANGE (0, G_MAXINT));
-  gst_caps_set(srccaps, "height", GST_PROPS_INT_RANGE (0, G_MAXINT));
+    GST_DEBUG ("intersected caps are %s", gst_caps_to_string(icaps));
 
-  peercaps = gst_pad_get_allowed_caps(videoscale->srcpad);
+    if (icaps == NULL) {
+      /* the new caps are not compatible with the existing, set caps */
+      /* currently, we don't force renegotiation */
+      return GST_PAD_LINK_REFUSED;
+    }
 
-  caps1 = gst_caps_intersect(peercaps, srccaps);
-  if (!caps1) {
-    /* apparently, the sink element doesn't like the input of the
-     * source element. The user should add a colorspace converter
-     * or so. */
-    return GST_PAD_LINK_REFUSED;
-  }
+    if (!GST_CAPS_IS_FIXED (icaps)) {
+      return GST_PAD_LINK_REFUSED;
+    }
 
-  if (!GST_CAPS_IS_FIXED (caps1)) {
-    /* FIXME */
-    return GST_PAD_LINK_DELAYED;
+    /* ok, we have a candidate caps */
+    ret = gst_pad_try_set_caps (otherpad, gst_caps_copy(icaps));
+    if (ret == GST_PAD_LINK_DELAYED || ret == GST_PAD_LINK_REFUSED) {
+      return ret;
+    }
   }
 
-  g_print("setting caps to %s\n", gst_caps_to_string(caps1));
-
-  ret = gst_pad_try_set_caps (videoscale->srcpad, caps1);
-  if (ret != GST_PAD_LINK_OK && ret != GST_PAD_LINK_DONE) {
-    return ret;
+  if (pad == videoscale->srcpad) {
+    gst_caps_get_int (icaps, "width", &videoscale->from_width);
+    gst_caps_get_int (icaps, "height", &videoscale->from_height);
+    gst_caps_get_int (caps, "width", &videoscale->to_width);
+    gst_caps_get_int (caps, "height", &videoscale->to_height);
+  } else {
+    gst_caps_get_int (icaps, "width", &videoscale->to_width);
+    gst_caps_get_int (icaps, "height", &videoscale->to_height);
+    gst_caps_get_int (caps, "width", &videoscale->from_width);
+    gst_caps_get_int (caps, "height", &videoscale->from_height);
   }
 
-  gst_caps_get_int (caps1, "width", &videoscale->to_width);
-  gst_caps_get_int (caps1, "height", &videoscale->to_height);
-
-  gst_caps_get_int (caps, "width", &videoscale->from_width);
-  gst_caps_get_int (caps, "height", &videoscale->from_height);
-  gst_caps_get_float (caps, "framerate", &videoscale->framerate);
-
-  caps = gst_pad_get_caps (videoscale->srcpad);
-
+  videoscale->format = videoscale_find_by_caps (caps);
   gst_videoscale_setup(videoscale);
 
-  return ret;
+  return GST_PAD_LINK_OK;
 }
 
 static void
@@ -385,14 +385,14 @@ gst_videoscale_init (GstVideoscale *videoscale)
                  "sink");
   gst_element_add_pad(GST_ELEMENT(videoscale),videoscale->sinkpad);
   gst_pad_set_chain_function(videoscale->sinkpad,gst_videoscale_chain);
-  gst_pad_set_link_function(videoscale->sinkpad,gst_videoscale_sink_link);
+  gst_pad_set_link_function(videoscale->sinkpad,gst_videoscale_link);
   gst_pad_set_getcaps_function(videoscale->sinkpad,gst_videoscale_getcaps);
 
   videoscale->srcpad = gst_pad_new_from_template (
                  GST_PAD_TEMPLATE_GET (gst_videoscale_src_template_factory),
                  "src");
   gst_element_add_pad(GST_ELEMENT(videoscale),videoscale->srcpad);
-  gst_pad_set_link_function(videoscale->srcpad,gst_videoscale_src_link);
+  gst_pad_set_link_function(videoscale->srcpad,gst_videoscale_link);
   gst_pad_set_getcaps_function(videoscale->srcpad,gst_videoscale_getcaps);
 
   videoscale->inited = FALSE;
index 82103f3..2457fa6 100644 (file)
@@ -146,6 +146,9 @@ videoscale_find_by_caps(GstCaps *caps)
 void
 gst_videoscale_setup (GstVideoscale *videoscale)
 {
+  g_return_if_fail (GST_IS_VIDEOSCALE (videoscale));
+  g_return_if_fail (videoscale->format != NULL);
+
   GST_DEBUG ("format=%p \"%s\" from %dx%d to %dx%d",
                videoscale->format, videoscale->format->fourcc,
                videoscale->from_width, videoscale->from_height,
@@ -171,6 +174,7 @@ gst_videoscale_setup (GstVideoscale *videoscale)
   videoscale->to_buf_size = (videoscale->to_width * videoscale->to_height
                  * videoscale->format->depth) / 8;
 
+  videoscale->passthru = FALSE;
   videoscale->inited = TRUE;
 }