4b20d6d77e312e5c6cec428041bb3abe2e258b8a
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / tests / check / elements / vorbistag.c
1 /* GStreamer
2  *
3  * unit test for vorbisdec
4  *
5  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
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., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <unistd.h>
24 #include <glib.h>
25
26 #include <vorbis/codec.h>
27 #include <vorbis/vorbisenc.h>
28
29 #include <gst/gsttagsetter.h>
30 #include <gst/check/gstcheck.h>
31
32 /* a valid first header packet */
33 static guchar identification_header[30] = {
34   1,                            /* packet_type */
35   'v', 'o', 'r', 'b', 'i', 's',
36   0, 0, 0, 0,                   /* vorbis_version */
37   2,                            /* audio_channels */
38   0x44, 0xac, 0, 0,             /* sample_rate */
39   0xff, 0xff, 0xff, 0xff,       /* bitrate_maximum */
40   0x00, 0xee, 0x02, 0x00,       /* bitrate_nominal */
41   0xff, 0xff, 0xff, 0xff,       /* bitrate_minimum */
42   0xb8,                         /* blocksize_0, blocksize_1 */
43   0x01                          /* framing_flag */
44 };
45
46 static guchar artist_comment_header[] = {
47   3,                            /* packet_type */
48   'v', 'o', 'r', 'b', 'i', 's',
49   2, 0, 0, 0,                   /* vendor_length */
50   'm', 'e',
51   1, 0, 0, 0,                   /* user_comment_list_length */
52   9, 0, 0, 0,                   /* length comment[0] */
53   'A', 'R', 'T', 'I', 'S', 'T', '=', 'm', 'e',
54   0x01,                         /* framing bit */
55 };
56
57 static guchar title_comment_header[] = {
58   3,                            /* packet_type */
59   'v', 'o', 'r', 'b', 'i', 's',
60   2, 0, 0, 0,                   /* vendor_length */
61   'm', 'e',
62   1, 0, 0, 0,                   /* user_comment_list_length */
63   12, 0, 0, 0,                  /* length comment[0] */
64   'T', 'I', 'T', 'L', 'E', '=', 'f', 'o', 'o', 'b', 'a', 'r',
65   0x01,                         /* framing bit */
66 };
67
68 static guchar empty_comment_header[] = {
69   3,                            /* packet_type */
70   'v', 'o', 'r', 'b', 'i', 's',
71   2, 0, 0, 0,                   /* vendor_length */
72   'm', 'e',
73   0, 0, 0, 0,                   /* user_comment_list_length */
74   0x01,                         /* framing bit */
75 };
76
77
78 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
79     GST_PAD_SINK,
80     GST_PAD_ALWAYS,
81     GST_STATIC_CAPS_ANY);
82 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
83     GST_PAD_SRC,
84     GST_PAD_ALWAYS,
85     GST_STATIC_CAPS_ANY);
86
87 static GstPad *mysrcpad, *mysinkpad;
88 static GAsyncQueue *pending_buffers;
89 static gulong id;
90
91
92 static GstElement *
93 setup_vorbistag (void)
94 {
95   GstElement *vorbistag;
96
97   GST_DEBUG ("setup_vorbistag");
98   vorbistag = gst_check_setup_element ("vorbistag");
99   mysrcpad = gst_check_setup_src_pad (vorbistag, &srctemplate, NULL);
100   mysinkpad = gst_check_setup_sink_pad (vorbistag, &sinktemplate, NULL);
101   gst_pad_set_active (mysrcpad, TRUE);
102   gst_pad_set_active (mysinkpad, TRUE);
103
104   return vorbistag;
105 }
106
107 static void
108 cleanup_vorbistag (GstElement * vorbistag)
109 {
110   GST_DEBUG ("cleanup_vorbistag");
111   gst_element_set_state (vorbistag, GST_STATE_NULL);
112
113   gst_pad_set_active (mysrcpad, FALSE);
114   gst_pad_set_active (mysinkpad, FALSE);
115   gst_check_teardown_src_pad (vorbistag);
116   gst_check_teardown_sink_pad (vorbistag);
117   gst_check_teardown_element (vorbistag);
118 }
119
120
121 static gboolean
122 buffer_probe (GstPad * pad, GstBuffer * buffer, gpointer unused)
123 {
124   g_async_queue_push (pending_buffers, gst_buffer_ref (buffer));
125   return TRUE;
126 }
127
128 static void
129 start_pipeline (GstElement * element)
130 {
131   id = gst_pad_add_buffer_probe (mysinkpad, G_CALLBACK (buffer_probe), NULL);
132
133   pending_buffers = g_async_queue_new ();
134   gst_element_set_state (element, GST_STATE_PLAYING);
135 }
136
137 static GstBuffer *
138 get_buffer (void)
139 {
140   return GST_BUFFER (g_async_queue_pop (pending_buffers));
141 }
142
143 static void
144 stop_pipeline (GstElement * element)
145 {
146   GstBuffer *buf;
147
148   while ((buf = g_async_queue_try_pop (pending_buffers)))
149     gst_buffer_unref (buf);
150
151   gst_pad_remove_buffer_probe (mysinkpad, (guint) id);
152   id = 0;
153
154   gst_element_set_state (element, GST_STATE_NULL);
155
156   while ((buf = g_async_queue_try_pop (pending_buffers)))
157     gst_buffer_unref (buf);
158
159   g_async_queue_unref (pending_buffers);
160   pending_buffers = NULL;
161 }
162
163 static vorbis_comment vc;
164 static vorbis_dsp_state vd;
165 static vorbis_info vi;
166 static vorbis_block vb;
167
168 static GstBuffer *
169 _create_codebook_header_buffer (void)
170 {
171   GstBuffer *buffer;
172   ogg_packet header;
173   ogg_packet header_comm;
174   ogg_packet header_code;
175
176   vorbis_info_init (&vi);
177   vorbis_encode_setup_vbr (&vi, 1, 44000, 0.5);
178   vorbis_encode_setup_init (&vi);
179   vorbis_analysis_init (&vd, &vi);
180   vorbis_block_init (&vd, &vb);
181   vorbis_comment_init (&vc);
182   vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code);
183
184   buffer = gst_buffer_new_and_alloc (header_code.bytes);
185   memcpy (GST_BUFFER_DATA (buffer), header_code.packet, header_code.bytes);
186
187   return buffer;
188 }
189
190 static GstBuffer *
191 _create_audio_buffer (void)
192 {
193   GstBuffer *buffer;
194   ogg_packet packet;
195   float **vorbis_buffer;
196
197   vorbis_buffer = vorbis_analysis_buffer (&vd, 0);
198   vorbis_analysis_wrote (&vd, 0);
199   vorbis_analysis_blockout (&vd, &vb);
200   vorbis_analysis (&vb, NULL);
201   vorbis_bitrate_addblock (&vb);
202   vorbis_bitrate_flushpacket (&vd, &packet);
203   buffer = gst_buffer_new_and_alloc (packet.bytes);
204   memcpy (GST_BUFFER_DATA (buffer), packet.packet, packet.bytes);
205
206   vorbis_comment_clear (&vc);
207   vorbis_block_clear (&vb);
208   vorbis_dsp_clear (&vd);
209   vorbis_info_clear (&vi);
210
211   return buffer;
212 }
213
214
215 GST_START_TEST (test_empty_tags_set)
216 {
217   GstTagList *tags;
218   GstElement *vorbistag;
219   GstBuffer *inbuffer, *outbuffer;
220
221   vorbistag = setup_vorbistag ();
222
223   tags = gst_tag_list_new ();
224   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, "foobar", NULL);
225   gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags,
226       GST_TAG_MERGE_REPLACE);
227   gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag),
228       GST_TAG_MERGE_KEEP_ALL);
229   gst_tag_list_free (tags);
230
231   start_pipeline (vorbistag);
232
233   /* send identification header */
234   inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header));
235   memcpy (GST_BUFFER_DATA (inbuffer), identification_header,
236       sizeof (identification_header));
237   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
238
239   /* send empty comment buffer */
240   inbuffer = gst_buffer_new_and_alloc (sizeof (empty_comment_header));
241   memcpy (GST_BUFFER_DATA (inbuffer), empty_comment_header,
242       sizeof (empty_comment_header));
243   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
244
245   /* send minimal codebook header and audio packers */
246   inbuffer = _create_codebook_header_buffer ();
247   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
248   inbuffer = _create_audio_buffer ();
249   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
250
251
252   /* check identification header is unchanged */
253   outbuffer = get_buffer ();
254   fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
255       sizeof (identification_header));
256   fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
257           identification_header, sizeof (identification_header)), 0);
258   gst_buffer_unref (outbuffer);
259
260   /* check comment header is correct */
261   outbuffer = get_buffer ();
262   fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
263       sizeof (title_comment_header));
264   fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
265           title_comment_header, sizeof (title_comment_header)), 0);
266   gst_buffer_unref (outbuffer);
267
268   stop_pipeline (vorbistag);
269   cleanup_vorbistag (vorbistag);
270 }
271
272 GST_END_TEST;
273
274
275 GST_START_TEST (test_filled_tags_unset)
276 {
277   GstTagList *tags;
278   GstElement *vorbistag;
279   GstBuffer *inbuffer, *outbuffer;
280
281   vorbistag = setup_vorbistag ();
282
283   tags = gst_tag_list_new ();
284   gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags,
285       GST_TAG_MERGE_REPLACE);
286   gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag),
287       GST_TAG_MERGE_KEEP_ALL);
288   gst_tag_list_free (tags);
289
290   start_pipeline (vorbistag);
291
292   /* send identification header */
293   inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header));
294   memcpy (GST_BUFFER_DATA (inbuffer), identification_header,
295       sizeof (identification_header));
296   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
297
298   /* send empty comment buffer */
299   inbuffer = gst_buffer_new_and_alloc (sizeof (title_comment_header));
300   memcpy (GST_BUFFER_DATA (inbuffer), title_comment_header,
301       sizeof (title_comment_header));
302   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
303
304   /* send minimal codebook header and audio packers */
305   inbuffer = _create_codebook_header_buffer ();
306   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
307   inbuffer = _create_audio_buffer ();
308   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
309
310
311   /* check identification header is unchanged */
312   outbuffer = get_buffer ();
313   fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
314       sizeof (identification_header));
315   fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
316           identification_header, sizeof (identification_header)), 0);
317   gst_buffer_unref (outbuffer);
318
319   /* check comment header is correct */
320   outbuffer = get_buffer ();
321   fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
322       sizeof (empty_comment_header));
323   fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
324           empty_comment_header, sizeof (empty_comment_header)), 0);
325   gst_buffer_unref (outbuffer);
326
327   stop_pipeline (vorbistag);
328   cleanup_vorbistag (vorbistag);
329 }
330
331 GST_END_TEST;
332
333
334 GST_START_TEST (test_filled_tags_change)
335 {
336   GstTagList *tags;
337   GstElement *vorbistag;
338   GstBuffer *inbuffer, *outbuffer;
339
340   vorbistag = setup_vorbistag ();
341
342   tags = gst_tag_list_new ();
343   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, "foobar", NULL);
344   gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags,
345       GST_TAG_MERGE_REPLACE);
346   gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag),
347       GST_TAG_MERGE_KEEP_ALL);
348   gst_tag_list_free (tags);
349
350   start_pipeline (vorbistag);
351
352   /* send identification header */
353   inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header));
354   memcpy (GST_BUFFER_DATA (inbuffer), identification_header,
355       sizeof (identification_header));
356   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
357
358   /* send empty comment buffer */
359   inbuffer = gst_buffer_new_and_alloc (sizeof (artist_comment_header));
360   memcpy (GST_BUFFER_DATA (inbuffer), artist_comment_header,
361       sizeof (artist_comment_header));
362   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
363
364   /* send minimal codebook header and audio packers */
365   inbuffer = _create_codebook_header_buffer ();
366   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
367   inbuffer = _create_audio_buffer ();
368   fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
369
370
371   /* check identification header is unchanged */
372   outbuffer = get_buffer ();
373   fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
374       sizeof (identification_header));
375   fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
376           identification_header, sizeof (identification_header)), 0);
377   gst_buffer_unref (outbuffer);
378
379   /* check comment header is correct */
380   outbuffer = get_buffer ();
381   fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer),
382       sizeof (title_comment_header));
383   fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer),
384           title_comment_header, sizeof (title_comment_header)), 0);
385   gst_buffer_unref (outbuffer);
386
387   stop_pipeline (vorbistag);
388   cleanup_vorbistag (vorbistag);
389 }
390
391 GST_END_TEST;
392
393
394
395 static Suite *
396 vorbistag_suite (void)
397 {
398   Suite *s = suite_create ("vorbistag");
399   TCase *tc_chain = tcase_create ("general");
400
401   suite_add_tcase (s, tc_chain);
402   tcase_add_test (tc_chain, test_empty_tags_set);
403   tcase_add_test (tc_chain, test_filled_tags_unset);
404   tcase_add_test (tc_chain, test_filled_tags_change);
405
406   return s;
407 }
408
409 GST_CHECK_MAIN (vorbistag)