mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
audiomixer: Port to GstAggregator
https://bugzilla.gnome.org/show_bug.cgi?id=737183 Co-Authored by: Mathieu Duponchelle <mathieu.duponchelle@opencreed.com>
This commit is contained in:
parent
2ddbaaf866
commit
183f4b3227
4 changed files with 406 additions and 673 deletions
|
@ -6,11 +6,15 @@ include $(top_srcdir)/common/orc.mak
|
||||||
|
|
||||||
libgstaudiomixer_la_SOURCES = gstaudiomixer.c
|
libgstaudiomixer_la_SOURCES = gstaudiomixer.c
|
||||||
nodist_libgstaudiomixer_la_SOURCES = $(ORC_NODIST_SOURCES)
|
nodist_libgstaudiomixer_la_SOURCES = $(ORC_NODIST_SOURCES)
|
||||||
libgstaudiomixer_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(ORC_CFLAGS)
|
libgstaudiomixer_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
|
||||||
|
$(GST_CFLAGS) $(ORC_CFLAGS) \
|
||||||
|
-I$(top_srcdir)/gst-libs \
|
||||||
|
-I$(top_builddir)/gst-libs
|
||||||
libgstaudiomixer_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
libgstaudiomixer_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||||
libgstaudiomixer_la_LIBADD = \
|
libgstaudiomixer_la_LIBADD = \
|
||||||
$(GST_PLUGINS_BASE_LIBS) \
|
$(GST_PLUGINS_BASE_LIBS) \
|
||||||
-lgstaudio-@GST_API_VERSION@ \
|
-lgstaudio-@GST_API_VERSION@ \
|
||||||
|
$(top_builddir)/gst-libs/gst/base/libgstbadbase-$(GST_API_VERSION).la \
|
||||||
$(GST_BASE_LIBS) $(GST_LIBS) $(ORC_LIBS)
|
$(GST_BASE_LIBS) $(GST_LIBS) $(ORC_LIBS)
|
||||||
libgstaudiomixer_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
|
libgstaudiomixer_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,7 +25,7 @@
|
||||||
#define __GST_AUDIO_MIXER_H__
|
#define __GST_AUDIO_MIXER_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/base/gstcollectpads.h>
|
#include <gst/base/gstaggregator.h>
|
||||||
#include <gst/audio/audio.h>
|
#include <gst/audio/audio.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
@ -49,12 +49,7 @@ typedef struct _GstAudioMixerPadClass GstAudioMixerPadClass;
|
||||||
* The audiomixer object structure.
|
* The audiomixer object structure.
|
||||||
*/
|
*/
|
||||||
struct _GstAudioMixer {
|
struct _GstAudioMixer {
|
||||||
GstElement element;
|
GstAggregator element;
|
||||||
|
|
||||||
GstPad *srcpad;
|
|
||||||
GstCollectPads *collect;
|
|
||||||
/* pad counter, used for creating unique request pads */
|
|
||||||
gint padcount;
|
|
||||||
|
|
||||||
/* the next are valid for both int and float */
|
/* the next are valid for both int and float */
|
||||||
GstAudioInfo info;
|
GstAudioInfo info;
|
||||||
|
@ -64,13 +59,9 @@ struct _GstAudioMixer {
|
||||||
/* Buffer starting at offset containing block_size samples */
|
/* Buffer starting at offset containing block_size samples */
|
||||||
GstBuffer *current_buffer;
|
GstBuffer *current_buffer;
|
||||||
|
|
||||||
/* sink event handling */
|
|
||||||
GstSegment segment;
|
|
||||||
volatile gboolean segment_pending;
|
|
||||||
volatile gboolean flush_stop_pending;
|
|
||||||
|
|
||||||
/* current caps */
|
/* current caps */
|
||||||
GstCaps *current_caps;
|
GstCaps *current_caps;
|
||||||
|
gboolean send_caps;
|
||||||
|
|
||||||
/* target caps (set via property) */
|
/* target caps (set via property) */
|
||||||
GstCaps *filter_caps;
|
GstCaps *filter_caps;
|
||||||
|
@ -83,16 +74,10 @@ struct _GstAudioMixer {
|
||||||
|
|
||||||
/* Size in samples that is output per buffer */
|
/* Size in samples that is output per buffer */
|
||||||
guint blocksize;
|
guint blocksize;
|
||||||
|
|
||||||
/* Pending inline events */
|
|
||||||
GList *pending_events;
|
|
||||||
|
|
||||||
gboolean send_stream_start;
|
|
||||||
gboolean send_caps;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstAudioMixerClass {
|
struct _GstAudioMixerClass {
|
||||||
GstElementClass parent_class;
|
GstAggregatorClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_audiomixer_get_type (void);
|
GType gst_audiomixer_get_type (void);
|
||||||
|
@ -105,17 +90,30 @@ GType gst_audiomixer_get_type (void);
|
||||||
#define GST_AUDIO_MIXER_PAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_MIXER_PAD,GstAudioMixerPadClass))
|
#define GST_AUDIO_MIXER_PAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_AUDIO_MIXER_PAD,GstAudioMixerPadClass))
|
||||||
|
|
||||||
struct _GstAudioMixerPad {
|
struct _GstAudioMixerPad {
|
||||||
GstPad parent;
|
GstAggregatorPad parent;
|
||||||
|
|
||||||
gdouble volume;
|
gdouble volume;
|
||||||
gint volume_i32;
|
gint volume_i32;
|
||||||
gint volume_i16;
|
gint volume_i16;
|
||||||
gint volume_i8;
|
gint volume_i8;
|
||||||
gboolean mute;
|
gboolean mute;
|
||||||
|
|
||||||
|
/* < private > */
|
||||||
|
GstBuffer *buffer; /* current buffer we're mixing,
|
||||||
|
for comparison with collect.buffer
|
||||||
|
to see if we need to update our
|
||||||
|
cached values. */
|
||||||
|
guint position, size;
|
||||||
|
|
||||||
|
guint64 output_offset; /* Offset in output segment that
|
||||||
|
collect.pos refers to in the
|
||||||
|
current buffer. */
|
||||||
|
|
||||||
|
guint64 next_offset; /* Next expected offset in the input segment */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstAudioMixerPadClass {
|
struct _GstAudioMixerPadClass {
|
||||||
GstPadClass parent_class;
|
GstAggregatorPadClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_audiomixer_pad_get_type (void);
|
GType gst_audiomixer_pad_get_type (void);
|
||||||
|
|
|
@ -870,12 +870,35 @@ GST_END_TEST;
|
||||||
|
|
||||||
|
|
||||||
static GstBuffer *handoff_buffer = NULL;
|
static GstBuffer *handoff_buffer = NULL;
|
||||||
|
static gboolean
|
||||||
|
_quit (GMainLoop * ml)
|
||||||
|
{
|
||||||
|
g_main_loop_quit (ml);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handoff_buffer_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
|
handoff_buffer_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
|
||||||
gpointer user_data)
|
GstClockTime * wanted_end)
|
||||||
{
|
{
|
||||||
GST_DEBUG ("got buffer %p", buffer);
|
GST_DEBUG ("got buffer -- SIZE: %ld -- %p DURATION is %" GST_TIME_FORMAT
|
||||||
|
" -- WANTED END %" GST_TIME_FORMAT, gst_buffer_get_size (buffer), buffer,
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer)),
|
||||||
|
GST_TIME_ARGS (*wanted_end));
|
||||||
|
|
||||||
gst_buffer_replace (&handoff_buffer, buffer);
|
gst_buffer_replace (&handoff_buffer, buffer);
|
||||||
|
|
||||||
|
|
||||||
|
/* Buffers we push in will be 'cut' into different smaller buffers,
|
||||||
|
* we make sure that the last chunck was pushes before we concider the buffer
|
||||||
|
* we pushed as being done */
|
||||||
|
if (main_loop && *wanted_end
|
||||||
|
&& *wanted_end <=
|
||||||
|
GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer)) {
|
||||||
|
*wanted_end = 0;
|
||||||
|
g_idle_add ((GSourceFunc) _quit, main_loop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if clipping works as expected */
|
/* check if clipping works as expected */
|
||||||
|
@ -891,9 +914,14 @@ GST_START_TEST (test_clip)
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
GMainLoop *local_mainloop;
|
||||||
|
GstClockTime wanted_end = 0;
|
||||||
|
|
||||||
GST_INFO ("preparing test");
|
GST_INFO ("preparing test");
|
||||||
|
|
||||||
|
local_mainloop = g_main_loop_new (NULL, FALSE);
|
||||||
|
main_loop = NULL;
|
||||||
|
|
||||||
/* build pipeline */
|
/* build pipeline */
|
||||||
bin = gst_pipeline_new ("pipeline");
|
bin = gst_pipeline_new ("pipeline");
|
||||||
bus = gst_element_get_bus (bin);
|
bus = gst_element_get_bus (bin);
|
||||||
|
@ -907,7 +935,8 @@ GST_START_TEST (test_clip)
|
||||||
audiomixer = gst_element_factory_make ("audiomixer", "audiomixer");
|
audiomixer = gst_element_factory_make ("audiomixer", "audiomixer");
|
||||||
sink = gst_element_factory_make ("fakesink", "sink");
|
sink = gst_element_factory_make ("fakesink", "sink");
|
||||||
g_object_set (sink, "signal-handoffs", TRUE, NULL);
|
g_object_set (sink, "signal-handoffs", TRUE, NULL);
|
||||||
g_signal_connect (sink, "handoff", (GCallback) handoff_buffer_cb, NULL);
|
g_signal_connect (sink, "handoff", (GCallback) handoff_buffer_cb,
|
||||||
|
&wanted_end);
|
||||||
gst_bin_add_many (GST_BIN (bin), audiomixer, sink, NULL);
|
gst_bin_add_many (GST_BIN (bin), audiomixer, sink, NULL);
|
||||||
|
|
||||||
res = gst_element_link (audiomixer, sink);
|
res = gst_element_link (audiomixer, sink);
|
||||||
|
@ -948,8 +977,19 @@ GST_START_TEST (test_clip)
|
||||||
buffer = gst_buffer_new_and_alloc (44100);
|
buffer = gst_buffer_new_and_alloc (44100);
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = 0;
|
GST_BUFFER_TIMESTAMP (buffer) = 0;
|
||||||
GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
|
GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
|
||||||
GST_DEBUG ("pushing buffer %p", buffer);
|
GST_DEBUG ("pushing buffer %p END is %" GST_TIME_FORMAT,
|
||||||
|
buffer,
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer)));
|
||||||
ret = gst_pad_chain (sinkpad, buffer);
|
ret = gst_pad_chain (sinkpad, buffer);
|
||||||
|
main_loop = local_mainloop;
|
||||||
|
|
||||||
|
/* The aggregation is done in a dedicated thread, so we can't
|
||||||
|
* not know when it is actually going to happen, so we just add\
|
||||||
|
* a 100 ms timeout to be able to then check that the aggregation
|
||||||
|
* did happen as we do not have much other choice.
|
||||||
|
*/
|
||||||
|
g_timeout_add (100, (GSourceFunc) _quit, main_loop);
|
||||||
|
g_main_loop_run (main_loop);
|
||||||
ck_assert_int_eq (ret, GST_FLOW_OK);
|
ck_assert_int_eq (ret, GST_FLOW_OK);
|
||||||
fail_unless (handoff_buffer == NULL);
|
fail_unless (handoff_buffer == NULL);
|
||||||
|
|
||||||
|
@ -957,9 +997,16 @@ GST_START_TEST (test_clip)
|
||||||
buffer = gst_buffer_new_and_alloc (44100);
|
buffer = gst_buffer_new_and_alloc (44100);
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = 900 * GST_MSECOND;
|
GST_BUFFER_TIMESTAMP (buffer) = 900 * GST_MSECOND;
|
||||||
GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
|
GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
|
||||||
GST_DEBUG ("pushing buffer %p", buffer);
|
|
||||||
|
wanted_end = 135 * GST_MSECOND;
|
||||||
|
GST_DEBUG ("pushing buffer %p START %" GST_TIME_FORMAT " -- DURATION is %"
|
||||||
|
GST_TIME_FORMAT, buffer, GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
|
||||||
|
|
||||||
|
main_loop = local_mainloop;
|
||||||
ret = gst_pad_chain (sinkpad, buffer);
|
ret = gst_pad_chain (sinkpad, buffer);
|
||||||
ck_assert_int_eq (ret, GST_FLOW_OK);
|
ck_assert_int_eq (ret, GST_FLOW_OK);
|
||||||
|
g_main_loop_run (main_loop);
|
||||||
fail_unless (handoff_buffer != NULL);
|
fail_unless (handoff_buffer != NULL);
|
||||||
gst_buffer_replace (&handoff_buffer, NULL);
|
gst_buffer_replace (&handoff_buffer, NULL);
|
||||||
|
|
||||||
|
@ -967,18 +1014,28 @@ GST_START_TEST (test_clip)
|
||||||
buffer = gst_buffer_new_and_alloc (44100);
|
buffer = gst_buffer_new_and_alloc (44100);
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
|
GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
|
||||||
GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
|
GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
|
||||||
GST_DEBUG ("pushing buffer %p", buffer);
|
|
||||||
|
wanted_end = 390 * GST_MSECOND;
|
||||||
|
GST_DEBUG ("pushing buffer %p END is %" GST_TIME_FORMAT,
|
||||||
|
buffer,
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer)));
|
||||||
ret = gst_pad_chain (sinkpad, buffer);
|
ret = gst_pad_chain (sinkpad, buffer);
|
||||||
ck_assert_int_eq (ret, GST_FLOW_OK);
|
ck_assert_int_eq (ret, GST_FLOW_OK);
|
||||||
|
g_main_loop_run (main_loop);
|
||||||
fail_unless (handoff_buffer != NULL);
|
fail_unless (handoff_buffer != NULL);
|
||||||
gst_buffer_replace (&handoff_buffer, NULL);
|
gst_buffer_replace (&handoff_buffer, NULL);
|
||||||
|
fail_unless (handoff_buffer == NULL);
|
||||||
|
|
||||||
/* should be clipped and ok */
|
/* should be clipped and ok */
|
||||||
buffer = gst_buffer_new_and_alloc (44100);
|
buffer = gst_buffer_new_and_alloc (44100);
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
|
GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
|
||||||
GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
|
GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
|
||||||
GST_DEBUG ("pushing buffer %p", buffer);
|
GST_DEBUG ("pushing buffer %p END is %" GST_TIME_FORMAT,
|
||||||
|
buffer,
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_PTS (buffer) + GST_BUFFER_DURATION (buffer)));
|
||||||
ret = gst_pad_chain (sinkpad, buffer);
|
ret = gst_pad_chain (sinkpad, buffer);
|
||||||
|
g_timeout_add (100, (GSourceFunc) _quit, main_loop);
|
||||||
|
g_main_loop_run (main_loop);
|
||||||
ck_assert_int_eq (ret, GST_FLOW_OK);
|
ck_assert_int_eq (ret, GST_FLOW_OK);
|
||||||
fail_unless (handoff_buffer == NULL);
|
fail_unless (handoff_buffer == NULL);
|
||||||
|
|
||||||
|
@ -1245,9 +1302,11 @@ GST_START_TEST (test_flush_start_flush_stop)
|
||||||
audiomixer_src = gst_element_get_static_pad (audiomixer, "src");
|
audiomixer_src = gst_element_get_static_pad (audiomixer, "src");
|
||||||
fail_if (GST_PAD_IS_FLUSHING (audiomixer_src));
|
fail_if (GST_PAD_IS_FLUSHING (audiomixer_src));
|
||||||
gst_pad_send_event (sinkpad1, gst_event_new_flush_start ());
|
gst_pad_send_event (sinkpad1, gst_event_new_flush_start ());
|
||||||
fail_unless (GST_PAD_IS_FLUSHING (audiomixer_src));
|
fail_if (GST_PAD_IS_FLUSHING (audiomixer_src));
|
||||||
|
fail_unless (GST_PAD_IS_FLUSHING (sinkpad1));
|
||||||
gst_pad_send_event (sinkpad1, gst_event_new_flush_stop (TRUE));
|
gst_pad_send_event (sinkpad1, gst_event_new_flush_stop (TRUE));
|
||||||
fail_if (GST_PAD_IS_FLUSHING (audiomixer_src));
|
fail_if (GST_PAD_IS_FLUSHING (audiomixer_src));
|
||||||
|
fail_if (GST_PAD_IS_FLUSHING (sinkpad1));
|
||||||
gst_object_unref (audiomixer_src);
|
gst_object_unref (audiomixer_src);
|
||||||
|
|
||||||
gst_element_release_request_pad (audiomixer, sinkpad1);
|
gst_element_release_request_pad (audiomixer, sinkpad1);
|
||||||
|
|
Loading…
Reference in a new issue