From 2bd77e1c8a6dda6ca68de3e4048162f3d648b42a Mon Sep 17 00:00:00 2001 From: Philippe Normand Date: Mon, 17 Dec 2012 16:35:56 +0100 Subject: [PATCH] interleave: set src pad caps upon last sink pad CAPS event Gather caps on all sink pads before setting the src pad caps. This is specially needed when the audio channel mapping is set on the sink pads and the element needs to preserve it on its src pad. https://bugzilla.gnome.org/show_bug.cgi?id=690267 --- gst/interleave/interleave.c | 63 +++++++++++++++++++++---------------- gst/interleave/interleave.h | 1 + 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/gst/interleave/interleave.c b/gst/interleave/interleave.c index 7f3bd07bf4..82104224f8 100644 --- a/gst/interleave/interleave.c +++ b/gst/interleave/interleave.c @@ -219,7 +219,7 @@ static gboolean gst_interleave_sink_event (GstCollectPads * pads, GstCollectData * data, GstEvent * event, gpointer user_data); static gboolean gst_interleave_sink_setcaps (GstInterleave * self, - GstPad * pad, const GstCaps * caps); + GstPad * pad, const GstCaps * caps, const GstAudioInfo * info); static GstCaps *gst_interleave_sink_getcaps (GstPad * pad, GstObject * parent, GstCaps * filter); @@ -547,6 +547,9 @@ gst_interleave_release_pad (GstElement * element, GstPad * pad) g_atomic_int_add (&self->channels, -1); + if (gst_pad_has_current_caps (pad)) + g_atomic_int_add (&self->configured_sinkpads_counter, -1); + position = GST_INTERLEAVE_PAD_CAST (pad)->channel; g_value_array_remove (self->input_channel_positions, position); @@ -734,11 +737,10 @@ gst_interleave_set_process_function (GstInterleave * self) static gboolean gst_interleave_sink_setcaps (GstInterleave * self, GstPad * pad, - const GstCaps * caps) + const GstCaps * caps, const GstAudioInfo * info) { g_return_val_if_fail (GST_IS_INTERLEAVE_PAD (pad), FALSE); - /* First caps that are set on a sink pad are used as output caps */ /* TODO: handle caps changes */ if (self->sinkcaps && !gst_caps_is_subset (caps, self->sinkcaps)) { goto cannot_change_caps; @@ -746,25 +748,11 @@ gst_interleave_sink_setcaps (GstInterleave * self, GstPad * pad, GstCaps *srccaps; GstStructure *s; gboolean res; - GstAudioInfo info; - GValue *val; - guint channel; - - if (!gst_audio_info_from_caps (&info, caps)) - goto invalid_caps; - - self->width = GST_AUDIO_INFO_WIDTH (&info); - self->rate = GST_AUDIO_INFO_RATE (&info); + self->width = GST_AUDIO_INFO_WIDTH (info); + self->rate = GST_AUDIO_INFO_RATE (info); gst_interleave_set_process_function (self); - channel = GST_INTERLEAVE_PAD_CAST (pad)->channel; - - if (self->channel_positions_from_input - && GST_AUDIO_INFO_CHANNELS (&info) == 1) { - val = g_value_array_get_nth (self->input_channel_positions, channel); - g_value_set_enum (val, GST_AUDIO_INFO_POSITION (&info, 0)); - } srccaps = gst_caps_copy (caps); s = gst_caps_get_structure (srccaps, 0); @@ -808,11 +796,6 @@ src_did_not_accept: GST_WARNING_OBJECT (self, "src did not accept setcaps()"); return FALSE; } -invalid_caps: - { - GST_WARNING_OBJECT (self, "invalid sink caps"); - return FALSE; - } } static gboolean @@ -841,11 +824,37 @@ gst_interleave_sink_event (GstCollectPads * pads, GstCollectData * data, case GST_EVENT_CAPS: { GstCaps *caps; + GstAudioInfo info; + GValue *val; + guint channel; gst_event_parse_caps (event, &caps); - ret = gst_interleave_sink_setcaps (self, data->pad, caps); - gst_event_unref (event); - event = NULL; + + if (!gst_audio_info_from_caps (&info, caps)) { + GST_WARNING_OBJECT (self, "invalid sink caps"); + gst_event_unref (event); + event = NULL; + ret = FALSE; + break; + } + + if (self->channel_positions_from_input + && GST_AUDIO_INFO_CHANNELS (&info) == 1) { + channel = GST_INTERLEAVE_PAD_CAST (data->pad)->channel; + val = g_value_array_get_nth (self->input_channel_positions, channel); + g_value_set_enum (val, GST_AUDIO_INFO_POSITION (&info, 0)); + } + + if (!gst_pad_has_current_caps (data->pad)) + g_atomic_int_add (&self->configured_sinkpads_counter, 1); + + /* Last caps that are set on a sink pad are used as output caps */ + if (g_atomic_int_get (&self->configured_sinkpads_counter) == + self->channels) { + ret = gst_interleave_sink_setcaps (self, data->pad, caps, &info); + gst_event_unref (event); + event = NULL; + } break; } case GST_EVENT_TAG: diff --git a/gst/interleave/interleave.h b/gst/interleave/interleave.h index 07b9ae712a..87a8eedb1d 100644 --- a/gst/interleave/interleave.h +++ b/gst/interleave/interleave.h @@ -61,6 +61,7 @@ struct _GstInterleave gboolean channel_positions_from_input; GstCaps *sinkcaps; + gint configured_sinkpads_counter; GstClockTime timestamp; guint64 offset;