mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-07-24 23:38:20 +00:00
Original commit message from CVS: Patch by: James "Doc" Livingston <doclivingston at gmail com> * ext/vorbis/Makefile.am: * ext/vorbis/vorbis.c: (plugin_init): * ext/vorbis/vorbisparse.c: (gst_vorbis_parse_class_init), (vorbis_parse_parse_packet), (vorbis_parse_chain): * ext/vorbis/vorbisparse.h: * ext/vorbis/vorbistag.c: (gst_vorbis_tag_base_init), (gst_vorbis_tag_class_init), (gst_vorbis_tag_init), (gst_vorbis_tag_parse_packet): * ext/vorbis/vorbistag.h: Add new vorbistag element which derives from vorbisparse and is essentially the same as well, only that it implements the GstTagSetter interface and can modify the stream's vorbiscomment on the fly (#335635). * tests/check/Makefile.am: * tests/check/elements/.cvsignore: * tests/check/elements/vorbistag.c: (setup_vorbistag), (cleanup_vorbistag), (buffer_probe), (start_pipeline), (get_buffer), (stop_pipeline), (_create_codebook_header_buffer), (_create_audio_buffer), (GST_START_TEST), (vorbistag_suite): Add unit test for new vorbistag element.
406 lines
12 KiB
C
406 lines
12 KiB
C
/* GStreamer
|
|
*
|
|
* unit test for vorbisdec
|
|
*
|
|
* Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
|
|
*
|
|
* 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., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <glib.h>
|
|
|
|
#include <vorbis/codec.h>
|
|
#include <vorbis/vorbisenc.h>
|
|
|
|
#include <gst/gsttagsetter.h>
|
|
#include <gst/check/gstcheck.h>
|
|
|
|
/* a valid first header packet */
|
|
guchar identification_header[30] = {
|
|
1, /* packet_type */
|
|
'v', 'o', 'r', 'b', 'i', 's',
|
|
0, 0, 0, 0, /* vorbis_version */
|
|
2, /* audio_channels */
|
|
0x44, 0xac, 0, 0, /* sample_rate */
|
|
0xff, 0xff, 0xff, 0xff, /* bitrate_maximum */
|
|
0x00, 0xee, 0x02, 0x00, /* bitrate_nominal */
|
|
0xff, 0xff, 0xff, 0xff, /* bitrate_minimum */
|
|
0xb8, /* blocksize_0, blocksize_1 */
|
|
0x01 /* framing_flag */
|
|
};
|
|
|
|
guchar artist_comment_header[] = {
|
|
3, /* packet_type */
|
|
'v', 'o', 'r', 'b', 'i', 's',
|
|
2, 0, 0, 0, /* vendor_length */
|
|
'm', 'e',
|
|
1, 0, 0, 0, /* user_comment_list_length */
|
|
9, 0, 0, 0, /* length comment[0] */
|
|
'A', 'R', 'T', 'I', 'S', 'T', '=', 'm', 'e',
|
|
0x01, /* framing bit */
|
|
};
|
|
|
|
guchar title_comment_header[] = {
|
|
3, /* packet_type */
|
|
'v', 'o', 'r', 'b', 'i', 's',
|
|
2, 0, 0, 0, /* vendor_length */
|
|
'm', 'e',
|
|
1, 0, 0, 0, /* user_comment_list_length */
|
|
12, 0, 0, 0, /* length comment[0] */
|
|
'T', 'I', 'T', 'L', 'E', '=', 'f', 'o', 'o', 'b', 'a', 'r',
|
|
0x01, /* framing bit */
|
|
};
|
|
|
|
guchar empty_comment_header[] = {
|
|
3, /* packet_type */
|
|
'v', 'o', 'r', 'b', 'i', 's',
|
|
2, 0, 0, 0, /* vendor_length */
|
|
'm', 'e',
|
|
0, 0, 0, 0, /* user_comment_list_length */
|
|
0x01, /* framing bit */
|
|
};
|
|
|
|
|
|
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
|
GST_PAD_SINK,
|
|
GST_PAD_ALWAYS,
|
|
GST_STATIC_CAPS_ANY);
|
|
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
|
GST_PAD_SRC,
|
|
GST_PAD_ALWAYS,
|
|
GST_STATIC_CAPS_ANY);
|
|
|
|
GstPad *mysrcpad, *mysinkpad;
|
|
GAsyncQueue *pending_buffers;
|
|
static gulong id;
|
|
|
|
|
|
static GstElement *
|
|
setup_vorbistag (void)
|
|
{
|
|
GstElement *vorbistag;
|
|
|
|
GST_DEBUG ("setup_vorbistag");
|
|
vorbistag = gst_check_setup_element ("vorbistag");
|
|
mysrcpad = gst_check_setup_src_pad (vorbistag, &srctemplate, NULL);
|
|
mysinkpad = gst_check_setup_sink_pad (vorbistag, &sinktemplate, NULL);
|
|
|
|
return vorbistag;
|
|
}
|
|
|
|
static void
|
|
cleanup_vorbistag (GstElement * vorbistag)
|
|
{
|
|
GST_DEBUG ("cleanup_vorbistag");
|
|
gst_element_set_state (vorbistag, GST_STATE_NULL);
|
|
|
|
gst_check_teardown_src_pad (vorbistag);
|
|
gst_check_teardown_sink_pad (vorbistag);
|
|
gst_check_teardown_element (vorbistag);
|
|
}
|
|
|
|
|
|
static gboolean
|
|
buffer_probe (GstPad * pad, GstBuffer * buffer, gpointer unused)
|
|
{
|
|
g_async_queue_push (pending_buffers, gst_buffer_ref (buffer));
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
start_pipeline (GstElement * element)
|
|
{
|
|
id = gst_pad_add_buffer_probe (mysinkpad, G_CALLBACK (buffer_probe), NULL);
|
|
|
|
pending_buffers = g_async_queue_new ();
|
|
gst_element_set_state (element, GST_STATE_PLAYING);
|
|
}
|
|
|
|
static GstBuffer *
|
|
get_buffer (void)
|
|
{
|
|
return GST_BUFFER (g_async_queue_pop (pending_buffers));
|
|
}
|
|
|
|
static void
|
|
stop_pipeline (GstElement * element)
|
|
{
|
|
GstBuffer *buf;
|
|
|
|
while ((buf = g_async_queue_try_pop (pending_buffers)))
|
|
gst_buffer_unref (buf);
|
|
|
|
gst_pad_remove_buffer_probe (mysinkpad, (guint) id);
|
|
id = 0;
|
|
|
|
gst_element_set_state (element, GST_STATE_NULL);
|
|
|
|
while ((buf = g_async_queue_try_pop (pending_buffers)))
|
|
gst_buffer_unref (buf);
|
|
|
|
g_async_queue_unref (pending_buffers);
|
|
pending_buffers = NULL;
|
|
}
|
|
|
|
vorbis_comment vc;
|
|
vorbis_dsp_state vd;
|
|
vorbis_info vi;
|
|
vorbis_block vb;
|
|
|
|
static GstBuffer *
|
|
_create_codebook_header_buffer (void)
|
|
{
|
|
GstBuffer *buffer;
|
|
ogg_packet header;
|
|
ogg_packet header_comm;
|
|
ogg_packet header_code;
|
|
|
|
vorbis_info_init (&vi);
|
|
vorbis_encode_setup_vbr (&vi, 1, 44000, 0.5);
|
|
vorbis_encode_setup_init (&vi);
|
|
vorbis_analysis_init (&vd, &vi);
|
|
vorbis_block_init (&vd, &vb);
|
|
vorbis_comment_init (&vc);
|
|
vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code);
|
|
|
|
buffer = gst_buffer_new_and_alloc (header_code.bytes);
|
|
memcpy (GST_BUFFER_DATA (buffer), header_code.packet, header_code.bytes);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
static GstBuffer *
|
|
_create_audio_buffer (void)
|
|
{
|
|
GstBuffer *buffer;
|
|
ogg_packet packet;
|
|
float **vorbis_buffer;
|
|
|
|
vorbis_buffer = vorbis_analysis_buffer (&vd, 0);
|
|
vorbis_analysis_wrote (&vd, 0);
|
|
vorbis_analysis_blockout (&vd, &vb);
|
|
vorbis_analysis (&vb, NULL);
|
|
vorbis_bitrate_addblock (&vb);
|
|
vorbis_bitrate_flushpacket (&vd, &packet);
|
|
buffer = gst_buffer_new_and_alloc (packet.bytes);
|
|
memcpy (GST_BUFFER_DATA (buffer), packet.packet, packet.bytes);
|
|
|
|
vorbis_comment_clear (&vc);
|
|
vorbis_block_clear (&vb);
|
|
vorbis_dsp_clear (&vd);
|
|
vorbis_info_clear (&vi);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
|
|
GST_START_TEST (test_empty_tags_set)
|
|
{
|
|
GstTagList *tags;
|
|
GstElement *vorbistag;
|
|
GstBuffer *inbuffer, *outbuffer;
|
|
|
|
vorbistag = setup_vorbistag ();
|
|
|
|
tags = gst_tag_list_new ();
|
|
gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, "foobar", NULL);
|
|
gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags,
|
|
GST_TAG_MERGE_REPLACE);
|
|
gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag),
|
|
GST_TAG_MERGE_KEEP_ALL);
|
|
gst_tag_list_free (tags);
|
|
|
|
start_pipeline (vorbistag);
|
|
|
|
/* send identification header */
|
|
inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header));
|
|
memcpy (GST_BUFFER_DATA (inbuffer), identification_header,
|
|
sizeof (identification_header));
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
|
|
/* send empty comment buffer */
|
|
inbuffer = gst_buffer_new_and_alloc (sizeof (empty_comment_header));
|
|
memcpy (GST_BUFFER_DATA (inbuffer), empty_comment_header,
|
|
sizeof (empty_comment_header));
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
|
|
/* send minimal codebook header and audio packers */
|
|
inbuffer = _create_codebook_header_buffer ();
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
inbuffer = _create_audio_buffer ();
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
|
|
|
|
/* check identification header is unchanged */
|
|
outbuffer = get_buffer ();
|
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
|
sizeof (identification_header));
|
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
|
identification_header, sizeof (identification_header)), 0);
|
|
gst_buffer_unref (outbuffer);
|
|
|
|
/* check comment header is correct */
|
|
outbuffer = get_buffer ();
|
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
|
sizeof (title_comment_header));
|
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
|
title_comment_header, sizeof (title_comment_header)), 0);
|
|
gst_buffer_unref (outbuffer);
|
|
|
|
stop_pipeline (vorbistag);
|
|
cleanup_vorbistag (vorbistag);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
|
|
GST_START_TEST (test_filled_tags_unset)
|
|
{
|
|
GstTagList *tags;
|
|
GstElement *vorbistag;
|
|
GstBuffer *inbuffer, *outbuffer;
|
|
|
|
vorbistag = setup_vorbistag ();
|
|
|
|
tags = gst_tag_list_new ();
|
|
gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags,
|
|
GST_TAG_MERGE_REPLACE);
|
|
gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag),
|
|
GST_TAG_MERGE_KEEP_ALL);
|
|
gst_tag_list_free (tags);
|
|
|
|
start_pipeline (vorbistag);
|
|
|
|
/* send identification header */
|
|
inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header));
|
|
memcpy (GST_BUFFER_DATA (inbuffer), identification_header,
|
|
sizeof (identification_header));
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
|
|
/* send empty comment buffer */
|
|
inbuffer = gst_buffer_new_and_alloc (sizeof (title_comment_header));
|
|
memcpy (GST_BUFFER_DATA (inbuffer), title_comment_header,
|
|
sizeof (title_comment_header));
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
|
|
/* send minimal codebook header and audio packers */
|
|
inbuffer = _create_codebook_header_buffer ();
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
inbuffer = _create_audio_buffer ();
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
|
|
|
|
/* check identification header is unchanged */
|
|
outbuffer = get_buffer ();
|
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
|
sizeof (identification_header));
|
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
|
identification_header, sizeof (identification_header)), 0);
|
|
gst_buffer_unref (outbuffer);
|
|
|
|
/* check comment header is correct */
|
|
outbuffer = get_buffer ();
|
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
|
sizeof (empty_comment_header));
|
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
|
empty_comment_header, sizeof (empty_comment_header)), 0);
|
|
gst_buffer_unref (outbuffer);
|
|
|
|
stop_pipeline (vorbistag);
|
|
cleanup_vorbistag (vorbistag);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
|
|
GST_START_TEST (test_filled_tags_change)
|
|
{
|
|
GstTagList *tags;
|
|
GstElement *vorbistag;
|
|
GstBuffer *inbuffer, *outbuffer;
|
|
|
|
vorbistag = setup_vorbistag ();
|
|
|
|
tags = gst_tag_list_new ();
|
|
gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, "foobar", NULL);
|
|
gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags,
|
|
GST_TAG_MERGE_REPLACE);
|
|
gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag),
|
|
GST_TAG_MERGE_KEEP_ALL);
|
|
gst_tag_list_free (tags);
|
|
|
|
start_pipeline (vorbistag);
|
|
|
|
/* send identification header */
|
|
inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header));
|
|
memcpy (GST_BUFFER_DATA (inbuffer), identification_header,
|
|
sizeof (identification_header));
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
|
|
/* send empty comment buffer */
|
|
inbuffer = gst_buffer_new_and_alloc (sizeof (artist_comment_header));
|
|
memcpy (GST_BUFFER_DATA (inbuffer), artist_comment_header,
|
|
sizeof (artist_comment_header));
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
|
|
/* send minimal codebook header and audio packers */
|
|
inbuffer = _create_codebook_header_buffer ();
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
inbuffer = _create_audio_buffer ();
|
|
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
|
|
|
|
|
/* check identification header is unchanged */
|
|
outbuffer = get_buffer ();
|
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
|
sizeof (identification_header));
|
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
|
identification_header, sizeof (identification_header)), 0);
|
|
gst_buffer_unref (outbuffer);
|
|
|
|
/* check comment header is correct */
|
|
outbuffer = get_buffer ();
|
|
fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
|
|
sizeof (title_comment_header));
|
|
fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
|
|
title_comment_header, sizeof (title_comment_header)), 0);
|
|
gst_buffer_unref (outbuffer);
|
|
|
|
stop_pipeline (vorbistag);
|
|
cleanup_vorbistag (vorbistag);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
|
|
|
|
static Suite *
|
|
vorbistag_suite (void)
|
|
{
|
|
Suite *s = suite_create ("vorbistag");
|
|
TCase *tc_chain = tcase_create ("general");
|
|
|
|
suite_add_tcase (s, tc_chain);
|
|
tcase_add_test (tc_chain, test_empty_tags_set);
|
|
tcase_add_test (tc_chain, test_filled_tags_unset);
|
|
tcase_add_test (tc_chain, test_filled_tags_change);
|
|
|
|
return s;
|
|
}
|
|
|
|
GST_CHECK_MAIN (vorbistag)
|