filter newlines out of GST_DEBUG statements to reflect new core behavior fixes to...
[platform/upstream/gstreamer.git] / gst / monoscope / gstmonoscope.c
1 /* gstmonoscope.c: implementation of monoscope drawing element
2  * Copyright (C) <2002> Richard Boulton <richard@tartarus.org>
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 <config.h>
21 #include <gst/gst.h>
22
23 #include "monoscope.h"
24
25 #define GST_TYPE_MONOSCOPE (gst_monoscope_get_type())
26 #define GST_MONOSCOPE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MONOSCOPE,GstMonoscope))
27 #define GST_MONOSCOPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MONOSCOPE,GstMonoscope))
28 #define GST_IS_MONOSCOPE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MONOSCOPE))
29 #define GST_IS_MONOSCOPE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MONOSCOPE))
30
31 typedef struct _GstMonoscope GstMonoscope;
32 typedef struct _GstMonoscopeClass GstMonoscopeClass;
33
34 struct _GstMonoscope {
35   GstElement element;
36
37   /* pads */
38   GstPad *sinkpad,*srcpad;
39   GstBufferPool *peerpool;
40
41   /* the timestamp of the next frame */
42   guint64 next_time;
43   gint16 datain[512];
44
45   /* video state */
46   gint fps;
47   gint width;
48   gint height;
49   gboolean first_buffer;
50
51   /* visualisation state */
52   struct monoscope_state * visstate;
53 };
54
55 struct _GstMonoscopeClass {
56   GstElementClass parent_class;
57 };
58
59 GType gst_monoscope_get_type(void);
60
61
62 /* elementfactory information */
63 static GstElementDetails gst_monoscope_details = {
64   "Monoscope",
65   "Filter/Visualization",
66   "Displays a highly stabilised waveform of audio input",
67   VERSION,
68   "Richard Boulton <richard@tartarus.org>",
69   "(C) 2002",
70 };
71
72 /* signals and args */
73 enum {
74   /* FILL ME */
75   LAST_SIGNAL
76 };
77
78 enum {
79   ARG_0,
80   ARG_WIDTH,
81   ARG_HEIGHT,
82   ARG_FPS,
83   /* FILL ME */
84 };
85
86 GST_PADTEMPLATE_FACTORY (src_template,
87   "src",
88   GST_PAD_SRC,
89   GST_PAD_ALWAYS,
90   GST_CAPS_NEW (
91     "monoscopesrc",
92     "video/raw",
93       "format",         GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")),
94       "bpp",            GST_PROPS_INT (32),
95       "depth",          GST_PROPS_INT (32),
96       "endianness",     GST_PROPS_INT (G_BYTE_ORDER),
97       "red_mask",       GST_PROPS_INT (0xff0000),
98       "green_mask",     GST_PROPS_INT (0xff00),
99       "blue_mask",      GST_PROPS_INT (0xff),
100       "width",          GST_PROPS_INT_RANGE (16, 4096),
101       "height",         GST_PROPS_INT_RANGE (16, 4096)
102   )
103 )
104
105 GST_PADTEMPLATE_FACTORY (sink_template,
106   "sink",                                       /* the name of the pads */
107   GST_PAD_SINK,                         /* type of the pad */
108   GST_PAD_ALWAYS,                               /* ALWAYS/SOMETIMES */
109   GST_CAPS_NEW (
110     "monoscopesink",                            /* the name of the caps */
111     "audio/raw",                                /* the mime type of the caps */
112        /* Properties follow: */
113       "format",     GST_PROPS_STRING ("int"),
114       "law",        GST_PROPS_INT (0),
115       "endianness", GST_PROPS_INT (G_BYTE_ORDER),
116       "signed",     GST_PROPS_BOOLEAN (TRUE),
117       "width",      GST_PROPS_INT (16),
118       "depth",      GST_PROPS_INT (16),
119       "rate",       GST_PROPS_INT_RANGE (8000, 96000),
120       "channels",   GST_PROPS_INT (1)
121   )
122 )
123
124
125 static void             gst_monoscope_class_init        (GstMonoscopeClass *klass);
126 static void             gst_monoscope_init              (GstMonoscope *monoscope);
127
128 static void             gst_monoscope_set_property      (GObject *object, guint prop_id, 
129                                                  const GValue *value, GParamSpec *pspec);
130 static void             gst_monoscope_get_property      (GObject *object, guint prop_id, 
131                                                  GValue *value, GParamSpec *pspec);
132
133 static void             gst_monoscope_chain             (GstPad *pad, GstBuffer *buf);
134
135 static GstPadConnectReturn 
136                         gst_monoscope_sinkconnect       (GstPad *pad, GstCaps *caps);
137
138 static GstElementClass *parent_class = NULL;
139
140 GType
141 gst_monoscope_get_type (void)
142 {
143   static GType type = 0;
144
145   if (!type) {
146     static const GTypeInfo info = {
147       sizeof (GstMonoscopeClass),      
148       NULL,      
149       NULL,      
150       (GClassInitFunc) gst_monoscope_class_init,
151       NULL,
152       NULL,
153       sizeof (GstMonoscope),
154       0,
155       (GInstanceInitFunc) gst_monoscope_init,
156     };
157     type = g_type_register_static (GST_TYPE_ELEMENT, "GstMonoscope", &info, 0);
158   }
159   return type;
160 }
161
162 static void
163 gst_monoscope_class_init(GstMonoscopeClass *klass)
164 {
165   GObjectClass *gobject_class;
166   GstElementClass *gstelement_class;
167
168   gobject_class = (GObjectClass*) klass;
169   gstelement_class = (GstElementClass*) klass;
170
171   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
172
173   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_WIDTH,
174     g_param_spec_int ("width","Width","The Width",
175                        1, 2048, 256, G_PARAM_READWRITE));
176   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HEIGHT,
177     g_param_spec_int ("height","Height","The height",
178                        1, 2048, 128, G_PARAM_READWRITE));
179   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FPS,
180     g_param_spec_int ("fps","FPS","Frames per second",
181                        1, 100, 25, G_PARAM_READWRITE));
182
183   gobject_class->set_property = gst_monoscope_set_property;
184   gobject_class->get_property = gst_monoscope_get_property;
185 }
186
187 static void
188 gst_monoscope_init (GstMonoscope *monoscope)
189 {
190   /* create the sink and src pads */
191   monoscope->sinkpad = gst_pad_new_from_template (
192                   GST_PADTEMPLATE_GET (sink_template ), "sink");
193   monoscope->srcpad = gst_pad_new_from_template (
194                   GST_PADTEMPLATE_GET (src_template ), "src");
195   gst_element_add_pad (GST_ELEMENT (monoscope), monoscope->sinkpad);
196   gst_element_add_pad (GST_ELEMENT (monoscope), monoscope->srcpad);
197
198   gst_pad_set_chain_function (monoscope->sinkpad, gst_monoscope_chain);
199   gst_pad_set_connect_function (monoscope->sinkpad, gst_monoscope_sinkconnect);
200
201   monoscope->next_time = 0;
202   monoscope->peerpool = NULL;
203
204   /* reset the initial video state */
205   monoscope->first_buffer = TRUE;
206   monoscope->width = 256;
207   monoscope->height = 128;
208   monoscope->fps = 25; /* desired frame rate */
209
210 }
211
212 static GstPadConnectReturn
213 gst_monoscope_sinkconnect (GstPad *pad, GstCaps *caps)
214 {
215   GstMonoscope *monoscope;
216   monoscope = GST_MONOSCOPE (gst_pad_get_parent (pad));
217
218   if (!GST_CAPS_IS_FIXED (caps)) {
219     return GST_PAD_CONNECT_DELAYED;
220   }
221
222   return GST_PAD_CONNECT_OK;
223 }
224
225 static void
226 gst_monoscope_chain (GstPad *pad, GstBuffer *bufin)
227 {
228   GstMonoscope *monoscope;
229   GstBuffer *bufout;
230   guint32 samples_in;
231   gint16 *data;
232   gint i;
233
234   monoscope = GST_MONOSCOPE (gst_pad_get_parent (pad));
235
236   GST_DEBUG (0, "Monoscope: chainfunc called");
237
238   samples_in = GST_BUFFER_SIZE (bufin) / sizeof (gint16);
239
240   GST_DEBUG (0, "input buffer has %d samples", samples_in);
241
242   /* FIXME: should really select the first 1024 samples after the timestamp. */
243   if (GST_BUFFER_TIMESTAMP (bufin) < monoscope->next_time || samples_in < 1024) {
244     GST_DEBUG (0, "timestamp is %llu: want >= %llu", GST_BUFFER_TIMESTAMP (bufin), monoscope->next_time);
245     gst_buffer_unref (bufin);
246     return;
247   }
248
249   data = (gint16 *) GST_BUFFER_DATA (bufin);
250   /* FIXME: Select samples in a better way. */
251   for (i=0; i < 512; i++) {
252     monoscope->datain[i] = *data++;
253   }
254
255   if (monoscope->first_buffer) {
256     GstCaps *caps;
257
258     monoscope->visstate = monoscope_init (monoscope->width, monoscope->height);
259     g_assert(monoscope->visstate != 0);
260     GST_DEBUG (0, "making new pad");
261
262     caps = GST_CAPS_NEW (
263                      "monoscopesrc",
264                      "video/raw",
265                        "format",        GST_PROPS_FOURCC (GST_STR_FOURCC ("RGB ")), 
266                        "bpp",           GST_PROPS_INT (32), 
267                        "depth",         GST_PROPS_INT (32), 
268                        "endianness",    GST_PROPS_INT (G_BYTE_ORDER), 
269                        "red_mask",      GST_PROPS_INT (0xff0000), 
270                        "green_mask",    GST_PROPS_INT (0x00ff00), 
271                        "blue_mask",     GST_PROPS_INT (0x0000ff), 
272                        "width",         GST_PROPS_INT (monoscope->width), 
273                        "height",        GST_PROPS_INT (monoscope->height)
274                    );
275
276     if (!gst_pad_try_set_caps (monoscope->srcpad, caps)) {
277       gst_element_error (GST_ELEMENT (monoscope), "could not set caps");
278       return;
279     }
280     monoscope->first_buffer = FALSE;
281   }
282
283   bufout = gst_buffer_new ();
284   GST_BUFFER_SIZE (bufout) = monoscope->width * monoscope->height * 4;
285   GST_BUFFER_DATA (bufout) = (guchar *) monoscope_update (monoscope->visstate, monoscope->datain);
286   GST_BUFFER_TIMESTAMP (bufout) = monoscope->next_time;
287   GST_BUFFER_FLAG_SET (bufout, GST_BUFFER_DONTFREE);
288
289   monoscope->next_time += 1000000LL / monoscope->fps;
290
291   gst_pad_push (monoscope->srcpad, bufout);
292
293   gst_buffer_unref (bufin);
294
295   GST_DEBUG (0, "Monoscope: exiting chainfunc");
296
297 }
298
299 static void
300 gst_monoscope_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
301 {
302   GstMonoscope *monoscope;
303
304   /* it's not null if we got it, but it might not be ours */
305   g_return_if_fail (GST_IS_MONOSCOPE (object));
306   monoscope = GST_MONOSCOPE (object);
307
308   switch (prop_id) {
309     case ARG_WIDTH:
310       monoscope->width = g_value_get_int (value);
311       break;
312     case ARG_HEIGHT:
313       monoscope->height = g_value_get_int (value);
314       break;
315     case ARG_FPS:
316       monoscope->fps = g_value_get_int (value);
317       break;
318     default:
319       break;
320   }
321 }
322
323 static void
324 gst_monoscope_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
325 {
326   GstMonoscope *monoscope;
327
328   /* it's not null if we got it, but it might not be ours */
329   g_return_if_fail (GST_IS_MONOSCOPE (object));
330   monoscope = GST_MONOSCOPE (object);
331
332   switch (prop_id) {
333     case ARG_WIDTH:
334       g_value_set_int (value, monoscope->width);
335       break;
336     case ARG_HEIGHT:
337       g_value_set_int (value, monoscope->height);
338       break;
339     case ARG_FPS:
340       g_value_set_int (value, monoscope->fps);
341       break;
342     default:
343       break;
344   }
345 }
346
347 static gboolean
348 plugin_init (GModule *module, GstPlugin *plugin)
349 {
350   GstElementFactory *factory;
351
352   /* create an elementfactory for the monoscope element */
353   factory = gst_elementfactory_new("monoscope",GST_TYPE_MONOSCOPE,
354                                    &gst_monoscope_details);
355   g_return_val_if_fail(factory != NULL, FALSE);
356
357   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_template));
358   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_template));
359
360   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
361
362   return TRUE;
363 }
364
365 GstPluginDesc plugin_desc = {
366   GST_VERSION_MAJOR,
367   GST_VERSION_MINOR,
368   "monoscope",
369   plugin_init
370 };