1 /* GStreamer unit tests for subparse
2 * Copyright (C) 2006-2008 Tim-Philipp Müller <tim centricular net>
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 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <gst/check/gstcheck.h>
25 #include <gst/check/gstharness.h>
26
27 #include <string.h>
28
29 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
30 GST_PAD_SINK,
31 GST_PAD_ALWAYS,
32 GST_STATIC_CAPS ("text/x-raw, format = { pango-markup, utf8 }")
33 );
34 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
35 GST_PAD_SRC,
36 GST_PAD_ALWAYS,
37 GST_STATIC_CAPS ("ANY")
38 );
39
40 static GstElement *subparse;
41 static GstPad *mysrcpad, *mysinkpad;
42
43 static GstBuffer *
buffer_from_static_string(const gchar * s)44 buffer_from_static_string (const gchar * s)
45 {
46 GstBuffer *buf;
47 gsize len;
48
49 len = strlen (s);
50
51 buf = gst_buffer_new ();
52 gst_buffer_append_memory (buf,
53 gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
54 (gpointer) s, len, 0, len, NULL, NULL));
55
56 return buf;
57 }
58
59 typedef struct
60 {
61 const gchar *in;
62 GstClockTime from_ts;
63 GstClockTime to_ts;
64 const gchar *out;
65 } SubParseInputChunk;
66
67 static SubParseInputChunk srt_input[] = {
68 {
69 "1\n00:00:01,000 --> 00:00:02,000\nOne\n\n",
70 1 * GST_SECOND, 2 * GST_SECOND, "One"}, {
71 "2\n00:00:02,000 --> 00:00:03,000\nTwo\n\n",
72 2 * GST_SECOND, 3 * GST_SECOND, "Two"}, {
73 "3\n00:00:03,000 --> 00:00:04,000\nThree\n\n",
74 3 * GST_SECOND, 4 * GST_SECOND, "Three"}, {
75 "4\n00:00:04,000 --> 00:00:05,000\nFour\n\n",
76 4 * GST_SECOND, 5 * GST_SECOND, "Four"}, {
77 "5\n00:00:05,000 --> 00:00:06,000\nFive\n\n",
78 5 * GST_SECOND, 6 * GST_SECOND, "Five"}, {
79 /* markup should be preserved */
80 "6\n00:00:06,000 --> 00:00:07,000\n<i>Six</i>\n\n",
81 6 * GST_SECOND, 7 * GST_SECOND, "<i>Six</i>"}, {
82 /* open markup tags should be closed */
83 "7\n00:00:07,000 --> 00:00:08,000\n<i>Seven\n\n",
84 7 * GST_SECOND, 8 * GST_SECOND, "<i>Seven</i>"}, {
85 /* open markup tags should be closed (II) */
86 "8\n00:00:08,000 --> 00:00:09,000\n<b><i>Eight\n\n",
87 8 * GST_SECOND, 9 * GST_SECOND, "<b><i>Eight</i></b>"}, {
88 /* broken markup should be fixed */
89 "9\n00:00:09,000 --> 00:00:10,000\n</b>\n\n",
90 9 * GST_SECOND, 10 * GST_SECOND, ""}, {
91 "10\n00:00:10,000 --> 00:00:11,000\n</b></i>\n\n",
92 10 * GST_SECOND, 11 * GST_SECOND, ""}, {
93 "11\n00:00:11,000 --> 00:00:12,000\n<i>xyz</b></i>\n\n",
94 11 * GST_SECOND, 12 * GST_SECOND, "<i>xyz</i>"}, {
95 "12\n00:00:12,000 --> 00:00:13,000\n<i>xyz</b>\n\n",
96 12 * GST_SECOND, 13 * GST_SECOND, "<i>xyz</i>"}, {
97 "13\n00:00:13,000 --> 00:00:14,000\n<i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i>Keep them comiiiiiing\n\n",
98 13 * GST_SECOND, 14 * GST_SECOND,
99 "<i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i><i>Keep them comiiiiiing</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>"}, {
100 /* skip a few chunk numbers here, the numbers shouldn't matter */
101 "24\n00:01:00,000 --> 00:02:00,000\nYep, still here\n\n",
102 60 * GST_SECOND, 120 * GST_SECOND, "Yep, still here"}, {
103 /* make sure stuff is escaped properly, but allowed markup stays intact */
104 "25\n00:03:00,000 --> 00:04:00,000\ngave <i>Rock & Roll</i> to\n\n",
105 180 * GST_SECOND, 240 * GST_SECOND, "gave <i>Rock & Roll</i> to"}, {
106 "26\n00:04:00,000 --> 00:05:00,000\n<i>Rock & Roll</i>\n\n",
107 240 * GST_SECOND, 300 * GST_SECOND, "<i>Rock & Roll</i>"}, {
108 "27\n00:06:00,000 --> 00:08:00,000\nRock & Roll\n\n",
109 360 * GST_SECOND, 480 * GST_SECOND, "Rock & Roll"}, {
110 "28\n00:10:00,000 --> 00:11:00,000\n"
111 "<font \"#0000FF\"><joj>This is </xxx>in blue but <5</font>\n\n",
112 600 * GST_SECOND, 660 * GST_SECOND, "This is in blue but <5"}, {
113 /* closing tags should be recognised properly even if there's a space */
114 "29\n00:11:00,000 --> 00:12:00,000\n" "<i>italics</ i>\n\n",
115 660 * GST_SECOND, 720 * GST_SECOND, "<i>italics</i>"}, {
116 /* closing tags should be escaped and fixed up if not recognised */
117 "30\n00:12:00,000 --> 00:12:01,000\n" "<i>italics</ x>\n\n",
118 720 * GST_SECOND, 721 * GST_SECOND, "<i>italics</ x></i>"},
119 };
120
121 /* starts with chunk number 0 (not exactly according to spec) */
122 static SubParseInputChunk srt_input0[] = {
123 {
124 "0\n00:00:01,000 --> 00:00:02,000\nOne\n\n",
125 1 * GST_SECOND, 2 * GST_SECOND, "One"}, {
126 "1\n00:00:02,000 --> 00:00:03,000\nTwo\n\n",
127 2 * GST_SECOND, 3 * GST_SECOND, "Two"}, {
128 "2\n00:00:03,000 --> 00:00:04,000\nThree\n\n",
129 3 * GST_SECOND, 4 * GST_SECOND, "Three"}
130 };
131
132 /* has spaces instead of doubled zeroes (not exactly according to spec) */
133 static SubParseInputChunk srt_input1[] = {
134 {
135 "1\n 0: 0:26, 26 --> 0: 0:28, 17\nI cant see.\n\n",
136 26 * GST_SECOND + 26 * GST_MSECOND,
137 28 * GST_SECOND + 17 * GST_MSECOND, "I cant see."},
138 {
139 "2\n 0: 0:30, 30 --> 0: 0:33, 22\nI really cant see.\n\n",
140 30 * GST_SECOND + 30 * GST_MSECOND,
141 33 * GST_SECOND + 22 * GST_MSECOND, "I really cant see."},
142 {
143 "3\n 0: 0:40, 40 --> 0: 0:44, 44\nI still cant see anything.\n\n",
144 40 * GST_SECOND + 40 * GST_MSECOND,
145 44 * GST_SECOND + 44 * GST_MSECOND, "I still cant see anything."}
146 };
147
148 /* has UTF-8 BOM at the start */
149 static SubParseInputChunk srt_input2[] = {
150 {
151 "\xef\xbb\xbf" "1\n00:00:00,000 --> 00:00:03,50\nJust testing.\n\n",
152 0, 3 * GST_SECOND + 500 * GST_MSECOND, "Just testing."}
153 };
154
155 /* starts with chunk number 0 and has less than three digits after the comma
156 * and a few extra spaces before the arrow or at the end of the line */
157 static SubParseInputChunk srt_input3[] = {
158 {
159 "0\n00:00:01,0 --> 00:00:02,0\nOne\n\n",
160 1000 * GST_MSECOND, 2000 * GST_MSECOND, "One"}, {
161 "1\n00:00:02,5 --> 00:00:03, 5 \nTwo\n\n",
162 2500 * GST_MSECOND, 3005 * GST_MSECOND, "Two"}, {
163 "2\n00:00:03, 9 --> 00:00:04,0 \nThree\n\n",
164 3090 * GST_MSECOND, 4000 * GST_MSECOND, "Three"}
165 };
166
167 /* Some WebVTT chunks, this format is similar to SRT but should be
168 * parsed differently nonetheless, the WebVTT tags should be stripped
169 * off. */
170 static SubParseInputChunk srt_input4[] = {
171 {
172 "1\n00:00:01,000 --> 00:00:02,000\n<v>some text\n\n",
173 1 * GST_SECOND, 2 * GST_SECOND, "some text"}
174 ,
175 {
176 "1\n00:00:01,000 --> 00:00:02,000\n<b.loud>some text\n\n",
177 1 * GST_SECOND, 2 * GST_SECOND, "<b>some text</b>"}
178 ,
179 {
180 "1\n00:00:01,000 --> 00:00:02,000\n<ruby>base text<rt>annotation</rt></ruby>\n\n",
181 1 * GST_SECOND, 2 * GST_SECOND,
182 "base textannotation"}
183 ,
184 };
185
186 /* Test broken timestamp */
187 static SubParseInputChunk srt_input5[] = {
188 {
189 "1\n00:00:01,000 --> 00:00:02,000\n<v>some text\n\n",
190 1 * GST_SECOND, 2 * GST_SECOND, "some text"}
191 ,
192 {
193 "2\n00:02:00,000 --> 00:03:0\n<v>some other text\n\n3\n00:00:03,000 --> 00:00:04,000\n<v>some more text\n\n",
194 3 * GST_SECOND, 4 * GST_SECOND, "some more text"}
195 ,
196 };
197
198 /* Test with no newline at the end */
199 static SubParseInputChunk srt_input6[] = {
200 {
201 "1\n00:00:01,000 --> 00:00:02,000\nLast cue, no newline at the end",
202 1 * GST_SECOND, 2 * GST_SECOND, "Last cue, no newline at the end"}
203 ,
204 };
205
206
207 static void
setup_subparse(void)208 setup_subparse (void)
209 {
210 GstSegment segment;
211 subparse = gst_check_setup_element ("subparse");
212
213 mysrcpad = gst_check_setup_src_pad (subparse, &srctemplate);
214 mysinkpad = gst_check_setup_sink_pad (subparse, &sinktemplate);
215
216 gst_pad_set_active (mysrcpad, TRUE);
217
218 gst_segment_init (&segment, GST_FORMAT_BYTES);
219 gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test"));
220 gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment));
221 gst_pad_set_active (mysinkpad, TRUE);
222
223 fail_unless_equals_int (gst_element_set_state (subparse, GST_STATE_PLAYING),
224 GST_STATE_CHANGE_SUCCESS);
225 }
226
227 static void
teardown_subparse(void)228 teardown_subparse (void)
229 {
230 GST_DEBUG ("cleaning up");
231
232 g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
233 g_list_free (buffers);
234 buffers = NULL;
235
236 gst_pad_set_active (mysrcpad, FALSE);
237 gst_pad_set_active (mysinkpad, FALSE);
238 gst_check_teardown_sink_pad (subparse);
239 gst_check_teardown_src_pad (subparse);
240 gst_check_teardown_element (subparse);
241 subparse = NULL;
242 mysrcpad = NULL;
243 mysinkpad = NULL;
244 }
245
246 static void
test_srt_do_test(SubParseInputChunk * input,guint start_idx,guint num)247 test_srt_do_test (SubParseInputChunk * input, guint start_idx, guint num)
248 {
249 guint n;
250 GstCaps *outcaps;
251
252 GST_LOG ("srt test: start_idx = %u, num = %u", start_idx, num);
253
254 setup_subparse ();
255
256 for (n = start_idx; n < start_idx + num; ++n) {
257 GstBuffer *buf;
258
259 buf = buffer_from_static_string (input[n].in);
260 fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK);
261 }
262
263 gst_pad_push_event (mysrcpad, gst_event_new_eos ());
264
265 fail_unless_equals_int (g_list_length (buffers), num);
266
267 outcaps = gst_pad_get_current_caps (mysinkpad);
268
269 for (n = start_idx; n < start_idx + num; ++n) {
270 const GstStructure *buffer_caps_struct;
271 GstBuffer *buf;
272 GstMapInfo map;
273
274 buf = g_list_nth_data (buffers, n - start_idx);
275 fail_unless (buf != NULL);
276 fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf), NULL);
277 fail_unless (GST_BUFFER_DURATION_IS_VALID (buf), NULL);
278 fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buf), input[n].from_ts);
279 fail_unless_equals_uint64 (GST_BUFFER_DURATION (buf),
280 input[n].to_ts - input[n].from_ts);
281
282 gst_buffer_map (buf, &map, GST_MAP_READ);
283 /* can be NULL */
284 if (map.data != NULL) {
285 /* shouldn't have trailing newline characters */
286 fail_if (map.size > 0 && map.data[map.size - 1] == '\n');
287 /* shouldn't include NUL-terminator in data size */
288 fail_if (map.size > 0 && map.data[map.size - 1] == '\0');
289 /* but should still have a NUL-terminator behind the declared data */
290 fail_unless_equals_int (map.data[map.size], '\0');
291 /* make sure out string matches expected string */
292 fail_unless_equals_string ((gchar *) map.data, input[n].out);
293 }
294 gst_buffer_unmap (buf, &map);
295 /* check caps */
296 fail_unless (outcaps != NULL);
297 buffer_caps_struct = gst_caps_get_structure (outcaps, 0);
298 fail_unless (gst_structure_has_name (buffer_caps_struct, "text/x-raw"));
299 fail_unless_equals_string (gst_structure_get_string (buffer_caps_struct,
300 "format"), "pango-markup");
301 }
302 gst_caps_unref (outcaps);
303
304 teardown_subparse ();
305 }
306
307 static void
test_vtt_do_test(SubParseInputChunk * input,guint start_idx,guint num)308 test_vtt_do_test (SubParseInputChunk * input, guint start_idx, guint num)
309 {
310 guint n;
311
312 GST_LOG ("vtt test: start_idx = %u, num = %u", start_idx, num);
313
314 setup_subparse ();
315
316 for (n = start_idx; n < start_idx + num; ++n) {
317 GstBuffer *buf;
318 gchar *data = g_strconcat ("WEBVTT FILE\n", input[n].in, NULL);
319 buf = buffer_from_static_string (data);
320 fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK);
321 g_free (data);
322 }
323
324 gst_pad_push_event (mysrcpad, gst_event_new_eos ());
325
326 fail_unless_equals_int (g_list_length (buffers), num);
327
328 for (n = start_idx; n < start_idx + num; ++n) {
329 const GstStructure *buffer_caps_struct;
330 GstMapInfo map;
331 GstBuffer *buf;
332 GstCaps *outcaps;
333 gchar *out;
334 guint out_size;
335
336 buf = g_list_nth_data (buffers, n - start_idx);
337 fail_unless (buf != NULL);
338 fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf), NULL);
339 fail_unless (GST_BUFFER_DURATION_IS_VALID (buf), NULL);
340 fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buf), input[n].from_ts);
341 fail_unless_equals_uint64 (GST_BUFFER_DURATION (buf),
342 input[n].to_ts - input[n].from_ts);
343 fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ));
344 out = (gchar *) map.data;
345
346 out_size = gst_buffer_get_size (buf);
347 /* shouldn't have trailing newline characters */
348 fail_if (out_size > 0 && out[out_size - 1] == '\n');
349 /* shouldn't include NUL-terminator in data size */
350 fail_if (out_size > 0 && out[out_size - 1] == '\0');
351 /* but should still have a NUL-terminator behind the declared data */
352 fail_unless_equals_int (out[out_size], '\0');
353 /* make sure out string matches expected string */
354 fail_unless_equals_string (out, input[n].out);
355
356 gst_buffer_unmap (buf, &map);
357
358 /* check caps */
359 outcaps = gst_pad_get_current_caps (mysinkpad);
360 fail_unless (outcaps != NULL);
361 buffer_caps_struct = gst_caps_get_structure (outcaps, 0);
362 fail_unless_equals_string (gst_structure_get_name (buffer_caps_struct),
363 "text/x-raw");
364 fail_unless_equals_string (gst_structure_get_string (buffer_caps_struct,
365 "format"), "pango-markup");
366 gst_caps_unref (outcaps);
367 }
368
369 teardown_subparse ();
370 }
371
GST_START_TEST(test_srt)372 GST_START_TEST (test_srt)
373 {
374 test_srt_do_test (srt_input, 0, G_N_ELEMENTS (srt_input));
375
376 /* make sure everything works fine if we don't start with chunk 1 */
377 test_srt_do_test (srt_input, 1, G_N_ELEMENTS (srt_input) - 1);
378 test_srt_do_test (srt_input, 2, G_N_ELEMENTS (srt_input) - 2);
379 test_srt_do_test (srt_input, 3, G_N_ELEMENTS (srt_input) - 3);
380 test_srt_do_test (srt_input, 4, G_N_ELEMENTS (srt_input) - 4);
381
382 /* try with empty input, immediate EOS */
383 test_srt_do_test (srt_input, 5, G_N_ELEMENTS (srt_input) - 5);
384
385 /* try with chunk number 0 (which is not exactly according to spec) */
386 test_srt_do_test (srt_input0, 0, G_N_ELEMENTS (srt_input0));
387
388 /* try with spaces instead of doubled zeroes (which is not exactly according to spec) */
389 test_srt_do_test (srt_input1, 0, G_N_ELEMENTS (srt_input1));
390
391 /* try with UTF-8 BOM at the start */
392 test_srt_do_test (srt_input2, 0, G_N_ELEMENTS (srt_input2));
393
394 /* try with fewer than three post-comma digits, and some extra spaces */
395 test_srt_do_test (srt_input3, 0, G_N_ELEMENTS (srt_input3));
396
397 /* try with some WebVTT chunks */
398 test_srt_do_test (srt_input4, 0, G_N_ELEMENTS (srt_input4));
399
400 /* try with some broken/cut-off timestamp */
401 test_srt_do_test (srt_input5, 0, G_N_ELEMENTS (srt_input5));
402
403 /* try without an empty line at the end */
404 test_srt_do_test (srt_input6, 0, G_N_ELEMENTS (srt_input6));
405 }
406
407 GST_END_TEST;
408
409
GST_START_TEST(test_webvtt)410 GST_START_TEST (test_webvtt)
411 {
412 SubParseInputChunk webvtt_input[] = {
413 {
414 "1\n00:00:01.000 --> 00:00:02.000 D:vertical T:50%\nOne\n\n",
415 1 * GST_SECOND, 2 * GST_SECOND, "One"}
416 ,
417 {
418 "1\n00:00:01.000 --> 00:00:02.000 D:vertical T:50%\nOne\n\n",
419 1 * GST_SECOND, 2 * GST_SECOND, "One"}
420 ,
421 {
422 "1\n00:00:01.000 --> 00:00:02.000 D:vertical\tT:50%\nOne\n\n",
423 1 * GST_SECOND, 2 * GST_SECOND, "One"}
424 ,
425 {
426 "1\n00:00:01.000 --> 00:00:02.000 D:vertical-lr\nOne\n\n",
427 1 * GST_SECOND, 2 * GST_SECOND, "One"}
428 ,
429 {
430 "1\n00:00:01.000 --> 00:00:02.000 L:-123\nOne\n\n",
431 1 * GST_SECOND, 2 * GST_SECOND, "One"}
432 ,
433 {
434 "1\n00:00:01.000 --> 00:00:02.000 L:123\nOne\n\n",
435 1 * GST_SECOND, 2 * GST_SECOND, "One"}
436 ,
437 {
438 "1\n00:00:01.000 --> 00:00:02.000 L:12%\nOne\n\n",
439 1 * GST_SECOND, 2 * GST_SECOND, "One"}
440 ,
441 {
442 "1\n00:00:01.000 --> 00:00:02.000 L:12% S:35% A:start\nOne\n\n",
443 1 * GST_SECOND, 2 * GST_SECOND, "One"}
444 ,
445 {
446 "1\n00:00:01.000 --> 00:00:02.000 A:middle\nOne\n\n",
447 1 * GST_SECOND, 2 * GST_SECOND, "One"}
448 ,
449 {
450 "1\n00:00:01.000 --> 00:00:02.000 A:end\nOne\n\n",
451 1 * GST_SECOND, 2 * GST_SECOND, "One"}
452 ,
453 {
454 "1\n00:00:01.000 --> 00:00:02.000\nOne & Two\n\n",
455 1 * GST_SECOND, 2 * GST_SECOND, "One & Two"}
456 ,
457 {
458 "1\n00:00:01.000 --> 00:00:02.000\nOne < Two\n\n",
459 1 * GST_SECOND, 2 * GST_SECOND, "One < Two"}
460 ,
461 {
462 "1\n00:00:01.000 --> 00:00:02.000\n<v Spoke>Live long and prosper\n\n",
463 1 * GST_SECOND, 2 * GST_SECOND, "<v Spoke>Live long and prosper</v>"}
464 ,
465 {
466 "1\n00:00:01.000 --> 00:00:02.000\n<v The Joker>HAHAHA\n\n",
467 1 * GST_SECOND, 2 * GST_SECOND, "<v The Joker>HAHAHA</v>"}
468 ,
469 {
470 "1\n00:00:01.000 --> 00:00:02.000\n<c.someclass>some text\n\n",
471 1 * GST_SECOND, 2 * GST_SECOND, "<c.someclass>some text</c>"}
472 ,
473 {
474 "1\n00:00:01.000 --> 00:00:02.000\n<b.loud>some text\n\n",
475 1 * GST_SECOND, 2 * GST_SECOND, "<b.loud>some text</b>"}
476 ,
477 {
478 "1\n00:00:01.000 --> 00:00:02.000\n<ruby>base text<rt>annotation</rt></ruby>\n\n",
479 1 * GST_SECOND, 2 * GST_SECOND,
480 "<ruby>base text<rt>annotation</rt></ruby>"}
481 ,
482 {
483 "1\n00:00:01.000 --> 00:00:03.000\nOne... <00:00:00,200>Two... <00:00:00,500>Three...\n\n",
484 1 * GST_SECOND, 3 * GST_SECOND,
485 "One... <00:00:00,200>Two... <00:00:00,500>Three..."}
486 ,
487 {"1\n00:00:02.000 --> 00:00:03.000\nHello\nWorld\n\n",
488 2 * GST_SECOND, 3 * GST_SECOND, "Hello\nWorld"}
489 ,
490 };
491
492 /* Test with no hour component */
493 SubParseInputChunk webvtt_input1[] = {
494 {
495 "1\n00:01.000 --> 00:02.000 D:vertical T:50%\nNo hour component\n\n",
496 1 * GST_SECOND, 2 * GST_SECOND, "No hour component"}
497 };
498
499 /* Test with no newline at the end */
500 SubParseInputChunk webvtt_input2[] = {
501 {
502 "1\n00:00:01,000 --> 00:00:02,000\nLast cue, no newline at the end",
503 1 * GST_SECOND, 2 * GST_SECOND, "Last cue, no newline at the end"}
504 ,
505 };
506
507 test_vtt_do_test (webvtt_input, 0, G_N_ELEMENTS (webvtt_input));
508 test_vtt_do_test (webvtt_input1, 0, G_N_ELEMENTS (webvtt_input1));
509 test_vtt_do_test (webvtt_input2, 0, G_N_ELEMENTS (webvtt_input2));
510 }
511
512 GST_END_TEST;
513
514 static void
do_test(SubParseInputChunk * input,guint num,const gchar * format)515 do_test (SubParseInputChunk * input, guint num, const gchar * format)
516 {
517 guint n;
518 GstCaps *outcaps;
519
520 setup_subparse ();
521
522 for (n = 0; n < num; ++n) {
523 GstBuffer *buf;
524
525 buf = buffer_from_static_string (input[n].in);
526 fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK);
527 }
528
529 gst_pad_push_event (mysrcpad, gst_event_new_eos ());
530
531 fail_unless_equals_int (g_list_length (buffers), num);
532
533 outcaps = gst_pad_get_current_caps (mysinkpad);
534
535 for (n = 0; n < num; ++n) {
536 const GstStructure *buffer_caps_struct;
537 GstBuffer *buf;
538 GstMapInfo map;
539
540 buf = g_list_nth_data (buffers, n);
541 fail_unless (buf != NULL);
542
543 /* check timestamp */
544 fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf), NULL);
545 fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buf), input[n].from_ts);
546
547 /* might not be able to put a duration on the last buffer */
548 if (input[n].to_ts != GST_CLOCK_TIME_NONE) {
549 /* check duration */
550 fail_unless (GST_BUFFER_DURATION_IS_VALID (buf), NULL);
551 fail_unless_equals_uint64 (GST_BUFFER_DURATION (buf),
552 input[n].to_ts - input[n].from_ts);
553 }
554
555 gst_buffer_map (buf, &map, GST_MAP_READ);
556 /* can be NULL */
557 if (map.data != NULL) {
558 /* shouldn't have trailing newline characters */
559 fail_if (map.size > 0 && map.data[map.size - 1] == '\n');
560 /* shouldn't include NUL-terminator in data size */
561 fail_if (map.size > 0 && map.data[map.size - 1] == '\0');
562 /* but should still have a NUL-terminator behind the declared data */
563 fail_unless_equals_int (map.data[map.size], '\0');
564 /* make sure out string matches expected string */
565 fail_unless_equals_string ((gchar *) map.data, input[n].out);
566 }
567 gst_buffer_unmap (buf, &map);
568 /* check caps */
569 fail_unless (outcaps != NULL);
570 buffer_caps_struct = gst_caps_get_structure (outcaps, 0);
571 fail_unless (gst_structure_has_name (buffer_caps_struct, "text/x-raw"));
572 fail_unless_equals_string (gst_structure_get_string (buffer_caps_struct,
573 "format"), format);
574 }
575 gst_caps_unref (outcaps);
576
577 teardown_subparse ();
578 }
579
580 static void
test_tmplayer_do_test(SubParseInputChunk * input,guint num)581 test_tmplayer_do_test (SubParseInputChunk * input, guint num)
582 {
583 do_test (input, num, "utf8");
584 }
585
586 static void
test_microdvd_do_test(SubParseInputChunk * input,guint num)587 test_microdvd_do_test (SubParseInputChunk * input, guint num)
588 {
589 do_test (input, num, "pango-markup");
590 }
591
GST_START_TEST(test_tmplayer_multiline)592 GST_START_TEST (test_tmplayer_multiline)
593 {
594 static SubParseInputChunk tmplayer_multiline_input[] = {
595 {
596 "00:00:10,1=This is the Earth at a time\n"
597 "00:00:10,2=when the dinosaurs roamed...\n" "00:00:13,1=\n",
598 10 * GST_SECOND, 13 * GST_SECOND,
599 "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
600 "00:00:14,1=a lush and fertile planet.\n" "00:00:16,1=\n",
601 14 * GST_SECOND, 16 * GST_SECOND,
602 "a lush and fertile planet."}
603 };
604
605 test_tmplayer_do_test (tmplayer_multiline_input,
606 G_N_ELEMENTS (tmplayer_multiline_input));
607 }
608
609 GST_END_TEST;
610
GST_START_TEST(test_tmplayer_multiline_with_bogus_lines)611 GST_START_TEST (test_tmplayer_multiline_with_bogus_lines)
612 {
613 static SubParseInputChunk tmplayer_multiline_b_input[] = {
614 {
615 "00:00:10,1=This is the Earth at a time\n"
616 "Yooboo wabahablablahuguug bogus line hello test 1-2-3-4\n"
617 "00:00:10,2=when the dinosaurs roamed...\n" "00:00:13,1=\n",
618 10 * GST_SECOND, 13 * GST_SECOND,
619 "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
620 "00:00:14,1=a lush and fertile planet.\n" "00:00:16,1=\n",
621 14 * GST_SECOND, 16 * GST_SECOND,
622 "a lush and fertile planet."}
623 };
624
625 test_tmplayer_do_test (tmplayer_multiline_b_input,
626 G_N_ELEMENTS (tmplayer_multiline_b_input));
627 }
628
629 GST_END_TEST;
630
GST_START_TEST(test_tmplayer_style1)631 GST_START_TEST (test_tmplayer_style1)
632 {
633 static SubParseInputChunk tmplayer_style1_input[] = {
634 {
635 "00:00:10:This is the Earth at a time|when the dinosaurs roamed...\n"
636 "00:00:13:\n",
637 10 * GST_SECOND, 13 * GST_SECOND,
638 "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
639 "00:00:14:a lush and fertile planet.\n" "00:00:16:\n",
640 14 * GST_SECOND, 16 * GST_SECOND,
641 "a lush and fertile planet."}
642 };
643
644 test_tmplayer_do_test (tmplayer_style1_input,
645 G_N_ELEMENTS (tmplayer_style1_input));
646 }
647
648 GST_END_TEST;
649
GST_START_TEST(test_tmplayer_style2)650 GST_START_TEST (test_tmplayer_style2)
651 {
652 static SubParseInputChunk tmplayer_style2_input[] = {
653 {
654 "00:00:10=This is the Earth at a time|when the dinosaurs roamed...\n"
655 "00:00:13=\n",
656 10 * GST_SECOND, 13 * GST_SECOND,
657 "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
658 "00:00:14=a lush and fertile planet.\n" "00:00:16=\n",
659 14 * GST_SECOND, 16 * GST_SECOND,
660 "a lush and fertile planet."}
661 };
662
663 test_tmplayer_do_test (tmplayer_style2_input,
664 G_N_ELEMENTS (tmplayer_style2_input));
665 }
666
667 GST_END_TEST;
668
GST_START_TEST(test_tmplayer_style3)669 GST_START_TEST (test_tmplayer_style3)
670 {
671 static SubParseInputChunk tmplayer_style3_input[] = {
672 {
673 "0:00:10:This is the Earth at a time|when the dinosaurs roamed...\n"
674 "0:00:13:\n",
675 10 * GST_SECOND, 13 * GST_SECOND,
676 "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
677 "0:00:14:a lush and fertile planet.\n" "0:00:16:\n",
678 14 * GST_SECOND, 16 * GST_SECOND,
679 "a lush and fertile planet."}
680 };
681
682 test_tmplayer_do_test (tmplayer_style3_input,
683 G_N_ELEMENTS (tmplayer_style3_input));
684 }
685
686 GST_END_TEST;
687
688 /* also tests the max_duration stuff (see second-last chunk which is supposed
689 * to be clipped to 5s duration) */
GST_START_TEST(test_tmplayer_style3b)690 GST_START_TEST (test_tmplayer_style3b)
691 {
692 static SubParseInputChunk tmplayer_style3b_input[] = {
693 {
694 "0:00:10:This is the Earth at a time|when the dinosaurs roamed...\n",
695 10 * GST_SECOND, 14 * GST_SECOND,
696 "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
697 "0:00:14:a lush and fertile planet.\n",
698 14 * GST_SECOND, 16 * GST_SECOND,
699 "a lush and fertile planet."}, {
700 "0:00:16:And they liked it a lot.\n",
701 16 * GST_SECOND, (16 + 5) * GST_SECOND, "And they liked it a lot."}, {
702 "0:00:30:Last line.",
703 30 * GST_SECOND, GST_CLOCK_TIME_NONE, "Last line."}
704 };
705
706 test_tmplayer_do_test (tmplayer_style3b_input,
707 G_N_ELEMENTS (tmplayer_style3b_input));
708 }
709
710 GST_END_TEST;
711
GST_START_TEST(test_tmplayer_style4)712 GST_START_TEST (test_tmplayer_style4)
713 {
714 static SubParseInputChunk tmplayer_style4_input[] = {
715 {
716 "0:00:10=This is the Earth at a time|when the dinosaurs roamed...\n"
717 "0:00:13=\n",
718 10 * GST_SECOND, 13 * GST_SECOND,
719 "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
720 "0:00:14=a lush and fertile planet.\n" "0:00:16=\n",
721 14 * GST_SECOND, 16 * GST_SECOND,
722 "a lush and fertile planet."}
723 };
724
725 test_tmplayer_do_test (tmplayer_style4_input,
726 G_N_ELEMENTS (tmplayer_style4_input));
727 }
728
729 GST_END_TEST;
730
GST_START_TEST(test_tmplayer_style4_with_bogus_lines)731 GST_START_TEST (test_tmplayer_style4_with_bogus_lines)
732 {
733 static SubParseInputChunk tmplayer_style4b_input[] = {
734 {
735 "0:00:10=This is the Earth at a time|when the dinosaurs roamed...\n"
736 "# This is a bogus line with a comment and should just be skipped\n"
737 "0:00:13=\n",
738 10 * GST_SECOND, 13 * GST_SECOND,
739 "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
740 "0:00:14=a lush and fertile planet.\n"
741 " \n"
742 "0:00:16=\n",
743 14 * GST_SECOND, 16 * GST_SECOND,
744 "a lush and fertile planet."}
745 };
746
747 test_tmplayer_do_test (tmplayer_style4b_input,
748 G_N_ELEMENTS (tmplayer_style4b_input));
749 }
750
751 GST_END_TEST;
752
GST_START_TEST(test_microdvd_with_italics)753 GST_START_TEST (test_microdvd_with_italics)
754 {
755 static SubParseInputChunk microdvd_italics[] = {
756 {
757 "{1}{1}25.000 movie info: XVID 608x256 25.0fps 699.0 MB|"
758 "/SubEdit b.4060(http://subedit.com.pl)/\n"
759 "{100}{200}/italics/|not italics\n",
760 4 * GST_SECOND, 8 * GST_SECOND,
761 "<span style=\"italic\">italics</span>\n" "<span>not italics</span>"}
762 };
763
764 test_microdvd_do_test (microdvd_italics, G_N_ELEMENTS (microdvd_italics));
765 }
766
767 GST_END_TEST;
768
GST_START_TEST(test_microdvd_with_fps)769 GST_START_TEST (test_microdvd_with_fps)
770 {
771 static SubParseInputChunk microdvd_input[] = {
772 {
773 "{1}{1}12.500\n{100}{200}- Hi, Eddie.|- Hiya, Scotty.\n",
774 8 * GST_SECOND, 16 * GST_SECOND,
775 "<span>- Hi, Eddie.</span>\n<span>- Hiya, Scotty.</span>"}, {
776 "{1250}{1350}- Cold enough for you?|- Well, I'm only faintly alive. "
777 "It's 25 below\n",
778 100 * GST_SECOND, 108 * GST_SECOND,
779 "<span>- Cold enough for you?</span>\n"
780 "<span>- Well, I'm only faintly alive. It's 25 below</span>"}
781 };
782
783 test_microdvd_do_test (microdvd_input, G_N_ELEMENTS (microdvd_input));
784
785 /* and the same with ',' instead of '.' as floating point divider */
786 microdvd_input[0].in =
787 "{1}{1}12,500\n{100}{200}- Hi, Eddie.|- Hiya, Scotty.\n";
788 test_microdvd_do_test (microdvd_input, G_N_ELEMENTS (microdvd_input));
789 }
790
791 GST_END_TEST;
792
GST_START_TEST(test_mpl2)793 GST_START_TEST (test_mpl2)
794 {
795 SubParseInputChunk mpl2_input[] = {
796 {
797 "[123][456] This is the Earth at a time|when the dinosaurs roamed\n",
798 (123 * GST_SECOND) / 10, (456 * GST_SECOND) / 10,
799 "This is the Earth at a time\nwhen the dinosaurs roamed"}, {
800 "[1234][5678]a lush and fertile planet.\n",
801 (1234 * GST_SECOND) / 10, (5678 * GST_SECOND) / 10,
802 "a lush and fertile planet."}, {
803 "[12345][27890] /Italic|Normal\n",
804 (12345 * GST_SECOND) / 10, (27890 * GST_SECOND) / 10,
805 "<i>Italic</i>\nNormal"}, {
806 "[32345][37890]/Italic|/Italic\n",
807 (32345 * GST_SECOND) / 10, (37890 * GST_SECOND) / 10,
808 "<i>Italic</i>\n<i>Italic</i>"}, {
809 "[42345][47890] Normal|/Italic",
810 (42345 * GST_SECOND) / 10, (47890 * GST_SECOND) / 10,
811 "Normal\n<i>Italic</i>"}
812 };
813
814 do_test (mpl2_input, G_N_ELEMENTS (mpl2_input), "pango-markup");
815 }
816
817 GST_END_TEST;
818
GST_START_TEST(test_subviewer)819 GST_START_TEST (test_subviewer)
820 {
821 SubParseInputChunk subviewer_input[] = {
822 {
823 "[INFORMATION]\n"
824 "[TITLE]xxxxxxxxxx\n"
825 "[AUTHOR]xxxxxxxx\n"
826 "[SOURCE]xxxxxxxxxxxxxxxx\n"
827 "[FILEPATH]\n"
828 "[DELAY]0\n"
829 "[COMMENT]\n"
830 "[END INFORMATION]\n"
831 "[SUBTITLE]\n"
832 "[COLF]&HFFFFFF,[STYLE]bd,[SIZE]18,[FONT]Arial\n"
833 "00:00:41.00,00:00:44.40\n"
834 "The Age of Gods was closing.\n"
835 "Eternity had come to an end.\n"
836 "\n", 41 * GST_SECOND, 44 * GST_SECOND + 40 * GST_MSECOND,
837 "The Age of Gods was closing.\nEternity had come to an end."}, {
838 "00:00:55.00,00:00:58.40\n"
839 "The heavens shook as the armies\n"
840 "of Falis, God of Light...\n\n", 55 * GST_SECOND,
841 58 * GST_SECOND + 40 * GST_MSECOND,
842 "The heavens shook as the armies\nof Falis, God of Light..."}
843 };
844
845 do_test (subviewer_input, G_N_ELEMENTS (subviewer_input), "utf8");
846 }
847
848 GST_END_TEST;
849
GST_START_TEST(test_subviewer2)850 GST_START_TEST (test_subviewer2)
851 {
852 SubParseInputChunk subviewer2_input[] = {
853 {
854 "[INFORMATION]\n"
855 "[TITLE]xxxxxxxxxx\n"
856 "[AUTHOR]xxxxxxxxxx\n"
857 "[SOURCE]xxxxxxxxxx\n"
858 "[PRG]\n"
859 "[FILEPATH]\n"
860 "[DELAY]0\n"
861 "[CD TRACK]0\n"
862 "[COMMENT]\n"
863 "[END INFORMATION]\n"
864 "[SUBTITLE]\n"
865 "[COLF]&H00FFFF,[STYLE]no,[SIZE]12,[FONT]Courier New\n"
866 "00:00:07.00,00:00:11.91\n"
867 "THERE IS A PLACE ON EARTH WHERE IT[br]IS STILL THE MORNING OF LIFE...\n\n",
868 7 * GST_SECOND, 11 * GST_SECOND + 91 * GST_MSECOND,
869 "THERE IS A PLACE ON EARTH WHERE IT\nIS STILL THE MORNING OF LIFE..."}, {
870 "00:00:12.48,00:00:15.17\n"
871 "AND THE GREAT HERDS RUN FREE.[br]SO WHAT?!\n\n",
872 12 * GST_SECOND + 48 * GST_MSECOND,
873 15 * GST_SECOND + 17 * GST_MSECOND,
874 "AND THE GREAT HERDS RUN FREE.\nSO WHAT?!"}
875 };
876
877 do_test (subviewer2_input, G_N_ELEMENTS (subviewer2_input), "utf8");
878 }
879
880 GST_END_TEST;
881
GST_START_TEST(test_dks)882 GST_START_TEST (test_dks)
883 {
884 SubParseInputChunk dks_input[] = {
885 {
886 "[00:00:07]THERE IS A PLACE ON EARTH WHERE IT[br]IS STILL THE MORNING OF LIFE...\n[00:00:12]\n",
887 7 * GST_SECOND, 12 * GST_SECOND,
888 "THERE IS A PLACE ON EARTH WHERE IT\nIS STILL THE MORNING OF LIFE..."}, {
889 "[00:00:13]AND THE GREAT HERDS RUN FREE.[br]SO WHAT?!\n[00:00:15]\n",
890 13 * GST_SECOND, 15 * GST_SECOND,
891 "AND THE GREAT HERDS RUN FREE.\nSO WHAT?!"}
892 };
893
894 do_test (dks_input, G_N_ELEMENTS (dks_input), "utf8");
895 }
896
897 GST_END_TEST;
898
GST_START_TEST(test_sami)899 GST_START_TEST (test_sami)
900 {
901 SubParseInputChunk sami_input[] = {
902 {"<SAMI>\n"
903 "<HEAD>\n"
904 " <TITLE>Subtitle</TITLE>\n"
905 " <STYLE TYPE=\"text/css\">\n"
906 " <!--\n"
907 " P {margin-left:8pt; margin-right:8pt; margin-bottom:2pt; margin-top:2pt; text-align:center; font-size:12pt; font-weight:normal; color:black;}\n"
908 " .CC {Name:English; lang:en-AU; SAMIType:CC;}\n"
909 " #STDPrn {Name:Standard Print;}\n"
910 " #LargePrn {Name:Large Print; font-size:24pt;}\n"
911 " #SmallPrn {Name:Small Print; font-size:16pt;}\n"
912 " -->\n"
913 " </Style>\n"
914 "</HEAD>\n"
915 "<BODY>\n"
916 " <SYNC Start=1000>\n"
917 " <P Class=CC>\n"
918 " This is a comment.<br>\n"
919 " This is a second comment.\n",
920 1000 * GST_MSECOND, 2000 * GST_MSECOND,
921 "This is a comment.\nThis is a second comment."},
922 {" <SYNC Start=2000>\n"
923 " <P Class=CC>\n"
924 " This is a third comment.<br>\n"
925 " This is a fourth comment.\n" "</BODY>\n" "</SAMI>\n",
926 2000 * GST_MSECOND, GST_CLOCK_TIME_NONE,
927 "This is a third comment.\nThis is a fourth comment."}
928 };
929
930 do_test (sami_input, G_N_ELEMENTS (sami_input), "pango-markup");
931 }
932
933 GST_END_TEST;
934
GST_START_TEST(test_sami_xml_entities)935 GST_START_TEST (test_sami_xml_entities)
936 {
937 SubParseInputChunk sami_input[] = {
938 {"<SAMI>\n"
939 "<BODY>\n"
940 " <SYNC Start=1000>\n"
941 " <P Class=CC>\n" " <Hello> &\n",
942 1000 * GST_MSECOND, 2000 * GST_MSECOND,
943 "<Hello> &"},
944 {" <SYNC Start=2000>\n"
945 " <P Class=CC>\n"
946 " "World'\n" "</BODY>\n" "</SAMI>\n",
947 2000 * GST_MSECOND, GST_CLOCK_TIME_NONE,
948 ""World'"}
949
950 };
951
952 do_test (sami_input, G_N_ELEMENTS (sami_input), "pango-markup");
953 }
954
955 GST_END_TEST;
956
GST_START_TEST(test_sami_html_entities)957 GST_START_TEST (test_sami_html_entities)
958 {
959 SubParseInputChunk sami_input[] = {
960 {"<SAMI>\n"
961 "<BODY>\n"
962 " <SYNC Start=1000>\n"
963 " <P Class=CC>\n" " ± ´\n",
964 1000 * GST_MSECOND, 2000 * GST_MSECOND,
965 "\xc2\xa0 \xc2\xb1 \xc2\xb4"},
966 {" <SYNC Start=2000>\n"
967 " <P Class=CC>\n" " Α ω\n",
968 2000 * GST_MSECOND, 3000 * GST_MSECOND,
969 "\xce\x91 \xcf\x89"},
970 {" <SYNC Start=3000>\n"
971 " <P Class=CC>\n"
972 "   ± ´\n" "</BODY>\n" "</SAMI>\n",
973 3000 * GST_MSECOND, GST_CLOCK_TIME_NONE,
974 "\xc2\xa0 \xc2\xb1 \xc2\xb4"}
975 };
976
977 do_test (sami_input, G_N_ELEMENTS (sami_input), "pango-markup");
978 }
979
980 GST_END_TEST;
981
GST_START_TEST(test_sami_bad_entities)982 GST_START_TEST (test_sami_bad_entities)
983 {
984 SubParseInputChunk sami_input[] = {
985 {"<SAMI>\n"
986 "<BODY>\n"
987 " <SYNC Start=1000>\n"
988 " <P Class=CC>\n" "   &\n",
989 1000 * GST_MSECOND, 2000 * GST_MSECOND,
990 "\xc2\xa0 &"},
991 {" <SYNC Start=2000>\n"
992 " <P Class=CC>\n"
993 "   ± ´\n" "</BODY>\n" "</SAMI>\n",
994 2000 * GST_MSECOND, GST_CLOCK_TIME_NONE,
995 "\xc2\xa0 \xc2\xb1 \xc2\xb4"}
996 };
997
998 do_test (sami_input, G_N_ELEMENTS (sami_input), "pango-markup");
999 }
1000
1001 GST_END_TEST;
1002
GST_START_TEST(test_sami_comment)1003 GST_START_TEST (test_sami_comment)
1004 {
1005 SubParseInputChunk sami_input[] = {
1006 {"<SAMI>\n"
1007 "<!--\n"
1008 "=======\n"
1009 "foo bar\n"
1010 "=======\n"
1011 "-->\n"
1012 "<BODY>\n"
1013 " <SYNC Start=1000>\n"
1014 " <P Class=\"C====\">\n" "   &\n",
1015 1000 * GST_MSECOND, 2000 * GST_MSECOND,
1016 "\xc2\xa0 &"},
1017 {" <SYNC Start=2000>\n"
1018 " <P Class=CC>\n"
1019 "   ± ´\n" "</BODY>\n" "</SAMI>\n",
1020 2000 * GST_MSECOND, GST_CLOCK_TIME_NONE,
1021 "\xc2\xa0 \xc2\xb1 \xc2\xb4"}
1022 };
1023
1024 do_test (sami_input, G_N_ELEMENTS (sami_input), "pango-markup");
1025 }
1026
1027 GST_END_TEST;
1028
GST_START_TEST(test_lrc)1029 GST_START_TEST (test_lrc)
1030 {
1031 SubParseInputChunk lrc_input[] = {
1032 {"[ar:123]\n" "[ti:Title]\n" "[al:Album]\n" "[00:02.23]Line 1\n",
1033 2230 * GST_MSECOND, GST_CLOCK_TIME_NONE,
1034 "Line 1"},
1035 {"[00:05.10]Line 2\n",
1036 5100 * GST_MSECOND, GST_CLOCK_TIME_NONE,
1037 "Line 2"},
1038 {"[00:06.123]Line 3\n",
1039 6123 * GST_MSECOND, GST_CLOCK_TIME_NONE,
1040 "Line 3"}
1041 };
1042
1043 do_test (lrc_input, G_N_ELEMENTS (lrc_input), "utf8");
1044 }
1045
1046 GST_END_TEST;
1047
GST_START_TEST(test_raw_conversion)1048 GST_START_TEST (test_raw_conversion)
1049 {
1050 GstHarness *h;
1051 GstBuffer *buffer;
1052 GstMapInfo map;
1053
1054 h = gst_harness_new ("subparse");
1055
1056 gst_harness_set_src_caps_str (h, "application/x-subtitle");
1057 gst_harness_set_sink_caps_str (h, "text/x-raw, format=utf8");
1058
1059 buffer = buffer_from_static_string (srt_input[5].in);
1060
1061 buffer = gst_harness_push_and_pull (h, buffer);
1062
1063 gst_buffer_map (buffer, &map, GST_MAP_READ);
1064 fail_unless_equals_int (map.size, 3);
1065 fail_unless_equals_string ((gchar *) map.data, "Six");
1066 gst_buffer_unmap (buffer, &map);
1067
1068 gst_clear_buffer (&buffer);
1069
1070 gst_harness_teardown (h);
1071 }
1072
1073 GST_END_TEST;
1074
1075 /* TODO:
1076 * - add/modify tests so that lines aren't dogfed to the parsers in complete
1077 * lines or sets of complete lines, but rather in random chunks
1078 */
1079
1080 static Suite *
subparse_suite(void)1081 subparse_suite (void)
1082 {
1083 Suite *s = suite_create ("subparse");
1084 TCase *tc_chain = tcase_create ("general");
1085
1086 suite_add_tcase (s, tc_chain);
1087
1088 tcase_add_test (tc_chain, test_srt);
1089 tcase_add_test (tc_chain, test_webvtt);
1090 tcase_add_test (tc_chain, test_tmplayer_multiline);
1091 tcase_add_test (tc_chain, test_tmplayer_multiline_with_bogus_lines);
1092 tcase_add_test (tc_chain, test_tmplayer_style1);
1093 tcase_add_test (tc_chain, test_tmplayer_style2);
1094 tcase_add_test (tc_chain, test_tmplayer_style3);
1095 tcase_add_test (tc_chain, test_tmplayer_style3b);
1096 tcase_add_test (tc_chain, test_tmplayer_style4);
1097 tcase_add_test (tc_chain, test_tmplayer_style4_with_bogus_lines);
1098 tcase_add_test (tc_chain, test_microdvd_with_fps);
1099 tcase_add_test (tc_chain, test_microdvd_with_italics);
1100 tcase_add_test (tc_chain, test_mpl2);
1101 tcase_add_test (tc_chain, test_subviewer);
1102 tcase_add_test (tc_chain, test_subviewer2);
1103 tcase_add_test (tc_chain, test_dks);
1104 tcase_add_test (tc_chain, test_sami);
1105 tcase_add_test (tc_chain, test_sami_xml_entities);
1106 tcase_add_test (tc_chain, test_sami_html_entities);
1107 tcase_add_test (tc_chain, test_sami_bad_entities);
1108 tcase_add_test (tc_chain, test_sami_comment);
1109 tcase_add_test (tc_chain, test_lrc);
1110 tcase_add_test (tc_chain, test_raw_conversion);
1111 return s;
1112 }
1113
1114 GST_CHECK_MAIN (subparse);
1115