Merge branch 'master' into 0.11
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 6 Jul 2011 10:05:12 +0000 (12:05 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 6 Jul 2011 10:05:12 +0000 (12:05 +0200)
1  2 
ext/jpeg/gstjpegdec.c
ext/pulse/pulsesink.c
gst/goom/gstgoom.c

diff --combined ext/jpeg/gstjpegdec.c
@@@ -1061,7 -1061,7 +1061,7 @@@ gst_jpeg_dec_update_qos (GstJpegDec * d
    GST_OBJECT_LOCK (dec);
    dec->proportion = proportion;
    if (G_LIKELY (ts != GST_CLOCK_TIME_NONE)) {
 -    if (G_UNLIKELY (diff > 0))
 +    if (G_UNLIKELY (diff > dec->qos_duration))
        dec->earliest_time = ts + 2 * diff + dec->qos_duration;
      else
        dec->earliest_time = ts + diff;
@@@ -1346,12 -1346,16 +1346,16 @@@ again
      GST_WARNING_OBJECT (dec, "reading the header failed, %d", hdr_ok);
    }
  
+   GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
+   GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
+   if (!dec->cinfo.num_components || !dec->cinfo.comp_info)
+     goto components_not_supported;
    r_h = dec->cinfo.comp_info[0].h_samp_factor;
    r_v = dec->cinfo.comp_info[0].v_samp_factor;
  
    GST_LOG_OBJECT (dec, "r_h = %d, r_v = %d", r_h, r_v);
-   GST_LOG_OBJECT (dec, "num_components=%d", dec->cinfo.num_components);
-   GST_LOG_OBJECT (dec, "jpeg_color_space=%d", dec->cinfo.jpeg_color_space);
  
    if (dec->cinfo.num_components > 3)
      goto components_not_supported;
@@@ -1624,7 -1628,8 +1628,8 @@@ drop_buffer
  components_not_supported:
    {
      gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
-         "more components than supported: %d > 3", dec->cinfo.num_components);
+         "number of components not supported: %d (max 3)",
+         dec->cinfo.num_components);
      ret = GST_FLOW_ERROR;
      goto done;
    }
diff --combined ext/pulse/pulsesink.c
@@@ -988,6 -988,7 +988,7 @@@ gst_pulseringbuffer_clear (GstRingBuffe
    pa_threaded_mainloop_unlock (mainloop);
  }
  
+ /* called from pulse with the mainloop lock */
  static void
  mainloop_enter_defer_cb (pa_mainloop_api * api, void *userdata)
  {
  
    gst_element_post_message (GST_ELEMENT (pulsesink), message);
  
-   /* signal the waiter */
-   pulsesink->pa_defer_ran = TRUE;
+   g_return_if_fail (pulsesink->defer_pending);
+   pulsesink->defer_pending--;
    pa_threaded_mainloop_signal (mainloop, 0);
  }
  
@@@ -1023,7 -1024,7 +1024,7 @@@ gst_pulseringbuffer_start (GstRingBuffe
    pa_threaded_mainloop_lock (mainloop);
  
    GST_DEBUG_OBJECT (psink, "scheduling stream status");
-   psink->pa_defer_ran = FALSE;
+   psink->defer_pending++;
    pa_mainloop_api_once (pa_threaded_mainloop_get_api (mainloop),
        mainloop_enter_defer_cb, psink);
  
  
    /* EOS needs running clock */
    if (GST_BASE_SINK_CAST (psink)->eos ||
 -      g_atomic_int_get (&GST_BASE_AUDIO_SINK (psink)->abidata.ABI.
 -          eos_rendering))
 +      g_atomic_int_get (&GST_BASE_AUDIO_SINK (psink)->eos_rendering))
      gst_pulsering_set_corked (pbuf, FALSE, FALSE);
  
    pa_threaded_mainloop_unlock (mainloop);
@@@ -1066,6 -1068,7 +1067,7 @@@ gst_pulseringbuffer_pause (GstRingBuffe
    return res;
  }
  
+ /* called from pulse with the mainloop lock */
  static void
  mainloop_leave_defer_cb (pa_mainloop_api * api, void *userdata)
  {
    gst_message_set_stream_status_object (message, &val);
    gst_element_post_message (GST_ELEMENT (pulsesink), message);
  
-   pulsesink->pa_defer_ran = TRUE;
+   g_return_if_fail (pulsesink->defer_pending);
+   pulsesink->defer_pending--;
    pa_threaded_mainloop_signal (mainloop, 0);
-   gst_object_unref (pulsesink);
  }
  
  /* stop playback, we flush everything. */
@@@ -1128,12 -1131,10 +1130,10 @@@ cleanup
    }
  
    GST_DEBUG_OBJECT (psink, "scheduling stream status");
-   psink->pa_defer_ran = FALSE;
-   gst_object_ref (psink);
+   psink->defer_pending++;
    pa_mainloop_api_once (pa_threaded_mainloop_get_api (mainloop),
        mainloop_leave_defer_cb, psink);
  
-   GST_DEBUG_OBJECT (psink, "waiting for stream status");
    pa_threaded_mainloop_unlock (mainloop);
  
    return res;
@@@ -1246,7 -1247,7 +1246,7 @@@ gst_pulseringbuffer_commit (GstRingBuff
    if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
            GST_RING_BUFFER_STATE_STARTED)) {
      /* see if we are allowed to start it */
 -    if (G_UNLIKELY (g_atomic_int_get (&buf->abidata.ABI.may_start) == FALSE))
 +    if (G_UNLIKELY (g_atomic_int_get (&buf->may_start) == FALSE))
        goto no_start;
  
      GST_DEBUG_OBJECT (buf, "start!");
@@@ -1578,74 -1579,125 +1578,74 @@@ static gboolean gst_pulsesink_event (Gs
  static GstStateChangeReturn gst_pulsesink_change_state (GstElement * element,
      GstStateChange transition);
  
 -static void gst_pulsesink_init_interfaces (GType type);
 -
  #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
  # define ENDIANNESS   "LITTLE_ENDIAN, BIG_ENDIAN"
  #else
  # define ENDIANNESS   "BIG_ENDIAN, LITTLE_ENDIAN"
  #endif
  
 +static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
 +    GST_PAD_SINK,
 +    GST_PAD_ALWAYS,
 +    GST_STATIC_CAPS ("audio/x-raw-int, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "signed = (boolean) TRUE, "
 +        "width = (int) 16, "
 +        "depth = (int) 16, "
 +        "rate = (int) [ 1, MAX ], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-raw-float, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "width = (int) 32, "
 +        "rate = (int) [ 1, MAX ], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-raw-int, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "signed = (boolean) TRUE, "
 +        "width = (int) 32, "
 +        "depth = (int) 32, "
 +        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
 +#ifdef HAVE_PULSE_0_9_15
 +        "audio/x-raw-int, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "signed = (boolean) TRUE, "
 +        "width = (int) 24, "
 +        "depth = (int) 24, "
 +        "rate = (int) [ 1, MAX ], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-raw-int, "
 +        "endianness = (int) { " ENDIANNESS " }, "
 +        "signed = (boolean) TRUE, "
 +        "width = (int) 32, "
 +        "depth = (int) 24, "
 +        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
 +#endif
 +        "audio/x-raw-int, "
 +        "signed = (boolean) FALSE, "
 +        "width = (int) 8, "
 +        "depth = (int) 8, "
 +        "rate = (int) [ 1, MAX ], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-alaw, "
 +        "rate = (int) [ 1, MAX], "
 +        "channels = (int) [ 1, 32 ];"
 +        "audio/x-mulaw, "
 +        "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ]")
 +    );
 +
  GST_IMPLEMENT_PULSEPROBE_METHODS (GstPulseSink, gst_pulsesink);
  
  #define _do_init(type) \
    gst_pulsesink_init_contexts (); \
    gst_pulsesink_init_interfaces (type);
  
 -GST_BOILERPLATE_FULL (GstPulseSink, gst_pulsesink, GstBaseAudioSink,
 -    GST_TYPE_BASE_AUDIO_SINK, _do_init);
 -
 -static gboolean
 -gst_pulsesink_interface_supported (GstImplementsInterface *
 -    iface, GType interface_type)
 -{
 -  GstPulseSink *this = GST_PULSESINK_CAST (iface);
 -
 -  if (interface_type == GST_TYPE_PROPERTY_PROBE && this->probe)
 -    return TRUE;
 -  if (interface_type == GST_TYPE_STREAM_VOLUME)
 -    return TRUE;
 -
 -  return FALSE;
 -}
 -
 -static void
 -gst_pulsesink_implements_interface_init (GstImplementsInterfaceClass * klass)
 -{
 -  klass->supported = gst_pulsesink_interface_supported;
 -}
 -
 -static void
 -gst_pulsesink_init_interfaces (GType type)
 -{
 -  static const GInterfaceInfo implements_iface_info = {
 -    (GInterfaceInitFunc) gst_pulsesink_implements_interface_init,
 -    NULL,
 -    NULL,
 -  };
 -  static const GInterfaceInfo probe_iface_info = {
 -    (GInterfaceInitFunc) gst_pulsesink_property_probe_interface_init,
 -    NULL,
 -    NULL,
 -  };
 -  static const GInterfaceInfo svol_iface_info = {
 -    NULL, NULL, NULL
 -  };
 -
 -  g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_iface_info);
 -  g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
 -      &implements_iface_info);
 -  g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
 -      &probe_iface_info);
 -}
 -
 -static void
 -gst_pulsesink_base_init (gpointer g_class)
 -{
 -  static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
 -      GST_PAD_SINK,
 -      GST_PAD_ALWAYS,
 -      GST_STATIC_CAPS ("audio/x-raw-int, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "signed = (boolean) TRUE, "
 -          "width = (int) 16, "
 -          "depth = (int) 16, "
 -          "rate = (int) [ 1, MAX ], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-float, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "width = (int) 32, "
 -          "rate = (int) [ 1, MAX ], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-int, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "signed = (boolean) TRUE, "
 -          "width = (int) 32, "
 -          "depth = (int) 32, "
 -          "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-int, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "signed = (boolean) TRUE, "
 -          "width = (int) 24, "
 -          "depth = (int) 24, "
 -          "rate = (int) [ 1, MAX ], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-int, "
 -          "endianness = (int) { " ENDIANNESS " }, "
 -          "signed = (boolean) TRUE, "
 -          "width = (int) 32, "
 -          "depth = (int) 24, "
 -          "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
 -          "audio/x-raw-int, "
 -          "signed = (boolean) FALSE, "
 -          "width = (int) 8, "
 -          "depth = (int) 8, "
 -          "rate = (int) [ 1, MAX ], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-alaw, "
 -          "rate = (int) [ 1, MAX], "
 -          "channels = (int) [ 1, 32 ];"
 -          "audio/x-mulaw, "
 -          "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ]")
 -      );
 -
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_set_details_simple (element_class,
 -      "PulseAudio Audio Sink",
 -      "Sink/Audio", "Plays audio to a PulseAudio server", "Lennart Poettering");
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&pad_template));
 -}
 +#define gst_pulsesink_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstPulseSink, gst_pulsesink, GST_TYPE_BASE_AUDIO_SINK,
 +    gst_pulsesink_init_contexts ();
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE,
 +        gst_pulsesink_property_probe_interface_init);
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL)
 +    );
  
  static GstRingBuffer *
  gst_pulsesink_create_ringbuffer (GstBaseAudioSink * sink)
@@@ -1749,12 -1801,6 +1749,12 @@@ gst_pulsesink_class_init (GstPulseSinkC
        g_param_spec_boxed ("stream-properties", "stream properties",
            "list of pulseaudio stream properties",
            GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 +
 +  gst_element_class_set_details_simple (gstelement_class,
 +      "PulseAudio Audio Sink",
 +      "Sink/Audio", "Plays audio to a PulseAudio server", "Lennart Poettering");
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&pad_template));
  }
  
  /* returns the current time of the sink ringbuffer */
@@@ -1800,7 -1846,7 +1800,7 @@@ server_dead
  }
  
  static void
 -gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass)
 +gst_pulsesink_init (GstPulseSink * pulsesink)
  {
    pulsesink->server = NULL;
    pulsesink->device = NULL;
@@@ -2519,6 -2565,30 +2519,30 @@@ gst_pulsesink_event (GstBaseSink * sink
    return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
  }
  
+ static void
+ gst_pulsesink_release_mainloop (GstPulseSink * psink)
+ {
+   if (!mainloop)
+     return;
+   pa_threaded_mainloop_lock (mainloop);
+   while (psink->defer_pending) {
+     GST_DEBUG_OBJECT (psink, "waiting for stream status message emission");
+     pa_threaded_mainloop_wait (mainloop);
+   }
+   pa_threaded_mainloop_unlock (mainloop);
+   g_mutex_lock (pa_shared_resource_mutex);
+   mainloop_ref_ct--;
+   if (!mainloop_ref_ct) {
+     GST_INFO_OBJECT (psink, "terminating pa main loop thread");
+     pa_threaded_mainloop_stop (mainloop);
+     pa_threaded_mainloop_free (mainloop);
+     mainloop = NULL;
+   }
+   g_mutex_unlock (pa_shared_resource_mutex);
+ }
  static GstStateChangeReturn
  gst_pulsesink_change_state (GstElement * element, GstStateChange transition)
  {
                GST_BASE_AUDIO_SINK (pulsesink)->provided_clock));
        break;
      case GST_STATE_CHANGE_READY_TO_NULL:
-       if (mainloop) {
-         g_mutex_lock (pa_shared_resource_mutex);
-         mainloop_ref_ct--;
-         if (!mainloop_ref_ct) {
-           GST_INFO_OBJECT (element, "terminating pa main loop thread");
-           pa_threaded_mainloop_stop (mainloop);
-           pa_threaded_mainloop_free (mainloop);
-           mainloop = NULL;
-         }
-         g_mutex_unlock (pa_shared_resource_mutex);
-       }
+       gst_pulsesink_release_mainloop (pulsesink);
        break;
      default:
        break;
@@@ -2592,15 -2652,7 +2606,7 @@@ state_failure
      if (transition == GST_STATE_CHANGE_NULL_TO_READY) {
        /* Clear the PA mainloop if baseaudiosink failed to open the ring_buffer */
        g_assert (mainloop);
-       g_mutex_lock (pa_shared_resource_mutex);
-       mainloop_ref_ct--;
-       if (!mainloop_ref_ct) {
-         GST_INFO_OBJECT (element, "terminating pa main loop thread");
-         pa_threaded_mainloop_stop (mainloop);
-         pa_threaded_mainloop_free (mainloop);
-         mainloop = NULL;
-       }
-       g_mutex_unlock (pa_shared_resource_mutex);
+       gst_pulsesink_release_mainloop (pulsesink);
      }
      return ret;
    }
diff --combined gst/goom/gstgoom.c
@@@ -1,7 -1,6 +1,7 @@@
  /* gstgoom.c: implementation of goom drawing element
   * Copyright (C) <2001> Richard Boulton <richard@tartarus.org>
   *           (C) <2006> Wim Taymans <wim at fluendo dot com>
 + *           (C) <2011> Wim Taymans <wim.taymans at gmail dot com>
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Library General Public
@@@ -87,6 -86,9 +87,6 @@@ static GstStaticPadTemplate sink_templa
      );
  
  
 -static void gst_goom_class_init (GstGoomClass * klass);
 -static void gst_goom_base_init (GstGoomClass * klass);
 -static void gst_goom_init (GstGoom * goom);
  static void gst_goom_finalize (GObject * object);
  
  static GstStateChangeReturn gst_goom_change_state (GstElement * element,
@@@ -98,8 -100,48 +98,8 @@@ static gboolean gst_goom_sink_event (Gs
  
  static gboolean gst_goom_src_query (GstPad * pad, GstQuery * query);
  
 -static gboolean gst_goom_sink_setcaps (GstPad * pad, GstCaps * caps);
 -static gboolean gst_goom_src_setcaps (GstPad * pad, GstCaps * caps);
 -
 -static GstElementClass *parent_class = NULL;
 -
 -GType
 -gst_goom_get_type (void)
 -{
 -  static GType type = 0;
 -
 -  if (!type) {
 -    static const GTypeInfo info = {
 -      sizeof (GstGoomClass),
 -      (GBaseInitFunc) gst_goom_base_init,
 -      NULL,
 -      (GClassInitFunc) gst_goom_class_init,
 -      NULL,
 -      NULL,
 -      sizeof (GstGoom),
 -      0,
 -      (GInstanceInitFunc) gst_goom_init,
 -    };
 -
 -    type = g_type_register_static (GST_TYPE_ELEMENT, "GstGoom", &info, 0);
 -  }
 -  return type;
 -}
 -
 -static void
 -gst_goom_base_init (GstGoomClass * klass)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 -
 -  gst_element_class_set_details_simple (element_class, "GOOM: what a GOOM!",
 -      "Visualization",
 -      "Takes frames of data and outputs video frames using the GOOM filter",
 -      "Wim Taymans <wim@fluendo.com>");
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&sink_template));
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&src_template));
 -}
 +#define gst_goom_parent_class parent_class
 +G_DEFINE_TYPE (GstGoom, gst_goom, GST_TYPE_ELEMENT);
  
  static void
  gst_goom_class_init (GstGoomClass * klass)
    gobject_class = (GObjectClass *) klass;
    gstelement_class = (GstElementClass *) klass;
  
 -  parent_class = g_type_class_peek_parent (klass);
 -
    gobject_class->finalize = gst_goom_finalize;
  
 +  gst_element_class_set_details_simple (gstelement_class, "GOOM: what a GOOM!",
 +      "Visualization",
 +      "Takes frames of data and outputs video frames using the GOOM filter",
 +      "Wim Taymans <wim@fluendo.com>");
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&sink_template));
 +  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&src_template));
 +
    gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_goom_change_state);
  }
  
@@@ -133,9 -168,13 +133,9 @@@ gst_goom_init (GstGoom * goom
        GST_DEBUG_FUNCPTR (gst_goom_chain));
    gst_pad_set_event_function (goom->sinkpad,
        GST_DEBUG_FUNCPTR (gst_goom_sink_event));
 -  gst_pad_set_setcaps_function (goom->sinkpad,
 -      GST_DEBUG_FUNCPTR (gst_goom_sink_setcaps));
    gst_element_add_pad (GST_ELEMENT (goom), goom->sinkpad);
  
    goom->srcpad = gst_pad_new_from_static_template (&src_template, "src");
 -  gst_pad_set_setcaps_function (goom->srcpad,
 -      GST_DEBUG_FUNCPTR (gst_goom_src_setcaps));
    gst_pad_set_event_function (goom->srcpad,
        GST_DEBUG_FUNCPTR (gst_goom_src_event));
    gst_pad_set_query_function (goom->srcpad,
@@@ -164,8 -203,6 +164,8 @@@ gst_goom_finalize (GObject * object
    goom->plugin = NULL;
  
    g_object_unref (goom->adapter);
 +  if (goom->pool)
 +    gst_object_unref (goom->pool);
  
    G_OBJECT_CLASS (parent_class)->finalize (object);
  }
@@@ -183,32 -220,39 +183,32 @@@ gst_goom_reset (GstGoom * goom
  }
  
  static gboolean
 -gst_goom_sink_setcaps (GstPad * pad, GstCaps * caps)
 +gst_goom_sink_setcaps (GstGoom * goom, GstCaps * caps)
  {
 -  GstGoom *goom;
    GstStructure *structure;
 -  gboolean res;
 -
 -  goom = GST_GOOM (GST_PAD_PARENT (pad));
  
    structure = gst_caps_get_structure (caps, 0);
  
 -  res = gst_structure_get_int (structure, "channels", &goom->channels);
 -  res &= gst_structure_get_int (structure, "rate", &goom->rate);
 +  gst_structure_get_int (structure, "channels", &goom->channels);
 +  gst_structure_get_int (structure, "rate", &goom->rate);
  
    goom->bps = goom->channels * sizeof (gint16);
  
 -  return res;
 +  return TRUE;
  }
  
  static gboolean
 -gst_goom_src_setcaps (GstPad * pad, GstCaps * caps)
 +gst_goom_src_setcaps (GstGoom * goom, GstCaps * caps)
  {
 -  GstGoom *goom;
    GstStructure *structure;
 -
 -  goom = GST_GOOM (GST_PAD_PARENT (pad));
 +  gboolean res;
  
    structure = gst_caps_get_structure (caps, 0);
 -
    if (!gst_structure_get_int (structure, "width", &goom->width) ||
        !gst_structure_get_int (structure, "height", &goom->height) ||
        !gst_structure_get_fraction (structure, "framerate", &goom->fps_n,
            &goom->fps_d))
 -    return FALSE;
 +    goto error;
  
    goom_set_resolution (goom->plugin, goom->width, goom->height);
  
    GST_DEBUG_OBJECT (goom, "dimension %dx%d, framerate %d/%d, spf %d",
        goom->width, goom->height, goom->fps_n, goom->fps_d, goom->spf);
  
 -  return TRUE;
 +  res = gst_pad_push_event (goom->srcpad, gst_event_new_caps (caps));
 +
 +  return res;
 +
 +  /* ERRORS */
 +error:
 +  {
 +    GST_DEBUG_OBJECT (goom, "error parsing caps");
 +    return FALSE;
 +  }
  }
  
  static gboolean
@@@ -239,28 -274,24 +239,28 @@@ gst_goom_src_negotiate (GstGoom * goom
  {
    GstCaps *othercaps, *target;
    GstStructure *structure;
 -  const GstCaps *templ;
 +  GstCaps *templ;
 +  GstQuery *query;
 +  GstBufferPool *pool = NULL;
 +  guint size, min, max, prefix, alignment;
  
    templ = gst_pad_get_pad_template_caps (goom->srcpad);
  
    GST_DEBUG_OBJECT (goom, "performing negotiation");
  
    /* see what the peer can do */
 -  othercaps = gst_pad_peer_get_caps (goom->srcpad);
 +  othercaps = gst_pad_peer_get_caps (goom->srcpad, NULL);
    if (othercaps) {
      target = gst_caps_intersect (othercaps, templ);
      gst_caps_unref (othercaps);
 +    gst_caps_unref (templ);
  
      if (gst_caps_is_empty (target))
        goto no_format;
  
      gst_caps_truncate (target);
    } else {
 -    target = gst_caps_ref ((GstCaps *) templ);
 +    target = templ;
    }
  
    structure = gst_caps_get_structure (target, 0);
    gst_structure_fixate_field_nearest_fraction (structure, "framerate",
        DEFAULT_FPS_N, DEFAULT_FPS_D);
  
 -  gst_pad_set_caps (goom->srcpad, target);
 +  gst_goom_src_setcaps (goom, target);
 +
 +  /* try to get a bufferpool now */
 +  /* find a pool for the negotiated caps now */
 +  query = gst_query_new_allocation (target, TRUE);
 +
 +  if (gst_pad_peer_query (goom->srcpad, query)) {
 +    /* we got configuration from our peer, parse them */
 +    gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
 +        &alignment, &pool);
 +  } else {
 +    size = goom->outsize;
 +    min = max = 0;
 +    prefix = 0;
 +    alignment = 0;
 +  }
 +
 +  if (pool == NULL) {
 +    GstStructure *config;
 +
 +    /* we did not get a pool, make one ourselves then */
 +    pool = gst_buffer_pool_new ();
 +
 +    config = gst_buffer_pool_get_config (pool);
 +    gst_buffer_pool_config_set (config, target, size, min, max, prefix,
 +        alignment);
 +    gst_buffer_pool_set_config (pool, config);
 +  }
 +
 +  if (goom->pool)
 +    gst_object_unref (goom->pool);
 +  goom->pool = pool;
 +
 +  /* and activate */
 +  gst_buffer_pool_set_active (pool, TRUE);
 +
    gst_caps_unref (target);
  
    return TRUE;
@@@ -331,7 -327,7 +331,7 @@@ gst_goom_src_event (GstPad * pad, GstEv
        GstClockTimeDiff diff;
        GstClockTime timestamp;
  
 -      gst_event_parse_qos (event, &proportion, &diff, &timestamp);
 +      gst_event_parse_qos (event, NULL, &proportion, &diff, &timestamp);
  
        /* save stuff for the _chain() function */
        GST_OBJECT_LOCK (goom);
@@@ -365,14 -361,6 +365,14 @@@ gst_goom_sink_event (GstPad * pad, GstE
    goom = GST_GOOM (gst_pad_get_parent (pad));
  
    switch (GST_EVENT_TYPE (event)) {
 +    case GST_EVENT_CAPS:
 +    {
 +      GstCaps *caps;
 +
 +      gst_event_parse_caps (event, &caps);
 +      res = gst_goom_sink_setcaps (goom, caps);
 +      break;
 +    }
      case GST_EVENT_FLUSH_START:
        res = gst_pad_push_event (goom->srcpad, event);
        break;
        gst_goom_reset (goom);
        res = gst_pad_push_event (goom->srcpad, event);
        break;
 -    case GST_EVENT_NEWSEGMENT:
 +    case GST_EVENT_SEGMENT:
      {
 -      GstFormat format;
 -      gdouble rate, arate;
 -      gint64 start, stop, time;
 -      gboolean update;
 -
        /* the newsegment values are used to clip the input samples
         * and to convert the incomming timestamps to running time so
         * we can do QoS */
 -      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
 -          &start, &stop, &time);
 -
 -      /* now configure the values */
 -      gst_segment_set_newsegment_full (&goom->segment, update,
 -          rate, arate, format, start, stop, time);
 +      gst_event_copy_segment (event, &goom->segment);
  
        res = gst_pad_push_event (goom->srcpad, event);
        break;
  static gboolean
  gst_goom_src_query (GstPad * pad, GstQuery * query)
  {
-   gboolean res;
+   gboolean res = FALSE;
    GstGoom *goom;
  
    goom = GST_GOOM (gst_pad_get_parent (pad));
        GstClockTime our_latency;
        guint max_samples;
  
+       if (goom->rate == 0)
+         break;
        if ((res = gst_pad_peer_query (goom->sinkpad, query))) {
          gst_query_parse_latency (query, &us_live, &min_latency, &max_latency);
  
    return res;
  }
  
 +/* make sure we are negotiated */
  static GstFlowReturn
 -get_buffer (GstGoom * goom, GstBuffer ** outbuf)
 +ensure_negotiated (GstGoom * goom)
  {
 -  GstFlowReturn ret;
 +  gboolean reconfigure;
 +
 +  GST_OBJECT_LOCK (goom->srcpad);
 +  reconfigure = GST_PAD_NEEDS_RECONFIGURE (goom->srcpad);
 +  GST_OBJECT_FLAG_UNSET (goom->srcpad, GST_PAD_NEED_RECONFIGURE);
 +  GST_OBJECT_UNLOCK (goom->srcpad);
  
 -  if (GST_PAD_CAPS (goom->srcpad) == NULL) {
 +  /* we don't know an output format yet, pick one */
 +  if (reconfigure || !gst_pad_has_current_caps (goom->srcpad)) {
      if (!gst_goom_src_negotiate (goom))
        return GST_FLOW_NOT_NEGOTIATED;
    }
 -
 -  GST_DEBUG_OBJECT (goom, "allocating output buffer with caps %"
 -      GST_PTR_FORMAT, GST_PAD_CAPS (goom->srcpad));
 -
 -  ret =
 -      gst_pad_alloc_buffer_and_set_caps (goom->srcpad,
 -      GST_BUFFER_OFFSET_NONE, goom->outsize,
 -      GST_PAD_CAPS (goom->srcpad), outbuf);
 -  if (ret != GST_FLOW_OK)
 -    return ret;
 -
    return GST_FLOW_OK;
  }
  
 +
  static GstFlowReturn
  gst_goom_chain (GstPad * pad, GstBuffer * buffer)
  {
      goto beach;
    }
  
 -  /* If we don't have an output format yet, preallocate a buffer to try and
 -   * set one */
 -  if (GST_PAD_CAPS (goom->srcpad) == NULL) {
 -    ret = get_buffer (goom, &outbuf);
 -    if (ret != GST_FLOW_OK) {
 -      gst_buffer_unref (buffer);
 -      goto beach;
 -    }
 +  /* Make sure have an output format */
 +  ret = ensure_negotiated (goom);
 +  if (ret != GST_FLOW_OK) {
 +    gst_buffer_unref (buffer);
 +    goto beach;
    }
  
    /* don't try to combine samples from discont buffer */
  
    GST_DEBUG_OBJECT (goom,
        "Input buffer has %d samples, time=%" G_GUINT64_FORMAT,
 -      GST_BUFFER_SIZE (buffer) / goom->bps, GST_BUFFER_TIMESTAMP (buffer));
 +      gst_buffer_get_size (buffer) / goom->bps, GST_BUFFER_TIMESTAMP (buffer));
  
    /* Collect samples until we have enough for an output frame */
    gst_adapter_push (goom->adapter, buffer);
  
      /* get next GOOM_SAMPLES, we have at least this amount of samples */
      data =
 -        (const guint16 *) gst_adapter_peek (goom->adapter,
 +        (const guint16 *) gst_adapter_map (goom->adapter,
          GOOM_SAMPLES * goom->bps);
  
      if (goom->channels == 2) {
      /* alloc a buffer if we don't have one yet, this happens
       * when we pushed a buffer in this while loop before */
      if (outbuf == NULL) {
 -      ret = get_buffer (goom, &outbuf);
 +      GST_DEBUG_OBJECT (goom, "allocating output buffer");
 +      ret = gst_buffer_pool_acquire_buffer (goom->pool, &outbuf, NULL);
        if (ret != GST_FLOW_OK) {
 +        gst_adapter_unmap (goom->adapter, 0);
          goto beach;
        }
      }
  
      GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
      GST_BUFFER_DURATION (outbuf) = goom->duration;
 -    GST_BUFFER_SIZE (outbuf) = goom->outsize;
  
      out_frame = (guchar *) goom_update (goom->plugin, goom->datain, 0, 0);
 -    memcpy (GST_BUFFER_DATA (outbuf), out_frame, goom->outsize);
 +    gst_buffer_fill (outbuf, 0, out_frame, goom->outsize);
 +
 +    gst_adapter_unmap (goom->adapter, 0);
  
      GST_DEBUG ("Pushing frame with time=%" GST_TIME_FORMAT ", duration=%"
          GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
@@@ -644,11 -648,6 +647,11 @@@ gst_goom_change_state (GstElement * ele
  
    switch (transition) {
      case GST_STATE_CHANGE_PAUSED_TO_READY:
 +      if (goom->pool) {
 +        gst_buffer_pool_set_active (goom->pool, FALSE);
 +        gst_object_unref (goom->pool);
 +        goom->pool = NULL;
 +      }
        break;
      case GST_STATE_CHANGE_READY_TO_NULL:
        break;