diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index c33dc0f154..1611bb8f23 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -104,6 +104,7 @@ check_PROGRAMS = \ libs/libsabi \ libs/audio \ libs/audiocdsrc \ + libs/audiodecoder \ libs/discoverer \ libs/fft \ libs/navigation \ @@ -200,6 +201,16 @@ libs_audio_LDADD = \ $(GST_BASE_LIBS) \ $(LDADD) +libs_audiodecoder_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_audiodecoder_LDADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_API_VERSION@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + libs_audiocdsrc_CFLAGS = \ $(GST_PLUGINS_BASE_CFLAGS) \ $(GST_BASE_CFLAGS) \ diff --git a/tests/check/libs/.gitignore b/tests/check/libs/.gitignore index ca1ed9103d..18aeed69ca 100644 --- a/tests/check/libs/.gitignore +++ b/tests/check/libs/.gitignore @@ -1,6 +1,7 @@ .dirstamp audio audiocdsrc +audiodecoder discoverer fft gstlibscpp diff --git a/tests/check/libs/audiodecoder.c b/tests/check/libs/audiodecoder.c new file mode 100644 index 0000000000..1704adf230 --- /dev/null +++ b/tests/check/libs/audiodecoder.c @@ -0,0 +1,294 @@ +/* GStreamer + * + * Copyright (C) 2014 Samsung Electronics. All rights reserved. + * Author: Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include + +static GstPad *mysrcpad, *mysinkpad; +static GstElement *dec; +static GList *events = NULL; + +#define TEST_MSECS_PER_SAMPLE 44100 + +#define GST_AUDIO_DECODER_TESTER_TYPE gst_audio_decoder_tester_get_type() +static GType gst_audio_decoder_tester_get_type (void); + +typedef struct _GstAudioDecoderTester GstAudioDecoderTester; +typedef struct _GstAudioDecoderTesterClass GstAudioDecoderTesterClass; + +struct _GstAudioDecoderTester +{ + GstAudioDecoder parent; +}; + +struct _GstAudioDecoderTesterClass +{ + GstAudioDecoderClass parent_class; +}; + +G_DEFINE_TYPE (GstAudioDecoderTester, gst_audio_decoder_tester, + GST_TYPE_AUDIO_DECODER); + +static gboolean +gst_audio_decoder_tester_start (GstAudioDecoder * dec) +{ + return TRUE; +} + +static gboolean +gst_audio_decoder_tester_stop (GstAudioDecoder * dec) +{ + return TRUE; +} + +static void +gst_audio_decoder_tester_flush (GstAudioDecoder * dec, gboolean hard) +{ +} + +static gboolean +gst_audio_decoder_tester_set_format (GstAudioDecoder * dec, GstCaps * caps) +{ + GstAudioInfo info; + gst_caps_unref (caps); + + caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16LE", + "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 44100, + "layout", G_TYPE_STRING, "interleaved", NULL); + gst_audio_info_from_caps (&info, caps); + gst_caps_unref (caps); + + gst_audio_decoder_set_output_format (dec, &info); + + return TRUE; +} + +static GstFlowReturn +gst_audio_decoder_tester_handle_frame (GstAudioDecoder * dec, + GstBuffer * buffer) +{ + guint8 *data; + gint size; + GstMapInfo map; + GstBuffer *output_buffer; + guint64 samples; + + if (buffer == NULL) + return GST_FLOW_OK; + + gst_buffer_map (buffer, &map, GST_MAP_READ); + + /* the output is SE16LE stereo 44100 Hz */ + samples = + gst_util_uint64_scale_round (44100, GST_BUFFER_DURATION (buffer), + GST_SECOND); + size = 2 * 2 * samples; + data = g_malloc0 (size); + + memcpy (data, map.data, sizeof (guint64)); + + output_buffer = gst_buffer_new_wrapped (data, size); + + gst_buffer_unmap (buffer, &map); + + return gst_audio_decoder_finish_frame (dec, output_buffer, 1); +} + +static void +gst_audio_decoder_tester_class_init (GstAudioDecoderTesterClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstAudioDecoderClass *audiosink_class = GST_AUDIO_DECODER_CLASS (klass); + + static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-test-custom")); + + static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw")); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_templ)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_templ)); + + gst_element_class_set_metadata (element_class, + "AudioDecoderTester", "Decoder/Audio", "yep", "me"); + + audiosink_class->start = gst_audio_decoder_tester_start; + audiosink_class->stop = gst_audio_decoder_tester_stop; + audiosink_class->flush = gst_audio_decoder_tester_flush; + audiosink_class->handle_frame = gst_audio_decoder_tester_handle_frame; + audiosink_class->set_format = gst_audio_decoder_tester_set_format; +} + +static void +gst_audio_decoder_tester_init (GstAudioDecoderTester * tester) +{ +} + +static gboolean +_mysinkpad_event (GstPad * pad, GstObject * parent, GstEvent * event) +{ + events = g_list_append (events, event); + return TRUE; +} + +static void +setup_audiodecodertester (void) +{ + GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw") + ); + GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-test-custom") + ); + + dec = g_object_new (GST_AUDIO_DECODER_TESTER_TYPE, NULL); + mysrcpad = gst_check_setup_src_pad (dec, &srctemplate); + mysinkpad = gst_check_setup_sink_pad (dec, &sinktemplate); + + gst_pad_set_event_function (mysinkpad, _mysinkpad_event); +} + +static void +cleanup_audiodecodertest (void) +{ + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (dec); + gst_check_teardown_sink_pad (dec); + gst_check_teardown_element (dec); +} + +static GstBuffer * +create_test_buffer (guint64 num) +{ + GstBuffer *buffer; + guint64 *data = g_malloc (sizeof (guint64)); + + *data = num; + + buffer = gst_buffer_new_wrapped (data, sizeof (guint64)); + + GST_BUFFER_PTS (buffer) = + gst_util_uint64_scale_round (num, GST_SECOND, TEST_MSECS_PER_SAMPLE); + GST_BUFFER_DURATION (buffer) = + gst_util_uint64_scale_round (1, GST_SECOND, TEST_MSECS_PER_SAMPLE); + + return buffer; +} + +static void +send_startup_events (void) +{ + GstCaps *caps; + + fail_unless (gst_pad_push_event (mysrcpad, + gst_event_new_stream_start ("randomvalue"))); + + /* push caps */ + caps = + gst_caps_new_simple ("audio/x-test-custom", "channels", G_TYPE_INT, 2, + "rate", G_TYPE_INT, 44100, NULL); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps))); + +} + +#define NUM_BUFFERS 1000 +GST_START_TEST (audiodecoder_playback) +{ + GstSegment segment; + GstBuffer *buffer; + guint64 i; + + setup_audiodecodertester (); + + gst_pad_set_active (mysrcpad, TRUE); + gst_element_set_state (dec, GST_STATE_PLAYING); + gst_pad_set_active (mysinkpad, TRUE); + + send_startup_events (); + + /* push a new segment */ + gst_segment_init (&segment, GST_FORMAT_TIME); + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment))); + + /* push buffers, the data is actually a number so we can track them */ + for (i = 0; i < NUM_BUFFERS; i++) { + GstMapInfo map; + guint64 num; + + buffer = create_test_buffer (i); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + + /* check that buffer was received by our source pad */ + buffer = buffers->data; + + gst_buffer_map (buffer, &map, GST_MAP_READ); + + num = *(guint64 *) map.data; + fail_unless (i == num); + fail_unless (GST_BUFFER_PTS (buffer) == gst_util_uint64_scale_round (i, + GST_SECOND, TEST_MSECS_PER_SAMPLE)); + fail_unless (GST_BUFFER_DURATION (buffer) == gst_util_uint64_scale_round (1, + GST_SECOND, TEST_MSECS_PER_SAMPLE)); + + gst_buffer_unmap (buffer, &map); + + gst_buffer_unref (buffer); + buffers = g_list_delete_link (buffers, buffers); + } + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); + + fail_unless (buffers == NULL); + + cleanup_audiodecodertest (); +} + +GST_END_TEST; + + +static Suite * +gst_audiodecoder_suite (void) +{ + Suite *s = suite_create ("GstAudioDecoder"); + TCase *tc = tcase_create ("general"); + + suite_add_tcase (s, tc); + tcase_add_test (tc, audiodecoder_playback); + + return s; +} + +GST_CHECK_MAIN (gst_audiodecoder);