mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
deinterleave: implement accept-caps
Avoid using default accept-caps handler that will query downstream and is more expensive. Just check if the caps is compatible with the template and check if the channels are the same.
This commit is contained in:
parent
c0c8d503da
commit
5c7b051b90
2 changed files with 96 additions and 38 deletions
|
@ -360,6 +360,56 @@ gst_deinterleave_set_process_function (GstDeinterleave * self)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_deinterleave_check_caps_change (GstDeinterleave * self,
|
||||
GstAudioInfo * old_info, GstAudioInfo * new_info)
|
||||
{
|
||||
gint i;
|
||||
gboolean same_layout = TRUE;
|
||||
gboolean was_unpositioned;
|
||||
gboolean is_unpositioned = GST_AUDIO_INFO_IS_UNPOSITIONED (new_info);
|
||||
gint new_channels = GST_AUDIO_INFO_CHANNELS (new_info);
|
||||
gint old_channels;
|
||||
|
||||
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)
|
||||
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 (new_info))
|
||||
goto cannot_change_caps;
|
||||
for (i = 0; i < GST_AUDIO_INFO_CHANNELS (old_info); i++) {
|
||||
if (new_info->position[i] != old_info->position[i]) {
|
||||
same_layout = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!same_layout)
|
||||
goto cannot_change_caps;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
cannot_change_caps:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_deinterleave_sink_setcaps (GstDeinterleave * self, GstCaps * caps)
|
||||
{
|
||||
|
@ -375,51 +425,17 @@ gst_deinterleave_sink_setcaps (GstDeinterleave * self, GstCaps * caps)
|
|||
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);
|
||||
if (!gst_audio_info_from_caps (&old_info, self->sinkcaps))
|
||||
goto info_from_caps_failed;
|
||||
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))
|
||||
if (gst_deinterleave_check_caps_change (self, &old_info, &self->audio_info)) {
|
||||
if (!gst_deinterleave_set_process_function (self))
|
||||
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;
|
||||
}
|
||||
} else
|
||||
goto cannot_change_caps;
|
||||
|
||||
}
|
||||
|
||||
|
@ -504,6 +520,35 @@ __set_channels (GstCaps * caps, gint channels)
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_deinterleave_sink_acceptcaps (GstPad * pad, GstObject * parent,
|
||||
GstCaps * caps)
|
||||
{
|
||||
GstDeinterleave *self = GST_DEINTERLEAVE (parent);
|
||||
GstCaps *templ_caps = gst_pad_get_pad_template_caps (pad);
|
||||
gboolean ret;
|
||||
|
||||
ret = gst_caps_can_intersect (templ_caps, caps);
|
||||
gst_caps_unref (templ_caps);
|
||||
if (ret && self->sinkcaps) {
|
||||
GstAudioInfo new_info;
|
||||
|
||||
gst_audio_info_init (&new_info);
|
||||
if (!gst_audio_info_from_caps (&new_info, caps))
|
||||
goto info_from_caps_failed;
|
||||
ret =
|
||||
gst_deinterleave_check_caps_change (self, &self->audio_info, &new_info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
info_from_caps_failed:
|
||||
{
|
||||
GST_ERROR_OBJECT (self, "coud not get info from caps");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_deinterleave_getcaps (GstPad * pad, GstObject * parent, GstCaps * filter)
|
||||
{
|
||||
|
@ -642,6 +687,16 @@ gst_deinterleave_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
|||
res = TRUE;
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_ACCEPT_CAPS:{
|
||||
GstCaps *caps;
|
||||
gboolean ret;
|
||||
|
||||
gst_query_parse_accept_caps (query, &caps);
|
||||
ret = gst_deinterleave_sink_acceptcaps (pad, parent, caps);
|
||||
gst_query_set_accept_caps_result (query, ret);
|
||||
res = TRUE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
res = gst_pad_query_default (pad, parent, query);
|
||||
break;
|
||||
|
|
|
@ -306,6 +306,7 @@ GST_START_TEST (test_2_channels_caps_change)
|
|||
|
||||
ret_caps = gst_pad_peer_query_caps (mysrcpad, caps);
|
||||
fail_if (gst_caps_is_empty (ret_caps));
|
||||
fail_unless (gst_pad_peer_query_accept_caps (mysrcpad, caps));
|
||||
gst_caps_unref (ret_caps);
|
||||
gst_check_setup_events (mysrcpad, deinterleave, caps, GST_FORMAT_TIME);
|
||||
|
||||
|
@ -340,6 +341,7 @@ GST_START_TEST (test_2_channels_caps_change)
|
|||
NULL);
|
||||
ret_caps = gst_pad_peer_query_caps (mysrcpad, caps2);
|
||||
fail_if (gst_caps_is_empty (ret_caps));
|
||||
fail_unless (gst_pad_peer_query_accept_caps (mysrcpad, caps2));
|
||||
gst_caps_unref (ret_caps);
|
||||
gst_pad_set_caps (mysrcpad, caps2);
|
||||
|
||||
|
@ -371,6 +373,7 @@ GST_START_TEST (test_2_channels_caps_change)
|
|||
ret_caps = gst_pad_peer_query_caps (mysrcpad, caps2);
|
||||
fail_unless (gst_caps_is_empty (ret_caps));
|
||||
gst_caps_unref (ret_caps);
|
||||
fail_if (gst_pad_peer_query_accept_caps (mysrcpad, caps2));
|
||||
gst_pad_set_caps (mysrcpad, caps2);
|
||||
|
||||
inbuf = gst_buffer_new_and_alloc (3 * 48000 * sizeof (gfloat));
|
||||
|
|
Loading…
Reference in a new issue