blob: ef7fcc3e29c82cab8435f20c3ec5aa96e37212d5 [file] [log] [blame]
From 382b844e4c10638730786d61ccc96c8c6b2f428d Mon Sep 17 00:00:00 2001
From: Philippe Normand <philn@igalia.com>
Date: Tue, 30 Mar 2021 14:40:53 +0100
Subject: [PATCH] debugutils: Add fakeaudiosink element
This element can be useful for CI purposes on machines not running any system
audio daemon. The element implements the GstStreamVolume interface.
---
docs/plugins/gst_plugins_cache.json | 333 ++++++++++++++++++++++++++++
gst/debugutils/debugutilsbad.c | 3 +
gst/debugutils/gstfakeaudiosink.c | 262 ++++++++++++++++++++++
gst/debugutils/gstfakeaudiosink.h | 63 ++++++
gst/debugutils/meson.build | 3 +-
5 files changed, 663 insertions(+), 1 deletion(-)
create mode 100644 gst/debugutils/gstfakeaudiosink.c
create mode 100644 gst/debugutils/gstfakeaudiosink.h
diff --git a/docs/plugins/gst_plugins_cache.json b/docs/plugins/gst_plugins_cache.json
index 02da7405d..f46f2a4c7 100644
--- a/docs/plugins/gst_plugins_cache.json
+++ b/docs/plugins/gst_plugins_cache.json
@@ -8417,6 +8417,339 @@
},
"rank": "none"
},
+ "fakeaudiosink": {
+ "author": "Philippe Normand <philn@igalia.com>",
+ "description": "Fake audio renderer",
+ "hierarchy": [
+ "GstFakeAudioSink",
+ "GstBin",
+ "GstElement",
+ "GstObject",
+ "GInitiallyUnowned",
+ "GObject"
+ ],
+ "interfaces": [
+ "GstChildProxy",
+ "GstStreamVolume"
+ ],
+ "klass": "Audio/Sink",
+ "long-name": "Fake Audio Sink",
+ "pad-templates": {
+ "sink": {
+ "caps": "audio/x-raw:\n format: { F64LE, F64BE, F32LE, F32BE, S32LE, S32BE, U32LE, U32BE, S24_32LE, S24_32BE, U24_32LE, U24_32BE, S24LE, S24BE, U24LE, U24BE, S20LE, S20BE, U20LE, U20BE, S18LE, S18BE, U18LE, U18BE, S16LE, S16BE, U16LE, U16BE, S8, U8 }\n rate: [ 1, 2147483647 ]\n channels: [ 1, 2147483647 ]\n",
+ "direction": "sink",
+ "presence": "always"
+ }
+ },
+ "properties": {
+ "async": {
+ "blurb": "Go asynchronously to PAUSED",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "true",
+ "mutable": "null",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "blocksize": {
+ "blurb": "Size in bytes to pull per buffer (0 = default)",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "4096",
+ "max": "-1",
+ "min": "0",
+ "mutable": "null",
+ "readable": true,
+ "type": "guint",
+ "writable": true
+ },
+ "can-activate-pull": {
+ "blurb": "Can activate in pull mode",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "false",
+ "mutable": "null",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "can-activate-push": {
+ "blurb": "Can activate in push mode",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "true",
+ "mutable": "null",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "drop-out-of-segment": {
+ "blurb": "Drop and don't render / hand off out-of-segment buffers",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "true",
+ "mutable": "null",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "dump": {
+ "blurb": "Dump buffer contents to stdout",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "false",
+ "mutable": "playing",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "enable-last-sample": {
+ "blurb": "Enable the last-sample property",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "true",
+ "mutable": "null",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "last-message": {
+ "blurb": "The message describing current status",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "NULL",
+ "mutable": "null",
+ "readable": true,
+ "type": "gchararray",
+ "writable": false
+ },
+ "last-sample": {
+ "blurb": "The last sample received in the sink",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "mutable": "null",
+ "readable": true,
+ "type": "GstSample",
+ "writable": false
+ },
+ "max-bitrate": {
+ "blurb": "The maximum bits per second to render (0 = disabled)",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "0",
+ "max": "18446744073709551615",
+ "min": "0",
+ "mutable": "null",
+ "readable": true,
+ "type": "guint64",
+ "writable": true
+ },
+ "max-lateness": {
+ "blurb": "Maximum number of nanoseconds that a buffer can be late before it is dropped (-1 unlimited)",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "18446744073709551615",
+ "max": "9223372036854775807",
+ "min": "-1",
+ "mutable": "null",
+ "readable": true,
+ "type": "gint64",
+ "writable": true
+ },
+ "mute": {
+ "blurb": "Mute the audio channel without changing the volume",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "false",
+ "mutable": "null",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "num-buffers": {
+ "blurb": "Number of buffers to accept going EOS",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "-1",
+ "max": "2147483647",
+ "min": "-1",
+ "mutable": "null",
+ "readable": true,
+ "type": "gint",
+ "writable": true
+ },
+ "processing-deadline": {
+ "blurb": "Maximum processing time for a buffer in nanoseconds",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "20000000",
+ "max": "18446744073709551615",
+ "min": "0",
+ "mutable": "null",
+ "readable": true,
+ "type": "guint64",
+ "writable": true
+ },
+ "qos": {
+ "blurb": "Generate Quality-of-Service events upstream",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "true",
+ "mutable": "null",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "render-delay": {
+ "blurb": "Additional render delay of the sink in nanoseconds",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "0",
+ "max": "18446744073709551615",
+ "min": "0",
+ "mutable": "null",
+ "readable": true,
+ "type": "guint64",
+ "writable": true
+ },
+ "signal-handoffs": {
+ "blurb": "Send a signal before unreffing the buffer",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "false",
+ "mutable": "null",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "silent": {
+ "blurb": "Don't produce last_message events",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "true",
+ "mutable": "playing",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "state-error": {
+ "blurb": "Generate a state change error",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "none (0)",
+ "mutable": "null",
+ "readable": true,
+ "type": "GstFakeSinkStateError",
+ "writable": true
+ },
+ "stats": {
+ "blurb": "Sink Statistics",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "application/x-gst-base-sink-stats, average-rate=(double)0, dropped=(guint64)0, rendered=(guint64)0;",
+ "mutable": "null",
+ "readable": true,
+ "type": "GstStructure",
+ "writable": false
+ },
+ "sync": {
+ "blurb": "Sync on the clock",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "true",
+ "mutable": "null",
+ "readable": true,
+ "type": "gboolean",
+ "writable": true
+ },
+ "throttle-time": {
+ "blurb": "The time to keep between rendered buffers (0 = disabled)",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "0",
+ "max": "18446744073709551615",
+ "min": "0",
+ "mutable": "null",
+ "readable": true,
+ "type": "guint64",
+ "writable": true
+ },
+ "ts-offset": {
+ "blurb": "Timestamp offset in nanoseconds",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "0",
+ "max": "9223372036854775807",
+ "min": "-9223372036854775808",
+ "mutable": "null",
+ "readable": true,
+ "type": "gint64",
+ "writable": true
+ },
+ "volume": {
+ "blurb": "The audio volume, 1.0=100%%",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "1",
+ "max": "10",
+ "min": "0",
+ "mutable": "null",
+ "readable": true,
+ "type": "gdouble",
+ "writable": true
+ }
+ },
+ "rank": "none"
+ },
"fakevideosink": {
"author": "Nicolas Dufresne <nicolas.dufresne@collabora.com>",
"description": "Fake video display that allows zero-copy",
diff --git a/gst/debugutils/debugutilsbad.c b/gst/debugutils/debugutilsbad.c
index 3774f7bb5..51682e9c8 100644
--- a/gst/debugutils/debugutilsbad.c
+++ b/gst/debugutils/debugutilsbad.c
@@ -30,6 +30,7 @@ GType gst_compare_get_type (void);
GType gst_debug_spy_get_type (void);
GType gst_error_ignore_get_type (void);
GType gst_watchdog_get_type (void);
+GType gst_fake_audio_sink_get_type (void);
GType gst_fake_video_sink_get_type (void);
GType gst_test_src_bin_get_type (void);
GType gst_clock_select_get_type (void);
@@ -51,6 +52,8 @@ plugin_init (GstPlugin * plugin)
gst_watchdog_get_type ());
gst_element_register (plugin, "errorignore", GST_RANK_NONE,
gst_error_ignore_get_type ());
+ gst_element_register (plugin, "fakeaudiosink", GST_RANK_NONE,
+ gst_fake_audio_sink_get_type ());
gst_element_register (plugin, "fakevideosink", GST_RANK_NONE,
gst_fake_video_sink_get_type ());
gst_element_register (plugin, "testsrcbin", GST_RANK_NONE,
diff --git a/gst/debugutils/gstfakeaudiosink.c b/gst/debugutils/gstfakeaudiosink.c
new file mode 100644
index 000000000..8f8c56bf8
--- /dev/null
+++ b/gst/debugutils/gstfakeaudiosink.c
@@ -0,0 +1,262 @@
+/*
+ * GStreamer
+ * Copyright (C) 2017 Collabora Inc.
+ * Copyright (C) 2021 Igalia S.L.
+ * Author: Philippe Normand <philn@igalia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:element-fakeaudiosink
+ * @title: fakeaudiosink
+ *
+ * This element is the same as fakesink but will pretend to act as an audio sink
+ * supporting the `GstStreamVolume` interface. This is useful for throughput
+ * testing while creating a new pipeline or for CI purposes on machines not
+ * running a real audio daemon.
+ *
+ * ## Example launch lines
+ * |[
+ * gst-launch-1.0 audiotestsrc ! fakeaudiosink
+ * ]|
+ *
+ * Since: 1.20
+ */
+
+#include "gstfakeaudiosink.h"
+
+#include <gst/audio/audio.h>
+
+enum
+{
+ PROP_0,
+ PROP_VOLUME,
+ PROP_MUTE,
+ PROP_LAST
+};
+
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE (GST_AUDIO_FORMATS_ALL)));
+
+G_DEFINE_TYPE_WITH_CODE (GstFakeAudioSink, gst_fake_audio_sink, GST_TYPE_BIN,
+ G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL););
+
+/* TODO complete the types and make this an utility */
+static void
+gst_fake_audio_sink_proxy_properties (GstFakeAudioSink * self,
+ GstElement * child)
+{
+ static gsize initialized = 0;
+
+ if (g_once_init_enter (&initialized)) {
+ GObjectClass *object_class;
+ GParamSpec **properties;
+ guint n_properties, i;
+
+ object_class = G_OBJECT_CLASS (GST_FAKE_AUDIO_SINK_GET_CLASS (self));
+ properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (child),
+ &n_properties);
+
+ for (i = 0; i < n_properties; i++) {
+ guint property_id = i + PROP_LAST;
+
+ if (properties[i]->owner_type != G_OBJECT_TYPE (child) &&
+ properties[i]->owner_type != GST_TYPE_BASE_SINK)
+ continue;
+
+ if (G_IS_PARAM_SPEC_BOOLEAN (properties[i])) {
+ GParamSpecBoolean *prop = G_PARAM_SPEC_BOOLEAN (properties[i]);
+ g_object_class_install_property (object_class, property_id,
+ g_param_spec_boolean (g_param_spec_get_name (properties[i]),
+ g_param_spec_get_nick (properties[i]),
+ g_param_spec_get_blurb (properties[i]),
+ prop->default_value, properties[i]->flags));
+ } else if (G_IS_PARAM_SPEC_INT (properties[i])) {
+ GParamSpecInt *prop = G_PARAM_SPEC_INT (properties[i]);
+ g_object_class_install_property (object_class, property_id,
+ g_param_spec_int (g_param_spec_get_name (properties[i]),
+ g_param_spec_get_nick (properties[i]),
+ g_param_spec_get_blurb (properties[i]),
+ prop->minimum, prop->maximum, prop->default_value,
+ properties[i]->flags));
+ } else if (G_IS_PARAM_SPEC_UINT (properties[i])) {
+ GParamSpecUInt *prop = G_PARAM_SPEC_UINT (properties[i]);
+ g_object_class_install_property (object_class, property_id,
+ g_param_spec_uint (g_param_spec_get_name (properties[i]),
+ g_param_spec_get_nick (properties[i]),
+ g_param_spec_get_blurb (properties[i]),
+ prop->minimum, prop->maximum, prop->default_value,
+ properties[i]->flags));
+ } else if (G_IS_PARAM_SPEC_INT64 (properties[i])) {
+ GParamSpecInt64 *prop = G_PARAM_SPEC_INT64 (properties[i]);
+ g_object_class_install_property (object_class, property_id,
+ g_param_spec_int64 (g_param_spec_get_name (properties[i]),
+ g_param_spec_get_nick (properties[i]),
+ g_param_spec_get_blurb (properties[i]),
+ prop->minimum, prop->maximum, prop->default_value,
+ properties[i]->flags));
+ } else if (G_IS_PARAM_SPEC_UINT64 (properties[i])) {
+ GParamSpecUInt64 *prop = G_PARAM_SPEC_UINT64 (properties[i]);
+ g_object_class_install_property (object_class, property_id,
+ g_param_spec_uint64 (g_param_spec_get_name (properties[i]),
+ g_param_spec_get_nick (properties[i]),
+ g_param_spec_get_blurb (properties[i]),
+ prop->minimum, prop->maximum, prop->default_value,
+ properties[i]->flags));
+ } else if (G_IS_PARAM_SPEC_ENUM (properties[i])) {
+ GParamSpecEnum *prop = G_PARAM_SPEC_ENUM (properties[i]);
+ g_object_class_install_property (object_class, property_id,
+ g_param_spec_enum (g_param_spec_get_name (properties[i]),
+ g_param_spec_get_nick (properties[i]),
+ g_param_spec_get_blurb (properties[i]),
+ properties[i]->value_type, prop->default_value,
+ properties[i]->flags));
+ } else if (G_IS_PARAM_SPEC_STRING (properties[i])) {
+ GParamSpecString *prop = G_PARAM_SPEC_STRING (properties[i]);
+ g_object_class_install_property (object_class, property_id,
+ g_param_spec_string (g_param_spec_get_name (properties[i]),
+ g_param_spec_get_nick (properties[i]),
+ g_param_spec_get_blurb (properties[i]),
+ prop->default_value, properties[i]->flags));
+ } else if (G_IS_PARAM_SPEC_BOXED (properties[i])) {
+ g_object_class_install_property (object_class, property_id,
+ g_param_spec_boxed (g_param_spec_get_name (properties[i]),
+ g_param_spec_get_nick (properties[i]),
+ g_param_spec_get_blurb (properties[i]),
+ properties[i]->value_type, properties[i]->flags));
+ }
+ }
+
+ g_free (properties);
+ g_once_init_leave (&initialized, 1);
+ }
+}
+
+static void
+gst_fake_audio_sink_init (GstFakeAudioSink * self)
+{
+ GstElement *child;
+ GstPadTemplate *template = gst_static_pad_template_get (&sink_factory);
+
+ self->volume = 1.0;
+ self->mute = FALSE;
+
+ child = gst_element_factory_make ("fakesink", "sink");
+
+ if (child) {
+ GstPad *sink_pad = gst_element_get_static_pad (child, "sink");
+ GstPad *ghost_pad;
+
+ /* mimic GstAudioSink base class */
+ g_object_set (child, "qos", TRUE, "sync", TRUE, NULL);
+
+ gst_bin_add (GST_BIN_CAST (self), child);
+
+ ghost_pad = gst_ghost_pad_new_from_template ("sink", sink_pad, template);
+ gst_object_unref (template);
+ gst_element_add_pad (GST_ELEMENT_CAST (self), ghost_pad);
+ gst_object_unref (sink_pad);
+
+ self->child = child;
+
+ gst_fake_audio_sink_proxy_properties (self, child);
+ } else {
+ g_warning ("Check your GStreamer installation, "
+ "core element 'fakesink' is missing.");
+ }
+}
+
+static void
+gst_fake_audio_sink_get_property (GObject * object, guint property_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstFakeAudioSink *self = GST_FAKE_AUDIO_SINK (object);
+
+ switch (property_id) {
+ case PROP_VOLUME:
+ g_value_set_double (value, self->volume);
+ break;
+ case PROP_MUTE:
+ g_value_set_boolean (value, self->mute);
+ break;
+ default:
+ g_object_get_property (G_OBJECT (self->child), pspec->name, value);
+ break;
+ }
+}
+
+static void
+gst_fake_audio_sink_set_property (GObject * object, guint property_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstFakeAudioSink *self = GST_FAKE_AUDIO_SINK (object);
+
+ switch (property_id) {
+ case PROP_VOLUME:
+ self->volume = g_value_get_double (value);
+ break;
+ case PROP_MUTE:
+ self->mute = g_value_get_boolean (value);
+ break;
+ default:
+ g_object_set_property (G_OBJECT (self->child), pspec->name, value);
+ break;
+ }
+}
+
+static void
+gst_fake_audio_sink_class_init (GstFakeAudioSinkClass * klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gst_fake_audio_sink_get_property;
+ object_class->set_property = gst_fake_audio_sink_set_property;
+
+
+ /**
+ * GstFakeAudioSink:volume
+ *
+ * Control the audio volume
+ *
+ * Since: 1.20
+ */
+ g_object_class_install_property (object_class, PROP_VOLUME,
+ g_param_spec_double ("volume", "Volume", "The audio volume, 1.0=100%",
+ 0, 10, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GstFakeAudioSink:mute
+ *
+ * Control the mute state
+ *
+ * Since: 1.20
+ */
+ g_object_class_install_property (object_class, PROP_MUTE,
+ g_param_spec_boolean ("mute", "Mute",
+ "Mute the audio channel without changing the volume", FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+
+ gst_element_class_add_static_pad_template (element_class, &sink_factory);
+ gst_element_class_set_static_metadata (element_class, "Fake Audio Sink",
+ "Audio/Sink", "Fake audio renderer",
+ "Philippe Normand <philn@igalia.com>");
+}
diff --git a/gst/debugutils/gstfakeaudiosink.h b/gst/debugutils/gstfakeaudiosink.h
new file mode 100644
index 000000000..8fd70d911
--- /dev/null
+++ b/gst/debugutils/gstfakeaudiosink.h
@@ -0,0 +1,63 @@
+/*
+ * GStreamer
+ * Copyright (C) 2017 Collabora Inc.
+ * Copyright (C) 2021 Igalia S.L.
+ * Author: Philippe Normand <philn@igalia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _GST_FAKE_AUDIO_SINK_H_
+#define _GST_FAKE_AUDIO_SINK_H_
+
+#include <gst/gst.h>
+
+#define GST_TYPE_FAKE_AUDIO_SINK \
+ (gst_fake_audio_sink_get_type())
+#define GST_FAKE_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_FAKE_AUDIO_SINK, GstFakeAudioSink))
+#define GST_FAKE_AUDIO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_FAKE_AUDIO_SINK, GstFakeAudioSinkClass))
+#define GST_FAKE_AUDIO_SINK_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_FAKE_AUDIO_SINK, GstFakeAudioSinkClass))
+#define GST_IS_FAKE_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_FAKE_AUDIO_SINK))
+#define GST_IS_FAKE_AUDIO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_FAKE_AUDIO_SINK))
+
+G_BEGIN_DECLS
+
+typedef struct _GstFakeAudioSink GstFakeAudioSink;
+typedef struct _GstFakeAudioSinkClass GstFakeAudioSinkClass;
+
+struct _GstFakeAudioSink
+{
+ GstBin parent;
+ GstElement *child;
+ gdouble volume;
+ gboolean mute;
+};
+
+struct _GstFakeAudioSinkClass
+{
+ GstBinClass parent;
+};
+
+GType gst_fake_audio_sink_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/gst/debugutils/meson.build b/gst/debugutils/meson.build
index c863556fe..d05161195 100644
--- a/gst/debugutils/meson.build
+++ b/gst/debugutils/meson.build
@@ -6,6 +6,7 @@ debugutilsbad_sources = [
'gstchecksumsink.c',
'gstchopmydata.c',
'gstcompare.c',
+ 'gstfakeaudiosink.c',
'gstfakevideosink.c',
'gstwatchdog.c',
'gsttestsrcbin.c',
@@ -16,7 +17,7 @@ gstdebugutilsbad = library('gstdebugutilsbad',
debugutilsbad_sources,
c_args : gst_plugins_bad_args,
include_directories : [configinc],
- dependencies : [gstbase_dep, gstvideo_dep, gstnet_dep],
+ dependencies : [gstbase_dep, gstvideo_dep, gstnet_dep, gstaudio_dep],
install : true,
install_dir : plugins_install_dir,
)
--
2.30.2