1 /* GStreamer unit tests for flvdemux
2 *
3 * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
4 * Copyright (C) 2016 Havard Graff <havard@pexip.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include <gst/check/gstcheck.h>
23 #include <gst/check/gstharness.h>
24
25 #include <gst/gst.h>
26 #include <gst/tag/tag.h>
27
28 static void
pad_added_cb(GstElement * flvdemux,GstPad * pad,GstBin * pipeline)29 pad_added_cb (GstElement * flvdemux, GstPad * pad, GstBin * pipeline)
30 {
31 GstElement *sink;
32
33 sink = gst_bin_get_by_name (pipeline, "fakesink");
34 fail_unless (gst_element_link (flvdemux, sink));
35 gst_object_unref (sink);
36
37 gst_element_set_state (sink, GST_STATE_PAUSED);
38 }
39
40 static GstBusSyncReply
error_cb(GstBus * bus,GstMessage * msg,gpointer user_data)41 error_cb (GstBus * bus, GstMessage * msg, gpointer user_data)
42 {
43 if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
44 const gchar *file = (const gchar *) user_data;
45 GError *err = NULL;
46 gchar *dbg = NULL;
47
48 gst_message_parse_error (msg, &err, &dbg);
49 g_error ("ERROR for %s: %s\n%s\n", file, err->message, dbg);
50 }
51
52 return GST_BUS_PASS;
53 }
54
55 static void
handoff_cb(GstElement * element,GstBuffer * buf,GstPad * pad,gint * p_counter)56 handoff_cb (GstElement * element, GstBuffer * buf, GstPad * pad,
57 gint * p_counter)
58 {
59 *p_counter += 1;
60 GST_LOG ("counter = %d", *p_counter);
61 }
62
63 static void
process_file(const gchar * file,gboolean push_mode,gint repeat,gint num_buffers)64 process_file (const gchar * file, gboolean push_mode, gint repeat,
65 gint num_buffers)
66 {
67 GstElement *src, *sep, *sink, *flvdemux, *pipeline;
68 GstBus *bus;
69 gchar *path;
70 gint counter;
71
72 pipeline = gst_pipeline_new ("pipeline");
73 fail_unless (pipeline != NULL, "Failed to create pipeline!");
74
75 bus = gst_element_get_bus (pipeline);
76
77 /* kids, don't use a sync handler for this at home, really; we do because
78 * we just want to abort and nothing else */
79 gst_bus_set_sync_handler (bus, error_cb, (gpointer) file, NULL);
80
81 src = gst_element_factory_make ("filesrc", "filesrc");
82 fail_unless (src != NULL, "Failed to create 'filesrc' element!");
83
84 if (push_mode) {
85 sep = gst_element_factory_make ("queue", "queue");
86 fail_unless (sep != NULL, "Failed to create 'queue' element");
87 } else {
88 sep = gst_element_factory_make ("identity", "identity");
89 fail_unless (sep != NULL, "Failed to create 'identity' element");
90 }
91
92 flvdemux = gst_element_factory_make ("flvdemux", "flvdemux");
93 fail_unless (flvdemux != NULL, "Failed to create 'flvdemux' element!");
94
95 sink = gst_element_factory_make ("fakesink", "fakesink");
96 fail_unless (sink != NULL, "Failed to create 'fakesink' element!");
97
98 g_object_set (sink, "signal-handoffs", TRUE, NULL);
99 g_signal_connect (sink, "handoff", G_CALLBACK (handoff_cb), &counter);
100
101 gst_bin_add_many (GST_BIN (pipeline), src, sep, flvdemux, sink, NULL);
102
103 fail_unless (gst_element_link (src, sep));
104 fail_unless (gst_element_link (sep, flvdemux));
105
106 /* can't link flvdemux and sink yet, do that later */
107 g_signal_connect (flvdemux, "pad-added", G_CALLBACK (pad_added_cb), pipeline);
108
109 path = g_build_filename (GST_TEST_FILES_PATH, file, NULL);
110 GST_LOG ("processing file '%s'", path);
111 g_object_set (src, "location", path, NULL);
112
113 do {
114 GstStateChangeReturn state_ret;
115 GstMessage *msg;
116
117 GST_LOG ("repeat=%d", repeat);
118
119 counter = 0;
120
121 state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
122 fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);
123
124 if (state_ret == GST_STATE_CHANGE_ASYNC) {
125 GST_LOG ("waiting for pipeline to reach PAUSED state");
126 state_ret = gst_element_get_state (pipeline, NULL, NULL, -1);
127 fail_unless_equals_int (state_ret, GST_STATE_CHANGE_SUCCESS);
128 }
129
130 GST_LOG ("PAUSED, let's read all of it");
131
132 state_ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
133 fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);
134
135 msg = gst_bus_poll (bus, GST_MESSAGE_EOS, -1);
136 fail_unless (msg != NULL, "Expected EOS message on bus! (%s)", file);
137
138 gst_message_unref (msg);
139
140 if (num_buffers >= 0) {
141 fail_unless_equals_int (counter, num_buffers);
142 }
143
144 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
145 GST_STATE_CHANGE_SUCCESS);
146
147 --repeat;
148 } while (repeat > 0);
149
150 gst_object_unref (bus);
151 gst_object_unref (pipeline);
152
153 g_free (path);
154 }
155
GST_START_TEST(test_reuse_pull)156 GST_START_TEST (test_reuse_pull)
157 {
158 process_file ("pcm16sine.flv", FALSE, 3, 129);
159 gst_task_cleanup_all ();
160 }
161
162 GST_END_TEST;
163
GST_START_TEST(test_reuse_push)164 GST_START_TEST (test_reuse_push)
165 {
166 process_file ("pcm16sine.flv", TRUE, 3, 129);
167 gst_task_cleanup_all ();
168 }
169
170 GST_END_TEST;
171
172 static GstBuffer *
create_buffer(guint8 * data,gsize size)173 create_buffer (guint8 * data, gsize size)
174 {
175 GstBuffer *buf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
176 data, size, 0, size, NULL, NULL);
177 GST_BUFFER_PTS (buf) = GST_CLOCK_TIME_NONE;
178 GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
179 GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE;
180 GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
181 GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;
182 return buf;
183 }
184
185 static void
flvdemux_pad_added(GstElement * flvdemux,GstPad * srcpad,GstHarness * h)186 flvdemux_pad_added (GstElement * flvdemux, GstPad * srcpad, GstHarness * h)
187 {
188 GstCaps *caps;
189 (void) flvdemux;
190
191 caps = gst_pad_get_current_caps (srcpad);
192 fail_unless (caps != NULL);
193 gst_caps_unref (caps);
194 gst_harness_add_element_src_pad (h, srcpad);
195 }
196
GST_START_TEST(test_speex)197 GST_START_TEST (test_speex)
198 {
199 guint8 flv_header0[] = {
200 0x46, 0x4c, 0x56, 0x01, 0x04, 0x00, 0x00, 0x00,
201 0x09, 0x00, 0x00, 0x00, 0x00
202 };
203
204 guint8 flv_header1[] = {
205 0x12, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x6f, 0x6e,
207 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61,
208 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x61,
209 0x75, 0x64, 0x69, 0x6f, 0x63, 0x6f, 0x64, 0x65,
210 0x63, 0x69, 0x64, 0x00, 0x40, 0x26, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x6d, 0x65,
212 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x63, 0x72,
213 0x65, 0x61, 0x74, 0x6f, 0x72, 0x02, 0x00, 0x13,
214 0x47, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65,
215 0x72, 0x20, 0x46, 0x4c, 0x56, 0x20, 0x6d, 0x75,
216 0x78, 0x65, 0x72, 0x00, 0x0c, 0x63, 0x72, 0x65,
217 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x61, 0x74,
218 0x65, 0x02, 0x00, 0x18, 0x57, 0x65, 0x64, 0x20,
219 0x53, 0x65, 0x70, 0x20, 0x32, 0x33, 0x20, 0x31,
220 0x30, 0x3a, 0x34, 0x39, 0x3a, 0x35, 0x36, 0x20,
221 0x32, 0x30, 0x31, 0x35, 0x00, 0x00, 0x09, 0x00,
222 0x00, 0x00, 0x87,
223 };
224
225 guint8 speex_header0[] = {
226 0x08, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
227 0x00, 0x00, 0x00, 0xb2, 0x53, 0x70, 0x65, 0x65,
228 0x78, 0x20, 0x20, 0x20, 0x31, 0x2e, 0x32, 0x72,
229 0x63, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
232 0x80, 0x3e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
233 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
234 0xff, 0xff, 0xff, 0xff, 0x40, 0x01, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
238 };
239
240 guint8 speex_header1[] = {
241 0x08, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0xb2, 0x1f, 0x00, 0x00, 0x00,
243 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20,
244 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x53, 0x74,
245 0x72, 0x65, 0x61, 0x6d, 0x65, 0x72, 0x20, 0x53,
246 0x70, 0x65, 0x65, 0x78, 0x65, 0x6e, 0x63, 0x00,
247 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x34,
248 };
249
250 guint8 buffer[] = {
251 0x08, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0xb2, 0x36, 0x9d, 0x1b, 0x9a,
253 0x20, 0x00, 0x01, 0x68, 0xe8, 0xe8, 0xe8, 0xe8,
254 0xe8, 0xe8, 0xe8, 0x84, 0x00, 0xb4, 0x74, 0x74,
255 0x74, 0x74, 0x74, 0x74, 0x74, 0x42, 0x00, 0x5a,
256 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x21,
257 0x00, 0x2d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
258 0x1d, 0x1b, 0x3b, 0x60, 0xab, 0xab, 0xab, 0xab,
259 0xab, 0x0a, 0xba, 0xba, 0xba, 0xba, 0xb0, 0xab,
260 0xab, 0xab, 0xab, 0xab, 0x0a, 0xba, 0xba, 0xba,
261 0xba, 0xb7, 0x00, 0x00, 0x00, 0x52,
262 };
263
264 GstHarness *h = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
265 gst_harness_set_src_caps_str (h, "video/x-flv");
266
267 g_signal_connect (h->element, "pad-added",
268 G_CALLBACK (flvdemux_pad_added), h);
269
270 gst_harness_push (h, create_buffer (flv_header0, sizeof (flv_header0)));
271 gst_harness_push (h, create_buffer (flv_header1, sizeof (flv_header1)));
272 gst_harness_push (h, create_buffer (speex_header0, sizeof (speex_header0)));
273 gst_harness_push (h, create_buffer (speex_header1, sizeof (speex_header1)));
274 gst_harness_push (h, create_buffer (buffer, sizeof (buffer)));
275
276 {
277 GstCaps *caps;
278 const GstStructure *s;
279 const GValue *streamheader;
280 const GValue *header;
281 const GValue *vorbiscomment;
282 GstBuffer *buf;
283 GstTagList *list;
284 gint rate;
285 gint channels;
286
287 caps = gst_pad_get_current_caps (h->sinkpad);
288 s = gst_caps_get_structure (caps, 0);
289
290 fail_unless (gst_structure_has_name (s, "audio/x-speex"));
291
292 streamheader = gst_structure_get_value (s, "streamheader");
293 fail_unless (streamheader != NULL);
294 fail_unless (G_VALUE_HOLDS (streamheader, GST_TYPE_ARRAY));
295 fail_unless_equals_int (2, gst_value_array_get_size (streamheader));
296
297 header = gst_value_array_get_value (streamheader, 0);
298 fail_unless (header != NULL);
299 fail_unless (G_VALUE_HOLDS (header, GST_TYPE_BUFFER));
300 buf = gst_value_get_buffer (header);
301
302 vorbiscomment = gst_value_array_get_value (streamheader, 1);
303 fail_unless (header != NULL);
304 fail_unless (G_VALUE_HOLDS (header, GST_TYPE_BUFFER));
305 buf = gst_value_get_buffer (vorbiscomment);
306 list = gst_tag_list_from_vorbiscomment_buffer (buf, NULL, 0, NULL);
307 fail_unless (list != NULL);
308 gst_tag_list_unref (list);
309
310 gst_structure_get_int (s, "rate", &rate);
311 fail_unless_equals_int (16000, rate);
312
313 gst_structure_get_int (s, "channels", &channels);
314 fail_unless_equals_int (1, channels);
315
316 gst_caps_unref (caps);
317 }
318
319 /* we should have gotten 2x speex-headers, and one encoded buffer */
320 fail_unless_equals_int (3, gst_harness_buffers_in_queue (h));
321
322 gst_harness_teardown (h);
323 }
324
325 GST_END_TEST;
326
327
GST_START_TEST(test_aac)328 GST_START_TEST (test_aac)
329 {
330 guint8 flv_header[] = {
331 0x46, 0x4c, 0x56, 0x01, 0x04, 0x00, 0x00, 0x00,
332 0x09, 0x00, 0x00, 0x00, 0x00,
333 0x12, 0x00, 0x00, 0x2d, /* script tag */
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
335 0x00, 0x0a, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61,
336 0x44, 0x61, 0x74, 0x61, 0x03, 0x00, 0x06, 0x53,
337 0x65, 0x72, 0x76, 0x65, 0x72, 0x02, 0x00, 0x11,
338 0x50, 0x65, 0x78, 0x69, 0x70, 0x20, 0x52, 0x54,
339 0x4d, 0x50, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65,
340 0x72, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x38,
341 };
342
343 guint8 aac_header[] = {
344 0x08, 0x00, 0x00, 0x04, /* audio tag */
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf,
346 0x00, 0x13, 0x10, 0x00, 0x00, 0x00, 0x0f,
347 };
348
349 guint8 aac_buffer[] = {
350 0x08, 0x00, 0x01, 0x57, /* audio tag */
351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf,
352 0x01, 0x21, 0x21, 0x45, 0x00, 0x14, 0x50, 0x01,
353 0x46, 0xf0, 0x4d, 0xfb, 0x01, 0x3c, 0x08, 0x40,
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x00, 0x07, 0x0e, 0x00, 0x0d, 0xff, 0xe2, 0x14,
356 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
357 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
358 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
359 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
360 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
361 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
362 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
363 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
364 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
365 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
366 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
367 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
368 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
369 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
370 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
371 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
372 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
373 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
374 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
375 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
376 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
377 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
378 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
379 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
380 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
381 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
382 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
383 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
384 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
385 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
386 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
387 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
388 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
389 0xb4, 0xb4, 0xb4, 0xbb, 0xc6, 0x84, 0x29, 0x69,
390 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
391 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
392 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
393 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
394 0x69, 0x69, 0x69, 0x69, 0x69, 0x78, 0x00, 0x00,
395 0x01, 0x62
396 };
397
398 GstHarness *h = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
399 gst_harness_set_src_caps_str (h, "video/x-flv");
400
401 g_signal_connect (h->element, "pad-added",
402 G_CALLBACK (flvdemux_pad_added), h);
403
404 gst_harness_push (h, create_buffer (flv_header, sizeof (flv_header)));
405 gst_harness_push (h, create_buffer (aac_header, sizeof (aac_header)));
406 gst_harness_push (h, create_buffer (aac_buffer, sizeof (aac_buffer)));
407
408 {
409 GstCaps *caps;
410 const GstStructure *s;
411 gint mpegversion;
412 gboolean framed;
413 const gchar *stream_format;
414 gint rate;
415 gint channels;
416 const GValue *codec_data;
417
418 caps = gst_pad_get_current_caps (h->sinkpad);
419 s = gst_caps_get_structure (caps, 0);
420
421 fail_unless (gst_structure_has_name (s, "audio/mpeg"));
422
423 gst_structure_get_int (s, "mpegversion", &mpegversion);
424 fail_unless_equals_int (4, mpegversion);
425
426 gst_structure_get_boolean (s, "framed", &framed);
427 fail_unless (framed == TRUE);
428
429 stream_format = gst_structure_get_string (s, "stream-format");
430 fail_unless_equals_string ("raw", stream_format);
431
432 gst_structure_get_int (s, "rate", &rate);
433 fail_unless_equals_int (24000, rate);
434
435 gst_structure_get_int (s, "channels", &channels);
436 fail_unless_equals_int (2, channels);
437
438 codec_data = gst_structure_get_value (s, "codec_data");
439 fail_unless (codec_data != NULL);
440 fail_unless (G_VALUE_HOLDS (codec_data, GST_TYPE_BUFFER));
441
442 gst_caps_unref (caps);
443 }
444
445 /* we should have gotten one encoded buffer */
446 fail_unless_equals_int (1, gst_harness_buffers_in_queue (h));
447
448 gst_harness_teardown (h);
449 }
450
451 GST_END_TEST;
452
GST_START_TEST(test_aac_not_support_rate_channels)453 GST_START_TEST (test_aac_not_support_rate_channels)
454 {
455 guint8 flv_header[] = {
456 0x46, 0x4c, 0x56, 0x01, 0x04, 0x00, 0x00, 0x00,
457 0x09, 0x00, 0x00, 0x00, 0x00,
458 0x12, 0x00, 0x00, 0x44, /* script tag */
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
460 0x00, 0x0a, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61,
461 0x44, 0x61, 0x74, 0x61, 0x08, 0x00, 0x00, 0x00,
462 0x04, 0x00, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x6f,
463 0x63, 0x6f, 0x64, 0x65, 0x63, 0x69, 0x64, 0x00,
464 0x40, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465 0x00, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x64,
466 0x61, 0x74, 0x61, 0x72, 0x61, 0x74, 0x65, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4f,
469 };
470
471 guint8 aac_header[] = {
472 0x08, 0x00, 0x00, 0x04, /* audio tag */
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf,
474 0x00, 0x13, 0x88, 0x00, 0x00, 0x00, 0x0f,
475 };
476
477 guint8 aac_buffer[] = {
478 0x08, 0x00, 0x01, 0x57, /* audio tag */
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf,
480 0x01, 0x21, 0x21, 0x45, 0x00, 0x14, 0x50, 0x01,
481 0x46, 0xf0, 0x4d, 0xfb, 0x01, 0x3c, 0x08, 0x40,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x07, 0x0e, 0x00, 0x0d, 0xff, 0xe2, 0x14,
484 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
485 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
486 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
487 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
488 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
489 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
490 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
491 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
492 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
493 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
494 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
495 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
496 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
497 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
498 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
499 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
500 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
501 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
502 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
503 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
504 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
505 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
506 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
507 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
508 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
509 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
510 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
511 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
512 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
513 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
514 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
515 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
516 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
517 0xb4, 0xb4, 0xb4, 0xbb, 0xc6, 0x84, 0x29, 0x69,
518 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
519 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
520 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
521 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
522 0x69, 0x69, 0x69, 0x69, 0x69, 0x78, 0x00, 0x00,
523 0x01, 0x62
524 };
525
526 GstHarness *h = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
527 gst_harness_set_src_caps_str (h, "video/x-flv");
528
529 g_signal_connect (h->element, "pad-added",
530 G_CALLBACK (flvdemux_pad_added), h);
531
532 gst_harness_push (h, create_buffer (flv_header, sizeof (flv_header)));
533 gst_harness_push (h, create_buffer (aac_header, sizeof (aac_header)));
534 gst_harness_push (h, create_buffer (aac_buffer, sizeof (aac_buffer)));
535
536 {
537 GstCaps *caps;
538 const GstStructure *s;
539 gint mpegversion;
540 gboolean framed;
541 const gchar *stream_format;
542 gint rate;
543 gint channels;
544 const GValue *codec_data;
545
546 caps = gst_pad_get_current_caps (h->sinkpad);
547 s = gst_caps_get_structure (caps, 0);
548
549 fail_unless (gst_structure_has_name (s, "audio/mpeg"));
550
551 gst_structure_get_int (s, "mpegversion", &mpegversion);
552 fail_unless_equals_int (4, mpegversion);
553
554 gst_structure_get_boolean (s, "framed", &framed);
555 fail_unless (framed == TRUE);
556
557 stream_format = gst_structure_get_string (s, "stream-format");
558 fail_unless_equals_string ("raw", stream_format);
559
560 gst_structure_get_int (s, "rate", &rate);
561 fail_unless_equals_int (22050, rate);
562
563 gst_structure_get_int (s, "channels", &channels);
564 fail_unless_equals_int (1, channels);
565
566 codec_data = gst_structure_get_value (s, "codec_data");
567 fail_unless (codec_data != NULL);
568 fail_unless (G_VALUE_HOLDS (codec_data, GST_TYPE_BUFFER));
569
570 gst_caps_unref (caps);
571 }
572
573 /* we should have gotten one encoded buffer */
574 fail_unless_equals_int (1, gst_harness_buffers_in_queue (h));
575
576 gst_harness_teardown (h);
577 }
578
579 GST_END_TEST;
580
GST_START_TEST(test_h264)581 GST_START_TEST (test_h264)
582 {
583 guint8 flv_header[] = {
584 0x46, 0x4c, 0x56, 0x01, 0x01, 0x00, 0x00, 0x00,
585 0x09, 0x00, 0x00, 0x00, 0x00,
586 0x12, 0x00, 0x00, 0x2d, /* script tag */
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
588 0x00, 0x0a, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61,
589 0x44, 0x61, 0x74, 0x61, 0x03, 0x00, 0x06, 0x53,
590 0x65, 0x72, 0x76, 0x65, 0x72, 0x02, 0x00, 0x11,
591 0x50, 0x65, 0x78, 0x69, 0x70, 0x20, 0x52, 0x54,
592 0x4d, 0x50, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65,
593 0x72, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x38,
594 };
595
596 guint8 h264_packet0[] = {
597 0x09, 0x00, 0x00, 0x1e, /* video tag */
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
599 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0xc0, 0x1e,
600 0xff, 0xe1, 0x00, 0x0a, 0x67, 0x42, 0xc0, 0x1e,
601 0x95, 0xa0, 0x28, 0x0b, 0xde, 0x54, 0x01, 0x00,
602 0x04, 0x68, 0xce, 0x3c, 0x80, 0x00, 0x00, 0x00,
603 0x29
604 };
605
606 guint8 h264_packet1[] = {
607 0x09, 0x00, 0x00, 0x1b, /* video tag */
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27,
609 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
610 0x67, 0x42, 0xc0, 0x1e, 0x95, 0xa0, 0x28, 0x0b,
611 0xde, 0x54, 0x00, 0x00, 0x00, 0x04, 0x68, 0xce,
612 0x3c, 0x80, 0x00, 0x00, 0x00, 0x26
613 };
614
615 GstHarness *h = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
616 gst_harness_set_src_caps_str (h, "video/x-flv");
617
618 g_signal_connect (h->element, "pad-added",
619 G_CALLBACK (flvdemux_pad_added), h);
620
621 gst_harness_push (h, create_buffer (flv_header, sizeof (flv_header)));
622 gst_harness_push (h, create_buffer (h264_packet0, sizeof (h264_packet0)));
623 gst_harness_push (h, create_buffer (h264_packet1, sizeof (h264_packet1)));
624
625 {
626 GstCaps *caps;
627 const GstStructure *s;
628 const gchar *stream_format;
629 const GValue *codec_data;
630
631 caps = gst_pad_get_current_caps (h->sinkpad);
632 s = gst_caps_get_structure (caps, 0);
633
634 fail_unless (gst_structure_has_name (s, "video/x-h264"));
635
636 stream_format = gst_structure_get_string (s, "stream-format");
637 fail_unless_equals_string ("avc", stream_format);
638
639 codec_data = gst_structure_get_value (s, "codec_data");
640 fail_unless (codec_data != NULL);
641 fail_unless (G_VALUE_HOLDS (codec_data, GST_TYPE_BUFFER));
642
643 gst_caps_unref (caps);
644 }
645
646 /* we should have gotten one encoded buffer */
647 fail_unless_equals_int (1, gst_harness_buffers_in_queue (h));
648
649 gst_harness_teardown (h);
650 }
651
652 GST_END_TEST;
653
654
655 static Suite *
flvdemux_suite(void)656 flvdemux_suite (void)
657 {
658 Suite *s = suite_create ("flvdemux");
659 TCase *tc_chain = tcase_create ("general");
660
661 suite_add_tcase (s, tc_chain);
662 tcase_add_test (tc_chain, test_reuse_push);
663 tcase_add_test (tc_chain, test_reuse_pull);
664
665 tcase_add_test (tc_chain, test_speex);
666 tcase_add_test (tc_chain, test_aac);
667 tcase_add_test (tc_chain, test_h264);
668 tcase_add_test (tc_chain, test_aac_not_support_rate_channels);
669
670 return s;
671 }
672
673 GST_CHECK_MAIN (flvdemux)
674