1 /* GStreamer unit tests for flvmux
3 * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
4 * Copyright (C) 2016 Havard Graff <havard@pexip.com>
5 * Copyright (C) 2016 David Buchmann <david@pexip.com>
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.
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.
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.
28 # include <valgrind/valgrind.h>
31 #include <gst/check/gstcheck.h>
32 #include <gst/check/gstharness.h>
36 static GstBusSyncReply
37 error_cb (GstBus * bus, GstMessage * msg, gpointer user_data)
39 if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
43 gst_message_parse_error (msg, &err, &dbg);
44 g_error ("ERROR: %s\n%s\n", err->message, dbg);
51 handoff_cb (GstElement * element, GstBuffer * buf, GstPad * pad,
55 GST_LOG ("counter = %d", *p_counter);
59 mux_pcm_audio (guint num_buffers, guint repeat)
61 GstElement *src, *sink, *flvmux, *conv, *pipeline;
62 GstPad *sinkpad, *srcpad;
65 GST_LOG ("num_buffers = %u", num_buffers);
67 pipeline = gst_pipeline_new ("pipeline");
68 fail_unless (pipeline != NULL, "Failed to create pipeline!");
70 /* kids, don't use a sync handler for this at home, really; we do because
71 * we just want to abort and nothing else */
72 gst_bus_set_sync_handler (GST_ELEMENT_BUS (pipeline), error_cb, NULL, NULL);
74 src = gst_element_factory_make ("audiotestsrc", "audiotestsrc");
75 fail_unless (src != NULL, "Failed to create 'audiotestsrc' element!");
77 g_object_set (src, "num-buffers", num_buffers, NULL);
79 conv = gst_element_factory_make ("audioconvert", "audioconvert");
80 fail_unless (conv != NULL, "Failed to create 'audioconvert' element!");
82 flvmux = gst_element_factory_make ("flvmux", "flvmux");
83 fail_unless (flvmux != NULL, "Failed to create 'flvmux' element!");
85 sink = gst_element_factory_make ("fakesink", "fakesink");
86 fail_unless (sink != NULL, "Failed to create 'fakesink' element!");
88 g_object_set (sink, "signal-handoffs", TRUE, NULL);
89 g_signal_connect (sink, "handoff", G_CALLBACK (handoff_cb), &counter);
91 gst_bin_add_many (GST_BIN (pipeline), src, conv, flvmux, sink, NULL);
93 fail_unless (gst_element_link (src, conv));
94 fail_unless (gst_element_link (flvmux, sink));
96 /* now link the elements */
97 sinkpad = gst_element_get_request_pad (flvmux, "audio");
98 fail_unless (sinkpad != NULL, "Could not get audio request pad");
100 srcpad = gst_element_get_static_pad (conv, "src");
101 fail_unless (srcpad != NULL, "Could not get audioconvert's source pad");
103 fail_unless_equals_int (gst_pad_link (srcpad, sinkpad), GST_PAD_LINK_OK);
105 gst_object_unref (srcpad);
106 gst_object_unref (sinkpad);
109 GstStateChangeReturn state_ret;
112 GST_LOG ("repeat=%d", repeat);
116 state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
117 fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);
119 if (state_ret == GST_STATE_CHANGE_ASYNC) {
120 GST_LOG ("waiting for pipeline to reach PAUSED state");
121 state_ret = gst_element_get_state (pipeline, NULL, NULL, -1);
122 fail_unless_equals_int (state_ret, GST_STATE_CHANGE_SUCCESS);
125 GST_LOG ("PAUSED, let's do the rest of it");
127 state_ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
128 fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);
130 msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), GST_MESSAGE_EOS, -1);
131 fail_unless (msg != NULL, "Expected EOS message on bus!");
134 gst_message_unref (msg);
136 /* should have some output */
137 fail_unless (counter > 2);
139 fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
140 GST_STATE_CHANGE_SUCCESS);
142 /* repeat = test re-usability */
144 } while (repeat > 0);
146 gst_object_unref (pipeline);
149 GST_START_TEST (test_index_writing)
151 /* note: there's a magic 128 value in flvmux when doing index writing */
152 mux_pcm_audio (__i__ * 33 + 1, 2);
158 create_buffer (guint8 * data, gsize size,
159 GstClockTime timestamp, GstClockTime duration)
161 GstBuffer *buf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
162 data, size, 0, size, NULL, NULL);
163 GST_BUFFER_PTS (buf) = timestamp;
164 GST_BUFFER_DTS (buf) = timestamp;
165 GST_BUFFER_DURATION (buf) = duration;
166 GST_BUFFER_OFFSET (buf) = 0;
167 GST_BUFFER_OFFSET_END (buf) = 0;
171 guint8 speex_hdr0[] = {
172 0x53, 0x70, 0x65, 0x65, 0x78, 0x20, 0x20, 0x20,
173 0x31, 0x2e, 0x32, 0x72, 0x63, 0x31, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
176 0x50, 0x00, 0x00, 0x00, 0x80, 0x3e, 0x00, 0x00,
177 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
178 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
179 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
184 guint8 speex_hdr1[] = {
185 0x1f, 0x00, 0x00, 0x00, 0x45, 0x6e, 0x63, 0x6f,
186 0x64, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68,
187 0x20, 0x47, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
188 0x65, 0x72, 0x20, 0x53, 0x70, 0x65, 0x65, 0x78,
189 0x65, 0x6e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x01
192 guint8 speex_buf[] = {
193 0x36, 0x9d, 0x1b, 0x9a, 0x20, 0x00, 0x01, 0x68,
194 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0x84,
195 0x00, 0xb4, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
196 0x74, 0x42, 0x00, 0x5a, 0x3a, 0x3a, 0x3a, 0x3a,
197 0x3a, 0x3a, 0x3a, 0x21, 0x00, 0x2d, 0x1d, 0x1d,
198 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1b, 0x3b, 0x60,
199 0xab, 0xab, 0xab, 0xab, 0xab, 0x0a, 0xba, 0xba,
200 0xba, 0xba, 0xb0, 0xab, 0xab, 0xab, 0xab, 0xab,
201 0x0a, 0xba, 0xba, 0xba, 0xba, 0xb7
204 guint8 h264_buf[] = {
205 0x00, 0x00, 0x00, 0x0b, 0x67, 0x42, 0xc0, 0x0c,
206 0x95, 0xa7, 0x20, 0x1e, 0x11, 0x08, 0xd4, 0x00,
207 0x00, 0x00, 0x04, 0x68, 0xce, 0x3c, 0x80, 0x00,
208 0x00, 0x00, 0x55, 0x65, 0xb8, 0x04, 0x0e, 0x7e,
209 0x1f, 0x22, 0x60, 0x34, 0x01, 0xe2, 0x00, 0x3c,
210 0xe1, 0xfc, 0x91, 0x40, 0xa6, 0x9e, 0x07, 0x42,
211 0x56, 0x44, 0x73, 0x75, 0x40, 0x9f, 0x0c, 0x87,
212 0x83, 0xc9, 0x52, 0x60, 0x6d, 0xd8, 0x98, 0x01,
213 0x16, 0xbd, 0x0f, 0xa6, 0xaf, 0x75, 0x83, 0xdd,
214 0xfa, 0xe7, 0x8f, 0xe3, 0x58, 0x10, 0x0f, 0x5c,
215 0x18, 0x2f, 0x41, 0x40, 0x23, 0x0b, 0x03, 0x70,
216 0x00, 0xff, 0xe4, 0xa6, 0x7d, 0x7f, 0x3f, 0x76,
217 0x01, 0xd0, 0x98, 0x2a, 0x0c, 0xb8, 0x02, 0x32,
218 0xbc, 0x56, 0xfd, 0x34, 0x4f, 0xcf, 0xfe, 0xa0,
221 GST_START_TEST (test_speex_streamable)
224 GstMapInfo map = GST_MAP_INFO_INIT;
227 GstCaps *caps = gst_caps_new_simple ("audio/x-speex",
228 "rate", G_TYPE_INT, 16000,
229 "channels", G_TYPE_INT, 1,
232 const GstClockTime base_time = 123456789;
233 const GstClockTime duration_ms = 20;
234 const GstClockTime duration = duration_ms * GST_MSECOND;
236 GstHarness *h = gst_harness_new_with_padnames ("flvmux", "audio", "src");
237 gst_harness_set_src_caps (h, caps);
238 g_object_set (h->element, "streamable", 1, NULL);
240 /* push speex header0 */
241 gst_harness_push (h, create_buffer (speex_hdr0,
242 sizeof (speex_hdr0), base_time, 0));
244 /* push speex header1 */
245 gst_harness_push (h, create_buffer (speex_hdr1,
246 sizeof (speex_hdr1), base_time, 0));
248 /* push speex data */
249 gst_harness_push (h, create_buffer (speex_buf,
250 sizeof (speex_buf), base_time, duration));
252 /* push speex data 2 */
253 gst_harness_push (h, create_buffer (speex_buf,
254 sizeof (speex_buf), base_time + duration, duration));
256 /* pull out stream-start event */
257 gst_event_unref (gst_harness_pull_event (h));
259 /* pull out caps event */
260 gst_event_unref (gst_harness_pull_event (h));
262 /* pull out segment event and verify we are using GST_FORMAT_TIME */
264 GstEvent *event = gst_harness_pull_event (h);
265 const GstSegment *segment;
266 gst_event_parse_segment (event, &segment);
267 fail_unless_equals_int (GST_FORMAT_TIME, segment->format);
268 gst_event_unref (event);
271 /* pull FLV header buffer */
272 buf = gst_harness_pull (h);
273 gst_buffer_unref (buf);
275 /* pull Metadata buffer */
276 buf = gst_harness_pull (h);
277 gst_buffer_unref (buf);
280 buf = gst_harness_pull (h);
281 fail_unless_equals_uint64 (base_time, GST_BUFFER_PTS (buf));
282 fail_unless_equals_uint64 (GST_CLOCK_TIME_NONE, GST_BUFFER_DTS (buf));
283 fail_unless_equals_uint64 (0, GST_BUFFER_DURATION (buf));
284 gst_buffer_map (buf, &map, GST_MAP_READ);
285 /* 0x08 means it is audio */
286 fail_unless_equals_int (0x08, map.data[0]);
287 /* timestamp should be starting from 0 */
288 fail_unless_equals_int (0x00, map.data[6]);
289 /* 0xb2 means Speex, 16000Hz, Mono */
290 fail_unless_equals_int (0xb2, map.data[11]);
291 /* verify content is intact */
292 fail_unless_equals_int (0, memcmp (&map.data[12], speex_hdr0,
293 sizeof (speex_hdr0)));
294 gst_buffer_unmap (buf, &map);
295 gst_buffer_unref (buf);
298 buf = gst_harness_pull (h);
299 fail_unless_equals_uint64 (base_time, GST_BUFFER_PTS (buf));
300 fail_unless_equals_uint64 (GST_CLOCK_TIME_NONE, GST_BUFFER_DTS (buf));
301 fail_unless_equals_uint64 (0, GST_BUFFER_DURATION (buf));
302 gst_buffer_map (buf, &map, GST_MAP_READ);
303 /* 0x08 means it is audio */
304 fail_unless_equals_int (0x08, map.data[0]);
305 /* timestamp should be starting from 0 */
306 fail_unless_equals_int (0x00, map.data[6]);
307 /* 0xb2 means Speex, 16000Hz, Mono */
308 fail_unless_equals_int (0xb2, map.data[11]);
309 /* verify content is intact */
310 fail_unless_equals_int (0, memcmp (&map.data[12], speex_hdr1,
311 sizeof (speex_hdr1)));
312 gst_buffer_unmap (buf, &map);
313 gst_buffer_unref (buf);
316 buf = gst_harness_pull (h);
317 fail_unless_equals_uint64 (base_time, GST_BUFFER_PTS (buf));
318 fail_unless_equals_uint64 (GST_CLOCK_TIME_NONE, GST_BUFFER_DTS (buf));
319 fail_unless_equals_uint64 (duration, GST_BUFFER_DURATION (buf));
320 fail_unless_equals_uint64 (GST_BUFFER_OFFSET_NONE, GST_BUFFER_OFFSET (buf));
321 fail_unless_equals_uint64 (GST_BUFFER_OFFSET_NONE,
322 GST_BUFFER_OFFSET_END (buf));
323 gst_buffer_map (buf, &map, GST_MAP_READ);
324 /* 0x08 means it is audio */
325 fail_unless_equals_int (0x08, map.data[0]);
326 /* timestamp should be starting from 0 */
327 fail_unless_equals_int (0x00, map.data[6]);
328 /* 0xb2 means Speex, 16000Hz, Mono */
329 fail_unless_equals_int (0xb2, map.data[11]);
330 /* verify content is intact */
331 fail_unless_equals_int (0, memcmp (&map.data[12], speex_buf,
332 sizeof (speex_buf)));
333 gst_buffer_unmap (buf, &map);
334 gst_buffer_unref (buf);
337 buf = gst_harness_pull (h);
338 fail_unless_equals_uint64 (base_time + duration, GST_BUFFER_PTS (buf));
339 fail_unless_equals_uint64 (GST_CLOCK_TIME_NONE, GST_BUFFER_DTS (buf));
340 fail_unless_equals_uint64 (duration, GST_BUFFER_DURATION (buf));
341 fail_unless_equals_uint64 (GST_BUFFER_OFFSET_NONE, GST_BUFFER_OFFSET (buf));
342 fail_unless_equals_uint64 (GST_BUFFER_OFFSET_NONE,
343 GST_BUFFER_OFFSET_END (buf));
344 gst_buffer_map (buf, &map, GST_MAP_READ);
345 /* 0x08 means it is audio */
346 fail_unless_equals_int (0x08, map.data[0]);
347 /* timestamp should reflect the duration_ms */
348 fail_unless_equals_int (duration_ms, map.data[6]);
349 /* 0xb2 means Speex, 16000Hz, Mono */
350 fail_unless_equals_int (0xb2, map.data[11]);
351 /* verify content is intact */
352 fail_unless_equals_int (0, memcmp (&map.data[12], speex_buf,
353 sizeof (speex_buf)));
354 gst_buffer_unmap (buf, &map);
355 gst_buffer_unref (buf);
357 gst_harness_teardown (h);
363 check_buf_type_timestamp (GstBuffer * buf, gint packet_type, gint timestamp)
365 GstMapInfo map = GST_MAP_INFO_INIT;
366 gst_buffer_map (buf, &map, GST_MAP_READ);
367 fail_unless_equals_int (packet_type, map.data[0]);
368 fail_unless_equals_int (timestamp, map.data[6]);
369 gst_buffer_unmap (buf, &map);
370 gst_buffer_unref (buf);
373 GST_START_TEST (test_increasing_timestamp_when_pts_none)
375 const gint AUDIO = 0x08;
376 const gint VIDEO = 0x09;
378 GstClockTime base_time = 42 * GST_SECOND;
379 GstPad *audio_sink, *video_sink, *audio_src, *video_src;
380 GstHarness *h, *audio, *video, *audio_q, *video_q;
381 GstCaps *audio_caps, *video_caps;
384 h = gst_harness_new_with_padnames ("flvmux", NULL, "src");
385 audio = gst_harness_new_with_element (h->element, "audio", NULL);
386 video = gst_harness_new_with_element (h->element, "video", NULL);
387 audio_q = gst_harness_new ("queue");
388 video_q = gst_harness_new ("queue");
390 audio_sink = GST_PAD_PEER (audio->srcpad);
391 video_sink = GST_PAD_PEER (video->srcpad);
392 audio_src = GST_PAD_PEER (audio_q->sinkpad);
393 video_src = GST_PAD_PEER (video_q->sinkpad);
395 gst_pad_unlink (audio->srcpad, audio_sink);
396 gst_pad_unlink (video->srcpad, video_sink);
397 gst_pad_unlink (audio_src, audio_q->sinkpad);
398 gst_pad_unlink (video_src, video_q->sinkpad);
399 gst_pad_link (audio_src, audio_sink);
400 gst_pad_link (video_src, video_sink);
402 audio_caps = gst_caps_new_simple ("audio/x-speex",
403 "rate", G_TYPE_INT, 16000, "channels", G_TYPE_INT, 1, NULL);
404 gst_harness_set_src_caps (audio_q, audio_caps);
405 video_caps = gst_caps_new_simple ("video/x-h264",
406 "stream-format", G_TYPE_STRING, "avc", NULL);
407 gst_harness_set_src_caps (video_q, video_caps);
409 /* Push audio + video + audio with increasing DTS, but PTS for video is
410 * GST_CLOCK_TIME_NONE
412 buf = gst_buffer_new ();
413 GST_BUFFER_DTS (buf) = timestamp * GST_MSECOND + base_time;
414 GST_BUFFER_PTS (buf) = timestamp * GST_MSECOND + base_time;
415 gst_harness_push (audio_q, buf);
417 buf = gst_buffer_new ();
418 GST_BUFFER_DTS (buf) = (timestamp + 1) * GST_MSECOND + base_time;
419 GST_BUFFER_PTS (buf) = GST_CLOCK_TIME_NONE;
420 gst_harness_push (video_q, buf);
422 buf = gst_buffer_new ();
423 GST_BUFFER_DTS (buf) = (timestamp + 2) * GST_MSECOND + base_time;
424 GST_BUFFER_PTS (buf) = (timestamp + 2) * GST_MSECOND + base_time;
425 gst_harness_push (audio_q, buf);
427 /* Pull two metadata packets out */
428 gst_buffer_unref (gst_harness_pull (h));
429 gst_buffer_unref (gst_harness_pull (h));
431 /* Check that we receive the packets in monotonically increasing order and
432 * that their timestamps are correct (should start at 0)
434 buf = gst_harness_pull (h);
435 check_buf_type_timestamp (buf, AUDIO, 0);
436 buf = gst_harness_pull (h);
437 check_buf_type_timestamp (buf, VIDEO, 1);
440 gst_harness_teardown (h);
441 gst_harness_teardown (audio);
442 gst_harness_teardown (video);
443 gst_harness_teardown (audio_q);
444 gst_harness_teardown (video_q);
456 flvdemux_pad_added (GstElement * flvdemux, GstPad * srcpad, DemuxHarnesses * h)
458 GstCaps *caps = gst_pad_get_current_caps (srcpad);
459 const gchar *name = gst_structure_get_name (gst_caps_get_structure (caps, 0));
461 if (g_ascii_strncasecmp ("audio", name, 5) == 0)
462 gst_harness_add_element_src_pad (h->a_sink, srcpad);
464 gst_harness_add_element_src_pad (h->v_sink, srcpad);
466 gst_caps_unref (caps);
469 GST_START_TEST (test_video_caps_late)
471 GstHarness *mux = gst_harness_new_with_padnames ("flvmux", NULL, "src");
473 gst_harness_new_with_element (mux->element, "audio", NULL);
475 gst_harness_new_with_element (mux->element, "video", NULL);
476 GstHarness *demux = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
478 gst_harness_new_with_element (demux->element, NULL, NULL);
480 gst_harness_new_with_element (demux->element, NULL, NULL);
481 DemuxHarnesses harnesses = { a_sink, v_sink };
483 GstTestClock *tclock;
485 g_object_set (mux->element, "streamable", TRUE,
486 "latency", G_GUINT64_CONSTANT (1), NULL);
487 gst_harness_use_testclock (mux);
489 g_signal_connect (demux->element, "pad-added",
490 G_CALLBACK (flvdemux_pad_added), &harnesses);
491 gst_harness_add_sink_harness (mux, demux);
493 gst_harness_set_src_caps_str (a_src,
494 "audio/x-speex, rate=(int)16000, channels=(int)1");
496 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (a_src,
497 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
498 speex_hdr0, sizeof (speex_hdr0), 0, sizeof (speex_hdr0), NULL,
501 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (a_src,
502 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
503 speex_hdr1, sizeof (speex_hdr1), 0, sizeof (speex_hdr1), NULL,
506 /* Wait a little and make sure no clock was scheduled as this shouldn't happen
507 * before the caps are set */
508 g_usleep (40 * 1000);
509 tclock = gst_harness_get_testclock (mux);
510 fail_unless (gst_test_clock_get_next_entry_time (tclock) ==
511 GST_CLOCK_TIME_NONE);
513 gst_harness_set_src_caps_str (v_src,
514 "video/x-h264, stream-format=(string)avc, alignment=(string)au, "
515 "codec_data=(buffer)0142c00cffe1000b6742c00c95a7201e1108d401000468ce3c80");
517 gst_harness_crank_single_clock_wait (mux);
519 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (a_src,
520 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
521 speex_buf, sizeof (speex_buf), 0, sizeof (speex_buf), NULL,
524 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (v_src,
525 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
526 h264_buf, sizeof (h264_buf), 0, sizeof (h264_buf), NULL, NULL)));
528 gst_harness_crank_single_clock_wait (mux);
529 gst_harness_crank_single_clock_wait (mux);
530 gst_harness_crank_single_clock_wait (mux);
533 /* push from flvmux to demux */
534 for (i = 0; i < 6; i++)
535 gst_harness_push_to_sink (mux);
537 /* verify we got 2x audio and 1x video buffers out of flvdemux */
538 gst_buffer_unref (gst_harness_pull (a_sink));
539 gst_buffer_unref (gst_harness_pull (a_sink));
540 gst_buffer_unref (gst_harness_pull (v_sink));
542 fail_unless (gst_test_clock_get_next_entry_time (tclock) ==
543 GST_CLOCK_TIME_NONE);
545 g_clear_object (&tclock);
546 gst_harness_teardown (a_src);
547 gst_harness_teardown (v_src);
548 gst_harness_teardown (mux);
549 gst_harness_teardown (a_sink);
550 gst_harness_teardown (v_sink);
555 guint8 raw_frame_short[] = {
556 0x27, 0x00, 0x03, 0x20, 0x64, 0x1c
559 GST_START_TEST (test_video_caps_change_streamable)
562 GstCaps *a_caps1, *v_caps1, *v_caps2, *ret_caps;
563 GstHarness *mux = gst_harness_new_with_padnames ("flvmux", NULL, "src");
565 gst_harness_new_with_element (mux->element, "audio", NULL);
567 gst_harness_new_with_element (mux->element, "video", NULL);
568 GstHarness *demux = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
570 gst_harness_new_with_element (demux->element, NULL, NULL);
572 gst_harness_new_with_element (demux->element, NULL, NULL);
573 DemuxHarnesses harnesses = { a_sink, v_sink };
576 const GstClockTime base_time = 123456789;
577 const GstClockTime duration_ms = 20;
578 const GstClockTime duration = duration_ms * GST_MSECOND;
580 g_object_set (mux->element, "streamable", TRUE, NULL);
582 g_signal_connect (demux->element, "pad-added",
583 G_CALLBACK (flvdemux_pad_added), &harnesses);
584 gst_harness_add_sink_harness (mux, demux);
588 ("audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, "
589 "rate=(int)44100, channels=(int)1, codec_data=(buffer)1208");
591 v_caps1 = gst_caps_from_string ("video/x-h264, stream-format=(string)avc, "
592 "codec_data=(buffer)0142c00cffe1000b6742c00c95a7201e1108d401000468ce3c80");
594 gst_harness_set_src_caps (a_src, gst_caps_ref (a_caps1));
595 gst_harness_set_src_caps (v_src, gst_caps_ref (v_caps1));
597 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (a_src,
598 create_buffer (raw_frame_short, sizeof (raw_frame_short), base_time,
601 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (v_src,
602 create_buffer (h264_buf, sizeof (h264_buf), base_time, duration)));
604 gst_harness_crank_single_clock_wait (mux);
606 /* push from flvmux to demux */
607 for (i = 0; i < 6; i++) {
608 gst_harness_push_to_sink (mux);
611 /* should accept without the constraint */
612 while ((event = gst_harness_try_pull_event (v_sink))) {
613 if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
614 gst_event_parse_caps (event, &ret_caps);
615 GST_LOG ("v_caps1 %" GST_PTR_FORMAT ", ret caps %" GST_PTR_FORMAT,
617 fail_unless (gst_caps_is_equal (v_caps1, ret_caps));
619 gst_event_unref (event);
623 v_caps2 = gst_caps_from_string ("video/x-h264, stream-format=(string)avc, "
624 "codec_data=(buffer)0164001fffe1001c6764001facd9405005bb016a02020280000003008000001e478c18cb01000568ebecb22c");
626 gst_harness_set_src_caps (v_src, gst_caps_ref (v_caps2));
628 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (v_src,
629 create_buffer (h264_buf, sizeof (h264_buf), base_time + duration,
632 gst_harness_crank_single_clock_wait (mux);
634 /* push from flvmux to demux */
635 for (i = 0; i < 2; i++) {
636 gst_harness_push_to_sink (mux);
639 /* should accept without the constraint */
640 while ((event = gst_harness_try_pull_event (v_sink))) {
641 if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
642 gst_event_parse_caps (event, &ret_caps);
643 GST_LOG ("v_caps2 %" GST_PTR_FORMAT ", ret caps %" GST_PTR_FORMAT,
645 fail_unless (gst_caps_is_equal (v_caps2, ret_caps));
647 gst_event_unref (event);
650 /* verify we got 1x audio and 2x video buffers out of flvdemux */
651 gst_buffer_unref (gst_harness_pull (a_sink));
652 gst_buffer_unref (gst_harness_pull (v_sink));
653 gst_buffer_unref (gst_harness_pull (v_sink));
654 gst_caps_unref (a_caps1);
655 gst_caps_unref (v_caps1);
656 gst_caps_unref (v_caps2);
658 gst_harness_teardown (a_src);
659 gst_harness_teardown (v_src);
660 gst_harness_teardown (mux);
661 gst_harness_teardown (a_sink);
662 gst_harness_teardown (v_sink);
667 GST_START_TEST (test_audio_caps_change_streamable)
670 GstCaps *a_caps1, *a_caps2, *v_caps1, *ret_caps;
671 GstHarness *mux = gst_harness_new_with_padnames ("flvmux", NULL, "src");
673 gst_harness_new_with_element (mux->element, "audio", NULL);
675 gst_harness_new_with_element (mux->element, "video", NULL);
676 GstHarness *demux = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
678 gst_harness_new_with_element (demux->element, NULL, NULL);
680 gst_harness_new_with_element (demux->element, NULL, NULL);
681 DemuxHarnesses harnesses = { a_sink, v_sink };
684 const GstClockTime base_time = 123456789;
685 const GstClockTime duration_ms = 20;
686 const GstClockTime duration = duration_ms * GST_MSECOND;
688 g_object_set (mux->element, "streamable", TRUE, NULL);
690 g_signal_connect (demux->element, "pad-added",
691 G_CALLBACK (flvdemux_pad_added), &harnesses);
692 gst_harness_add_sink_harness (mux, demux);
696 ("audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, "
697 "rate=(int)44100, channels=(int)1, codec_data=(buffer)1208");
699 v_caps1 = gst_caps_from_string ("video/x-h264, stream-format=(string)avc, "
700 "codec_data=(buffer)0142c00cffe1000b6742c00c95a7201e1108d401000468ce3c80");
702 gst_harness_set_src_caps (a_src, gst_caps_ref (a_caps1));
703 gst_harness_set_src_caps (v_src, gst_caps_ref (v_caps1));
705 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (a_src,
706 create_buffer (raw_frame_short, sizeof (raw_frame_short), base_time,
709 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (v_src,
710 create_buffer (h264_buf, sizeof (h264_buf), base_time, duration)));
712 gst_harness_crank_single_clock_wait (mux);
714 /* push from flvmux to demux */
715 for (i = 0; i < 6; i++) {
716 gst_harness_push_to_sink (mux);
719 /* should accept without the constraint */
720 while ((event = gst_harness_try_pull_event (a_sink))) {
721 if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
722 gst_event_parse_caps (event, &ret_caps);
723 GST_LOG ("a_caps1 %" GST_PTR_FORMAT ", ret caps %" GST_PTR_FORMAT,
725 fail_unless (gst_caps_is_equal (a_caps1, ret_caps));
727 gst_event_unref (event);
733 ("audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, "
734 "rate=(int)22050, channels=(int)1, codec_data=(buffer)1388");
736 gst_harness_set_src_caps (a_src, gst_caps_ref (a_caps2));
738 fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (a_src,
739 create_buffer (raw_frame_short, sizeof (raw_frame_short),
740 base_time + duration, duration)));
742 gst_harness_crank_single_clock_wait (mux);
744 /* push from flvmux to demux */
745 for (i = 0; i < 2; i++) {
746 gst_harness_push_to_sink (mux);
749 /* should accept without the constraint */
750 while ((event = gst_harness_try_pull_event (a_sink))) {
751 if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
752 gst_event_parse_caps (event, &ret_caps);
753 GST_LOG ("a_caps2 %" GST_PTR_FORMAT ", ret caps %" GST_PTR_FORMAT,
755 fail_unless (gst_caps_is_equal (a_caps2, ret_caps));
757 gst_event_unref (event);
760 /* verify we got 2x audio and 1x video buffers out of flvdemux */
761 gst_buffer_unref (gst_harness_pull (a_sink));
762 gst_buffer_unref (gst_harness_pull (a_sink));
763 gst_buffer_unref (gst_harness_pull (v_sink));
764 gst_caps_unref (a_caps1);
765 gst_caps_unref (a_caps2);
766 gst_caps_unref (v_caps1);
768 gst_harness_teardown (a_src);
769 gst_harness_teardown (v_src);
770 gst_harness_teardown (mux);
771 gst_harness_teardown (a_sink);
772 gst_harness_teardown (v_sink);
780 Suite *s = suite_create ("flvmux");
781 TCase *tc_chain = tcase_create ("general");
784 suite_add_tcase (s, tc_chain);
787 if (RUNNING_ON_VALGRIND) {
792 tcase_add_loop_test (tc_chain, test_index_writing, 0, loop);
794 tcase_add_test (tc_chain, test_speex_streamable);
795 tcase_add_test (tc_chain, test_increasing_timestamp_when_pts_none);
796 tcase_add_test (tc_chain, test_video_caps_late);
797 tcase_add_test (tc_chain, test_audio_caps_change_streamable);
798 tcase_add_test (tc_chain, test_video_caps_change_streamable);
803 GST_CHECK_MAIN (flvmux)