static gboolean gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps) { GstDeinterleave *self; GstCaps *srccaps; GstStructure *s; self = GST_DEINTERLEAVE (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (self, "got caps: %" GST_PTR_FORMAT, caps); if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) { gint new_channels, i; GstAudioChannelPosition *pos; gboolean same_layout = TRUE; s = gst_caps_get_structure (caps, 0); /* We allow caps changes as long as the number of channels doesn't change * and the channel positions stay the same. _getcaps() should've cared * for this already but better be safe. */ if (!gst_structure_get_int (s, "channels", &new_channels) || new_channels != self->channels || !gst_deinterleave_set_process_function (self, caps)) goto cannot_change_caps; /* Now check the channel positions. If we had no channel positions * and get them or the other way around things have changed. * 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 (pos) { for (i = 0; i < self->channels; i++) { if (self->pos[i] != pos[i]) { same_layout = FALSE; break; } } g_free (pos); if (!same_layout) goto cannot_change_caps; } } else { s = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (s, "channels", &self->channels)) goto no_channels; if (!gst_deinterleave_set_process_function (self, caps)) goto unsupported_caps; self->pos = gst_audio_get_channel_positions (s); } gst_caps_replace (&self->sinkcaps, caps); /* Get srcpad caps */ srccaps = gst_caps_copy (caps); s = gst_caps_get_structure (srccaps, 0); gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL); gst_structure_remove_field (s, "channel-positions"); /* If we already have pads, update the caps otherwise * add new pads */ if (self->srcpads) { gst_deinterleave_set_pads_caps (self, srccaps); } else { gst_deinterleave_add_new_pads (self, srccaps); } gst_caps_unref (srccaps); gst_object_unref (self); return TRUE; cannot_change_caps: { GST_ERROR_OBJECT (self, "can't set new caps: %" GST_PTR_FORMAT, caps); gst_object_unref (self); return FALSE; } unsupported_caps: { GST_ERROR_OBJECT (self, "caps not supported: %" GST_PTR_FORMAT, caps); gst_object_unref (self); return FALSE; } no_channels: { GST_ERROR_OBJECT (self, "invalid caps"); gst_object_unref (self); return FALSE; } }
static gboolean gst_deinterleave_sink_setcaps (GstDeinterleave * self, GstCaps * caps) { GstCaps *srccaps; GstStructure *s; GST_DEBUG_OBJECT (self, "got caps: %" GST_PTR_FORMAT, caps); if (!gst_audio_info_from_caps (&self->audio_info, caps)) goto invalid_caps; if (!gst_deinterleave_set_process_function (self)) goto unsupported_caps; if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) { gint i; gboolean same_layout = TRUE; gboolean was_unpositioned; gboolean is_unpositioned = GST_AUDIO_INFO_IS_UNPOSITIONED (&self->audio_info); gint new_channels = GST_AUDIO_INFO_CHANNELS (&self->audio_info); gint old_channels; GstAudioInfo old_info; gst_audio_info_init (&old_info); gst_audio_info_from_caps (&old_info, self->sinkcaps); was_unpositioned = GST_AUDIO_INFO_IS_UNPOSITIONED (&old_info); old_channels = GST_AUDIO_INFO_CHANNELS (&old_info); /* We allow caps changes as long as the number of channels doesn't change * and the channel positions stay the same. _getcaps() should've cared * for this already but better be safe. */ if (new_channels != old_channels || !gst_deinterleave_set_process_function (self)) goto cannot_change_caps; /* Now check the channel positions. If we had no channel positions * and get them or the other way around things have changed. * If we had channel positions and get different ones things have * changed too of course */ if ((!was_unpositioned && is_unpositioned) || (was_unpositioned && !is_unpositioned)) goto cannot_change_caps; if (!is_unpositioned) { if (GST_AUDIO_INFO_CHANNELS (&old_info) != GST_AUDIO_INFO_CHANNELS (&self->audio_info)) goto cannot_change_caps; for (i = 0; i < GST_AUDIO_INFO_CHANNELS (&old_info); i++) { if (self->audio_info.position[i] != old_info.position[i]) { same_layout = FALSE; break; } } if (!same_layout) goto cannot_change_caps; } } gst_caps_replace (&self->sinkcaps, caps); /* Get srcpad caps */ srccaps = gst_caps_copy (caps); s = gst_caps_get_structure (srccaps, 0); gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL); gst_structure_remove_field (s, "channel-mask"); /* If we already have pads, update the caps otherwise * add new pads */ if (self->srcpads) { gst_deinterleave_set_pads_caps (self, srccaps); } else { gst_deinterleave_add_new_pads (self, srccaps); } gst_caps_unref (srccaps); return TRUE; cannot_change_caps: { GST_WARNING_OBJECT (self, "caps change from %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT " not supported: channel number or channel " "positions change", self->sinkcaps, caps); return FALSE; } unsupported_caps: { GST_ERROR_OBJECT (self, "caps not supported: %" GST_PTR_FORMAT, caps); return FALSE; } invalid_caps: { GST_ERROR_OBJECT (self, "invalid caps"); return FALSE; } }