1 /* GStreamer
2 * Copyright (C) 2009 Thomas Vander Stichele <thomas at apestaart dot org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include <gst/check/gstcheck.h>
21 #include <gst/audio/audio.h>
22 #include <glib/gstdio.h>
23
24 static guint16
_get_first_sample(GstSample * sample)25 _get_first_sample (GstSample * sample)
26 {
27 GstAudioInfo info;
28 GstCaps *caps;
29 GstBuffer *buf;
30 GstMapInfo map;
31 guint16 res;
32
33 fail_unless (sample != NULL, "NULL sample");
34
35 caps = gst_sample_get_caps (sample);
36 fail_unless (caps != NULL, "sample without caps");
37
38 buf = gst_sample_get_buffer (sample);
39 GST_DEBUG ("buffer with size=%" G_GSIZE_FORMAT ", caps=%" GST_PTR_FORMAT,
40 gst_buffer_get_size (buf), caps);
41
42 gst_buffer_map (buf, &map, GST_MAP_READ);
43 /* log buffer details */
44 GST_MEMDUMP ("buffer data from decoder", map.data, map.size);
45
46 /* make sure it's the format we expect */
47 fail_unless (gst_audio_info_from_caps (&info, caps));
48
49 fail_unless_equals_int (GST_AUDIO_INFO_WIDTH (&info), 16);
50 fail_unless_equals_int (GST_AUDIO_INFO_DEPTH (&info), 16);
51 fail_unless_equals_int (GST_AUDIO_INFO_RATE (&info), 44100);
52 fail_unless_equals_int (GST_AUDIO_INFO_CHANNELS (&info), 1);
53
54 if (GST_AUDIO_INFO_IS_LITTLE_ENDIAN (&info))
55 res = GST_READ_UINT16_LE (map.data);
56 else
57 res = GST_READ_UINT16_BE (map.data);
58
59 gst_buffer_unmap (buf, &map);
60
61 return res;
62 }
63
GST_START_TEST(test_decode)64 GST_START_TEST (test_decode)
65 {
66 GstElement *pipeline;
67 GstElement *appsink;
68 GstSample *sample = NULL;
69 guint16 first_sample = 0;
70 guint size = 0;
71 gchar *path =
72 g_build_filename (GST_TEST_FILES_PATH, "audiotestsrc.flac", NULL);
73 gchar *pipe_desc =
74 g_strdup_printf
75 ("filesrc location=\"%s\" ! flacparse ! flacdec ! appsink name=sink",
76 path);
77
78 pipeline = gst_parse_launch (pipe_desc, NULL);
79 fail_unless (pipeline != NULL);
80
81 g_free (path);
82 g_free (pipe_desc);
83
84 appsink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
85 fail_unless (appsink != NULL);
86
87 gst_element_set_state (pipeline, GST_STATE_PLAYING);
88
89 do {
90 g_signal_emit_by_name (appsink, "pull-sample", &sample);
91 if (sample == NULL)
92 break;
93 if (first_sample == 0)
94 first_sample = _get_first_sample (sample);
95
96 size += gst_buffer_get_size (gst_sample_get_buffer (sample));
97
98 gst_sample_unref (sample);
99 sample = NULL;
100 }
101 while (TRUE);
102
103 /* audiotestsrc with samplesperbuffer 1024 and 10 num-buffers */
104 fail_unless_equals_int (size, 20480);
105 fail_unless_equals_int (first_sample, 0x066a);
106
107 gst_element_set_state (pipeline, GST_STATE_NULL);
108 g_object_unref (pipeline);
109 g_object_unref (appsink);
110 }
111
112 GST_END_TEST;
113
GST_START_TEST(test_decode_seek_full)114 GST_START_TEST (test_decode_seek_full)
115 {
116 GstElement *pipeline;
117 GstElement *appsink;
118 GstEvent *event;
119 GstSample *sample = NULL;
120 guint16 first_sample = 0;
121 guint size = 0;
122 gchar *path =
123 g_build_filename (GST_TEST_FILES_PATH, "audiotestsrc.flac", NULL);
124 gchar *pipe_desc =
125 g_strdup_printf
126 ("filesrc location=\"%s\" ! flacparse ! flacdec ! appsink name=sink",
127 path);
128
129 pipeline = gst_parse_launch (pipe_desc, NULL);
130 fail_unless (pipeline != NULL);
131
132 g_free (pipe_desc);
133 g_free (path);
134
135 appsink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
136 fail_unless (appsink != NULL);
137
138 gst_element_set_state (pipeline, GST_STATE_PAUSED);
139 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
140
141 /* do a seek that should give us the complete output */
142 event = gst_event_new_seek (1.0, GST_FORMAT_DEFAULT, GST_SEEK_FLAG_FLUSH,
143 GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 20480);
144 fail_unless (gst_element_send_event (appsink, event));
145
146 gst_element_set_state (pipeline, GST_STATE_PLAYING);
147
148 do {
149 g_signal_emit_by_name (appsink, "pull-sample", &sample);
150 if (sample == NULL)
151 break;
152 if (first_sample == 0)
153 first_sample = _get_first_sample (sample);
154 size += gst_buffer_get_size (gst_sample_get_buffer (sample));
155
156 gst_sample_unref (sample);
157 sample = NULL;
158 }
159 while (TRUE);
160
161 /* file was generated with audiotestsrc
162 * with 1024 samplesperbuffer and 10 num-buffers in 16 bit audio */
163 fail_unless_equals_int (size, 20480);
164 fail_unless_equals_int (first_sample, 0x066a);
165
166 gst_element_set_state (pipeline, GST_STATE_NULL);
167
168 g_object_unref (pipeline);
169 g_object_unref (appsink);
170 }
171
172 GST_END_TEST;
173
GST_START_TEST(test_decode_seek_partial)174 GST_START_TEST (test_decode_seek_partial)
175 {
176 GstElement *pipeline;
177 GstElement *appsink;
178 GstEvent *event;
179 GstSample *sample = NULL;
180 guint size = 0;
181 guint16 first_sample = 0;
182 gchar *path =
183 g_build_filename (GST_TEST_FILES_PATH, "audiotestsrc.flac", NULL);
184 gchar *pipe_desc =
185 g_strdup_printf
186 ("filesrc location=\"%s\" ! flacparse ! flacdec ! appsink name=sink",
187 path);
188
189 pipeline = gst_parse_launch (pipe_desc, NULL);
190 fail_unless (pipeline != NULL);
191
192 g_free (path);
193 g_free (pipe_desc);
194
195 appsink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
196 fail_unless (appsink != NULL);
197
198 gst_element_set_state (pipeline, GST_STATE_PAUSED);
199 gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
200
201 /* do a partial seek to get the first 1024 samples or 2048 bytes */
202 event = gst_event_new_seek (1.0, GST_FORMAT_DEFAULT, GST_SEEK_FLAG_FLUSH,
203 GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 1024);
204 GST_DEBUG ("seeking");
205 fail_unless (gst_element_send_event (appsink, event));
206 GST_DEBUG ("seeked");
207
208 gst_element_set_state (pipeline, GST_STATE_PLAYING);
209
210 do {
211 GST_DEBUG ("pulling sample");
212 g_signal_emit_by_name (appsink, "pull-sample", &sample);
213 GST_DEBUG ("pulled sample %p", sample);
214 if (sample == NULL)
215 break;
216 if (first_sample == 0) {
217 first_sample = _get_first_sample (sample);
218 }
219 size += gst_buffer_get_size (gst_sample_get_buffer (sample));
220
221 gst_sample_unref (sample);
222 sample = NULL;
223 }
224 while (TRUE);
225
226 /* allow for sample round-up clipping effect */
227 fail_unless (size == 2048 || size == 2050);
228 fail_unless_equals_int (first_sample, 0x066a);
229
230 gst_element_set_state (pipeline, GST_STATE_NULL);
231
232 g_object_unref (pipeline);
233 g_object_unref (appsink);
234 }
235
236 GST_END_TEST;
237
238 static Suite *
flacdec_suite(void)239 flacdec_suite (void)
240 {
241 Suite *s = suite_create ("flacdec");
242
243 TCase *tc_chain = tcase_create ("linear");
244
245 /* time out after 60s, not the default 3 */
246 tcase_set_timeout (tc_chain, 60);
247
248 suite_add_tcase (s, tc_chain);
249 tcase_add_test (tc_chain, test_decode);
250 tcase_add_test (tc_chain, test_decode_seek_full);
251 tcase_add_test (tc_chain, test_decode_seek_partial);
252
253 return s;
254 }
255
256 GST_CHECK_MAIN (flacdec);
257