mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-03 04:52:28 +00:00
audioaggregator: Sync pad values before aggregating
We need to sync the pad values before taking the aggregator and pad locks otherwise the element will just deadlock if there's any property changes scheduled using GstController since that involves taking the aggregator and pad locks. Also add a test for this. https://bugzilla.gnome.org/show_bug.cgi?id=749574
This commit is contained in:
parent
a1cdede940
commit
74d7944cbb
2 changed files with 103 additions and 10 deletions
|
@ -739,7 +739,6 @@ gst_audio_aggregator_fill_buffer (GstAudioAggregator * aagg,
|
|||
GstClockTime start_time, end_time;
|
||||
gboolean discont = FALSE;
|
||||
guint64 start_offset, end_offset;
|
||||
GstClockTime timestamp, stream_time = GST_CLOCK_TIME_NONE;
|
||||
gint rate, bpf;
|
||||
|
||||
GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
|
||||
|
@ -762,15 +761,6 @@ gst_audio_aggregator_fill_buffer (GstAudioAggregator * aagg,
|
|||
goto done;
|
||||
}
|
||||
|
||||
timestamp = GST_BUFFER_PTS (inbuf);
|
||||
stream_time = gst_segment_to_stream_time (&aggpad->segment, GST_FORMAT_TIME,
|
||||
timestamp);
|
||||
|
||||
/* sync object properties on stream time */
|
||||
/* TODO: Ideally we would want to do that on every sample */
|
||||
if (GST_CLOCK_TIME_IS_VALID (stream_time))
|
||||
gst_object_sync_values (GST_OBJECT (pad), stream_time);
|
||||
|
||||
start_time = GST_BUFFER_PTS (inbuf);
|
||||
end_time =
|
||||
start_time + gst_util_uint64_scale_ceil (pad->priv->size, GST_SECOND,
|
||||
|
@ -964,6 +954,29 @@ gst_audio_aggregator_create_output_buffer (GstAudioAggregator * aagg,
|
|||
return outbuf;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sync_pad_values (GstAudioAggregator * aagg, GstAudioAggregatorPad * pad)
|
||||
{
|
||||
GstAggregatorPad *bpad = GST_AGGREGATOR_PAD (pad);
|
||||
GstClockTime timestamp, stream_time;
|
||||
|
||||
if (pad->priv->buffer == NULL)
|
||||
return TRUE;
|
||||
|
||||
timestamp = GST_BUFFER_PTS (pad->priv->buffer);
|
||||
GST_OBJECT_LOCK (bpad);
|
||||
stream_time = gst_segment_to_stream_time (&bpad->segment, GST_FORMAT_TIME,
|
||||
timestamp);
|
||||
GST_OBJECT_UNLOCK (bpad);
|
||||
|
||||
/* sync object properties on stream time */
|
||||
/* TODO: Ideally we would want to do that on every sample */
|
||||
if (GST_CLOCK_TIME_IS_VALID (stream_time))
|
||||
gst_object_sync_values (GST_OBJECT (pad), stream_time);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout)
|
||||
{
|
||||
|
@ -1011,6 +1024,10 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout)
|
|||
element = GST_ELEMENT (agg);
|
||||
aagg = GST_AUDIO_AGGREGATOR (agg);
|
||||
|
||||
/* Sync pad properties to the stream time */
|
||||
gst_aggregator_iterate_sinkpads (agg,
|
||||
(GstAggregatorPadForeachFunc) sync_pad_values, NULL);
|
||||
|
||||
GST_AUDIO_AGGREGATOR_LOCK (aagg);
|
||||
GST_OBJECT_LOCK (agg);
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include <gst/check/gstconsistencychecker.h>
|
||||
#include <gst/audio/audio.h>
|
||||
#include <gst/base/gstbasesrc.h>
|
||||
#include <gst/controller/gstdirectcontrolbinding.h>
|
||||
#include <gst/controller/gstinterpolationcontrolsource.h>
|
||||
|
||||
static GMainLoop *main_loop;
|
||||
|
||||
|
@ -1835,6 +1837,79 @@ GST_START_TEST (test_segment_base_handling)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
set_pad_volume_fade (GstPad * pad, GstClockTime start, gdouble start_value,
|
||||
GstClockTime end, gdouble end_value)
|
||||
{
|
||||
GstControlSource *cs;
|
||||
GstTimedValueControlSource *tvcs;
|
||||
|
||||
cs = gst_interpolation_control_source_new ();
|
||||
fail_unless (gst_object_add_control_binding (GST_OBJECT_CAST (pad),
|
||||
gst_direct_control_binding_new_absolute (GST_OBJECT_CAST (pad),
|
||||
"volume", cs)));
|
||||
|
||||
/* set volume interpolation mode */
|
||||
g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
|
||||
|
||||
tvcs = (GstTimedValueControlSource *) cs;
|
||||
fail_unless (gst_timed_value_control_source_set (tvcs, start, start_value));
|
||||
fail_unless (gst_timed_value_control_source_set (tvcs, end, end_value));
|
||||
gst_object_unref (cs);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_sinkpad_property_controller)
|
||||
{
|
||||
GstBus *bus;
|
||||
GstMessage *msg;
|
||||
GstElement *pipeline, *sink, *mix, *src1;
|
||||
GstPad *srcpad, *sinkpad;
|
||||
GError *error = NULL;
|
||||
gchar *debug;
|
||||
|
||||
pipeline = gst_pipeline_new ("pipeline");
|
||||
mix = gst_element_factory_make ("audiomixer", "audiomixer");
|
||||
sink = gst_element_factory_make ("fakesink", "sink");
|
||||
src1 = gst_element_factory_make ("audiotestsrc", "src1");
|
||||
g_object_set (src1, "num-buffers", 100, NULL);
|
||||
gst_bin_add_many (GST_BIN (pipeline), src1, mix, sink, NULL);
|
||||
fail_unless (gst_element_link (mix, sink));
|
||||
|
||||
srcpad = gst_element_get_static_pad (src1, "src");
|
||||
sinkpad = gst_element_get_request_pad (mix, "sink_0");
|
||||
fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK);
|
||||
set_pad_volume_fade (sinkpad, 0, 0, 1.0, 2.0);
|
||||
gst_object_unref (sinkpad);
|
||||
gst_object_unref (srcpad);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
||||
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
|
||||
GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
|
||||
switch (GST_MESSAGE_TYPE (msg)) {
|
||||
case GST_MESSAGE_ERROR:
|
||||
gst_message_parse_error (msg, &error, &debug);
|
||||
g_printerr ("ERROR from element %s: %s\n",
|
||||
GST_OBJECT_NAME (msg->src), error->message);
|
||||
g_printerr ("Debug info: %s\n", debug);
|
||||
g_error_free (error);
|
||||
g_free (debug);
|
||||
break;
|
||||
case GST_MESSAGE_EOS:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
gst_message_unref (msg);
|
||||
g_object_unref (bus);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (pipeline);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
audiomixer_suite (void)
|
||||
{
|
||||
|
@ -1859,6 +1934,7 @@ audiomixer_suite (void)
|
|||
tcase_add_test (tc_chain, test_sync_discont);
|
||||
tcase_add_test (tc_chain, test_sync_unaligned);
|
||||
tcase_add_test (tc_chain, test_segment_base_handling);
|
||||
tcase_add_test (tc_chain, test_sinkpad_property_controller);
|
||||
|
||||
/* Use a longer timeout */
|
||||
#ifdef HAVE_VALGRIND
|
||||
|
|
Loading…
Reference in a new issue