diff options
Diffstat (limited to 'gst')
-rw-r--r-- | gst/audioconvert/gstaudioconvert.c | 143 |
1 files changed, 80 insertions, 63 deletions
diff --git a/gst/audioconvert/gstaudioconvert.c b/gst/audioconvert/gstaudioconvert.c index 7a1676f52..4448c0989 100644 --- a/gst/audioconvert/gstaudioconvert.c +++ b/gst/audioconvert/gstaudioconvert.c @@ -61,6 +61,8 @@ static void gst_audio_convert_dispose (GObject * obj); /* gstreamer functions */ static GstFlowReturn gst_audio_convert_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_audio_convert_link_src (GstAudioConvert * this, + GstCaps * sinkcaps, GstAudioConvertCaps * sink_ac_caps); static gboolean gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps); static GstCaps *gst_audio_convert_fixate (GstPad * pad, GstCaps * caps); static GstCaps *gst_audio_convert_getcaps (GstPad * pad); @@ -195,7 +197,7 @@ gst_audio_convert_init (GstAudioConvert * this) gst_pad_new_from_template (gst_static_pad_template_get (&gst_audio_convert_src_template), "src"); gst_pad_set_getcaps_function (this->src, gst_audio_convert_getcaps); - gst_pad_set_setcaps_function (this->src, gst_audio_convert_setcaps); + //gst_pad_set_setcaps_function (this->src, gst_audio_convert_setcaps); gst_pad_set_fixatecaps_function (this->src, gst_audio_convert_fixate); gst_element_add_pad (GST_ELEMENT (this), this->src); @@ -235,22 +237,6 @@ gst_audio_convert_chain (GstPad * pad, GstBuffer * buf) this = GST_AUDIO_CONVERT (GST_OBJECT_PARENT (pad)); - /* FIXME */ - -#if 0 - if (!GST_PAD_CAPS (this->sink)) { - GST_ELEMENT_ERROR (this, CORE, NEGOTIATION, (NULL), - ("Sink pad (connected to %s:%s) not negotiated before chain function", - GST_DEBUG_PAD_NAME (gst_pad_get_peer (this->sink)))); - gst_buffer_unref (buf); - return GST_FLOW_NOT_NEGOTIATED; - } - if (!GST_PAD_CAPS (this->src)) { - gst_buffer_unref (buf); - return GST_FLOW_NOT_NEGOTIATED; - } -#endif - /** * Theory of operation: * - convert the format (endianness, signedness, width, depth) to @@ -260,6 +246,16 @@ gst_audio_convert_chain (GstPad * pad, GstBuffer * buf) */ GST_STREAM_LOCK (pad); + if (!GST_RPAD_CAPS (this->sink)) { + goto not_negotiated; + } else if (!GST_RPAD_CAPS (this->src)) { + if (!gst_audio_convert_link_src (this, + GST_RPAD_CAPS (this->sink), &this->sinkcaps)) + goto no_format; + } else if (!this->matrix) { + gst_audio_convert_setup_matrix (this); + } + buf = gst_audio_convert_buffer_to_default_format (this, buf); buf = gst_audio_convert_channels (this, buf); buf = gst_audio_convert_buffer_from_default_format (this, buf); @@ -269,6 +265,23 @@ gst_audio_convert_chain (GstPad * pad, GstBuffer * buf) GST_STREAM_UNLOCK (pad); return ret; + +not_negotiated: + { + GST_ELEMENT_ERROR (this, CORE, NEGOTIATION, (NULL), + ("Pad not negotiated before chain function was called")); + gst_buffer_unref (buf); + GST_STREAM_UNLOCK (pad); + return GST_FLOW_NOT_NEGOTIATED; + } +no_format: + { + GST_ELEMENT_ERROR (this, CORE, NEGOTIATION, (NULL), + ("Could not negotiate format")); + gst_buffer_unref (buf); + GST_STREAM_UNLOCK (pad); + return GST_FLOW_ERROR; + } } static GstCaps * @@ -394,42 +407,23 @@ gst_audio_convert_parse_caps (const GstCaps * gst_caps, } static gboolean -gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps) +gst_audio_convert_link_src (GstAudioConvert * this, + GstCaps * sinkcaps, GstAudioConvertCaps * sink_ac_caps) { - GstAudioConvert *this; - GstPad *otherpad; GstAudioConvertCaps ac_caps = { 0 }; - GstAudioConvertCaps other_ac_caps = { 0 }; - GstCaps **other_prefered, **prefered; - - g_return_val_if_fail (GST_IS_PAD (pad), FALSE); - g_return_val_if_fail (GST_IS_AUDIO_CONVERT (GST_OBJECT_PARENT (pad)), FALSE); - g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); - this = GST_AUDIO_CONVERT (GST_OBJECT_PARENT (pad)); - - /* we'll need a new matrix after every new negotiation */ - gst_audio_convert_unset_matrix (this); - - ac_caps.pos = NULL; - if (!gst_audio_convert_parse_caps (caps, &ac_caps)) - return FALSE; - - otherpad = (pad == this->src ? this->sink : this->src); - prefered = (pad == this->src) ? &this->src_prefered : &this->sink_prefered; - other_prefered = - (pad == this->src) ? &this->sink_prefered : &this->src_prefered; - - *prefered = caps; - - /* check passthrough */ - if (gst_pad_peer_accept_caps (otherpad, caps)) { + if (gst_pad_peer_accept_caps (this->src, sinkcaps)) { /* great, so that will be our suggestion then */ - *other_prefered = gst_caps_ref (caps); + this->src_prefered = gst_caps_ref (sinkcaps); + gst_caps_replace (&GST_RPAD_CAPS (this->src), sinkcaps); + ac_caps = *sink_ac_caps; + if (ac_caps.pos) { + ac_caps.pos = g_memdup (ac_caps.pos, sizeof (gint) * ac_caps.channels); + } } else { /* nope, find something we can convert to and the peer can * accept. */ - GstCaps *othercaps = gst_pad_peer_get_caps (otherpad); + GstCaps *othercaps = gst_pad_peer_get_caps (this->src); if (othercaps) { /* peel off first one */ @@ -439,12 +433,12 @@ gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps) gst_caps_unref (othercaps); /* set the rate on the caps, this has to work */ - gst_structure_set (structure, "rate", G_TYPE_INT, ac_caps.rate, NULL); - gst_structure_set (structure, "channels", G_TYPE_INT, ac_caps.channels, - NULL); + gst_structure_set (structure, + "rate", G_TYPE_INT, sink_ac_caps->rate, + "channels", G_TYPE_INT, sink_ac_caps->channels, NULL); if (strcmp (gst_structure_get_name (structure), "audio/x-raw-float") == 0) { - if (!ac_caps.is_int) { + if (!sink_ac_caps->is_int) { /* copy over */ gst_structure_set (structure, "buffer-frames", G_TYPE_INT, ac_caps.buffer_frames, NULL); @@ -455,25 +449,48 @@ gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps) } /* this will be our suggestion */ - *other_prefered = targetcaps; - if (!gst_audio_convert_parse_caps (targetcaps, &other_ac_caps)) + this->src_prefered = targetcaps; + if (!gst_audio_convert_parse_caps (targetcaps, &ac_caps)) return FALSE; - gst_caps_replace (&GST_RPAD_CAPS (otherpad), targetcaps); + gst_caps_replace (&GST_RPAD_CAPS (this->src), targetcaps); } } - if (this->sink == pad) { - g_free (this->srccaps.pos); - this->srccaps = other_ac_caps; + this->srccaps = ac_caps; + + GST_DEBUG_OBJECT (this, "negotiated pad to %" GST_PTR_FORMAT, sinkcaps); + + return TRUE; +} + +static gboolean +gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps) +{ + GstAudioConvert *this; + GstAudioConvertCaps ac_caps = { 0 }; + gboolean res; + + g_return_val_if_fail (GST_IS_PAD (pad), FALSE); + g_return_val_if_fail (GST_IS_AUDIO_CONVERT (GST_OBJECT_PARENT (pad)), FALSE); + g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); + + this = GST_AUDIO_CONVERT (GST_OBJECT_PARENT (pad)); + + /* we'll need a new matrix after every new negotiation */ + gst_audio_convert_unset_matrix (this); + + ac_caps.pos = NULL; + if (!gst_audio_convert_parse_caps (caps, &ac_caps)) + return FALSE; + + this->sink_prefered = caps; + + if ((res = gst_audio_convert_link_src (this, caps, &ac_caps))) { this->sinkcaps = ac_caps; - } else { - g_free (this->sinkcaps.pos); - this->srccaps = ac_caps; - this->sinkcaps = other_ac_caps; + + GST_DEBUG_OBJECT (this, "negotiated pad to %" GST_PTR_FORMAT, caps); } - GST_DEBUG_OBJECT (this, "negotiated pad to %" GST_PTR_FORMAT, caps); - gst_audio_convert_setup_matrix (this); - return TRUE; + return res; } /* tries to fixate the given field of the given caps to the given int value */ |