1 /* GStreamer
2  *
3  * unit test for wavpackdec
4  *
5  * Copyright (c) 2006 Sebastian Dröge <slomo@circular-chaos.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include <unistd.h>
24 
25 #include <gst/check/gstcheck.h>
26 
27 /* For ease of programming we use globals to keep refs for our floating
28  * src and sink pads we create; otherwise we always have to do get_pad,
29  * get_peer, and then remove references in every test function */
30 static GstPad *mysrcpad, *mysinkpad;
31 
32 #if G_BYTE_ORDER == G_BIG_ENDIAN
33 #define AUDIO_FORMAT "S16BE"
34 #else
35 #define AUDIO_FORMAT "S16LE"
36 #endif
37 
38 guint8 test_frame[] = {
39   0x77, 0x76, 0x70, 0x6B,       /* "wvpk" */
40   0x2E, 0x00, 0x00, 0x00,       /* ckSize */
41   0x04, 0x04,                   /* version */
42   0x00,                         /* track_no */
43   0x00,                         /* index_no */
44   0x00, 0x64, 0x00, 0x00,       /* total_samples */
45   0x00, 0x00, 0x00, 0x00,       /* block_index */
46   0x00, 0x64, 0x00, 0x00,       /* block_samples */
47   0x05, 0x18, 0x80, 0x04,       /* flags */
48   0xFF, 0xAF, 0x80, 0x60,       /* crc */
49   0x02, 0x00, 0x03, 0x00,       /* data */
50   0x04, 0x00, 0x05, 0x03,
51   0x00, 0x00, 0x00, 0x00,
52   0x00, 0x00, 0x8A, 0x02,
53   0x00, 0x00, 0xFF, 0x7F,
54   0x00, 0xE4,
55 };
56 
57 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
58     GST_PAD_SINK,
59     GST_PAD_ALWAYS,
60     GST_STATIC_CAPS ("audio/x-raw, "
61         "format = (string) " AUDIO_FORMAT ", "
62         "layout = (string) interleaved, "
63         "channels = (int) 1, " "rate = (int) 44100")
64     );
65 
66 #define WAVPACK_CAPS "audio/x-wavpack, " \
67         "depth = (int) 16, " \
68         "channels = (int) 1, " "rate = (int) 44100, " "framed = (boolean) true"
69 
70 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
71     GST_PAD_SRC,
72     GST_PAD_ALWAYS,
73     GST_STATIC_CAPS (WAVPACK_CAPS)
74     );
75 
76 static GstElement *
setup_wavpackdec(void)77 setup_wavpackdec (void)
78 {
79   GstElement *wavpackdec;
80   GstCaps *caps;
81 
82   GST_DEBUG ("setup_wavpackdec");
83   wavpackdec = gst_check_setup_element ("wavpackdec");
84   mysrcpad = gst_check_setup_src_pad (wavpackdec, &srctemplate);
85   mysinkpad = gst_check_setup_sink_pad (wavpackdec, &sinktemplate);
86   gst_pad_set_active (mysrcpad, TRUE);
87   gst_pad_set_active (mysinkpad, TRUE);
88 
89   caps = gst_caps_from_string (WAVPACK_CAPS);
90   gst_check_setup_events (mysrcpad, wavpackdec, caps, GST_FORMAT_TIME);
91   gst_caps_unref (caps);
92 
93   fail_unless (gst_element_set_state (wavpackdec,
94           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
95       "could not set to playing");
96 
97   return wavpackdec;
98 }
99 
100 static void
cleanup_wavpackdec(GstElement * wavpackdec)101 cleanup_wavpackdec (GstElement * wavpackdec)
102 {
103   GST_DEBUG ("cleanup_wavpackdec");
104   gst_element_set_state (wavpackdec, GST_STATE_NULL);
105 
106   gst_pad_set_active (mysrcpad, FALSE);
107   gst_pad_set_active (mysinkpad, FALSE);
108   gst_check_teardown_src_pad (wavpackdec);
109   gst_check_teardown_sink_pad (wavpackdec);
110   gst_check_teardown_element (wavpackdec);
111 }
112 
GST_START_TEST(test_decode_frame)113 GST_START_TEST (test_decode_frame)
114 {
115   GstElement *wavpackdec;
116   GstBuffer *inbuffer, *outbuffer;
117   GstBus *bus;
118   int i;
119   GstMapInfo map;
120 
121   wavpackdec = setup_wavpackdec ();
122   bus = gst_bus_new ();
123 
124   inbuffer = gst_buffer_new_and_alloc (sizeof (test_frame));
125   gst_buffer_fill (inbuffer, 0, test_frame, sizeof (test_frame));
126   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
127   GST_BUFFER_TIMESTAMP (inbuffer) = 0;
128 
129   gst_element_set_bus (wavpackdec, bus);
130 
131   /* should decode the buffer without problems */
132   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
133 
134   outbuffer = GST_BUFFER (buffers->data);
135 
136   fail_if (outbuffer == NULL);
137 
138   gst_buffer_map (outbuffer, &map, GST_MAP_READ);
139 
140   /* uncompressed data should be 102400 bytes */
141   fail_unless_equals_int (map.size, 51200);
142 
143   /* and all bytes must be 0, i.e. silence */
144   for (i = 0; i < 51200; i++)
145     fail_unless_equals_int (map.data[i], 0);
146 
147   gst_buffer_unmap (outbuffer, &map);
148 
149   ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
150   gst_buffer_unref (outbuffer);
151   outbuffer = NULL;
152 
153   g_list_free (buffers);
154   buffers = NULL;
155 
156   gst_bus_set_flushing (bus, TRUE);
157   gst_element_set_bus (wavpackdec, NULL);
158   gst_object_unref (GST_OBJECT (bus));
159   cleanup_wavpackdec (wavpackdec);
160 }
161 
162 GST_END_TEST;
163 
GST_START_TEST(test_decode_frame_with_broken_header)164 GST_START_TEST (test_decode_frame_with_broken_header)
165 {
166   GstElement *wavpackdec;
167   GstBuffer *inbuffer;
168   GstBus *bus;
169   GstMessage *message;
170 
171   wavpackdec = setup_wavpackdec ();
172   bus = gst_bus_new ();
173 
174   inbuffer = gst_buffer_new_and_alloc (sizeof (test_frame));
175   gst_buffer_fill (inbuffer, 0, test_frame, sizeof (test_frame));
176   /* break header */
177   gst_buffer_memset (inbuffer, 2, 'e', 1);
178   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
179   GST_BUFFER_TIMESTAMP (inbuffer) = 0;
180 
181   gst_element_set_bus (wavpackdec, bus);
182 
183   /* should fail gracefully */
184   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_ERROR);
185 
186   fail_if ((message = gst_bus_pop (bus)) == NULL);
187   fail_unless_message_error (message, STREAM, DECODE);
188   gst_message_unref (message);
189 
190   gst_element_set_bus (wavpackdec, NULL);
191   gst_object_unref (GST_OBJECT (bus));
192   cleanup_wavpackdec (wavpackdec);
193 }
194 
195 GST_END_TEST;
196 
GST_START_TEST(test_decode_frame_with_incomplete_frame)197 GST_START_TEST (test_decode_frame_with_incomplete_frame)
198 {
199   GstElement *wavpackdec;
200   GstBuffer *inbuffer;
201   GstBus *bus;
202   GstMessage *message;
203 
204   wavpackdec = setup_wavpackdec ();
205   bus = gst_bus_new ();
206 
207   inbuffer = gst_buffer_new_and_alloc (sizeof (test_frame) - 2);
208   gst_buffer_fill (inbuffer, 0, test_frame, sizeof (test_frame) - 2);
209   ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
210   GST_BUFFER_TIMESTAMP (inbuffer) = 0;
211 
212   gst_element_set_bus (wavpackdec, bus);
213 
214   /* should fail gracefully */
215   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_ERROR);
216 
217   fail_if ((message = gst_bus_pop (bus)) == NULL);
218   fail_unless_message_error (message, STREAM, DECODE);
219   gst_message_unref (message);
220 
221 
222   gst_element_set_bus (wavpackdec, NULL);
223   gst_object_unref (GST_OBJECT (bus));
224   cleanup_wavpackdec (wavpackdec);
225 }
226 
227 GST_END_TEST;
228 
229 static Suite *
wavpackdec_suite(void)230 wavpackdec_suite (void)
231 {
232   Suite *s = suite_create ("wavpackdec");
233   TCase *tc_chain = tcase_create ("general");
234 
235   suite_add_tcase (s, tc_chain);
236   tcase_add_test (tc_chain, test_decode_frame);
237   tcase_add_test (tc_chain, test_decode_frame_with_broken_header);
238   tcase_add_test (tc_chain, test_decode_frame_with_incomplete_frame);
239 
240   return s;
241 }
242 
243 GST_CHECK_MAIN (wavpackdec);
244