|
Packit |
971217 |
/* GStreamer
|
|
Packit |
971217 |
* Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
|
|
Packit |
971217 |
* 2012 Stefan Sauer <ensonic@users.sf.net>
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
971217 |
* modify it under the terms of the GNU Library General Public
|
|
Packit |
971217 |
* License as published by the Free Software Foundation; either
|
|
Packit |
971217 |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
971217 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
971217 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
971217 |
* Library General Public License for more details.
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* You should have received a copy of the GNU Library General Public
|
|
Packit |
971217 |
* License along with this library; if not, write to the
|
|
Packit |
971217 |
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
Packit |
971217 |
* Boston, MA 02110-1301, USA.
|
|
Packit |
971217 |
*/
|
|
Packit |
971217 |
|
|
Packit |
971217 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
971217 |
#include "config.h"
|
|
Packit |
971217 |
#endif
|
|
Packit |
971217 |
|
|
Packit |
971217 |
#include "visual.h"
|
|
Packit |
971217 |
|
|
Packit |
971217 |
GST_DEBUG_CATEGORY_EXTERN (libvisual_debug);
|
|
Packit |
971217 |
#define GST_CAT_DEFAULT (libvisual_debug)
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/* amounf of samples before we can feed libvisual */
|
|
Packit |
971217 |
#define VISUAL_SAMPLES 512
|
|
Packit |
971217 |
|
|
Packit |
971217 |
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
|
Packit |
971217 |
#define RGB_ORDER_CAPS "xRGB, RGB"
|
|
Packit |
971217 |
#else
|
|
Packit |
971217 |
#define RGB_ORDER_CAPS "BGRx, BGR"
|
|
Packit |
971217 |
#endif
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
|
Packit |
971217 |
GST_PAD_SRC,
|
|
Packit |
971217 |
GST_PAD_ALWAYS,
|
|
Packit |
971217 |
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (" { " RGB_ORDER_CAPS ", RGB16 } "))
|
|
Packit |
971217 |
);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
|
Packit |
971217 |
GST_PAD_SINK,
|
|
Packit |
971217 |
GST_PAD_ALWAYS,
|
|
Packit |
971217 |
GST_STATIC_CAPS ("audio/x-raw, "
|
|
Packit |
971217 |
"format = (string) " GST_AUDIO_NE (S16) ", "
|
|
Packit |
971217 |
"layout = (string) interleaved, " "channels = (int) { 1, 2 }, "
|
|
Packit |
971217 |
"rate = (int) { 8000, 11250, 22500, 32000, 44100, 48000, 96000 }")
|
|
Packit |
971217 |
);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static void gst_visual_init (GstVisual * visual);
|
|
Packit |
971217 |
static void gst_visual_finalize (GObject * object);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static gboolean gst_visual_setup (GstAudioVisualizer * bscope);
|
|
Packit |
971217 |
static gboolean gst_visual_render (GstAudioVisualizer * bscope,
|
|
Packit |
971217 |
GstBuffer * audio, GstVideoFrame * video);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static GstElementClass *parent_class = NULL;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
GType
|
|
Packit |
971217 |
gst_visual_get_type (void)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
static GType type = 0;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (G_UNLIKELY (type == 0)) {
|
|
Packit |
971217 |
static const GTypeInfo info = {
|
|
Packit |
971217 |
sizeof (GstVisualClass),
|
|
Packit |
971217 |
NULL,
|
|
Packit |
971217 |
NULL,
|
|
Packit |
971217 |
gst_visual_class_init,
|
|
Packit |
971217 |
NULL,
|
|
Packit |
971217 |
NULL,
|
|
Packit |
971217 |
sizeof (GstVisual),
|
|
Packit |
971217 |
0,
|
|
Packit |
971217 |
(GInstanceInitFunc) gst_visual_init,
|
|
Packit |
971217 |
};
|
|
Packit |
971217 |
|
|
Packit |
971217 |
type =
|
|
Packit |
971217 |
g_type_register_static (GST_TYPE_AUDIO_VISUALIZER, "GstVisual",
|
|
Packit |
971217 |
&info, 0);
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
return type;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
void
|
|
Packit |
971217 |
gst_visual_class_init (gpointer g_class, gpointer class_data)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GObjectClass *gobject_class = (GObjectClass *) g_class;
|
|
Packit |
971217 |
GstElementClass *element_class = (GstElementClass *) g_class;
|
|
Packit |
971217 |
GstAudioVisualizerClass *scope_class = (GstAudioVisualizerClass *) g_class;
|
|
Packit |
971217 |
GstVisualClass *klass = (GstVisualClass *) g_class;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
klass->plugin = class_data;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (class_data == NULL) {
|
|
Packit |
971217 |
parent_class = g_type_class_peek_parent (g_class);
|
|
Packit |
971217 |
} else {
|
|
Packit |
971217 |
gchar *longname = g_strdup_printf ("libvisual %s plugin v.%s",
|
|
Packit |
971217 |
klass->plugin->info->name, klass->plugin->info->version);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/* FIXME: improve to only register what plugin supports? */
|
|
Packit |
971217 |
gst_element_class_add_static_pad_template (element_class, &src_template);
|
|
Packit |
971217 |
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
gst_element_class_set_static_metadata (element_class,
|
|
Packit |
971217 |
longname, "Visualization",
|
|
Packit |
971217 |
klass->plugin->info->about, "Benjamin Otte <otte@gnome.org>");
|
|
Packit |
971217 |
|
|
Packit |
971217 |
g_free (longname);
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
gobject_class->finalize = gst_visual_finalize;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
scope_class->setup = GST_DEBUG_FUNCPTR (gst_visual_setup);
|
|
Packit |
971217 |
scope_class->render = GST_DEBUG_FUNCPTR (gst_visual_render);
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static void
|
|
Packit |
971217 |
gst_visual_init (GstVisual * visual)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
/* do nothing */
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static void
|
|
Packit |
971217 |
gst_visual_clear_actors (GstVisual * visual)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
if (visual->actor) {
|
|
Packit |
971217 |
visual_object_unref (VISUAL_OBJECT (visual->actor));
|
|
Packit |
971217 |
visual->actor = NULL;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
if (visual->video) {
|
|
Packit |
971217 |
visual_object_unref (VISUAL_OBJECT (visual->video));
|
|
Packit |
971217 |
visual->video = NULL;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
if (visual->audio) {
|
|
Packit |
971217 |
visual_object_unref (VISUAL_OBJECT (visual->audio));
|
|
Packit |
971217 |
visual->audio = NULL;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static void
|
|
Packit |
971217 |
gst_visual_finalize (GObject * object)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GstVisual *visual = GST_VISUAL (object);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
gst_visual_clear_actors (visual);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static gboolean
|
|
Packit |
971217 |
gst_visual_setup (GstAudioVisualizer * bscope)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GstVisual *visual = GST_VISUAL (bscope);
|
|
Packit |
971217 |
gint depth;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
gst_visual_clear_actors (visual);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/* FIXME: we need to know how many bits we actually have in memory */
|
|
Packit |
971217 |
depth = bscope->vinfo.finfo->pixel_stride[0];
|
|
Packit |
971217 |
if (bscope->vinfo.finfo->bits >= 8) {
|
|
Packit |
971217 |
depth *= 8;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
visual->actor =
|
|
Packit |
971217 |
visual_actor_new (GST_VISUAL_GET_CLASS (visual)->plugin->info->plugname);
|
|
Packit |
971217 |
visual->video = visual_video_new ();
|
|
Packit |
971217 |
visual->audio = visual_audio_new ();
|
|
Packit |
971217 |
/* can't have a play without actors */
|
|
Packit |
971217 |
if (!visual->actor || !visual->video)
|
|
Packit |
971217 |
goto no_actors;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (visual_actor_realize (visual->actor) != 0)
|
|
Packit |
971217 |
goto no_realize;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
visual_actor_set_video (visual->actor, visual->video);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
visual_video_set_depth (visual->video,
|
|
Packit |
971217 |
visual_video_depth_enum_from_value (depth));
|
|
Packit |
971217 |
visual_video_set_dimension (visual->video,
|
|
Packit |
971217 |
GST_VIDEO_INFO_WIDTH (&bscope->vinfo),
|
|
Packit |
971217 |
GST_VIDEO_INFO_HEIGHT (&bscope->vinfo));
|
|
Packit |
971217 |
visual_actor_video_negotiate (visual->actor, 0, FALSE, FALSE);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
GST_DEBUG_OBJECT (visual, "WxH: %dx%d, bpp: %d, depth: %d",
|
|
Packit |
971217 |
GST_VIDEO_INFO_WIDTH (&bscope->vinfo),
|
|
Packit |
971217 |
GST_VIDEO_INFO_HEIGHT (&bscope->vinfo), visual->video->bpp, depth);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
return TRUE;
|
|
Packit |
971217 |
/* ERRORS */
|
|
Packit |
971217 |
no_actors:
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
|
|
Packit |
971217 |
("could not create actors"));
|
|
Packit |
971217 |
gst_visual_clear_actors (visual);
|
|
Packit |
971217 |
return FALSE;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
no_realize:
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
|
|
Packit |
971217 |
("could not realize actor"));
|
|
Packit |
971217 |
gst_visual_clear_actors (visual);
|
|
Packit |
971217 |
return FALSE;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static gboolean
|
|
Packit |
971217 |
gst_visual_render (GstAudioVisualizer * bscope, GstBuffer * audio,
|
|
Packit |
971217 |
GstVideoFrame * video)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GstVisual *visual = GST_VISUAL (bscope);
|
|
Packit |
971217 |
GstMapInfo amap;
|
|
Packit |
971217 |
const guint16 *adata;
|
|
Packit |
971217 |
gint i, channels;
|
|
Packit |
971217 |
gboolean res = TRUE;
|
|
Packit |
971217 |
VisBuffer *lbuf, *rbuf;
|
|
Packit |
971217 |
guint16 ldata[VISUAL_SAMPLES], rdata[VISUAL_SAMPLES];
|
|
Packit |
971217 |
VisAudioSampleRateType vrate;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
visual_video_set_buffer (visual->video, GST_VIDEO_FRAME_PLANE_DATA (video,
|
|
Packit |
971217 |
0));
|
|
Packit |
971217 |
visual_video_set_pitch (visual->video, GST_VIDEO_FRAME_PLANE_STRIDE (video,
|
|
Packit |
971217 |
0));
|
|
Packit |
971217 |
|
|
Packit |
971217 |
channels = GST_AUDIO_INFO_CHANNELS (&bscope->ainfo);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
gst_buffer_map (audio, &amap, GST_MAP_READ);
|
|
Packit |
971217 |
adata = (const guint16 *) amap.data;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
lbuf = visual_buffer_new_with_buffer (ldata, sizeof (ldata), NULL);
|
|
Packit |
971217 |
rbuf = visual_buffer_new_with_buffer (rdata, sizeof (rdata), NULL);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (channels == 2) {
|
|
Packit |
971217 |
for (i = 0; i < VISUAL_SAMPLES; i++) {
|
|
Packit |
971217 |
ldata[i] = *adata++;
|
|
Packit |
971217 |
rdata[i] = *adata++;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
} else {
|
|
Packit |
971217 |
for (i = 0; i < VISUAL_SAMPLES; i++) {
|
|
Packit |
971217 |
ldata[i] = *adata;
|
|
Packit |
971217 |
rdata[i] = *adata++;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/* TODO(ensonic): move to setup */
|
|
Packit |
971217 |
switch (bscope->ainfo.rate) {
|
|
Packit |
971217 |
case 8000:
|
|
Packit |
971217 |
vrate = VISUAL_AUDIO_SAMPLE_RATE_8000;
|
|
Packit |
971217 |
break;
|
|
Packit |
971217 |
case 11250:
|
|
Packit |
971217 |
vrate = VISUAL_AUDIO_SAMPLE_RATE_11250;
|
|
Packit |
971217 |
break;
|
|
Packit |
971217 |
case 22500:
|
|
Packit |
971217 |
vrate = VISUAL_AUDIO_SAMPLE_RATE_22500;
|
|
Packit |
971217 |
break;
|
|
Packit |
971217 |
case 32000:
|
|
Packit |
971217 |
vrate = VISUAL_AUDIO_SAMPLE_RATE_32000;
|
|
Packit |
971217 |
break;
|
|
Packit |
971217 |
case 44100:
|
|
Packit |
971217 |
vrate = VISUAL_AUDIO_SAMPLE_RATE_44100;
|
|
Packit |
971217 |
break;
|
|
Packit |
971217 |
case 48000:
|
|
Packit |
971217 |
vrate = VISUAL_AUDIO_SAMPLE_RATE_48000;
|
|
Packit |
971217 |
break;
|
|
Packit |
971217 |
case 96000:
|
|
Packit |
971217 |
vrate = VISUAL_AUDIO_SAMPLE_RATE_96000;
|
|
Packit |
971217 |
break;
|
|
Packit |
971217 |
default:
|
|
Packit |
971217 |
visual_object_unref (VISUAL_OBJECT (lbuf));
|
|
Packit |
971217 |
visual_object_unref (VISUAL_OBJECT (rbuf));
|
|
Packit |
971217 |
GST_ERROR_OBJECT (visual, "unsupported rate %d", bscope->ainfo.rate);
|
|
Packit |
971217 |
res = FALSE;
|
|
Packit |
971217 |
goto done;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
visual_audio_samplepool_input_channel (visual->audio->samplepool,
|
|
Packit |
971217 |
lbuf,
|
|
Packit |
971217 |
vrate, VISUAL_AUDIO_SAMPLE_FORMAT_S16,
|
|
Packit |
971217 |
(char *) VISUAL_AUDIO_CHANNEL_LEFT);
|
|
Packit |
971217 |
visual_audio_samplepool_input_channel (visual->audio->samplepool, rbuf,
|
|
Packit |
971217 |
vrate, VISUAL_AUDIO_SAMPLE_FORMAT_S16,
|
|
Packit |
971217 |
(char *) VISUAL_AUDIO_CHANNEL_RIGHT);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
visual_object_unref (VISUAL_OBJECT (lbuf));
|
|
Packit |
971217 |
visual_object_unref (VISUAL_OBJECT (rbuf));
|
|
Packit |
971217 |
|
|
Packit |
971217 |
visual_audio_analyze (visual->audio);
|
|
Packit |
971217 |
visual_actor_run (visual->actor, visual->audio);
|
|
Packit |
971217 |
visual_video_set_buffer (visual->video, NULL);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
GST_DEBUG_OBJECT (visual, "rendered one frame");
|
|
Packit |
971217 |
done:
|
|
Packit |
971217 |
gst_buffer_unmap (audio, &amap;;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
return res;
|
|
Packit |
971217 |
}
|