tests: flvdemux: Add new test for channel detect using aac codec-data
[platform/upstream/gst-plugins-good.git] / tests / check / elements / flvdemux.c
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
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
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
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
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
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
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 *
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
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
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
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
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
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 *
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)