remove copyright field from plugins
[platform/upstream/gst-plugins-good.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 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <gst/gst.h>
25 #include <gst/video/video.h>
26 #include "monoscope.h"
27
28 #define GST_TYPE_MONOSCOPE (gst_monoscope_get_type())
29 #define GST_MONOSCOPE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MONOSCOPE,GstMonoscope))
30 #define GST_MONOSCOPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MONOSCOPE,GstMonoscope))
31 #define GST_IS_MONOSCOPE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MONOSCOPE))
32 #define GST_IS_MONOSCOPE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MONOSCOPE))
33
34 typedef struct _GstMonoscope GstMonoscope;
35 typedef struct _GstMonoscopeClass GstMonoscopeClass;
36
37 struct _GstMonoscope {
38   GstElement element;
39
40   /* pads */
41   GstPad *sinkpad,*srcpad;
42   GstBufferPool *peerpool;
43
44   /* the timestamp of the next frame */
45   guint64 next_time;
46   gint16 datain[512];
47
48   /* video state */
49   gfloat fps;
50   gint width;
51   gint height;
52   gboolean first_buffer;
53
54   /* visualisation state */
55   struct monoscope_state * visstate;
56 };
57
58 struct _GstMonoscopeClass {
59   GstElementClass parent_class;
60 };
61
62 GType gst_monoscope_get_type(void);
63
64
65 /* elementfactory information */
66 static GstElementDetails gst_monoscope_details = {
67   "Monoscope",
68   "Visualization",
69   "Displays a highly stabilised waveform of audio input",
70   "Richard Boulton <richard@tartarus.org>"
71 };
72
73 /* signals and args */
74 enum {
75   /* FILL ME */
76   LAST_SIGNAL
77 };
78
79 enum {
80   ARG_0,
81   /* FILL ME */
82 };
83
84 GST_PAD_TEMPLATE_FACTORY (src_template,
85   "src",
86   GST_PAD_SRC,
87   GST_PAD_ALWAYS,
88   GST_CAPS_NEW (
89     "monoscopesrc",
90     "video/x-raw-rgb",
91       "bpp",            GST_PROPS_INT (32),
92       "depth",          GST_PROPS_INT (32),
93       "endianness",     GST_PROPS_INT (G_BIG_ENDIAN),
94       "red_mask",       GST_PROPS_INT (R_MASK_32),
95       "green_mask",     GST_PROPS_INT (G_MASK_32),
96       "blue_mask",      GST_PROPS_INT (B_MASK_32),
97       "width",          GST_PROPS_INT_RANGE (16, 4096),
98       "height",         GST_PROPS_INT_RANGE (16, 4096),
99       "framerate",      GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT)
100   )
101 )
102
103 GST_PAD_TEMPLATE_FACTORY (sink_template,
104   "sink",                                       /* the name of the pads */
105   GST_PAD_SINK,                         /* type of the pad */
106   GST_PAD_ALWAYS,                               /* ALWAYS/SOMETIMES */
107   GST_CAPS_NEW (
108     "monoscopesink",                            /* the name of the caps */
109     "audio/x-raw-int",                          /* the mime type of the caps */
110        /* Properties follow: */
111       "endianness", GST_PROPS_INT (G_BYTE_ORDER),
112       "signed",     GST_PROPS_BOOLEAN (TRUE),
113       "width",      GST_PROPS_INT (16),
114       "depth",      GST_PROPS_INT (16),
115       "rate",       GST_PROPS_INT_RANGE (8000, 96000),
116       "channels",   GST_PROPS_INT (1)
117   )
118 )
119
120
121 static void     gst_monoscope_class_init        (GstMonoscopeClass *klass);
122 static void     gst_monoscope_base_init         (GstMonoscopeClass *klass);
123 static void     gst_monoscope_init              (GstMonoscope *monoscope);
124
125 static void     gst_monoscope_chain             (GstPad *pad, GstData *_data);
126
127 static GstPadLinkReturn 
128                 gst_monoscope_sinkconnect       (GstPad *pad, GstCaps *caps);
129 static GstPadLinkReturn
130                 gst_monoscope_srcconnect        (GstPad *pad, GstCaps *caps);
131
132 static GstElementClass *parent_class = NULL;
133
134 GType
135 gst_monoscope_get_type (void)
136 {
137   static GType type = 0;
138
139   if (!type) {
140     static const GTypeInfo info = {
141       sizeof (GstMonoscopeClass),      
142       (GBaseInitFunc) gst_monoscope_base_init,      
143       NULL,      
144       (GClassInitFunc) gst_monoscope_class_init,
145       NULL,
146       NULL,
147       sizeof (GstMonoscope),
148       0,
149       (GInstanceInitFunc) gst_monoscope_init,
150     };
151     type = g_type_register_static (GST_TYPE_ELEMENT, "GstMonoscope", &info, 0);
152   }
153   return type;
154 }
155
156 static void
157 gst_monoscope_base_init (GstMonoscopeClass *klass)
158 {
159   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
160
161   gst_element_class_add_pad_template (element_class,
162                 GST_PAD_TEMPLATE_GET (src_template));
163   gst_element_class_add_pad_template (element_class,
164                 GST_PAD_TEMPLATE_GET (sink_template));
165   gst_element_class_set_details (element_class, &gst_monoscope_details);
166 }
167
168 static void
169 gst_monoscope_class_init(GstMonoscopeClass *klass)
170 {
171   GObjectClass *gobject_class;
172   GstElementClass *gstelement_class;
173
174   gobject_class = (GObjectClass*) klass;
175   gstelement_class = (GstElementClass*) klass;
176
177   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
178 }
179
180 static void
181 gst_monoscope_init (GstMonoscope *monoscope)
182 {
183   /* create the sink and src pads */
184   monoscope->sinkpad = gst_pad_new_from_template (
185                   GST_PAD_TEMPLATE_GET (sink_template ), "sink");
186   monoscope->srcpad = gst_pad_new_from_template (
187                   GST_PAD_TEMPLATE_GET (src_template ), "src");
188   gst_element_add_pad (GST_ELEMENT (monoscope), monoscope->sinkpad);
189   gst_element_add_pad (GST_ELEMENT (monoscope), monoscope->srcpad);
190
191   gst_pad_set_chain_function (monoscope->sinkpad, gst_monoscope_chain);
192   gst_pad_set_link_function (monoscope->sinkpad, gst_monoscope_sinkconnect);
193   gst_pad_set_link_function (monoscope->srcpad, gst_monoscope_srcconnect);
194
195   monoscope->next_time = 0;
196   monoscope->peerpool = NULL;
197
198   /* reset the initial video state */
199   monoscope->first_buffer = TRUE;
200   monoscope->width = 256;
201   monoscope->height = 128;
202   monoscope->fps = 25.; /* desired frame rate */
203 }
204
205 static GstPadLinkReturn
206 gst_monoscope_sinkconnect (GstPad *pad, GstCaps *caps)
207 {
208   GstMonoscope *monoscope;
209   monoscope = GST_MONOSCOPE (gst_pad_get_parent (pad));
210
211   if (!GST_CAPS_IS_FIXED (caps)) {
212     return GST_PAD_LINK_DELAYED;
213   }
214
215   return GST_PAD_LINK_OK;
216 }
217
218 static GstPadLinkReturn
219 gst_monoscope_negotiate (GstMonoscope *monoscope)
220 {
221   GstCaps *caps;
222
223   caps = GST_CAPS_NEW (
224                      "monoscopesrc",
225                      "video/x-raw-rgb",
226                        "bpp",           GST_PROPS_INT (32), 
227                        "depth",         GST_PROPS_INT (32), 
228                        "endianness",    GST_PROPS_INT (G_BIG_ENDIAN), 
229                        "red_mask",      GST_PROPS_INT (R_MASK_32), 
230                        "green_mask",    GST_PROPS_INT (G_MASK_32), 
231                        "blue_mask",     GST_PROPS_INT (B_MASK_32), 
232                        "width",         GST_PROPS_INT (monoscope->width), 
233                        "height",        GST_PROPS_INT (monoscope->height),
234                "framerate",     GST_PROPS_FLOAT (monoscope->fps)
235                    );
236
237   return gst_pad_try_set_caps (monoscope->srcpad, caps);
238 }
239
240 static GstPadLinkReturn
241 gst_monoscope_srcconnect (GstPad *pad, GstCaps *caps)
242 {
243   GstPadLinkReturn ret;
244   GstMonoscope *monoscope = GST_MONOSCOPE (gst_pad_get_parent (pad));
245
246   if (gst_caps_has_property_typed (caps, "width", GST_PROPS_INT_TYPE)) {
247     gst_caps_get_int (caps, "width", &monoscope->width);
248   }
249   if (gst_caps_has_property_typed (caps, "height", GST_PROPS_INT_TYPE)) {
250     gst_caps_get_int (caps, "height", &monoscope->height);
251   }
252   if (gst_caps_has_property_typed (caps, "framerate", GST_PROPS_FLOAT_TYPE)) {
253     gst_caps_get_float (caps, "framerate", &monoscope->fps);
254   }
255
256   if ((ret = gst_monoscope_negotiate (monoscope)) <= 0)
257     return ret;
258
259   return GST_PAD_LINK_DONE;
260 }
261
262 static void
263 gst_monoscope_chain (GstPad *pad, GstData *_data)
264 {
265   GstBuffer *bufin = GST_BUFFER (_data);
266   GstMonoscope *monoscope;
267   GstBuffer *bufout;
268   guint32 samples_in;
269   gint16 *data;
270   gint i;
271
272   monoscope = GST_MONOSCOPE (gst_pad_get_parent (pad));
273
274   GST_DEBUG ("Monoscope: chainfunc called");
275
276   samples_in = GST_BUFFER_SIZE (bufin) / sizeof (gint16);
277
278   GST_DEBUG ("input buffer has %d samples", samples_in);
279
280   /* FIXME: should really select the first 1024 samples after the timestamp. */
281   if (GST_BUFFER_TIMESTAMP (bufin) < monoscope->next_time || samples_in < 1024) {
282     GST_DEBUG ("timestamp is %" G_GUINT64_FORMAT ": want >= %" G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (bufin), monoscope->next_time);
283     gst_buffer_unref (bufin);
284     return;
285   }
286
287   data = (gint16 *) GST_BUFFER_DATA (bufin);
288   /* FIXME: Select samples in a better way. */
289   for (i=0; i < 512; i++) {
290     monoscope->datain[i] = *data++;
291   }
292
293   if (monoscope->first_buffer) {
294     monoscope->visstate = monoscope_init (monoscope->width, monoscope->height);
295     g_assert(monoscope->visstate != 0);
296     GST_DEBUG ("making new pad");
297     if (!GST_PAD_CAPS (monoscope->srcpad)) {
298       if (gst_monoscope_negotiate (monoscope) <= 0) {
299         gst_element_error (GST_ELEMENT (monoscope), "could not set caps");
300         return;
301       }
302     }
303     monoscope->first_buffer = FALSE;
304   }
305
306   bufout = gst_buffer_new ();
307   GST_BUFFER_SIZE (bufout) = monoscope->width * monoscope->height * 4;
308   GST_BUFFER_DATA (bufout) = (guchar *) monoscope_update (monoscope->visstate, monoscope->datain);
309   GST_BUFFER_TIMESTAMP (bufout) = monoscope->next_time;
310   GST_BUFFER_FLAG_SET (bufout, GST_BUFFER_DONTFREE);
311
312   monoscope->next_time += GST_SECOND / monoscope->fps;
313
314   gst_pad_push (monoscope->srcpad, GST_DATA (bufout));
315
316   gst_buffer_unref (bufin);
317
318   GST_DEBUG ("Monoscope: exiting chainfunc");
319
320 }
321
322 static gboolean
323 plugin_init (GstPlugin *plugin)
324 {
325   return gst_element_register(plugin, "monoscope",
326                               GST_RANK_NONE, GST_TYPE_MONOSCOPE);
327 }
328
329 GST_PLUGIN_DEFINE (
330   GST_VERSION_MAJOR,
331   GST_VERSION_MINOR,
332   "monoscope",
333   "Monoscope visualization",
334   plugin_init,
335   VERSION,
336   "LGPL",
337   GST_PACKAGE,
338   GST_ORIGIN
339 )