mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-16 21:36:35 +00:00
gst/audioconvert/gstaudioconvert.c: Implement instant setup switching.
Original commit message from CVS: * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_init), (gst_audio_convert_chain), (gst_audio_convert_link_src), (gst_audio_convert_setcaps): Implement instant setup switching.
This commit is contained in:
parent
1419d5ac97
commit
78016b40cf
2 changed files with 99 additions and 75 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
2005-05-23 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
|
* gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_init),
|
||||||
|
(gst_audio_convert_chain), (gst_audio_convert_link_src),
|
||||||
|
(gst_audio_convert_setcaps):
|
||||||
|
Implement instant setup switching.
|
||||||
|
|
||||||
2005-05-19 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
2005-05-19 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
* gst/playback/gstplaybasebin.c: (probe_triggered):
|
* gst/playback/gstplaybasebin.c: (probe_triggered):
|
||||||
|
|
|
@ -61,6 +61,8 @@ static void gst_audio_convert_dispose (GObject * obj);
|
||||||
|
|
||||||
/* gstreamer functions */
|
/* gstreamer functions */
|
||||||
static GstFlowReturn gst_audio_convert_chain (GstPad * pad, GstBuffer * buffer);
|
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 gboolean gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps);
|
||||||
static GstCaps *gst_audio_convert_fixate (GstPad * pad, GstCaps * caps);
|
static GstCaps *gst_audio_convert_fixate (GstPad * pad, GstCaps * caps);
|
||||||
static GstCaps *gst_audio_convert_getcaps (GstPad * pad);
|
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_pad_new_from_template (gst_static_pad_template_get
|
||||||
(&gst_audio_convert_src_template), "src");
|
(&gst_audio_convert_src_template), "src");
|
||||||
gst_pad_set_getcaps_function (this->src, gst_audio_convert_getcaps);
|
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_pad_set_fixatecaps_function (this->src, gst_audio_convert_fixate);
|
||||||
gst_element_add_pad (GST_ELEMENT (this), this->src);
|
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));
|
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:
|
* Theory of operation:
|
||||||
* - convert the format (endianness, signedness, width, depth) to
|
* - convert the format (endianness, signedness, width, depth) to
|
||||||
|
@ -260,6 +246,16 @@ gst_audio_convert_chain (GstPad * pad, GstBuffer * buf)
|
||||||
*/
|
*/
|
||||||
GST_STREAM_LOCK (pad);
|
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_buffer_to_default_format (this, buf);
|
||||||
buf = gst_audio_convert_channels (this, buf);
|
buf = gst_audio_convert_channels (this, buf);
|
||||||
buf = gst_audio_convert_buffer_from_default_format (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);
|
GST_STREAM_UNLOCK (pad);
|
||||||
|
|
||||||
return ret;
|
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 *
|
static GstCaps *
|
||||||
|
@ -393,14 +406,68 @@ gst_audio_convert_parse_caps (const GstCaps * gst_caps,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_audio_convert_link_src (GstAudioConvert * this,
|
||||||
|
GstCaps * sinkcaps, GstAudioConvertCaps * sink_ac_caps)
|
||||||
|
{
|
||||||
|
GstAudioConvertCaps ac_caps = { 0 };
|
||||||
|
|
||||||
|
if (gst_pad_peer_accept_caps (this->src, sinkcaps)) {
|
||||||
|
/* great, so that will be our suggestion then */
|
||||||
|
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 (this->src);
|
||||||
|
|
||||||
|
if (othercaps) {
|
||||||
|
/* peel off first one */
|
||||||
|
GstCaps *targetcaps = gst_caps_copy_nth (othercaps, 0);
|
||||||
|
GstStructure *structure = gst_caps_get_structure (targetcaps, 0);
|
||||||
|
|
||||||
|
gst_caps_unref (othercaps);
|
||||||
|
|
||||||
|
/* set the rate on the caps, this has to work */
|
||||||
|
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 (!sink_ac_caps->is_int) {
|
||||||
|
/* copy over */
|
||||||
|
gst_structure_set (structure, "buffer-frames", G_TYPE_INT,
|
||||||
|
ac_caps.buffer_frames, NULL);
|
||||||
|
} else {
|
||||||
|
/* set to anything */
|
||||||
|
gst_structure_set (structure, "buffer-frames", G_TYPE_INT, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this will be our suggestion */
|
||||||
|
this->src_prefered = targetcaps;
|
||||||
|
if (!gst_audio_convert_parse_caps (targetcaps, &ac_caps))
|
||||||
|
return FALSE;
|
||||||
|
gst_caps_replace (&GST_RPAD_CAPS (this->src), targetcaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->srccaps = ac_caps;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (this, "negotiated pad to %" GST_PTR_FORMAT, sinkcaps);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps)
|
gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstAudioConvert *this;
|
GstAudioConvert *this;
|
||||||
GstPad *otherpad;
|
|
||||||
GstAudioConvertCaps ac_caps = { 0 };
|
GstAudioConvertCaps ac_caps = { 0 };
|
||||||
GstAudioConvertCaps other_ac_caps = { 0 };
|
gboolean res;
|
||||||
GstCaps **other_prefered, **prefered;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
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_IS_AUDIO_CONVERT (GST_OBJECT_PARENT (pad)), FALSE);
|
||||||
|
@ -415,65 +482,15 @@ gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
if (!gst_audio_convert_parse_caps (caps, &ac_caps))
|
if (!gst_audio_convert_parse_caps (caps, &ac_caps))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
otherpad = (pad == this->src ? this->sink : this->src);
|
this->sink_prefered = caps;
|
||||||
prefered = (pad == this->src) ? &this->src_prefered : &this->sink_prefered;
|
|
||||||
other_prefered =
|
|
||||||
(pad == this->src) ? &this->sink_prefered : &this->src_prefered;
|
|
||||||
|
|
||||||
*prefered = caps;
|
if ((res = gst_audio_convert_link_src (this, caps, &ac_caps))) {
|
||||||
|
|
||||||
/* check passthrough */
|
|
||||||
if (gst_pad_peer_accept_caps (otherpad, caps)) {
|
|
||||||
/* great, so that will be our suggestion then */
|
|
||||||
*other_prefered = gst_caps_ref (caps);
|
|
||||||
} else {
|
|
||||||
/* nope, find something we can convert to and the peer can
|
|
||||||
* accept. */
|
|
||||||
GstCaps *othercaps = gst_pad_peer_get_caps (otherpad);
|
|
||||||
|
|
||||||
if (othercaps) {
|
|
||||||
/* peel off first one */
|
|
||||||
GstCaps *targetcaps = gst_caps_copy_nth (othercaps, 0);
|
|
||||||
GstStructure *structure = gst_caps_get_structure (targetcaps, 0);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (strcmp (gst_structure_get_name (structure), "audio/x-raw-float") == 0) {
|
|
||||||
if (!ac_caps.is_int) {
|
|
||||||
/* copy over */
|
|
||||||
gst_structure_set (structure, "buffer-frames", G_TYPE_INT,
|
|
||||||
ac_caps.buffer_frames, NULL);
|
|
||||||
} else {
|
|
||||||
/* set to anything */
|
|
||||||
gst_structure_set (structure, "buffer-frames", G_TYPE_INT, 0, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this will be our suggestion */
|
|
||||||
*other_prefered = targetcaps;
|
|
||||||
if (!gst_audio_convert_parse_caps (targetcaps, &other_ac_caps))
|
|
||||||
return FALSE;
|
|
||||||
gst_caps_replace (&GST_RPAD_CAPS (otherpad), targetcaps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this->sink == pad) {
|
|
||||||
g_free (this->srccaps.pos);
|
|
||||||
this->srccaps = other_ac_caps;
|
|
||||||
this->sinkcaps = 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 */
|
/* tries to fixate the given field of the given caps to the given int value */
|
||||||
|
|
Loading…
Reference in a new issue