tests: videorate: remove obsolete color-matrix caps field
[platform/upstream/gstreamer.git] / tests / check / elements / subparse.c
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., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, 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/plain; text/x-pango-markup")
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 *
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         /* skip a few chunk numbers here, the numbers shouldn't matter */
97         "24\n00:01:00,000 --> 00:02:00,000\nYep, still here\n\n",
98       60 * GST_SECOND, 120 * GST_SECOND, "Yep, still here"}, {
99         /* make sure stuff is escaped properly, but allowed markup stays intact */
100         "25\n00:03:00,000 --> 00:04:00,000\ngave <i>Rock & Roll</i> to\n\n",
101       180 * GST_SECOND, 240 * GST_SECOND, "gave <i>Rock &amp; Roll</i> to"}, {
102         "26\n00:04:00,000 --> 00:05:00,000\n<i>Rock & Roll</i>\n\n",
103       240 * GST_SECOND, 300 * GST_SECOND, "<i>Rock &amp; Roll</i>"}, {
104         "27\n00:06:00,000 --> 00:08:00,000\nRock & Roll\n\n",
105       360 * GST_SECOND, 480 * GST_SECOND, "Rock &amp; Roll"}, {
106         "28\n00:10:00,000 --> 00:11:00,000\n"
107         "<font \"#0000FF\"><joj>This is </xxx>in blue but <5</font>\n\n",
108       600 * GST_SECOND, 660 * GST_SECOND, "This is in blue but &lt;5"}
109 };
110
111 /* starts with chunk number 0 (not exactly according to spec) */
112 static SubParseInputChunk srt_input0[] = {
113   {
114         "0\n00:00:01,000 --> 00:00:02,000\nOne\n\n",
115       1 * GST_SECOND, 2 * GST_SECOND, "One"}, {
116         "1\n00:00:02,000 --> 00:00:03,000\nTwo\n\n",
117       2 * GST_SECOND, 3 * GST_SECOND, "Two"}, {
118         "2\n00:00:03,000 --> 00:00:04,000\nThree\n\n",
119       3 * GST_SECOND, 4 * GST_SECOND, "Three"}
120 };
121
122 /* has spaces instead of doubled zeroes (not exactly according to spec) */
123 static SubParseInputChunk srt_input1[] = {
124   {
125         "1\n 0: 0:26, 26 --> 0: 0:28, 17\nI cant see.\n\n",
126         26 * GST_SECOND + 26 * GST_MSECOND,
127       28 * GST_SECOND + 17 * GST_MSECOND, "I cant see."},
128   {
129         "2\n 0: 0:30, 30 --> 0: 0:33, 22\nI really cant see.\n\n",
130         30 * GST_SECOND + 30 * GST_MSECOND,
131       33 * GST_SECOND + 22 * GST_MSECOND, "I really cant see."},
132   {
133         "3\n 0: 0:40, 40 --> 0: 0:44, 44\nI still cant see anything.\n\n",
134         40 * GST_SECOND + 40 * GST_MSECOND,
135       44 * GST_SECOND + 44 * GST_MSECOND, "I still cant see anything."}
136 };
137
138 /* has UTF-8 BOM at the start */
139 static SubParseInputChunk srt_input2[] = {
140   {
141         "\xef\xbb\xbf" "1\n00:00:00,000 --> 00:00:03,50\nJust testing.\n\n",
142       0, 3 * GST_SECOND + 500 * GST_MSECOND, "Just testing."}
143 };
144
145 /* starts with chunk number 0 and has less than three digits after the comma
146  * and a few extra spaces before the arrow or at the end of the line */
147 static SubParseInputChunk srt_input3[] = {
148   {
149         "0\n00:00:01,0 --> 00:00:02,0\nOne\n\n",
150       1000 * GST_MSECOND, 2000 * GST_MSECOND, "One"}, {
151         "1\n00:00:02,5   --> 00:00:03,  5 \nTwo\n\n",
152       2500 * GST_MSECOND, 3005 * GST_MSECOND, "Two"}, {
153         "2\n00:00:03, 9 --> 00:00:04,0   \nThree\n\n",
154       3090 * GST_MSECOND, 4000 * GST_MSECOND, "Three"}
155 };
156
157 static void
158 setup_subparse (void)
159 {
160   subparse = gst_check_setup_element ("subparse");
161
162   mysrcpad = gst_check_setup_src_pad (subparse, &srctemplate);
163   mysinkpad = gst_check_setup_sink_pad (subparse, &sinktemplate);
164
165   gst_pad_set_active (mysrcpad, TRUE);
166   gst_pad_set_active (mysinkpad, TRUE);
167
168   fail_unless_equals_int (gst_element_set_state (subparse, GST_STATE_PLAYING),
169       GST_STATE_CHANGE_SUCCESS);
170 }
171
172 static void
173 teardown_subparse (void)
174 {
175   GST_DEBUG ("cleaning up");
176
177   g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL);
178   g_list_free (buffers);
179   buffers = NULL;
180
181   gst_pad_set_active (mysrcpad, FALSE);
182   gst_pad_set_active (mysinkpad, FALSE);
183   gst_check_teardown_sink_pad (subparse);
184   gst_check_teardown_src_pad (subparse);
185   gst_check_teardown_element (subparse);
186   subparse = NULL;
187   mysrcpad = NULL;
188   mysinkpad = NULL;
189 }
190
191 static void
192 test_srt_do_test (SubParseInputChunk * input, guint start_idx, guint num)
193 {
194   guint n;
195   GstCaps *outcaps;
196
197   GST_LOG ("srt test: start_idx = %u, num = %u", start_idx, num);
198
199   setup_subparse ();
200
201   for (n = start_idx; n < start_idx + num; ++n) {
202     GstBuffer *buf;
203
204     buf = buffer_from_static_string (input[n].in);
205     fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK);
206   }
207
208   gst_pad_push_event (mysrcpad, gst_event_new_eos ());
209
210   fail_unless_equals_int (g_list_length (buffers), num);
211
212   outcaps = gst_pad_get_current_caps (mysinkpad);
213
214   for (n = start_idx; n < start_idx + num; ++n) {
215     const GstStructure *buffer_caps_struct;
216     GstBuffer *buf;
217     GstMapInfo map;
218
219     buf = g_list_nth_data (buffers, n - start_idx);
220     fail_unless (buf != NULL);
221     fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf), NULL);
222     fail_unless (GST_BUFFER_DURATION_IS_VALID (buf), NULL);
223     fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buf), input[n].from_ts);
224     fail_unless_equals_uint64 (GST_BUFFER_DURATION (buf),
225         input[n].to_ts - input[n].from_ts);
226
227     gst_buffer_map (buf, &map, GST_MAP_READ);
228     /* can be NULL */
229     if (map.data != NULL) {
230       /* shouldn't have trailing newline characters */
231       fail_if (map.size > 0 && map.data[map.size - 1] == '\n');
232       /* shouldn't include NUL-terminator in data size */
233       fail_if (map.size > 0 && map.data[map.size - 1] == '\0');
234       /* but should still have a  NUL-terminator behind the declared data */
235       fail_unless_equals_int (map.data[map.size], '\0');
236       /* make sure out string matches expected string */
237       fail_unless_equals_string ((gchar *) map.data, input[n].out);
238     }
239     gst_buffer_unmap (buf, &map);
240     /* check caps */
241     fail_unless (outcaps != NULL);
242     buffer_caps_struct = gst_caps_get_structure (outcaps, 0);
243     fail_unless_equals_string (gst_structure_get_name (buffer_caps_struct),
244         "text/x-pango-markup");
245   }
246   gst_caps_unref (outcaps);
247
248   teardown_subparse ();
249 }
250
251 GST_START_TEST (test_srt)
252 {
253   test_srt_do_test (srt_input, 0, G_N_ELEMENTS (srt_input));
254
255   /* make sure everything works fine if we don't start with chunk 1 */
256   test_srt_do_test (srt_input, 1, G_N_ELEMENTS (srt_input) - 1);
257   test_srt_do_test (srt_input, 2, G_N_ELEMENTS (srt_input) - 2);
258   test_srt_do_test (srt_input, 3, G_N_ELEMENTS (srt_input) - 3);
259   test_srt_do_test (srt_input, 4, G_N_ELEMENTS (srt_input) - 4);
260
261   /* try with empty input, immediate EOS */
262   test_srt_do_test (srt_input, 5, G_N_ELEMENTS (srt_input) - 5);
263
264   /* try with chunk number 0 (which is not exactly according to spec) */
265   test_srt_do_test (srt_input0, 0, G_N_ELEMENTS (srt_input0));
266
267   /* try with spaces instead of doubled zeroes (which is not exactly according to spec) */
268   test_srt_do_test (srt_input1, 0, G_N_ELEMENTS (srt_input1));
269
270   /* try with UTF-8 BOM at the start */
271   test_srt_do_test (srt_input2, 0, G_N_ELEMENTS (srt_input2));
272
273   /* try with fewer than three post-comma digits, and some extra spaces */
274   test_srt_do_test (srt_input3, 0, G_N_ELEMENTS (srt_input3));
275 }
276
277 GST_END_TEST;
278
279 static void
280 do_test (SubParseInputChunk * input, guint num, const gchar * media_type)
281 {
282   guint n;
283   GstCaps *outcaps;
284
285   setup_subparse ();
286
287   for (n = 0; n < num; ++n) {
288     GstBuffer *buf;
289
290     buf = buffer_from_static_string (input[n].in);
291     fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK);
292   }
293
294   gst_pad_push_event (mysrcpad, gst_event_new_eos ());
295
296   fail_unless_equals_int (g_list_length (buffers), num);
297
298   outcaps = gst_pad_get_current_caps (mysinkpad);
299
300   for (n = 0; n < num; ++n) {
301     const GstStructure *buffer_caps_struct;
302     GstBuffer *buf;
303     GstMapInfo map;
304
305     buf = g_list_nth_data (buffers, n);
306     fail_unless (buf != NULL);
307
308     /* check timestamp */
309     fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf), NULL);
310     fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buf), input[n].from_ts);
311
312     /* might not be able to put a duration on the last buffer */
313     if (input[n].to_ts != GST_CLOCK_TIME_NONE) {
314       /* check duration */
315       fail_unless (GST_BUFFER_DURATION_IS_VALID (buf), NULL);
316       fail_unless_equals_uint64 (GST_BUFFER_DURATION (buf),
317           input[n].to_ts - input[n].from_ts);
318     }
319
320     gst_buffer_map (buf, &map, GST_MAP_READ);
321     /* can be NULL */
322     if (map.data != NULL) {
323       /* shouldn't have trailing newline characters */
324       fail_if (map.size > 0 && map.data[map.size - 1] == '\n');
325       /* shouldn't include NUL-terminator in data size */
326       fail_if (map.size > 0 && map.data[map.size - 1] == '\0');
327       /* but should still have a  NUL-terminator behind the declared data */
328       fail_unless_equals_int (map.data[map.size], '\0');
329       /* make sure out string matches expected string */
330       fail_unless_equals_string ((gchar *) map.data, input[n].out);
331     }
332     gst_buffer_unmap (buf, &map);
333     /* check caps */
334     fail_unless (outcaps != NULL);
335     buffer_caps_struct = gst_caps_get_structure (outcaps, 0);
336     fail_unless_equals_string (gst_structure_get_name (buffer_caps_struct),
337         media_type);
338   }
339   gst_caps_unref (outcaps);
340
341   teardown_subparse ();
342 }
343
344 static void
345 test_tmplayer_do_test (SubParseInputChunk * input, guint num)
346 {
347   do_test (input, num, "text/plain");
348 }
349
350 static void
351 test_microdvd_do_test (SubParseInputChunk * input, guint num)
352 {
353   do_test (input, num, "text/x-pango-markup");
354 }
355
356 GST_START_TEST (test_tmplayer_multiline)
357 {
358   static SubParseInputChunk tmplayer_multiline_input[] = {
359     {
360           "00:00:10,1=This is the Earth at a time\n"
361           "00:00:10,2=when the dinosaurs roamed...\n" "00:00:13,1=\n",
362           10 * GST_SECOND, 13 * GST_SECOND,
363         "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
364           "00:00:14,1=a lush and fertile planet.\n" "00:00:16,1=\n",
365           14 * GST_SECOND, 16 * GST_SECOND,
366         "a lush and fertile planet."}
367   };
368
369   test_tmplayer_do_test (tmplayer_multiline_input,
370       G_N_ELEMENTS (tmplayer_multiline_input));
371 }
372
373 GST_END_TEST;
374
375 GST_START_TEST (test_tmplayer_multiline_with_bogus_lines)
376 {
377   static SubParseInputChunk tmplayer_multiline_b_input[] = {
378     {
379           "00:00:10,1=This is the Earth at a time\n"
380           "Yooboo wabahablablahuguug bogus line hello test 1-2-3-4\n"
381           "00:00:10,2=when the dinosaurs roamed...\n" "00:00:13,1=\n",
382           10 * GST_SECOND, 13 * GST_SECOND,
383         "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
384           "00:00:14,1=a lush and fertile planet.\n" "00:00:16,1=\n",
385           14 * GST_SECOND, 16 * GST_SECOND,
386         "a lush and fertile planet."}
387   };
388
389   test_tmplayer_do_test (tmplayer_multiline_b_input,
390       G_N_ELEMENTS (tmplayer_multiline_b_input));
391 }
392
393 GST_END_TEST;
394
395 GST_START_TEST (test_tmplayer_style1)
396 {
397   static SubParseInputChunk tmplayer_style1_input[] = {
398     {
399           "00:00:10:This is the Earth at a time|when the dinosaurs roamed...\n"
400           "00:00:13:\n",
401           10 * GST_SECOND, 13 * GST_SECOND,
402         "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
403           "00:00:14:a lush and fertile planet.\n" "00:00:16:\n",
404           14 * GST_SECOND, 16 * GST_SECOND,
405         "a lush and fertile planet."}
406   };
407
408   test_tmplayer_do_test (tmplayer_style1_input,
409       G_N_ELEMENTS (tmplayer_style1_input));
410 }
411
412 GST_END_TEST;
413
414 GST_START_TEST (test_tmplayer_style2)
415 {
416   static SubParseInputChunk tmplayer_style2_input[] = {
417     {
418           "00:00:10=This is the Earth at a time|when the dinosaurs roamed...\n"
419           "00:00:13=\n",
420           10 * GST_SECOND, 13 * GST_SECOND,
421         "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
422           "00:00:14=a lush and fertile planet.\n" "00:00:16=\n",
423           14 * GST_SECOND, 16 * GST_SECOND,
424         "a lush and fertile planet."}
425   };
426
427   test_tmplayer_do_test (tmplayer_style2_input,
428       G_N_ELEMENTS (tmplayer_style2_input));
429 }
430
431 GST_END_TEST;
432
433 GST_START_TEST (test_tmplayer_style3)
434 {
435   static SubParseInputChunk tmplayer_style3_input[] = {
436     {
437           "0:00:10:This is the Earth at a time|when the dinosaurs roamed...\n"
438           "0:00:13:\n",
439           10 * GST_SECOND, 13 * GST_SECOND,
440         "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
441           "0:00:14:a lush and fertile planet.\n" "0:00:16:\n",
442           14 * GST_SECOND, 16 * GST_SECOND,
443         "a lush and fertile planet."}
444   };
445
446   test_tmplayer_do_test (tmplayer_style3_input,
447       G_N_ELEMENTS (tmplayer_style3_input));
448 }
449
450 GST_END_TEST;
451
452 /* also tests the max_duration stuff (see second-last chunk which is supposed
453  * to be clipped to 5s duration) */
454 GST_START_TEST (test_tmplayer_style3b)
455 {
456   static SubParseInputChunk tmplayer_style3b_input[] = {
457     {
458           "0:00:10:This is the Earth at a time|when the dinosaurs roamed...\n",
459           10 * GST_SECOND, 14 * GST_SECOND,
460         "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
461           "0:00:14:a lush and fertile planet.\n",
462           14 * GST_SECOND, 16 * GST_SECOND,
463         "a lush and fertile planet."}, {
464           "0:00:16:And they liked it a lot.\n",
465         16 * GST_SECOND, (16 + 5) * GST_SECOND, "And they liked it a lot."}, {
466           "0:00:30:Last line.",
467         30 * GST_SECOND, GST_CLOCK_TIME_NONE, "Last line."}
468   };
469
470   test_tmplayer_do_test (tmplayer_style3b_input,
471       G_N_ELEMENTS (tmplayer_style3b_input));
472 }
473
474 GST_END_TEST;
475
476 GST_START_TEST (test_tmplayer_style4)
477 {
478   static SubParseInputChunk tmplayer_style4_input[] = {
479     {
480           "0:00:10=This is the Earth at a time|when the dinosaurs roamed...\n"
481           "0:00:13=\n",
482           10 * GST_SECOND, 13 * GST_SECOND,
483         "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
484           "0:00:14=a lush and fertile planet.\n" "0:00:16=\n",
485           14 * GST_SECOND, 16 * GST_SECOND,
486         "a lush and fertile planet."}
487   };
488
489   test_tmplayer_do_test (tmplayer_style4_input,
490       G_N_ELEMENTS (tmplayer_style4_input));
491 }
492
493 GST_END_TEST;
494
495 GST_START_TEST (test_tmplayer_style4_with_bogus_lines)
496 {
497   static SubParseInputChunk tmplayer_style4b_input[] = {
498     {
499           "0:00:10=This is the Earth at a time|when the dinosaurs roamed...\n"
500           "# This is a bogus line with a comment and should just be skipped\n"
501           "0:00:13=\n",
502           10 * GST_SECOND, 13 * GST_SECOND,
503         "This is the Earth at a time\nwhen the dinosaurs roamed..."}, {
504           "0:00:14=a lush and fertile planet.\n"
505           "                                                            \n"
506           "0:00:16=\n",
507           14 * GST_SECOND, 16 * GST_SECOND,
508         "a lush and fertile planet."}
509   };
510
511   test_tmplayer_do_test (tmplayer_style4b_input,
512       G_N_ELEMENTS (tmplayer_style4b_input));
513 }
514
515 GST_END_TEST;
516
517 GST_START_TEST (test_microdvd_with_italics)
518 {
519   static SubParseInputChunk microdvd_italics[] = {
520     {
521           "{1}{1}25.000 movie info: XVID  608x256 25.0fps 699.0 MB|"
522           "/SubEdit b.4060(http://subedit.com.pl)/\n"
523           "{100}{200}/italics/|not italics\n",
524           4 * GST_SECOND, 8 * GST_SECOND,
525         "<span style=\"italic\">italics</span>\n" "<span>not italics</span>"}
526   };
527
528   test_microdvd_do_test (microdvd_italics, G_N_ELEMENTS (microdvd_italics));
529 }
530
531 GST_END_TEST;
532
533 GST_START_TEST (test_microdvd_with_fps)
534 {
535   static SubParseInputChunk microdvd_input[] = {
536     {
537           "{1}{1}12.500\n{100}{200}- Hi, Eddie.|- Hiya, Scotty.\n",
538           8 * GST_SECOND, 16 * GST_SECOND,
539         "<span>- Hi, Eddie.</span>\n<span>- Hiya, Scotty.</span>"}, {
540           "{1250}{1350}- Cold enough for you?|- Well, I'm only faintly alive. "
541           "It's 25 below\n",
542           100 * GST_SECOND, 108 * GST_SECOND,
543         "<span>- Cold enough for you?</span>\n"
544           "<span>- Well, I&apos;m only faintly alive. It&apos;s 25 below</span>"}
545   };
546
547   test_microdvd_do_test (microdvd_input, G_N_ELEMENTS (microdvd_input));
548
549   /* and the same with ',' instead of '.' as floating point divider */
550   microdvd_input[0].in =
551       "{1}{1}12,500\n{100}{200}- Hi, Eddie.|- Hiya, Scotty.\n";
552   test_microdvd_do_test (microdvd_input, G_N_ELEMENTS (microdvd_input));
553 }
554
555 GST_END_TEST;
556
557 GST_START_TEST (test_mpl2)
558 {
559   SubParseInputChunk mpl2_input[] = {
560     {
561           "[123][456] This is the Earth at a time|when the dinosaurs roamed\n",
562           (123 * GST_SECOND) / 10, (456 * GST_SECOND) / 10,
563         "This is the Earth at a time\nwhen the dinosaurs roamed"}, {
564           "[1234][5678]a lush and fertile planet.\n",
565           (1234 * GST_SECOND) / 10, (5678 * GST_SECOND) / 10,
566         "a lush and fertile planet."}, {
567           "[12345][27890] /Italic|Normal\n",
568           (12345 * GST_SECOND) / 10, (27890 * GST_SECOND) / 10,
569         "<i>Italic</i>\nNormal"}, {
570           "[32345][37890]/Italic|/Italic\n",
571           (32345 * GST_SECOND) / 10, (37890 * GST_SECOND) / 10,
572         "<i>Italic</i>\n<i>Italic</i>"}, {
573           "[42345][47890] Normal|/Italic",
574           (42345 * GST_SECOND) / 10, (47890 * GST_SECOND) / 10,
575         "Normal\n<i>Italic</i>"}
576   };
577
578   do_test (mpl2_input, G_N_ELEMENTS (mpl2_input), "text/x-pango-markup");
579 }
580
581 GST_END_TEST;
582
583 GST_START_TEST (test_subviewer)
584 {
585   SubParseInputChunk subviewer_input[] = {
586     {
587           "[INFORMATION]\n"
588           "[TITLE]xxxxxxxxxx\n"
589           "[AUTHOR]xxxxxxxx\n"
590           "[SOURCE]xxxxxxxxxxxxxxxx\n"
591           "[FILEPATH]\n"
592           "[DELAY]0\n"
593           "[COMMENT]\n"
594           "[END INFORMATION]\n"
595           "[SUBTITLE]\n"
596           "[COLF]&HFFFFFF,[STYLE]bd,[SIZE]18,[FONT]Arial\n"
597           "00:00:41.00,00:00:44.40\n"
598           "The Age of Gods was closing.\n"
599           "Eternity had come to an end.\n"
600           "\n", 41 * GST_SECOND, 44 * GST_SECOND + 40 * GST_MSECOND,
601         "The Age of Gods was closing.\nEternity had come to an end."}, {
602           "00:00:55.00,00:00:58.40\n"
603           "The heavens shook as the armies\n"
604           "of Falis, God of Light...\n\n", 55 * GST_SECOND,
605           58 * GST_SECOND + 40 * GST_MSECOND,
606         "The heavens shook as the armies\nof Falis, God of Light..."}
607   };
608
609   do_test (subviewer_input, G_N_ELEMENTS (subviewer_input), "text/plain");
610 }
611
612 GST_END_TEST;
613
614 GST_START_TEST (test_subviewer2)
615 {
616   SubParseInputChunk subviewer2_input[] = {
617     {
618           "[INFORMATION]\n"
619           "[TITLE]xxxxxxxxxx\n"
620           "[AUTHOR]xxxxxxxxxx\n"
621           "[SOURCE]xxxxxxxxxx\n"
622           "[PRG]\n"
623           "[FILEPATH]\n"
624           "[DELAY]0\n"
625           "[CD TRACK]0\n"
626           "[COMMENT]\n"
627           "[END INFORMATION]\n"
628           "[SUBTITLE]\n"
629           "[COLF]&H00FFFF,[STYLE]no,[SIZE]12,[FONT]Courier New\n"
630           "00:00:07.00,00:00:11.91\n"
631           "THERE IS A PLACE ON EARTH WHERE IT[br]IS STILL THE MORNING OF LIFE...\n\n",
632           7 * GST_SECOND, 11 * GST_SECOND + 91 * GST_MSECOND,
633         "THERE IS A PLACE ON EARTH WHERE IT\nIS STILL THE MORNING OF LIFE..."}, {
634           "00:00:12.48,00:00:15.17\n"
635           "AND THE GREAT HERDS RUN FREE.[br]SO WHAT?!\n\n",
636           12 * GST_SECOND + 48 * GST_MSECOND,
637           15 * GST_SECOND + 17 * GST_MSECOND,
638         "AND THE GREAT HERDS RUN FREE.\nSO WHAT?!"}
639   };
640
641   do_test (subviewer2_input, G_N_ELEMENTS (subviewer2_input), "text/plain");
642 }
643
644 GST_END_TEST;
645
646 GST_START_TEST (test_dks)
647 {
648   SubParseInputChunk dks_input[] = {
649     {
650           "[00:00:07]THERE IS A PLACE ON EARTH WHERE IT[br]IS STILL THE MORNING OF LIFE...\n[00:00:12]\n",
651           7 * GST_SECOND, 12 * GST_SECOND,
652         "THERE IS A PLACE ON EARTH WHERE IT\nIS STILL THE MORNING OF LIFE..."}, {
653           "[00:00:13]AND THE GREAT HERDS RUN FREE.[br]SO WHAT?!\n[00:00:15]\n",
654           13 * GST_SECOND, 15 * GST_SECOND,
655         "AND THE GREAT HERDS RUN FREE.\nSO WHAT?!"}
656   };
657
658   do_test (dks_input, G_N_ELEMENTS (dks_input), "text/plain");
659 }
660
661 GST_END_TEST;
662
663 #ifndef GST_DISABLE_XML
664 GST_START_TEST (test_sami)
665 {
666   SubParseInputChunk sami_input[] = {
667     {"<SAMI>\n"
668           "<HEAD>\n"
669           "    <TITLE>Subtitle</TITLE>\n"
670           "    <STYLE TYPE=\"text/css\">\n"
671           "    <!--\n"
672           "        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"
673           "        .CC {Name:English; lang:en-AU; SAMIType:CC;}\n"
674           "        #STDPrn {Name:Standard Print;}\n"
675           "        #LargePrn {Name:Large Print; font-size:24pt;}\n"
676           "        #SmallPrn {Name:Small Print; font-size:16pt;}\n"
677           "    -->\n"
678           "    </Style>\n"
679           "</HEAD>\n"
680           "<BODY>\n"
681           "    <SYNC Start=1000>\n"
682           "        <P Class=CC>\n"
683           "            This is a comment.<br>\n"
684           "            This is a second comment.\n",
685           1000 * GST_MSECOND, 2000 * GST_MSECOND,
686         "This is a comment.\nThis is a second comment."},
687     {"    <SYNC Start=2000>\n"
688           "        <P Class=CC>\n"
689           "            This is a third comment.<br>\n"
690           "            This is a fourth comment.\n" "</BODY>\n" "</SAMI>\n",
691           2000 * GST_MSECOND, GST_CLOCK_TIME_NONE,
692         "This is a third comment.\nThis is a fourth comment."}
693   };
694
695   do_test (sami_input, G_N_ELEMENTS (sami_input), "text/x-pango-markup");
696 }
697
698 GST_END_TEST;
699 #endif
700
701 /* TODO:
702  *  - add/modify tests so that lines aren't dogfed to the parsers in complete
703  *    lines or sets of complete lines, but rather in random chunks
704  */
705
706 static Suite *
707 subparse_suite (void)
708 {
709   Suite *s = suite_create ("subparse");
710   TCase *tc_chain = tcase_create ("general");
711
712   suite_add_tcase (s, tc_chain);
713
714   tcase_add_test (tc_chain, test_srt);
715   tcase_add_test (tc_chain, test_tmplayer_multiline);
716   tcase_add_test (tc_chain, test_tmplayer_multiline_with_bogus_lines);
717   tcase_add_test (tc_chain, test_tmplayer_style1);
718   tcase_add_test (tc_chain, test_tmplayer_style2);
719   tcase_add_test (tc_chain, test_tmplayer_style3);
720   tcase_add_test (tc_chain, test_tmplayer_style3b);
721   tcase_add_test (tc_chain, test_tmplayer_style4);
722   tcase_add_test (tc_chain, test_tmplayer_style4_with_bogus_lines);
723   tcase_add_test (tc_chain, test_microdvd_with_fps);
724   tcase_add_test (tc_chain, test_microdvd_with_italics);
725   tcase_add_test (tc_chain, test_mpl2);
726   tcase_add_test (tc_chain, test_subviewer);
727   tcase_add_test (tc_chain, test_subviewer2);
728   tcase_add_test (tc_chain, test_dks);
729 #ifndef GST_DISABLE_XML
730   tcase_add_test (tc_chain, test_sami);
731 #endif
732   return s;
733 }
734
735 GST_CHECK_MAIN (subparse);