1 /* GStreamer
2  *
3  * unit test for avisubtitle
4  *
5  * Copyright (C) <2007> Thijs Vermeir <thijsvermeir@gmail.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 /* Element-Checklist-Version: 5 */
23 
24 #include <gst/gst.h>
25 #include <gst/check/gstcheck.h>
26 
27 GstPad *mysinkpad;
28 GstPad *mysrcpad;
29 
30 guint8 avisub_utf_8_with_bom[] = {
31   0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
32   0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
33   0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68,
34   0x00, 0x00, 0x00, 0x04, 0x00, 0x8e, 0x00, 0x00,
35   0x00, 0xef, 0xbb, 0xbf, 0x31, 0x0d, 0x0a, 0x30,
36   0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x2c,
37   0x31, 0x30, 0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x20,
38   0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x32,
39   0x2c, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x3c, 0x62,
40   0x3e, 0x41, 0x6e, 0x20, 0x55, 0x54, 0x46, 0x38,
41   0x20, 0x53, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c,
42   0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x42,
43   0x4f, 0x4d, 0x3c, 0x2f, 0x62, 0x3e, 0x0d, 0x0a,
44   0x0d, 0x0a, 0x32, 0x0d, 0x0a, 0x30, 0x30, 0x3a,
45   0x30, 0x30, 0x3a, 0x30, 0x32, 0x2c, 0x31, 0x30,
46   0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x20, 0x30, 0x30,
47   0x3a, 0x30, 0x30, 0x3a, 0x30, 0x34, 0x2c, 0x30,
48   0x30, 0x30, 0x0d, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
49   0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f,
50   0x6e, 0x41, 0x53, 0x43, 0x49, 0x49, 0x20, 0x2d,
51   0x20, 0xc2, 0xb5, 0xc3, 0xb6, 0xc3, 0xa4, 0xc3,
52   0xbc, 0xc3, 0x9f, 0x0d, 0x0a, 0x0d, 0x0a
53 };
54 
55 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
56     GST_PAD_SINK,
57     GST_PAD_ALWAYS,
58     GST_STATIC_CAPS ("application/x-subtitle")
59     );
60 
61 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
62     GST_PAD_SRC,
63     GST_PAD_ALWAYS,
64     GST_STATIC_CAPS ("application/x-subtitle-avi")
65     );
66 
67 static GstElement *
setup_avisubtitle(void)68 setup_avisubtitle (void)
69 {
70   GstElement *avisubtitle;
71   GstCaps *srccaps;
72 
73   GST_DEBUG ("setup_avisubtitle");
74   avisubtitle = gst_check_setup_element ("avisubtitle");
75   mysinkpad = gst_check_setup_sink_pad (avisubtitle, &sink_template);
76   mysrcpad = gst_check_setup_src_pad (avisubtitle, &src_template);
77   gst_pad_set_active (mysinkpad, TRUE);
78   gst_pad_set_active (mysrcpad, TRUE);
79   srccaps = gst_caps_new_empty_simple ("application/x-subtitle-avi");
80   gst_check_setup_events (mysrcpad, avisubtitle, srccaps, GST_FORMAT_TIME);
81   gst_caps_unref (srccaps);
82   return avisubtitle;
83 }
84 
85 static void
cleanup_avisubtitle(GstElement * avisubtitle)86 cleanup_avisubtitle (GstElement * avisubtitle)
87 {
88   gst_pad_set_active (mysinkpad, FALSE);
89   gst_pad_set_active (mysrcpad, FALSE);
90   gst_check_teardown_sink_pad (avisubtitle);
91   gst_check_teardown_src_pad (avisubtitle);
92   gst_check_teardown_element (avisubtitle);
93 }
94 
95 static void
check_wrong_buffer(guint8 * data,guint length)96 check_wrong_buffer (guint8 * data, guint length)
97 {
98   GstBuffer *buffer = gst_buffer_new_allocate (NULL, length, 0);
99   GstElement *avisubtitle = setup_avisubtitle ();
100 
101   gst_buffer_fill (buffer, 0, data, length);
102   fail_unless (gst_element_set_state (avisubtitle,
103           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
104       "could not set to playing");
105   gst_buffer_ref (buffer);
106   ASSERT_BUFFER_REFCOUNT (buffer, "inbuffer", 2);
107   /* push the broken buffer */
108   fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_ERROR,
109       "accepted a broken buffer");
110   /* check if we have unreffed this buffer on failure */
111   ASSERT_BUFFER_REFCOUNT (buffer, "inbuffer", 1);
112   gst_buffer_unref (buffer);
113   fail_unless (gst_element_set_state (avisubtitle,
114           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
115   cleanup_avisubtitle (avisubtitle);
116 }
117 
118 static void
check_correct_buffer(guint8 * src_data,guint src_size,guint8 * dst_data,guint dst_size)119 check_correct_buffer (guint8 * src_data, guint src_size, guint8 * dst_data,
120     guint dst_size)
121 {
122   GstBuffer *buffer = gst_buffer_new_allocate (NULL, src_size, 0);
123   GstBuffer *newBuffer;
124   GstElement *avisubtitle = setup_avisubtitle ();
125   GstEvent *event;
126 
127   fail_unless (g_list_length (buffers) == 0, "Buffers list needs to be empty");
128   gst_buffer_fill (buffer, 0, src_data, src_size);
129   fail_unless (gst_element_set_state (avisubtitle,
130           GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
131       "could not set to playing");
132   ASSERT_BUFFER_REFCOUNT (buffer, "inbuffer", 1);
133   event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
134       GST_SEEK_TYPE_SET, 2 * GST_SECOND, GST_SEEK_TYPE_SET, 5 * GST_SECOND);
135   fail_unless (gst_element_send_event (avisubtitle, event) == FALSE,
136       "Seeking is not possible when there is no buffer yet");
137   fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK,
138       "not accepted a correct buffer");
139   /* we gave away our reference to the buffer, don't assume anything */
140   buffer = NULL;
141   /* a new buffer is created in the list */
142   fail_unless (g_list_length (buffers) == 1,
143       "No new buffer in the buffers list");
144   event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
145       GST_SEEK_TYPE_SET, 2 * GST_SECOND, GST_SEEK_TYPE_SET, 5 * GST_SECOND);
146   fail_unless (gst_element_send_event (avisubtitle, event) == TRUE,
147       "seeking should be working now");
148   fail_unless (g_list_length (buffers) == 2,
149       "After seeking we need another buffer in the buffers");
150   newBuffer = GST_BUFFER (buffers->data);
151   buffers = g_list_remove (buffers, newBuffer);
152   fail_unless (g_list_length (buffers) == 1, "Buffers list needs to be empty");
153   fail_unless (gst_buffer_get_size (newBuffer) == dst_size,
154       "size of the new buffer is wrong ( %d != %d)",
155       gst_buffer_get_size (newBuffer), dst_size);
156   fail_unless (gst_buffer_memcmp (newBuffer, 0, dst_data, dst_size) == 0,
157       "data of the buffer is not correct");
158   gst_buffer_unref (newBuffer);
159   /* free the buffer from seeking */
160   gst_buffer_unref (GST_BUFFER (buffers->data));
161   buffers = g_list_remove (buffers, buffers->data);
162   fail_unless (gst_element_set_state (avisubtitle,
163           GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
164   cleanup_avisubtitle (avisubtitle);
165 }
166 
167 
GST_START_TEST(test_avisubtitle_negative)168 GST_START_TEST (test_avisubtitle_negative)
169 {
170   guint8 wrong_magic[] =
171       { 0x47, 0x41, 0x41, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172     0x00, 0x00
173   };
174   guint8 wrong_fixed_word_2[] = {
175     0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x01, 0x10,
176     0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
177     0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68
178   };
179   guint8 wrong_length_after_name[] = {
180     0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
181     0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
182     0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68
183   };
184   guint8 wrong_fixed_word_4[] = {
185     0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
186     0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
187     0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68,
188     0x00, 0x00, 0x00, 0x04, 0x01, 0x8e, 0x00, 0x00,
189     0x00, 0xef, 0xbb, 0xbf, 0x31, 0x0d, 0x0a, 0x30
190   };
191   guint8 wrong_total_length[] = {
192     0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
193     0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
194     0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68,
195     0x00, 0x00, 0x00, 0x04, 0x00, 0x8e, 0x00, 0x00,
196     0x00, 0xef, 0xbb, 0xbf, 0x31, 0x0d, 0x0a, 0x30
197   };
198   /* size of the buffer must be larger than 11 */
199   check_wrong_buffer (avisub_utf_8_with_bom, 11);
200   /* buffer must start with 'GAB2\0' */
201   check_wrong_buffer (wrong_magic, 14);
202   /* next word must be 2 */
203   check_wrong_buffer (wrong_fixed_word_2, 24);
204   /* length must be larger than the length of the name + 17 */
205   check_wrong_buffer (wrong_length_after_name, 24);
206   /* next word must be 4 */
207   check_wrong_buffer (wrong_fixed_word_4, 36);
208   /* check wrong total length */
209   check_wrong_buffer (wrong_total_length, 36);
210 }
211 
212 GST_END_TEST;
213 
GST_START_TEST(test_avisubtitle_positive)214 GST_START_TEST (test_avisubtitle_positive)
215 {
216   guint8 avisub_utf_8_without_bom[] = {
217     0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
218     0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
219     0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68,
220     0x00, 0x00, 0x00, 0x04, 0x00, 0x8b, 0x00, 0x00,
221     0x00, 0x31, 0x0d, 0x0a, 0x30,
222     0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x2c,
223     0x31, 0x30, 0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x20,
224     0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x32,
225     0x2c, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x3c, 0x62,
226     0x3e, 0x41, 0x6e, 0x20, 0x55, 0x54, 0x46, 0x38,
227     0x20, 0x53, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c,
228     0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x42,
229     0x4f, 0x4d, 0x3c, 0x2f, 0x62, 0x3e, 0x0d, 0x0a,
230     0x0d, 0x0a, 0x32, 0x0d, 0x0a, 0x30, 0x30, 0x3a,
231     0x30, 0x30, 0x3a, 0x30, 0x32, 0x2c, 0x31, 0x30,
232     0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x20, 0x30, 0x30,
233     0x3a, 0x30, 0x30, 0x3a, 0x30, 0x34, 0x2c, 0x30,
234     0x30, 0x30, 0x0d, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
235     0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f,
236     0x6e, 0x41, 0x53, 0x43, 0x49, 0x49, 0x20, 0x2d,
237     0x20, 0xc2, 0xb5, 0xc3, 0xb6, 0xc3, 0xa4, 0xc3,
238     0xbc, 0xc3, 0x9f, 0x0d, 0x0a, 0x0d, 0x0a
239   };
240   check_correct_buffer (avisub_utf_8_with_bom, 175, avisub_utf_8_with_bom + 36,
241       139);
242   check_correct_buffer (avisub_utf_8_without_bom, 172,
243       avisub_utf_8_without_bom + 33, 139);
244 }
245 
246 GST_END_TEST;
247 
248 static Suite *
avisubtitle_suite(void)249 avisubtitle_suite (void)
250 {
251   Suite *s = suite_create ("avisubtitle");
252   TCase *tc_chain = tcase_create ("general");
253 
254   suite_add_tcase (s, tc_chain);
255   tcase_add_test (tc_chain, test_avisubtitle_negative);
256   tcase_add_test (tc_chain, test_avisubtitle_positive);
257 
258   return s;
259 }
260 
261 GST_CHECK_MAIN (avisubtitle);
262