audiovisualizer: shorten base class name
[platform/upstream/gstreamer.git] / ext / libvisual / visual.c
1 /* GStreamer
2  * Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
3  *               2012 Stefan Sauer <ensonic@users.sf.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "visual.h"
26
27 GST_DEBUG_CATEGORY_EXTERN (libvisual_debug);
28 #define GST_CAT_DEFAULT (libvisual_debug)
29
30 /* amounf of samples before we can feed libvisual */
31 #define VISUAL_SAMPLES  512
32
33 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
34     GST_PAD_SRC,
35     GST_PAD_ALWAYS,
36     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (" { "
37 #if G_BYTE_ORDER == G_BIG_ENDIAN
38             "\"xRGB\", " "\"RGB\", "
39 #else
40             "\"BGRx\", " "\"BGR\", "
41 #endif
42             "\"RGB16\" } "))
43     );
44
45 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
46     GST_PAD_SINK,
47     GST_PAD_ALWAYS,
48     GST_STATIC_CAPS ("audio/x-raw, "
49         "format = (string) " GST_AUDIO_NE (S16) ", "
50         "layout = (string) interleaved, " "channels = (int) { 1, 2 }, "
51         "channel-mask = (bitmask) 0x3, "
52 #if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
53         "rate = (int) { 8000, 11250, 22500, 32000, 44100, 48000, 96000 }"
54 #else
55         "rate = (int) [ 1000, MAX ]"
56 #endif
57     )
58     );
59
60
61 static void gst_visual_init (GstVisual * visual);
62 static void gst_visual_finalize (GObject * object);
63
64 static gboolean gst_visual_setup (GstAudioVisualizer * bscope);
65 static gboolean gst_visual_render (GstAudioVisualizer * bscope,
66     GstBuffer * audio, GstBuffer * video);
67
68 static GstElementClass *parent_class = NULL;
69
70 GType
71 gst_visual_get_type (void)
72 {
73   static GType type = 0;
74
75   if (G_UNLIKELY (type == 0)) {
76     static const GTypeInfo info = {
77       sizeof (GstVisualClass),
78       NULL,
79       NULL,
80       gst_visual_class_init,
81       NULL,
82       NULL,
83       sizeof (GstVisual),
84       0,
85       (GInstanceInitFunc) gst_visual_init,
86     };
87
88     type =
89         g_type_register_static (GST_TYPE_AUDIO_VISUALIZER, "GstVisual",
90         &info, 0);
91   }
92   return type;
93 }
94
95 void
96 gst_visual_class_init (gpointer g_class, gpointer class_data)
97 {
98   GObjectClass *gobject_class = (GObjectClass *) g_class;
99   GstElementClass *element_class = (GstElementClass *) g_class;
100   GstAudioVisualizerClass *scope_class = (GstAudioVisualizerClass *) g_class;
101   GstVisualClass *klass = (GstVisualClass *) g_class;
102
103   klass->plugin = class_data;
104
105   if (class_data == NULL) {
106     parent_class = g_type_class_peek_parent (g_class);
107   } else {
108     gchar *longname = g_strdup_printf ("libvisual %s plugin v.%s",
109         klass->plugin->info->name, klass->plugin->info->version);
110
111     /* FIXME: improve to only register what plugin supports? */
112     gst_element_class_add_pad_template (element_class,
113         gst_static_pad_template_get (&src_template));
114     gst_element_class_add_pad_template (element_class,
115         gst_static_pad_template_get (&sink_template));
116
117     gst_element_class_set_static_metadata (element_class,
118         longname, "Visualization",
119         klass->plugin->info->about, "Benjamin Otte <otte@gnome.org>");
120
121     g_free (longname);
122   }
123
124   gobject_class->finalize = gst_visual_finalize;
125
126   scope_class->setup = GST_DEBUG_FUNCPTR (gst_visual_setup);
127   scope_class->render = GST_DEBUG_FUNCPTR (gst_visual_render);
128 }
129
130 static void
131 gst_visual_init (GstVisual * visual)
132 {
133   /* do nothing */
134 }
135
136 static void
137 gst_visual_clear_actors (GstVisual * visual)
138 {
139   if (visual->actor) {
140     visual_object_unref (VISUAL_OBJECT (visual->actor));
141     visual->actor = NULL;
142   }
143   if (visual->video) {
144     visual_object_unref (VISUAL_OBJECT (visual->video));
145     visual->video = NULL;
146   }
147   if (visual->audio) {
148     visual_object_unref (VISUAL_OBJECT (visual->audio));
149     visual->audio = NULL;
150   }
151 }
152
153 static void
154 gst_visual_finalize (GObject * object)
155 {
156   GstVisual *visual = GST_VISUAL (object);
157
158   gst_visual_clear_actors (visual);
159
160   GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
161 }
162
163 static gboolean
164 gst_visual_setup (GstAudioVisualizer * bscope)
165 {
166   GstVisual *visual = GST_VISUAL (bscope);
167   gint pitch, depth;
168
169   gst_visual_clear_actors (visual);
170
171   depth = bscope->vinfo.finfo->pixel_stride[0];
172   if (bscope->vinfo.finfo->bits >= 8) {
173     depth *= 8;
174   }
175
176   visual->actor =
177       visual_actor_new (GST_VISUAL_GET_CLASS (visual)->plugin->info->plugname);
178   visual->video = visual_video_new ();
179   visual->audio = visual_audio_new ();
180   /* can't have a play without actors */
181   if (!visual->actor || !visual->video)
182     goto no_actors;
183
184   if (visual_actor_realize (visual->actor) != 0)
185     goto no_realize;
186
187   visual_actor_set_video (visual->actor, visual->video);
188
189   visual_video_set_depth (visual->video,
190       visual_video_depth_enum_from_value (depth));
191   visual_video_set_dimension (visual->video, bscope->width, bscope->height);
192   pitch = GST_ROUND_UP_4 (bscope->width * visual->video->bpp);
193   visual_video_set_pitch (visual->video, pitch);
194   visual_actor_video_negotiate (visual->actor, 0, FALSE, FALSE);
195
196   GST_DEBUG_OBJECT (visual, "WxH: %dx%d, bpp: %d, pitch: %d, depth: %d",
197       bscope->width, bscope->height, visual->video->bpp, pitch, depth);
198
199   return TRUE;
200   /* ERRORS */
201 no_actors:
202   {
203     GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
204         ("could not create actors"));
205     gst_visual_clear_actors (visual);
206     return FALSE;
207   }
208 no_realize:
209   {
210     GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
211         ("could not realize actor"));
212     gst_visual_clear_actors (visual);
213     return FALSE;
214   }
215 }
216
217 static gboolean
218 gst_visual_render (GstAudioVisualizer * bscope, GstBuffer * audio,
219     GstBuffer * video)
220 {
221   GstVisual *visual = GST_VISUAL (bscope);
222   GstMapInfo amap, vmap;
223   const guint16 *adata;
224   gint i, channels;
225   gboolean res = TRUE;
226
227   gst_buffer_map (audio, &amap, GST_MAP_READ);
228   gst_buffer_map (video, &vmap, GST_MAP_WRITE);
229
230   visual_video_set_buffer (visual->video, vmap.data);
231
232   channels = GST_AUDIO_INFO_CHANNELS (&bscope->ainfo);
233   adata = (const guint16 *) amap.data;
234
235 #if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
236   {
237     VisBuffer *lbuf, *rbuf;
238     guint16 ldata[VISUAL_SAMPLES], rdata[VISUAL_SAMPLES];
239     VisAudioSampleRateType vrate;
240
241     lbuf = visual_buffer_new_with_buffer (ldata, sizeof (ldata), NULL);
242     rbuf = visual_buffer_new_with_buffer (rdata, sizeof (rdata), NULL);
243
244     if (channels == 2) {
245       for (i = 0; i < VISUAL_SAMPLES; i++) {
246         ldata[i] = *adata++;
247         rdata[i] = *adata++;
248       }
249     } else {
250       for (i = 0; i < VISUAL_SAMPLES; i++) {
251         ldata[i] = *adata;
252         rdata[i] = *adata++;
253       }
254     }
255
256     /* TODO(ensonic): move to setup */
257     switch (bscope->ainfo.rate) {
258       case 8000:
259         vrate = VISUAL_AUDIO_SAMPLE_RATE_8000;
260         break;
261       case 11250:
262         vrate = VISUAL_AUDIO_SAMPLE_RATE_11250;
263         break;
264       case 22500:
265         vrate = VISUAL_AUDIO_SAMPLE_RATE_22500;
266         break;
267       case 32000:
268         vrate = VISUAL_AUDIO_SAMPLE_RATE_32000;
269         break;
270       case 44100:
271         vrate = VISUAL_AUDIO_SAMPLE_RATE_44100;
272         break;
273       case 48000:
274         vrate = VISUAL_AUDIO_SAMPLE_RATE_48000;
275         break;
276       case 96000:
277         vrate = VISUAL_AUDIO_SAMPLE_RATE_96000;
278         break;
279       default:
280         visual_object_unref (VISUAL_OBJECT (lbuf));
281         visual_object_unref (VISUAL_OBJECT (rbuf));
282         GST_ERROR_OBJECT (visual, "unsupported rate %d", bscope->ainfo.rate);
283         res = FALSE;
284         goto done;
285     }
286
287     visual_audio_samplepool_input_channel (visual->audio->samplepool,
288         lbuf,
289         vrate, VISUAL_AUDIO_SAMPLE_FORMAT_S16,
290         (char *) VISUAL_AUDIO_CHANNEL_LEFT);
291     visual_audio_samplepool_input_channel (visual->audio->samplepool, rbuf,
292         vrate, VISUAL_AUDIO_SAMPLE_FORMAT_S16,
293         (char *) VISUAL_AUDIO_CHANNEL_RIGHT);
294
295     visual_object_unref (VISUAL_OBJECT (lbuf));
296     visual_object_unref (VISUAL_OBJECT (rbuf));
297
298   }
299 #else
300   if (channels == 2) {
301     guint16 *ldata = visual->audio->plugpcm[0];
302     guint16 *rdata = visual->audio->plugpcm[1];
303     for (i = 0; i < VISUAL_SAMPLES; i++) {
304       ldata[i] = *adata++;
305       rdata[i] = *adata++;
306     }
307   } else {
308     for (i = 0; i < VISUAL_SAMPLES; i++) {
309       ldata[i] = *adata;
310       rdata[i] = *adata++;
311     }
312   }
313 #endif
314
315   visual_audio_analyze (visual->audio);
316   visual_actor_run (visual->actor, visual->audio);
317   visual_video_set_buffer (visual->video, NULL);
318
319   GST_DEBUG_OBJECT (visual, "rendered one frame");
320 done:
321   gst_buffer_unmap (video, &vmap);
322   gst_buffer_unmap (audio, &amap);
323   return res;
324 }