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;
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;
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;
}
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);
}
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);
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. */
}
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;
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!");
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)
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 */
}
static void
-gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass)
+gst_pulsesink_init (GstPulseSink * pulsesink)
{
pulsesink->server = NULL;
pulsesink->device = NULL;
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;
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;
}
/* 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
);
-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,
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);
}
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,
goom->plugin = NULL;
g_object_unref (goom->adapter);
+ if (goom->pool)
+ gst_object_unref (goom->pool);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
}
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
{
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;
GstClockTimeDiff diff;
GstClockTime timestamp;
- gst_event_parse_qos (event, &proportion, &diff, ×tamp);
+ gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp);
/* save stuff for the _chain() function */
GST_OBJECT_LOCK (goom);
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),
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;