s/Gnome-Streamer/GStreamer/
[platform/upstream/gst-plugins-good.git] / gst / level / gstlevel.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <gst/gst.h>
21 #include "gstlevel.h"
22 #include "math.h"
23
24
25 static GstElementDetails level_details = {
26   "Level",
27   "Filter/Effect",
28   "RMS Level indicator for audio/raw",
29   VERSION,
30   "Thomas <thomas@apestaart.org>",
31   "(C) 2001",
32 };
33
34
35 /* Filter signals and args */
36 enum {
37   /* FILL ME */
38   LAST_SIGNAL
39 };
40
41 enum {
42   ARG_0
43 };
44
45 static GstPadTemplate*
46 level_src_factory (void)
47 {
48   static GstPadTemplate *template = NULL;
49
50   if (!template) {
51     template = gst_padtemplate_new (
52       "src",
53       GST_PAD_SRC,
54       GST_PAD_ALWAYS,
55       gst_caps_new (
56         "test_src",
57         "audio/raw",
58         gst_props_new (
59           "channels", GST_PROPS_INT_RANGE (1, 2),
60           NULL)),
61       NULL);
62   }
63   return template;
64 }
65
66 static GstPadTemplate*
67 level_sink_factory (void)
68 {
69   static GstPadTemplate *template = NULL;
70
71   if (!template) {
72     template = gst_padtemplate_new (
73       "sink",
74       GST_PAD_SINK,
75       GST_PAD_ALWAYS,
76       gst_caps_new (
77         "test_src",
78         "audio/raw",
79         gst_props_new (
80           "channels", GST_PROPS_INT_RANGE (1, 2),
81           NULL)),
82       NULL);
83   }
84   return template;
85 }
86
87 static void             gst_level_class_init            (GstLevelClass *klass);
88 static void             gst_level_init                  (GstLevel *filter);
89
90 static void             gst_level_set_property                  (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
91 static void             gst_level_get_property                  (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
92
93 static void             gst_level_chain                 (GstPad *pad, GstBuffer *buf);
94 static void inline      gst_level_fast_16bit_chain      (gint16* data, gint16** out_data, 
95                                                                  guint numsamples);
96 static void inline      gst_level_fast_8bit_chain               (gint8* data, gint8** out_data,
97                                                                  guint numsamples);
98
99 static GstElementClass *parent_class = NULL;
100 /*static guint gst_filter_signals[LAST_SIGNAL] = { 0 }; */
101
102 GType
103 gst_level_get_type(void) {
104   static GType level_type = 0;
105
106   if (!level_type) {
107     static const GTypeInfo level_info = {
108       sizeof(GstLevelClass),      NULL,
109       NULL,
110       (GClassInitFunc)gst_level_class_init,
111       NULL,
112       NULL,
113       sizeof(GstLevel),
114       0,
115       (GInstanceInitFunc)gst_level_init,
116     };
117     level_type = g_type_register_static(GST_TYPE_ELEMENT, "GstLevel", &level_info, 0);
118   }
119   return level_type;
120 }
121
122 static void
123 gst_level_class_init (GstLevelClass *klass)
124 {
125   GObjectClass *gobject_class;
126   GstElementClass *gstelement_class;
127
128   gobject_class = (GObjectClass*)klass;
129   gstelement_class = (GstElementClass*)klass;
130
131   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
132
133   gobject_class->set_property = gst_level_set_property;
134   gobject_class->get_property = gst_level_get_property;
135 }
136
137 static void
138 gst_level_init (GstLevel *filter)
139 {
140   filter->sinkpad = gst_pad_new_from_template(level_sink_factory (),"sink");
141   filter->srcpad = gst_pad_new_from_template(level_src_factory (),"src");
142
143   gst_element_add_pad(GST_ELEMENT(filter),filter->sinkpad);
144   gst_pad_set_chain_function(filter->sinkpad,gst_level_chain);
145   filter->srcpad = gst_pad_new("src",GST_PAD_SRC);
146   gst_element_add_pad(GST_ELEMENT(filter),filter->srcpad);
147 }
148
149 static void
150 gst_level_chain (GstPad *pad,GstBuffer *buf)
151 {
152   GstLevel *filter;
153   gint16 *in_data;
154   gint16 *out_data;
155   GstBuffer* outbuf;
156   gint width;
157
158   GstCaps *caps;
159
160   g_return_if_fail(pad != NULL);
161   g_return_if_fail(GST_IS_PAD(pad));
162   g_return_if_fail(buf != NULL);
163
164   filter = GST_LEVEL(GST_OBJECT_PARENT (pad));
165   g_return_if_fail(filter != NULL);
166   g_return_if_fail(GST_IS_LEVEL(filter));
167
168   caps = NULL;
169   caps = GST_PAD_CAPS(pad);
170   if (caps == NULL)
171   {
172     /* FIXME : Please change this to a better warning method ! */
173     printf ("WARNING : chain : Could not get caps of pad !\n");
174   }
175
176   width = gst_caps_get_int(caps, "width");
177
178   in_data = (gint16 *)GST_BUFFER_DATA(buf);
179   outbuf=gst_buffer_new();
180   GST_BUFFER_DATA(outbuf) = (gchar*)g_new(gint16,GST_BUFFER_SIZE(buf)/2);
181   GST_BUFFER_SIZE(outbuf) = GST_BUFFER_SIZE(buf);
182
183   out_data = (gint16*)GST_BUFFER_DATA(outbuf);
184   
185   switch (width) {
186     case 16:
187         gst_level_fast_16bit_chain(in_data,&out_data,GST_BUFFER_SIZE(buf)/2);
188         break;
189     case 8:
190         gst_level_fast_8bit_chain((gint8*)in_data,(gint8**)&out_data,GST_BUFFER_SIZE(buf));
191         break;
192   }
193   gst_buffer_unref(buf);
194   gst_pad_push(filter->srcpad,outbuf);
195 }
196
197 static void inline
198 gst_level_fast_16bit_chain(gint16* in_data, gint16** out_data, 
199                                  guint num_samples)
200 #include "filter.func"
201
202 static void inline
203 gst_level_fast_8bit_chain(gint8* in_data, gint8** out_data,
204                                 guint num_samples)
205 #include "filter.func"
206
207 static void
208 gst_level_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
209 {
210   GstLevel *filter;
211
212   /* it's not null if we got it, but it might not be ours */
213   g_return_if_fail(GST_IS_LEVEL(object));
214   filter = GST_LEVEL(object);
215
216   switch (prop_id) {
217     default:
218       break;
219   }
220 }
221
222 static void
223 gst_level_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
224 {
225   GstLevel *filter;
226
227   /* it's not null if we got it, but it might not be ours */
228   g_return_if_fail(GST_IS_LEVEL(object));
229   filter = GST_LEVEL(object);
230
231   switch (prop_id) {
232     default:
233       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
234       break;
235   }
236 }
237
238 static gboolean
239 plugin_init (GModule *module, GstPlugin *plugin)
240 {
241   GstElementFactory *factory;
242
243   factory = gst_elementfactory_new("level",GST_TYPE_LEVEL,
244                                    &level_details);
245   g_return_val_if_fail(factory != NULL, FALSE);
246   
247   gst_elementfactory_add_padtemplate (factory, level_src_factory ());
248   gst_elementfactory_add_padtemplate (factory, level_sink_factory ());
249
250   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
251
252   return TRUE;
253 }
254
255 GstPluginDesc plugin_desc = {
256   GST_VERSION_MAJOR,
257   GST_VERSION_MINOR,
258   "level",
259   plugin_init
260 };