gst/interleave/deinterleave.c: Always set the channel positions when gst_audio_get_channel_positions() returns someth...

Original commit message from CVS:
* gst/interleave/deinterleave.c: (gst_deinterleave_sink_setcaps),
(gst_deinterleave_getcaps):
Always set the channel positions when gst_audio_get_channel_positions()
returns something, even if they're not set in the caps. This makes
sure that the output channels can be interleaved again correctly
in the mono/stereo cases too.
Don't ask for the peercaps of the current pad in getcaps() as this
might call getcaps() again and deadlock.
This commit is contained in:
Sebastian Dröge 2008-05-17 14:05:03 +00:00
parent 67515f39fc
commit 838e10c219
2 changed files with 35 additions and 20 deletions

View file

@ -1,3 +1,15 @@
2008-05-17 Sebastian Dröge <slomo@circular-chaos.org>
* gst/interleave/deinterleave.c: (gst_deinterleave_sink_setcaps),
(gst_deinterleave_getcaps):
Always set the channel positions when gst_audio_get_channel_positions()
returns something, even if they're not set in the caps. This makes
sure that the output channels can be interleaved again correctly
in the mono/stereo cases too.
Don't ask for the peercaps of the current pad in getcaps() as this
might call getcaps() again and deadlock.
2008-05-16 Sebastian Dröge <slomo@circular-chaos.org> 2008-05-16 Sebastian Dröge <slomo@circular-chaos.org>
* ext/timidity/gstwildmidi.c: (wildmidi_open_config): * ext/timidity/gstwildmidi.c: (wildmidi_open_config):

View file

@ -300,8 +300,9 @@ gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps)
GST_DEBUG_OBJECT (self, "got caps: %" GST_PTR_FORMAT, caps); GST_DEBUG_OBJECT (self, "got caps: %" GST_PTR_FORMAT, caps);
if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) { if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) {
gint new_channels; gint new_channels, i;
GstAudioChannelPosition *pos; GstAudioChannelPosition *pos;
gboolean same_layout = TRUE;
s = gst_caps_get_structure (caps, 0); s = gst_caps_get_structure (caps, 0);
@ -314,25 +315,27 @@ gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps)
!gst_deinterleave_set_process_function (self, caps)) !gst_deinterleave_set_process_function (self, caps))
goto cannot_change_caps; goto cannot_change_caps;
if (gst_structure_has_field (s, "channel-positions")) { /* Now check the channel positions. If we had no channel positions
gint i; * and get them or the other way around things have changed.
gboolean same = TRUE; * If we had channel positions and get different ones things have
* changed too of course
*/
pos = gst_audio_get_channel_positions (s);
if ((pos && !self->pos) || (!pos && self->pos))
goto cannot_change_caps;
if (!self->pos) if (pos) {
goto cannot_change_caps;
pos = gst_audio_get_channel_positions (s);
for (i = 0; i < self->channels; i++) { for (i = 0; i < self->channels; i++) {
if (self->pos[i] != pos[i]) { if (self->pos[i] != pos[i]) {
same = FALSE; same_layout = FALSE;
break; break;
} }
} }
g_free (pos); g_free (pos);
if (!same) if (!same_layout)
goto cannot_change_caps; goto cannot_change_caps;
} }
} else { } else {
s = gst_caps_get_structure (caps, 0); s = gst_caps_get_structure (caps, 0);
@ -342,8 +345,7 @@ gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps)
if (!gst_deinterleave_set_process_function (self, caps)) if (!gst_deinterleave_set_process_function (self, caps))
goto unsupported_caps; goto unsupported_caps;
if (gst_structure_has_field (s, "channel-positions")) self->pos = gst_audio_get_channel_positions (s);
self->pos = gst_audio_get_channel_positions (s);
} }
gst_caps_replace (&self->sinkcaps, caps); gst_caps_replace (&self->sinkcaps, caps);
@ -425,7 +427,6 @@ gst_deinterleave_getcaps (GstPad * pad)
GList *l; GList *l;
GST_OBJECT_LOCK (self); GST_OBJECT_LOCK (self);
/* Intersect all of our pad template caps with the peer caps of the pad /* Intersect all of our pad template caps with the peer caps of the pad
* to get all formats that are possible up- and downstream. * to get all formats that are possible up- and downstream.
* *
@ -436,7 +437,7 @@ gst_deinterleave_getcaps (GstPad * pad)
ret = gst_caps_new_any (); ret = gst_caps_new_any ();
for (l = GST_ELEMENT (self)->pads; l != NULL; l = l->next) { for (l = GST_ELEMENT (self)->pads; l != NULL; l = l->next) {
GstPad *ourpad = GST_PAD (l->data); GstPad *ourpad = GST_PAD (l->data);
GstCaps *peercaps, *ourcaps; GstCaps *peercaps = NULL, *ourcaps;
ourcaps = gst_caps_copy (gst_pad_get_pad_template_caps (ourpad)); ourcaps = gst_caps_copy (gst_pad_get_pad_template_caps (ourpad));
@ -447,18 +448,21 @@ gst_deinterleave_getcaps (GstPad * pad)
__set_channels (ourcaps, 1); __set_channels (ourcaps, 1);
} else { } else {
__remove_channels (ourcaps); __remove_channels (ourcaps);
/* Only ask for peer caps for other pads than pad
* as otherwise gst_pad_peer_get_caps() might call
* back into this function and deadlock
*/
peercaps = gst_pad_peer_get_caps (ourpad);
} }
peercaps = gst_pad_peer_get_caps (ourpad);
if (pad != ourpad && peercaps)
__remove_channels (peercaps);
/* If the peer exists and has caps add them to the intersection, /* If the peer exists and has caps add them to the intersection,
* otherwise assume that the peer accepts everything */ * otherwise assume that the peer accepts everything */
if (peercaps) { if (peercaps) {
GstCaps *intersection; GstCaps *intersection;
GstCaps *oldret = ret; GstCaps *oldret = ret;
__remove_channels (peercaps);
intersection = gst_caps_intersect (peercaps, ourcaps); intersection = gst_caps_intersect (peercaps, ourcaps);
ret = gst_caps_intersect (ret, intersection); ret = gst_caps_intersect (ret, intersection);
@ -473,7 +477,6 @@ gst_deinterleave_getcaps (GstPad * pad)
} }
gst_caps_unref (ourcaps); gst_caps_unref (ourcaps);
} }
GST_OBJECT_UNLOCK (self); GST_OBJECT_UNLOCK (self);
gst_object_unref (self); gst_object_unref (self);