mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
ofa: port to 1.0
This commit is contained in:
parent
0c23ac0565
commit
020c93b973
5 changed files with 92 additions and 118 deletions
|
@ -346,7 +346,7 @@ GST_PLUGINS_NONPORTED=" cdxaparse \
|
|||
linsys vcd \
|
||||
apexsink cdaudio dc1394 dirac directfb \
|
||||
gsettings \
|
||||
musepack nas ofa openal sdl sndfile timidity \
|
||||
musepack nas openal sdl sndfile timidity \
|
||||
directdraw direct3d9 acm wininet \
|
||||
xvid lv2 teletextdec sndio osx_video quicktime"
|
||||
AC_SUBST(GST_PLUGINS_NONPORTED)
|
||||
|
|
133
ext/ofa/gstofa.c
133
ext/ofa/gstofa.c
|
@ -1,7 +1,4 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* gstofa.c
|
||||
*
|
||||
/* GStreamer ofa fingerprinting element
|
||||
* Copyright (C) 2006 M. Derezynski
|
||||
* Copyright (C) 2008 Eric Buehl
|
||||
* Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
|
@ -31,13 +28,10 @@
|
|||
#include "gstofa.h"
|
||||
|
||||
#define PAD_CAPS \
|
||||
"audio/x-raw-int, " \
|
||||
"audio/x-raw, " \
|
||||
"format = { S16LE, S16BE }, " \
|
||||
"rate = (int) [ 1, MAX ], " \
|
||||
"channels = (int) [ 1, 2 ], " \
|
||||
"endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
|
||||
"width = (int) { 16 }, " \
|
||||
"depth = (int) { 16 }, " \
|
||||
"signed = (boolean) true"
|
||||
"channels = (int) [ 1, 2 ]"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_ofa_debug);
|
||||
#define GST_CAT_DEFAULT gst_ofa_debug
|
||||
|
@ -48,32 +42,15 @@ enum
|
|||
PROP_FINGERPRINT,
|
||||
};
|
||||
|
||||
|
||||
GST_BOILERPLATE (GstOFA, gst_ofa, GstAudioFilter, GST_TYPE_AUDIO_FILTER);
|
||||
#define parent_class gst_ofa_parent_class
|
||||
G_DEFINE_TYPE (GstOFA, gst_ofa, GST_TYPE_AUDIO_FILTER);
|
||||
|
||||
static void gst_ofa_finalize (GObject * object);
|
||||
static void gst_ofa_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static GstFlowReturn gst_ofa_transform_ip (GstBaseTransform * trans,
|
||||
GstBuffer * buf);
|
||||
static gboolean gst_ofa_event (GstBaseTransform * trans, GstEvent * event);
|
||||
|
||||
static void
|
||||
gst_ofa_base_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstAudioFilterClass *audio_filter_class = (GstAudioFilterClass *) g_class;
|
||||
GstCaps *caps;
|
||||
|
||||
gst_element_class_set_static_metadata (gstelement_class, "OFA",
|
||||
"MusicIP Fingerprinting element",
|
||||
"Find a music fingerprint using MusicIP's libofa",
|
||||
"Milosz Derezynski <internalerror@gmail.com>, Eric Buehl <eric.buehl@gmail.com>");
|
||||
|
||||
caps = gst_caps_from_string (PAD_CAPS);
|
||||
gst_audio_filter_class_add_pad_templates (audio_filter_class, caps);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
static gboolean gst_ofa_sink_event (GstBaseTransform * trans, GstEvent * event);
|
||||
|
||||
static void
|
||||
gst_ofa_finalize (GObject * object)
|
||||
|
@ -94,34 +71,45 @@ gst_ofa_finalize (GObject * object)
|
|||
static void
|
||||
gst_ofa_class_init (GstOFAClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstBaseTransformClass *gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
|
||||
GstAudioFilterClass *audio_filter_class = GST_AUDIO_FILTER_CLASS (klass);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstCaps *caps;
|
||||
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_ofa_get_property);
|
||||
gobject_class->get_property = gst_ofa_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_FINGERPRINT,
|
||||
g_param_spec_string ("fingerprint", "Resulting fingerprint",
|
||||
"Resulting fingerprint", NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ofa_finalize);
|
||||
gobject_class->finalize = gst_ofa_finalize;
|
||||
|
||||
gstbasetrans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_ofa_transform_ip);
|
||||
gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_ofa_event);
|
||||
gstbasetrans_class->sink_event = GST_DEBUG_FUNCPTR (gst_ofa_sink_event);
|
||||
gstbasetrans_class->passthrough_on_same_caps = TRUE;
|
||||
|
||||
gst_element_class_set_static_metadata (gstelement_class, "OFA",
|
||||
"MusicIP Fingerprinting element",
|
||||
"Find a music fingerprint using MusicIP's libofa",
|
||||
"Milosz Derezynski <internalerror@gmail.com>, "
|
||||
"Eric Buehl <eric.buehl@gmail.com>");
|
||||
|
||||
caps = gst_caps_from_string (PAD_CAPS);
|
||||
gst_audio_filter_class_add_pad_templates (audio_filter_class, caps);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
static void
|
||||
create_fingerprint (GstOFA * ofa)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
GstAudioFilter *ofa_filter = GST_AUDIO_FILTER (ofa);
|
||||
gint rate = ofa_filter->format.rate;
|
||||
gint channels = ofa_filter->format.channels;
|
||||
gint endianness =
|
||||
ofa_filter->format.bigend ? OFA_BIG_ENDIAN : OFA_LITTLE_ENDIAN;
|
||||
GstAudioFilter *audiofilter = GST_AUDIO_FILTER (ofa);
|
||||
const guint8 *samples;
|
||||
const gchar *fingerprint;
|
||||
gint rate, channels, endianness;
|
||||
GstTagList *tags;
|
||||
guint available;
|
||||
gsize available;
|
||||
|
||||
available = gst_adapter_available (ofa->adapter);
|
||||
|
||||
|
@ -131,52 +119,60 @@ create_fingerprint (GstOFA * ofa)
|
|||
return;
|
||||
}
|
||||
|
||||
if (GST_AUDIO_FILTER (ofa)->format.bigend)
|
||||
rate = GST_AUDIO_INFO_RATE (&audiofilter->info);
|
||||
channels = GST_AUDIO_INFO_CHANNELS (&audiofilter->info);
|
||||
if (GST_AUDIO_INFO_ENDIANNESS (&audiofilter->info) == G_BIG_ENDIAN)
|
||||
endianness = OFA_BIG_ENDIAN;
|
||||
else
|
||||
endianness = OFA_LITTLE_ENDIAN;
|
||||
|
||||
|
||||
GST_DEBUG_OBJECT (ofa, "Generating fingerprint for %u samples",
|
||||
available / 2);
|
||||
GST_DEBUG_OBJECT (ofa, "Generating fingerprint for %" G_GSIZE_FORMAT
|
||||
" samples", available / sizeof (gint16));
|
||||
|
||||
buf = gst_adapter_take_buffer (ofa->adapter, available);
|
||||
samples = gst_adapter_map (ofa->adapter, available);
|
||||
|
||||
ofa->fingerprint = g_strdup (ofa_create_print (GST_BUFFER_DATA (buf),
|
||||
endianness, GST_BUFFER_SIZE (buf) / 2, rate,
|
||||
(channels == 2) ? 1 : 0));
|
||||
fingerprint = ofa_create_print ((unsigned char *) samples, endianness,
|
||||
available / sizeof (gint16), rate, (channels == 2) ? 1 : 0);
|
||||
|
||||
if (ofa->fingerprint) {
|
||||
GST_INFO_OBJECT (ofa, "Generated fingerprint: %s", ofa->fingerprint);
|
||||
} else {
|
||||
gst_adapter_unmap (ofa->adapter);
|
||||
gst_adapter_flush (ofa->adapter, available);
|
||||
|
||||
if (fingerprint == NULL) {
|
||||
GST_WARNING_OBJECT (ofa, "Failed to generate fingerprint");
|
||||
goto done;
|
||||
}
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
GST_INFO_OBJECT (ofa, "Generated fingerprint: %s", fingerprint);
|
||||
ofa->fingerprint = g_strdup (fingerprint);
|
||||
|
||||
if (ofa->fingerprint) {
|
||||
tags = gst_tag_list_new ();
|
||||
gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
|
||||
GST_TAG_OFA_FINGERPRINT, ofa->fingerprint, NULL);
|
||||
gst_element_found_tags (GST_ELEMENT (ofa), tags);
|
||||
// FIXME: combine with upstream tags
|
||||
tags = gst_tag_list_new (GST_TAG_OFA_FINGERPRINT, ofa->fingerprint, NULL);
|
||||
gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (ofa),
|
||||
gst_event_new_tag (tags));
|
||||
|
||||
g_object_notify (G_OBJECT (ofa), "fingerprint");
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
ofa->record = FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ofa_event (GstBaseTransform * trans, GstEvent * event)
|
||||
gst_ofa_sink_event (GstBaseTransform * trans, GstEvent * event)
|
||||
{
|
||||
GstOFA *ofa = GST_OFA (trans);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
case GST_EVENT_SEGMENT:
|
||||
GST_DEBUG_OBJECT (ofa, "Got %s event, clearing buffer",
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
gst_adapter_clear (ofa->adapter);
|
||||
/* FIXME: should we really always reset this instead of using an
|
||||
* already-existing fingerprint? Assumes fingerprints are always
|
||||
* extracted in a separate pipeline instead of a live playback
|
||||
* situation */
|
||||
ofa->record = TRUE;
|
||||
g_free (ofa->fingerprint);
|
||||
ofa->fingerprint = NULL;
|
||||
|
@ -192,11 +188,11 @@ gst_ofa_event (GstBaseTransform * trans, GstEvent * event)
|
|||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ofa_init (GstOFA * ofa, GstOFAClass * g_class)
|
||||
gst_ofa_init (GstOFA * ofa)
|
||||
{
|
||||
gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (ofa), TRUE);
|
||||
|
||||
|
@ -209,14 +205,17 @@ gst_ofa_init (GstOFA * ofa, GstOFAClass * g_class)
|
|||
static GstFlowReturn
|
||||
gst_ofa_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
|
||||
{
|
||||
GstAudioFilter *audiofilter = GST_AUDIO_FILTER (trans);
|
||||
GstOFA *ofa = GST_OFA (trans);
|
||||
GstAudioFilter *ofa_filter = GST_AUDIO_FILTER (ofa);
|
||||
guint64 nframes;
|
||||
GstClockTime duration;
|
||||
gint rate = ofa_filter->format.rate;
|
||||
gint channels = ofa_filter->format.channels;
|
||||
gint rate, channels;
|
||||
|
||||
g_return_val_if_fail (rate > 0 && channels > 0, GST_FLOW_NOT_NEGOTIATED);
|
||||
rate = GST_AUDIO_INFO_RATE (&audiofilter->info);
|
||||
channels = GST_AUDIO_INFO_CHANNELS (&audiofilter->info);
|
||||
|
||||
if (rate == 0 || channels == 0)
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
|
||||
if (!ofa->record)
|
||||
return GST_FLOW_OK;
|
||||
|
@ -253,7 +252,6 @@ static gboolean
|
|||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
gboolean ret;
|
||||
|
||||
int major, minor, rev;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_ofa_debug, "ofa", 0, "ofa element");
|
||||
|
@ -273,6 +271,7 @@ plugin_init (GstPlugin * plugin)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: someone write a libofa replacement with an LGPL or BSD license */
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
ofa,
|
||||
|
|
|
@ -58,7 +58,7 @@ typedef struct _GstOFAClass GstOFAClass;
|
|||
|
||||
struct _GstOFA
|
||||
{
|
||||
GstAudioFilter element;
|
||||
GstAudioFilter audiofilter;
|
||||
|
||||
/*< private > */
|
||||
|
||||
|
@ -69,7 +69,7 @@ struct _GstOFA
|
|||
|
||||
struct _GstOFAClass
|
||||
{
|
||||
GstAudioFilterClass parent_class;
|
||||
GstAudioFilterClass audiofilter_class;
|
||||
};
|
||||
|
||||
GType gst_ofa_get_type (void);
|
||||
|
|
|
@ -40,7 +40,6 @@ bus_handler (GstBus * bus, GstMessage * message, gpointer data)
|
|||
else
|
||||
gst_message_parse_error (message, &gerror, &debug);
|
||||
gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
|
||||
gst_message_unref (message);
|
||||
g_error_free (gerror);
|
||||
g_free (debug);
|
||||
g_main_loop_quit (loop);
|
||||
|
@ -53,6 +52,13 @@ bus_handler (GstBus * bus, GstMessage * message, gpointer data)
|
|||
|
||||
gst_message_parse_tag (message, &tag_list);
|
||||
|
||||
GST_DEBUG ("tag message: %" GST_PTR_FORMAT, tag_list);
|
||||
|
||||
if (!gst_tag_list_get_value_index (tag_list, "ofa-fingerprint", 0)) {
|
||||
gst_tag_list_unref (tag_list);
|
||||
break;
|
||||
}
|
||||
|
||||
fail_unless (gst_tag_list_get_string (tag_list, "ofa-fingerprint", &fpr));
|
||||
|
||||
p = fpr;
|
||||
|
@ -102,12 +108,8 @@ GST_START_TEST (test_ofa_le_1ch)
|
|||
|
||||
capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
|
||||
fail_unless (capsfilter != NULL);
|
||||
caps = gst_caps_new_simple ("audio/x-raw-int",
|
||||
"rate", G_TYPE_INT, 44100,
|
||||
"channels", G_TYPE_INT, 1,
|
||||
"endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
|
||||
"width", G_TYPE_INT, 16,
|
||||
"depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
|
||||
caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16LE",
|
||||
"rate", G_TYPE_INT, 44100, "channels", G_TYPE_INT, 1, NULL);
|
||||
g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
|
@ -135,7 +137,7 @@ GST_START_TEST (test_ofa_le_1ch)
|
|||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
g_main_loop_run (loop);
|
||||
|
||||
fail_unless (gst_element_query_position (audiotestsrc, &fmt, &position));
|
||||
fail_unless (gst_element_query_position (audiotestsrc, fmt, &position));
|
||||
fail_unless (position >= 135 * GST_SECOND);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
@ -173,12 +175,8 @@ GST_START_TEST (test_ofa_be_1ch)
|
|||
|
||||
capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
|
||||
fail_unless (capsfilter != NULL);
|
||||
caps = gst_caps_new_simple ("audio/x-raw-int",
|
||||
"rate", G_TYPE_INT, 44100,
|
||||
"channels", G_TYPE_INT, 1,
|
||||
"endianness", G_TYPE_INT, G_BIG_ENDIAN,
|
||||
"width", G_TYPE_INT, 16,
|
||||
"depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
|
||||
caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16BE",
|
||||
"rate", G_TYPE_INT, 44100, "channels", G_TYPE_INT, 1, NULL);
|
||||
g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
|
@ -206,7 +204,7 @@ GST_START_TEST (test_ofa_be_1ch)
|
|||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
g_main_loop_run (loop);
|
||||
|
||||
fail_unless (gst_element_query_position (audiotestsrc, &fmt, &position));
|
||||
fail_unless (gst_element_query_position (audiotestsrc, fmt, &position));
|
||||
fail_unless (position >= 135 * GST_SECOND);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
@ -243,12 +241,8 @@ GST_START_TEST (test_ofa_le_2ch)
|
|||
|
||||
capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
|
||||
fail_unless (capsfilter != NULL);
|
||||
caps = gst_caps_new_simple ("audio/x-raw-int",
|
||||
"rate", G_TYPE_INT, 44100,
|
||||
"channels", G_TYPE_INT, 2,
|
||||
"endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
|
||||
"width", G_TYPE_INT, 16,
|
||||
"depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
|
||||
caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16LE",
|
||||
"rate", G_TYPE_INT, 44100, "channels", G_TYPE_INT, 2, NULL);
|
||||
g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
|
@ -276,7 +270,7 @@ GST_START_TEST (test_ofa_le_2ch)
|
|||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
g_main_loop_run (loop);
|
||||
|
||||
fail_unless (gst_element_query_position (audiotestsrc, &fmt, &position));
|
||||
fail_unless (gst_element_query_position (audiotestsrc, fmt, &position));
|
||||
fail_unless (position >= 135 * GST_SECOND);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
@ -314,12 +308,8 @@ GST_START_TEST (test_ofa_be_2ch)
|
|||
|
||||
capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
|
||||
fail_unless (capsfilter != NULL);
|
||||
caps = gst_caps_new_simple ("audio/x-raw-int",
|
||||
"rate", G_TYPE_INT, 44100,
|
||||
"channels", G_TYPE_INT, 2,
|
||||
"endianness", G_TYPE_INT, G_BIG_ENDIAN,
|
||||
"width", G_TYPE_INT, 16,
|
||||
"depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
|
||||
caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16BE",
|
||||
"rate", G_TYPE_INT, 44100, "channels", G_TYPE_INT, 2, NULL);
|
||||
g_object_set (G_OBJECT (capsfilter), "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
|
@ -347,7 +337,7 @@ GST_START_TEST (test_ofa_be_2ch)
|
|||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
g_main_loop_run (loop);
|
||||
|
||||
fail_unless (gst_element_query_position (audiotestsrc, &fmt, &position));
|
||||
fail_unless (gst_element_query_position (audiotestsrc, fmt, &position));
|
||||
fail_unless (position >= 135 * GST_SECOND);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
@ -378,19 +368,4 @@ ofa_suite (void)
|
|||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int nf;
|
||||
|
||||
Suite *s = ofa_suite ();
|
||||
SRunner *sr = srunner_create (s);
|
||||
|
||||
gst_check_init (&argc, &argv);
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
nf = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
|
||||
return nf;
|
||||
}
|
||||
GST_CHECK_MAIN (ofa)
|
||||
|
|
Loading…
Reference in a new issue