aggregator: add simple support for caps handling

Modelled off the videoaggregator caps handling as that seems the most
mature aggregtor-using implementation that has caps handling there is.

https://bugzilla.gnome.org/show_bug.cgi?id=776931
This commit is contained in:
Matthew Waters 2017-05-20 14:24:57 +02:00 committed by Olivier Crête
parent 26819ba296
commit 57673e608e
6 changed files with 69 additions and 74 deletions

View file

@ -144,8 +144,6 @@ struct _GstAudioAggregatorPrivate
{ {
GMutex mutex; GMutex mutex;
gboolean send_caps; /* aagg lock */
/* All three properties are unprotected, can't be modified while streaming */ /* All three properties are unprotected, can't be modified while streaming */
/* Size in frames that is output per buffer */ /* Size in frames that is output per buffer */
GstClockTime output_buffer_duration; GstClockTime output_buffer_duration;
@ -189,6 +187,8 @@ static GstFlowReturn gst_audio_aggregator_aggregate (GstAggregator * agg,
gboolean timeout); gboolean timeout);
static gboolean sync_pad_values (GstAudioAggregator * aagg, static gboolean sync_pad_values (GstAudioAggregator * aagg,
GstAudioAggregatorPad * pad); GstAudioAggregatorPad * pad);
static gboolean gst_audio_aggregator_negotiated_src_caps (GstAggregator * agg,
GstCaps * caps);
#define DEFAULT_OUTPUT_BUFFER_DURATION (10 * GST_MSECOND) #define DEFAULT_OUTPUT_BUFFER_DURATION (10 * GST_MSECOND)
#define DEFAULT_ALIGNMENT_THRESHOLD (40 * GST_MSECOND) #define DEFAULT_ALIGNMENT_THRESHOLD (40 * GST_MSECOND)
@ -251,6 +251,8 @@ gst_audio_aggregator_class_init (GstAudioAggregatorClass * klass)
GST_DEBUG_FUNCPTR (gst_audio_aggregator_aggregate); GST_DEBUG_FUNCPTR (gst_audio_aggregator_aggregate);
gstaggregator_class->clip = GST_DEBUG_FUNCPTR (gst_audio_aggregator_do_clip); gstaggregator_class->clip = GST_DEBUG_FUNCPTR (gst_audio_aggregator_do_clip);
gstaggregator_class->get_next_time = gst_audio_aggregator_get_next_time; gstaggregator_class->get_next_time = gst_audio_aggregator_get_next_time;
gstaggregator_class->negotiated_src_caps =
gst_audio_aggregator_negotiated_src_caps;
klass->create_output_buffer = gst_audio_aggregator_create_output_buffer; klass->create_output_buffer = gst_audio_aggregator_create_output_buffer;
@ -656,9 +658,10 @@ gst_audio_aggregator_set_sink_caps (GstAudioAggregator * aagg,
} }
gboolean static gboolean
gst_audio_aggregator_set_src_caps (GstAudioAggregator * aagg, GstCaps * caps) gst_audio_aggregator_negotiated_src_caps (GstAggregator * agg, GstCaps * caps)
{ {
GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (agg);
GstAudioInfo info; GstAudioInfo info;
if (!gst_audio_info_from_caps (&info, caps)) { if (!gst_audio_info_from_caps (&info, caps)) {
@ -674,8 +677,6 @@ gst_audio_aggregator_set_src_caps (GstAudioAggregator * aagg, GstCaps * caps)
gst_caps_replace (&aagg->current_caps, caps); gst_caps_replace (&aagg->current_caps, caps);
memcpy (&aagg->info, &info, sizeof (info)); memcpy (&aagg->info, &info, sizeof (info));
aagg->priv->send_caps = TRUE;
} }
GST_OBJECT_UNLOCK (aagg); GST_OBJECT_UNLOCK (aagg);
@ -683,7 +684,9 @@ gst_audio_aggregator_set_src_caps (GstAudioAggregator * aagg, GstCaps * caps)
/* send caps event later, after stream-start event */ /* send caps event later, after stream-start event */
return TRUE; return
GST_AGGREGATOR_CLASS
(gst_audio_aggregator_parent_class)->negotiated_src_caps (agg, caps);
} }
@ -1132,21 +1135,13 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout)
GST_OBJECT_UNLOCK (agg); GST_OBJECT_UNLOCK (agg);
GST_AUDIO_AGGREGATOR_UNLOCK (aagg); GST_AUDIO_AGGREGATOR_UNLOCK (aagg);
return GST_FLOW_OK; return GST_AGGREGATOR_FLOW_NEED_DATA;
} else { } else {
GST_OBJECT_UNLOCK (agg); GST_OBJECT_UNLOCK (agg);
goto not_negotiated; goto not_negotiated;
} }
} }
if (aagg->priv->send_caps) {
GST_OBJECT_UNLOCK (agg);
gst_aggregator_set_src_caps (agg, aagg->current_caps);
GST_OBJECT_LOCK (agg);
aagg->priv->send_caps = FALSE;
}
rate = GST_AUDIO_INFO_RATE (&aagg->info); rate = GST_AUDIO_INFO_RATE (&aagg->info);
bpf = GST_AUDIO_INFO_BPF (&aagg->info); bpf = GST_AUDIO_INFO_BPF (&aagg->info);
@ -1296,7 +1291,7 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout)
/* We dropped a buffer, retry */ /* We dropped a buffer, retry */
GST_LOG_OBJECT (aagg, "A pad dropped a buffer, wait for the next one"); GST_LOG_OBJECT (aagg, "A pad dropped a buffer, wait for the next one");
GST_AUDIO_AGGREGATOR_UNLOCK (aagg); GST_AUDIO_AGGREGATOR_UNLOCK (aagg);
return GST_FLOW_OK; return GST_AGGREGATOR_FLOW_NEED_DATA;
} }
if (!is_done && !is_eos) { if (!is_done && !is_eos) {
@ -1304,7 +1299,7 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout)
GST_LOG_OBJECT (aagg, GST_LOG_OBJECT (aagg,
"We're not done yet for the current offset, waiting for more data"); "We're not done yet for the current offset, waiting for more data");
GST_AUDIO_AGGREGATOR_UNLOCK (aagg); GST_AUDIO_AGGREGATOR_UNLOCK (aagg);
return GST_FLOW_OK; return GST_AGGREGATOR_FLOW_NEED_DATA;
} }
if (is_eos) { if (is_eos) {

View file

@ -162,9 +162,6 @@ void
gst_audio_aggregator_set_sink_caps (GstAudioAggregator * aagg, gst_audio_aggregator_set_sink_caps (GstAudioAggregator * aagg,
GstAudioAggregatorPad * pad, GstCaps * caps); GstAudioAggregatorPad * pad, GstCaps * caps);
gboolean
gst_audio_aggregator_set_src_caps (GstAudioAggregator * aagg, GstCaps * caps);
G_END_DECLS G_END_DECLS

View file

@ -432,10 +432,10 @@ gst_audio_interleave_setcaps (GstAudioInterleave * self, GstPad * pad,
GST_DEBUG_OBJECT (self, "setting sinkcaps %" GST_PTR_FORMAT, sinkcaps); GST_DEBUG_OBJECT (self, "setting sinkcaps %" GST_PTR_FORMAT, sinkcaps);
gst_caps_replace (&self->sinkcaps, sinkcaps); gst_caps_replace (&self->sinkcaps, sinkcaps);
gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (aagg));
gst_caps_unref (sinkcaps); gst_caps_unref (sinkcaps);
new = TRUE; new = TRUE;
self->new_caps = TRUE;
} }
if (self->channel_positions_from_input if (self->channel_positions_from_input
@ -504,52 +504,40 @@ gst_audio_interleave_sink_event (GstAggregator * agg, GstAggregatorPad * aggpad,
} }
static GstFlowReturn static GstFlowReturn
gst_audio_interleave_aggregate (GstAggregator * aggregator, gboolean timeout) gst_audio_interleave_update_src_caps (GstAggregator * agg, GstCaps * caps,
GstCaps ** ret)
{ {
GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (aggregator); GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (agg);
GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (aggregator); GstStructure *s;
GST_OBJECT_LOCK (aggregator); /* This means that either no caps have been set on the sink pad (if
if (self->new_caps) { * sinkcaps is NULL) or that there is no sink pad (if channels == 0).
GstCaps *srccaps; */
GstStructure *s; if (self->sinkcaps == NULL || self->channels == 0)
gboolean ret; return GST_FLOW_NOT_NEGOTIATED;
if (self->sinkcaps == NULL || self->channels == 0) { *ret = gst_caps_copy (self->sinkcaps);
/* In this case, let the base class handle it */ s = gst_caps_get_structure (*ret, 0);
goto not_negotiated;
}
srccaps = gst_caps_copy (self->sinkcaps); gst_structure_set (s, "channels", G_TYPE_INT, self->channels, "layout",
s = gst_caps_get_structure (srccaps, 0); G_TYPE_STRING, "interleaved", "channel-mask", GST_TYPE_BITMASK,
gst_audio_interleave_get_channel_mask (self), NULL);
gst_structure_set (s, "channels", G_TYPE_INT, self->channels, "layout", return GST_FLOW_OK;
G_TYPE_STRING, "interleaved", "channel-mask", GST_TYPE_BITMASK, }
gst_audio_interleave_get_channel_mask (self), NULL);
static gboolean
gst_audio_interleave_negotiated_src_caps (GstAggregator * agg, GstCaps * caps)
{
GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (agg);
GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (self);
GST_OBJECT_UNLOCK (aggregator); if (!GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps))
ret = gst_audio_aggregator_set_src_caps (aagg, srccaps); return FALSE;
gst_caps_unref (srccaps);
if (!ret) gst_audio_interleave_set_process_function (self, &aagg->info);
goto src_did_not_accept;
GST_OBJECT_LOCK (aggregator); return TRUE;
gst_audio_interleave_set_process_function (self, &aagg->info);
self->new_caps = FALSE;
}
not_negotiated:
GST_OBJECT_UNLOCK (aggregator);
return GST_AGGREGATOR_CLASS (parent_class)->aggregate (aggregator, timeout);
src_did_not_accept:
GST_WARNING_OBJECT (self, "src did not accept setcaps()");
return GST_FLOW_NOT_NEGOTIATED;;
} }
static void static void
@ -586,7 +574,8 @@ gst_audio_interleave_class_init (GstAudioInterleaveClass * klass)
agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_audio_interleave_sink_query); agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_audio_interleave_sink_query);
agg_class->sink_event = GST_DEBUG_FUNCPTR (gst_audio_interleave_sink_event); agg_class->sink_event = GST_DEBUG_FUNCPTR (gst_audio_interleave_sink_event);
agg_class->stop = gst_audio_interleave_stop; agg_class->stop = gst_audio_interleave_stop;
agg_class->aggregate = gst_audio_interleave_aggregate; agg_class->update_src_caps = gst_audio_interleave_update_src_caps;
agg_class->negotiated_src_caps = gst_audio_interleave_negotiated_src_caps;
aagg_class->aggregate_one_buffer = gst_audio_interleave_aggregate_one_buffer; aagg_class->aggregate_one_buffer = gst_audio_interleave_aggregate_one_buffer;
@ -720,7 +709,6 @@ gst_audio_interleave_stop (GstAggregator * agg)
if (!GST_AGGREGATOR_CLASS (parent_class)->stop (agg)) if (!GST_AGGREGATOR_CLASS (parent_class)->stop (agg))
return FALSE; return FALSE;
self->new_caps = FALSE;
gst_caps_replace (&self->sinkcaps, NULL); gst_caps_replace (&self->sinkcaps, NULL);
return TRUE; return TRUE;
@ -765,9 +753,7 @@ gst_audio_interleave_request_new_pad (GstElement * element,
g_value_unset (&val); g_value_unset (&val);
/* Update the src caps if we already have them */ /* Update the src caps if we already have them */
GST_OBJECT_LOCK (self); gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self));
self->new_caps = TRUE;
GST_OBJECT_UNLOCK (self);
return GST_PAD_CAST (newpad); return GST_PAD_CAST (newpad);
@ -804,7 +790,7 @@ gst_audio_interleave_release_pad (GstElement * element, GstPad * pad)
ipad->channel--; ipad->channel--;
} }
self->new_caps = TRUE; gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self));
GST_OBJECT_UNLOCK (self); GST_OBJECT_UNLOCK (self);

View file

@ -58,7 +58,6 @@ struct _GstAudioInterleave {
gint padcounter; gint padcounter;
guint channels; guint channels;
gboolean new_caps;
GstCaps *sinkcaps; GstCaps *sinkcaps;
GValueArray *channel_positions; GValueArray *channel_positions;

View file

@ -348,7 +348,6 @@ gst_audiomixer_setcaps (GstAudioMixer * audiomixer, GstPad * pad,
GstAudioInfo info; GstAudioInfo info;
GstStructure *s; GstStructure *s;
gint channels = 0; gint channels = 0;
gboolean ret;
caps = gst_caps_copy (orig_caps); caps = gst_caps_copy (orig_caps);
@ -405,20 +404,21 @@ gst_audiomixer_setcaps (GstAudioMixer * audiomixer, GstPad * pad,
gst_caps_unref (caps); gst_caps_unref (caps);
return FALSE; return FALSE;
} }
} else {
gst_caps_replace (&aagg->current_caps, caps);
aagg->info = info;
gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (agg));
} }
GST_OBJECT_UNLOCK (audiomixer); GST_OBJECT_UNLOCK (audiomixer);
ret = gst_audio_aggregator_set_src_caps (aagg, caps); gst_audio_aggregator_set_sink_caps (aagg, GST_AUDIO_AGGREGATOR_PAD (pad),
orig_caps);
if (ret)
gst_audio_aggregator_set_sink_caps (aagg, GST_AUDIO_AGGREGATOR_PAD (pad),
orig_caps);
GST_INFO_OBJECT (pad, "handle caps change to %" GST_PTR_FORMAT, caps); GST_INFO_OBJECT (pad, "handle caps change to %" GST_PTR_FORMAT, caps);
gst_caps_unref (caps); gst_caps_unref (caps);
return ret; return TRUE;
/* ERRORS */ /* ERRORS */
invalid_format: invalid_format:
@ -429,6 +429,20 @@ invalid_format:
} }
} }
static GstFlowReturn
gst_audiomixer_update_src_caps (GstAggregator * agg, GstCaps * caps,
GstCaps ** ret)
{
GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (agg);
if (aagg->current_caps == NULL)
return GST_AGGREGATOR_FLOW_NEED_DATA;
*ret = gst_caps_ref (aagg->current_caps);
return GST_FLOW_OK;
}
static gboolean static gboolean
gst_audiomixer_sink_event (GstAggregator * agg, GstAggregatorPad * aggpad, gst_audiomixer_sink_event (GstAggregator * agg, GstAggregatorPad * aggpad,
GstEvent * event) GstEvent * event)
@ -495,6 +509,8 @@ gst_audiomixer_class_init (GstAudioMixerClass * klass)
agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_audiomixer_sink_query); agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_audiomixer_sink_query);
agg_class->sink_event = GST_DEBUG_FUNCPTR (gst_audiomixer_sink_event); agg_class->sink_event = GST_DEBUG_FUNCPTR (gst_audiomixer_sink_event);
agg_class->update_src_caps =
GST_DEBUG_FUNCPTR (gst_audiomixer_update_src_caps);
aagg_class->aggregate_one_buffer = gst_audiomixer_aggregate_one_buffer; aagg_class->aggregate_one_buffer = gst_audiomixer_aggregate_one_buffer;
} }

View file

@ -1043,7 +1043,9 @@ GST_START_TEST (test_audiointerleave_2ch_smallbuf)
gst_caps_unref (caps); gst_caps_unref (caps);
gst_event_unref (ev); gst_event_unref (ev);
for (i = 0; i < 24; i++) /* eat the caps processing */
gst_harness_crank_single_clock_wait (h);
for (i = 0; i < 23; i++)
gst_harness_crank_single_clock_wait (h); gst_harness_crank_single_clock_wait (h);
fail_unless_equals_uint64 (gst_clock_get_time (GST_ELEMENT_CLOCK fail_unless_equals_uint64 (gst_clock_get_time (GST_ELEMENT_CLOCK
(h->element)), 750 * GST_MSECOND); (h->element)), 750 * GST_MSECOND);