• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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