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