1 /* GStreamer
2 *
3 * unit test for jpegparse
4 *
5 * Copyright (C) <2009> Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 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 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser 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 /* This test doesn't use actual JPEG data, but some fake data that we know
28 will trigger certain paths in jpegparse. */
29
30 guint8 test_data_garbage[] = { 0x00, 0x01, 0xff, 0x32, 0x00, 0xff };
31 guint8 test_data_short_frame[] = { 0xff, 0xd8, 0xff, 0xd9 };
32
33 guint8 test_data_normal_frame[] = { 0xff, 0xd8, 0xff, 0x12, 0x00, 0x03, 0x33,
34 0xff, 0xd9
35 };
36
37 guint8 test_data_entropy[] = { 0xff, 0xd8, 0xff, 0xda, 0x00, 0x04, 0x22, 0x33,
38 0x44, 0xff, 0x00, 0x55, 0xff, 0x04, 0x00, 0x04, 0x22, 0x33, 0xff, 0xd9
39 };
40 guint8 test_data_ff[] = { 0xff, 0xff };
41
42 guint8 test_data_extra_ff[] = { 0xff, 0xd8, 0xff, 0xff, 0xff, 0x12, 0x00, 0x03,
43 0x33, 0xff, 0xff, 0xff, 0xd9
44 };
45
46 guint8 test_data_soi[] = { 0xff, 0xd8 };
47
48 guint8 test_data_app1_exif[] = {
49 0xff, 0xe1,
50 0x00, 0xd2, /* length = 210 */
51 0x45, 0x78, 0x69, 0x66, 0x00, /* Exif */
52 0x00,
53 0x49, 0x49,
54 0x2a, 0x00,
55 0x08,
56 0x00, 0x00, 0x00,
57 0x09, /* number of entries */
58 0x00,
59 0x0e, 0x01, /* tag 0x10e */
60 0x02, 0x00, /* type 2 */
61 0x0b, 0x00, /* count 11 */
62 0x00, 0x00,
63 0x7a, /* offset 122 (0x7a) */
64 0x00, 0x00, 0x00,
65 0x0f, 0x01, /* tag 0x10f */
66 0x02, 0x00, /* type 2 */
67 0x06, 0x00, /* count 6 */
68 0x00, 0x00,
69 0x85, /* offset 133 (0x85) */
70 0x00, 0x00, 0x00,
71 0x10, 0x01, /* tag 0x110 */
72 0x02, 0x00, /* type 2 */
73 0x05, 0x00, /* count 5 */
74 0x00, 0x00,
75 0x8b, /* offset 139 (0x8b) */
76 0x00, 0x00, 0x00,
77 0x12, 0x01, /* tag 0x112 */
78 0x03, 0x00, /* type 3 */
79 0x01, 0x00, /* count 1 */
80 0x00, 0x00,
81 0x01, 0x00, 0x30, 0x2c, /* offset (0x2c300001) */
82 0x1a, 0x01, /* tag 0x11a */
83 0x05, 0x00, /* type 5 */
84 0x01, 0x00, /* count 1 */
85 0x00, 0x00,
86 0x90, /* offset 144 (0x90) */
87 0x00, 0x00, 0x00,
88 0x1b, 0x01, /* tag 0x11b */
89 0x05, 0x00, /* type 5 */
90 0x01, 0x00, /* count 1 */
91 0x00, 0x00,
92 0x98, /* offset 152 (0x98) */
93 0x00, 0x00, 0x00,
94 0x28, 0x01, /* tag 0x128 */
95 0x03, 0x00, /* type 3 */
96 0x01, 0x00, /* count 1 */
97 0x00, 0x00,
98 0x02, 0x00, 0x31, 0x2f, /* offset (0x2f310002) */
99 0x31, 0x01, /* tag 0x131 */
100 0x02, 0x00, /* type 2 */
101 0x08, 0x00, /* count 8 */
102 0x00, 0x00,
103 0xa0, /* offset 160 (0xa0) */
104 0x00, 0x00, 0x00,
105 0x32, 0x01, /* tag 0x132 */
106 0x02, 0x00, /* type 2 */
107 0x14, 0x00, /* count 20 */
108 0x00, 0x00,
109 0xa8, /* offset 168 (0xa8) */
110 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00,
112 0x00,
113 /* string */
114 /* 122: */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00,
115 /* string (NIKON) */
116 /* 133: */ 0x4e, 0x49, 0x4b, 0x4f, 0x4e, 0x00,
117 /* string (E800) */
118 /* 139: */ 0x45, 0x38, 0x30, 0x30, 0x00,
119 /* 144: */ 0x00, 0x00, 0x80, 0x25, /* / */ 0x00, 0x00, 0x20, 0x00,
120 /* 152: */ 0x00, 0x00, 0x80, 0x25, /* / */ 0x00, 0x00, 0x20, 0x00,
121 /* string (v984-75) */
122 /* 160: */ 0x76, 0x39, 0x38, 0x34, 0x2d, 0x37, 0x35, 0x00,
123 /* string (2001:08:18 21:44:21) */
124 /* 168: */ 0x32, 0x30, 0x30, 0x31, 0x3a, 0x30, 0x38, 0x3a,
125 0x31, 0x38, 0x20, 0x32, 0x31, 0x3a, 0x34, 0x34,
126 0x3a, 0x32, 0x31, 0x00,
127
128 0x1e, 0x21, 0x1f, 0x1e, 0x21, 0x1c, 0x20, 0x21, 0x22, 0x24, 0x24, 0x27,
129 0x22, 0x20,
130 };
131
132 guint8 test_data_comment[] = {
133 0xff, 0xfe,
134 0x00, 0x08, /* size */
135 /* xxxxx */
136 0x78, 0x78, 0x78, 0x78, 0x78, 0x00,
137 };
138
139 guint8 test_data_sof0[] = {
140 0xff, 0xc0, /* baseline dct-based */
141 0x00, 0x11, /* size */
142 0x08, /* precision */
143 0x00, 0x3c, /* width */
144 0x00, 0x50, /* height */
145 0x03, /* number of components */
146 0x01, 0x22, 0x00, /* component 1 */
147 0x02, 0x11, 0x01, /* component 2 */
148 0x03, 0x11, 0x01, /* component 3 */
149 };
150
151 guint8 test_data_eoi[] = { 0xff, 0xd9 };
152
153 static GList *
_make_buffers_in(GList * buffer_in,guint8 * test_data,gsize test_data_size)154 _make_buffers_in (GList * buffer_in, guint8 * test_data, gsize test_data_size)
155 {
156 GstBuffer *buffer;
157 gsize i;
158
159 for (i = 0; i < test_data_size; i++) {
160 buffer =
161 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, test_data + i, 1,
162 0, 1, NULL, NULL);
163 buffer_in = g_list_append (buffer_in, buffer);
164 }
165 return buffer_in;
166 }
167
168 #define make_buffers_in(buffer_in, test_data) \
169 _make_buffers_in(buffer_in, test_data, sizeof(test_data))
170
171 static GList *
_make_buffers_out(GList * buffer_out,guint8 * test_data,gsize test_data_size)172 _make_buffers_out (GList * buffer_out, guint8 * test_data, gsize test_data_size)
173 {
174 GstBuffer *buffer;
175
176 buffer =
177 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, test_data,
178 test_data_size, 0, test_data_size, NULL, NULL);
179 buffer_out = g_list_append (buffer_out, buffer);
180
181 return buffer_out;
182 }
183
184 #define make_buffers_out(buffer_out, test_data) \
185 _make_buffers_out(buffer_out, test_data, sizeof(test_data))
186
GST_START_TEST(test_parse_single_byte)187 GST_START_TEST (test_parse_single_byte)
188 {
189 GList *buffer_in = NULL, *buffer_out = NULL;
190 GstCaps *caps_in, *caps_out;
191
192 caps_in = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, FALSE,
193 NULL);
194 caps_out = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
195 "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
196
197 /* Push the data byte by byte, injecting some garbage. */
198 buffer_in = make_buffers_in (buffer_in, test_data_garbage);
199 buffer_in = make_buffers_in (buffer_in, test_data_short_frame);
200 buffer_in = make_buffers_in (buffer_in, test_data_garbage);
201 buffer_in = make_buffers_in (buffer_in, test_data_normal_frame);
202 buffer_in = make_buffers_in (buffer_in, test_data_ff);
203 buffer_in = make_buffers_in (buffer_in, test_data_entropy);
204 buffer_in = make_buffers_in (buffer_in, test_data_extra_ff);
205
206 buffer_out = make_buffers_out (buffer_out, test_data_short_frame);
207 buffer_out = make_buffers_out (buffer_out, test_data_normal_frame);
208 buffer_out = make_buffers_out (buffer_out, test_data_entropy);
209 buffer_out = make_buffers_out (buffer_out, test_data_extra_ff);
210 gst_check_element_push_buffer_list ("jpegparse", buffer_in, caps_in,
211 buffer_out, caps_out, GST_FLOW_OK);
212
213 gst_caps_unref (caps_in);
214 gst_caps_unref (caps_out);
215 }
216
217 GST_END_TEST;
218
219
220
GST_START_TEST(test_parse_all_in_one_buf)221 GST_START_TEST (test_parse_all_in_one_buf)
222 {
223 GList *buffer_in = NULL, *buffer_out = NULL;
224 GstBuffer *buffer = NULL;
225 gsize total_size = 0;
226 gsize offset = 0;
227 GstCaps *caps_in, *caps_out;
228
229 /* Push the data in a single buffer, injecting some garbage. */
230 total_size += sizeof (test_data_garbage);
231 total_size += sizeof (test_data_short_frame);
232 total_size += sizeof (test_data_garbage);
233 total_size += sizeof (test_data_normal_frame);
234 total_size += sizeof (test_data_ff);
235 total_size += sizeof (test_data_entropy);
236 total_size += sizeof (test_data_extra_ff);
237 buffer = gst_buffer_new_and_alloc (total_size);
238 gst_buffer_fill (buffer, offset, test_data_garbage,
239 sizeof (test_data_garbage));
240 offset += sizeof (test_data_garbage);
241 gst_buffer_fill (buffer, offset, test_data_short_frame,
242 sizeof (test_data_short_frame));
243 offset += sizeof (test_data_short_frame);
244 gst_buffer_fill (buffer, offset, test_data_garbage,
245 sizeof (test_data_garbage));
246 offset += sizeof (test_data_garbage);
247 gst_buffer_fill (buffer, offset, test_data_normal_frame,
248 sizeof (test_data_normal_frame));
249 offset += sizeof (test_data_normal_frame);
250 gst_buffer_fill (buffer, offset, test_data_ff, sizeof (test_data_ff));
251 offset += sizeof (test_data_ff);
252 gst_buffer_fill (buffer, offset, test_data_entropy,
253 sizeof (test_data_entropy));
254 offset += sizeof (test_data_entropy);
255 gst_buffer_fill (buffer, offset, test_data_extra_ff,
256 sizeof (test_data_extra_ff));
257 offset += sizeof (test_data_extra_ff);
258
259 caps_in = gst_caps_new_simple ("image/jpeg", "parsed",
260 G_TYPE_BOOLEAN, FALSE, NULL);
261 GST_LOG ("Pushing single buffer of %u bytes.", (guint) total_size);
262 buffer_in = g_list_append (buffer_in, buffer);
263
264 caps_out = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
265 "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
266 buffer_out = make_buffers_out (buffer_out, test_data_short_frame);
267 buffer_out = make_buffers_out (buffer_out, test_data_normal_frame);
268 buffer_out = make_buffers_out (buffer_out, test_data_entropy);
269 buffer_out = make_buffers_out (buffer_out, test_data_extra_ff);
270
271 gst_check_element_push_buffer_list ("jpegparse", buffer_in, caps_in,
272 buffer_out, caps_out, GST_FLOW_OK);
273
274 gst_caps_unref (caps_in);
275 gst_caps_unref (caps_out);
276 }
277
278 GST_END_TEST;
279
280 static inline GstBuffer *
make_my_input_buffer(guint8 * test_data_header,gsize test_data_size)281 make_my_input_buffer (guint8 * test_data_header, gsize test_data_size)
282 {
283 GstBuffer *buffer;
284 gsize total_size = 0, offset = 0;
285
286 total_size += sizeof (test_data_soi);
287 total_size += test_data_size;
288 total_size += sizeof (test_data_sof0);
289 total_size += sizeof (test_data_eoi);
290
291 buffer = gst_buffer_new_and_alloc (total_size);
292
293 gst_buffer_fill (buffer, offset, test_data_soi, sizeof (test_data_soi));
294 offset += sizeof (test_data_soi);
295 gst_buffer_fill (buffer, offset, test_data_header, test_data_size);
296 offset += test_data_size;
297 gst_buffer_fill (buffer, offset, test_data_sof0, sizeof (test_data_sof0));
298 offset += sizeof (test_data_sof0);
299 gst_buffer_fill (buffer, offset, test_data_eoi, sizeof (test_data_eoi));
300 offset += sizeof (test_data_eoi);
301
302 return buffer;
303 }
304
305 static inline GstBuffer *
make_my_output_buffer(GstBuffer * buffer_in)306 make_my_output_buffer (GstBuffer * buffer_in)
307 {
308 GstBuffer *buffer;
309 GstMapInfo map;
310
311 gst_buffer_map (buffer_in, &map, GST_MAP_READ);
312 buffer = gst_buffer_new_and_alloc (map.size);
313 gst_buffer_fill (buffer, 0, map.data, map.size);
314 gst_buffer_unmap (buffer_in, &map);
315
316 return buffer;
317 }
318
319
GST_START_TEST(test_parse_app1_exif)320 GST_START_TEST (test_parse_app1_exif)
321 {
322 GstBuffer *buffer_in, *buffer_out;
323 GstCaps *caps_in, *caps_out;
324
325 caps_in = gst_caps_new_simple ("image/jpeg", "parsed",
326 G_TYPE_BOOLEAN, FALSE, NULL);
327
328 caps_out = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
329 "framerate", GST_TYPE_FRACTION, 1, 1, "format", G_TYPE_STRING,
330 "I420", "width", G_TYPE_INT, 80, "height", G_TYPE_INT, 60, NULL);
331
332 buffer_in = make_my_input_buffer (test_data_app1_exif,
333 sizeof (test_data_app1_exif));
334 buffer_out = make_my_output_buffer (buffer_in);
335
336 gst_check_element_push_buffer ("jpegparse", buffer_in, caps_in, buffer_out,
337 caps_out);
338
339 gst_caps_unref (caps_in);
340 gst_caps_unref (caps_out);
341 }
342
343 GST_END_TEST;
344
GST_START_TEST(test_parse_comment)345 GST_START_TEST (test_parse_comment)
346 {
347 GstBuffer *buffer_in, *buffer_out;
348 GstCaps *caps_in, *caps_out;
349
350 caps_in = gst_caps_new_simple ("image/jpeg", "parsed",
351 G_TYPE_BOOLEAN, FALSE, NULL);
352
353 caps_out = gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
354 "framerate", GST_TYPE_FRACTION, 1, 1, "format", G_TYPE_STRING,
355 "I420", "width", G_TYPE_INT, 80, "height", G_TYPE_INT, 60, NULL);
356
357 buffer_in = make_my_input_buffer (test_data_comment,
358 sizeof (test_data_comment));
359 buffer_out = make_my_output_buffer (buffer_in);
360
361 gst_check_element_push_buffer ("jpegparse", buffer_in, caps_in, buffer_out,
362 caps_out);
363
364 gst_caps_unref (caps_in);
365 gst_caps_unref (caps_out);
366 }
367
368 GST_END_TEST;
369
370 static Suite *
jpegparse_suite(void)371 jpegparse_suite (void)
372 {
373 Suite *s = suite_create ("jpegparse");
374 TCase *tc_chain = tcase_create ("jpegparse");
375
376 suite_add_tcase (s, tc_chain);
377 tcase_add_test (tc_chain, test_parse_single_byte);
378 tcase_add_test (tc_chain, test_parse_all_in_one_buf);
379 tcase_add_test (tc_chain, test_parse_app1_exif);
380 tcase_add_test (tc_chain, test_parse_comment);
381
382 return s;
383 }
384
385 GST_CHECK_MAIN (jpegparse);
386