• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GStreamer
3  * Copyright (C) 2017 Collabora Inc.
4  * Copyright (C) 2021 Igalia S.L.
5  *   Author: Philippe Normand <philn@igalia.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 /**
24  * SECTION:element-fakeaudiosink
25  * @title: fakeaudiosink
26  *
27  * This element is the same as fakesink but will pretend to act as an audio sink
28  * supporting the `GstStreamVolume` interface. This is useful for throughput
29  * testing while creating a new pipeline or for CI purposes on machines not
30  * running a real audio daemon.
31  *
32  * ## Example launch lines
33  * |[
34  * gst-launch-1.0 audiotestsrc ! fakeaudiosink
35  * ]|
36  *
37  * Since: 1.20
38  */
39 
40 #include "gstdebugutilsbadelements.h"
41 #include "gstfakeaudiosink.h"
42 #include "gstfakesinkutils.h"
43 
44 #include <gst/audio/audio.h>
45 
46 enum
47 {
48   PROP_0,
49   PROP_VOLUME,
50   PROP_MUTE,
51   PROP_LAST
52 };
53 
54 
55 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
56     GST_PAD_SINK,
57     GST_PAD_ALWAYS,
58     GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE (GST_AUDIO_FORMATS_ALL)));
59 
60 G_DEFINE_TYPE_WITH_CODE (GstFakeAudioSink, gst_fake_audio_sink, GST_TYPE_BIN,
61     G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL););
62 GST_ELEMENT_REGISTER_DEFINE (fakeaudiosink, "fakeaudiosink",
63     GST_RANK_NONE, gst_fake_audio_sink_get_type ());
64 
65 static void
gst_fake_audio_sink_proxy_properties(GstFakeAudioSink * self,GstElement * child)66 gst_fake_audio_sink_proxy_properties (GstFakeAudioSink * self,
67     GstElement * child)
68 {
69   static gsize initialized = 0;
70 
71   if (g_once_init_enter (&initialized)) {
72     gst_fake_sink_proxy_properties (GST_ELEMENT_CAST (self), child, PROP_LAST);
73     g_once_init_leave (&initialized, 1);
74   }
75 }
76 
77 static void
gst_fake_audio_sink_init(GstFakeAudioSink * self)78 gst_fake_audio_sink_init (GstFakeAudioSink * self)
79 {
80   GstElement *child;
81   GstPadTemplate *template = gst_static_pad_template_get (&sink_factory);
82 
83   self->volume = 1.0;
84   self->mute = FALSE;
85 
86   child = gst_element_factory_make ("fakesink", "sink");
87 
88   if (child) {
89     GstPad *sink_pad = gst_element_get_static_pad (child, "sink");
90     GstPad *ghost_pad;
91 
92     /* mimic GstAudioSink base class */
93     g_object_set (child, "qos", TRUE, "sync", TRUE, NULL);
94 
95     gst_bin_add (GST_BIN_CAST (self), child);
96 
97     ghost_pad = gst_ghost_pad_new_from_template ("sink", sink_pad, template);
98     gst_object_unref (template);
99     gst_element_add_pad (GST_ELEMENT_CAST (self), ghost_pad);
100     gst_object_unref (sink_pad);
101 
102     self->child = child;
103 
104     gst_fake_audio_sink_proxy_properties (self, child);
105   } else {
106     g_warning ("Check your GStreamer installation, "
107         "core element 'fakesink' is missing.");
108   }
109 }
110 
111 static void
gst_fake_audio_sink_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)112 gst_fake_audio_sink_get_property (GObject * object, guint property_id,
113     GValue * value, GParamSpec * pspec)
114 {
115   GstFakeAudioSink *self = GST_FAKE_AUDIO_SINK (object);
116 
117   switch (property_id) {
118     case PROP_VOLUME:
119       g_value_set_double (value, self->volume);
120       break;
121     case PROP_MUTE:
122       g_value_set_boolean (value, self->mute);
123       break;
124     default:
125       g_object_get_property (G_OBJECT (self->child), pspec->name, value);
126       break;
127   }
128 }
129 
130 static void
gst_fake_audio_sink_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)131 gst_fake_audio_sink_set_property (GObject * object, guint property_id,
132     const GValue * value, GParamSpec * pspec)
133 {
134   GstFakeAudioSink *self = GST_FAKE_AUDIO_SINK (object);
135 
136   switch (property_id) {
137     case PROP_VOLUME:
138       self->volume = g_value_get_double (value);
139       break;
140     case PROP_MUTE:
141       self->mute = g_value_get_boolean (value);
142       break;
143     default:
144       g_object_set_property (G_OBJECT (self->child), pspec->name, value);
145       break;
146   }
147 }
148 
149 static void
gst_fake_audio_sink_class_init(GstFakeAudioSinkClass * klass)150 gst_fake_audio_sink_class_init (GstFakeAudioSinkClass * klass)
151 {
152   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
153   GObjectClass *object_class = G_OBJECT_CLASS (klass);
154 
155   object_class->get_property = gst_fake_audio_sink_get_property;
156   object_class->set_property = gst_fake_audio_sink_set_property;
157 
158 
159   /**
160    * GstFakeAudioSink:volume
161    *
162    * Control the audio volume
163    *
164    * Since: 1.20
165    */
166   g_object_class_install_property (object_class, PROP_VOLUME,
167       g_param_spec_double ("volume", "Volume", "The audio volume, 1.0=100%",
168           0, 10, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
169 
170   /**
171    * GstFakeAudioSink:mute
172    *
173    * Control the mute state
174    *
175    * Since: 1.20
176    */
177   g_object_class_install_property (object_class, PROP_MUTE,
178       g_param_spec_boolean ("mute", "Mute",
179           "Mute the audio channel without changing the volume", FALSE,
180           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
181 
182 
183   gst_element_class_add_static_pad_template (element_class, &sink_factory);
184   gst_element_class_set_static_metadata (element_class, "Fake Audio Sink",
185       "Audio/Sink", "Fake audio renderer",
186       "Philippe Normand <philn@igalia.com>");
187 }
188