dec83fbd7edf6114433b992bd449c2dcd745edb9
[platform/upstream/gst-plugins-good.git] / tests / check / elements / flvmux.c
1 /* GStreamer unit tests for flvmux
2  *
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>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #ifdef HAVE_VALGRIND
28 # include <valgrind/valgrind.h>
29 #endif
30
31 #include <gst/check/gstcheck.h>
32 #include <gst/check/gstharness.h>
33
34 #include <gst/gst.h>
35
36 static GstBusSyncReply
37 error_cb (GstBus * bus, GstMessage * msg, gpointer user_data)
38 {
39   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
40     GError *err = NULL;
41     gchar *dbg = NULL;
42
43     gst_message_parse_error (msg, &err, &dbg);
44     g_error ("ERROR: %s\n%s\n", err->message, dbg);
45   }
46
47   return GST_BUS_PASS;
48 }
49
50 static void
51 handoff_cb (GstElement * element, GstBuffer * buf, GstPad * pad,
52     gint * p_counter)
53 {
54   *p_counter += 1;
55   GST_LOG ("counter = %d", *p_counter);
56 }
57
58 static void
59 mux_pcm_audio (guint num_buffers, guint repeat)
60 {
61   GstElement *src, *sink, *flvmux, *conv, *pipeline;
62   GstPad *sinkpad, *srcpad;
63   gint counter;
64
65   GST_LOG ("num_buffers = %u", num_buffers);
66
67   pipeline = gst_pipeline_new ("pipeline");
68   fail_unless (pipeline != NULL, "Failed to create pipeline!");
69
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);
73
74   src = gst_element_factory_make ("audiotestsrc", "audiotestsrc");
75   fail_unless (src != NULL, "Failed to create 'audiotestsrc' element!");
76
77   g_object_set (src, "num-buffers", num_buffers, NULL);
78
79   conv = gst_element_factory_make ("audioconvert", "audioconvert");
80   fail_unless (conv != NULL, "Failed to create 'audioconvert' element!");
81
82   flvmux = gst_element_factory_make ("flvmux", "flvmux");
83   fail_unless (flvmux != NULL, "Failed to create 'flvmux' element!");
84
85   sink = gst_element_factory_make ("fakesink", "fakesink");
86   fail_unless (sink != NULL, "Failed to create 'fakesink' element!");
87
88   g_object_set (sink, "signal-handoffs", TRUE, NULL);
89   g_signal_connect (sink, "handoff", G_CALLBACK (handoff_cb), &counter);
90
91   gst_bin_add_many (GST_BIN (pipeline), src, conv, flvmux, sink, NULL);
92
93   fail_unless (gst_element_link (src, conv));
94   fail_unless (gst_element_link (flvmux, sink));
95
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");
99
100   srcpad = gst_element_get_static_pad (conv, "src");
101   fail_unless (srcpad != NULL, "Could not get audioconvert's source pad");
102
103   fail_unless_equals_int (gst_pad_link (srcpad, sinkpad), GST_PAD_LINK_OK);
104
105   gst_object_unref (srcpad);
106   gst_object_unref (sinkpad);
107
108   do {
109     GstStateChangeReturn state_ret;
110     GstMessage *msg;
111
112     GST_LOG ("repeat=%d", repeat);
113
114     counter = 0;
115
116     state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
117     fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);
118
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);
123     }
124
125     GST_LOG ("PAUSED, let's do the rest of it");
126
127     state_ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
128     fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);
129
130     msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), GST_MESSAGE_EOS, -1);
131     fail_unless (msg != NULL, "Expected EOS message on bus!");
132
133     GST_LOG ("EOS");
134     gst_message_unref (msg);
135
136     /* should have some output */
137     fail_unless (counter > 2);
138
139     fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
140         GST_STATE_CHANGE_SUCCESS);
141
142     /* repeat = test re-usability */
143     --repeat;
144   } while (repeat > 0);
145
146   gst_object_unref (pipeline);
147 }
148
149 GST_START_TEST (test_index_writing)
150 {
151   /* note: there's a magic 128 value in flvmux when doing index writing */
152   mux_pcm_audio (__i__ * 33 + 1, 2);
153 }
154
155 GST_END_TEST;
156
157 static GstBuffer *
158 create_buffer (guint8 * data, gsize size,
159     GstClockTime timestamp, GstClockTime duration)
160 {
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;
168   return buf;
169 }
170
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
182 };
183
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
190 };
191
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
202 };
203
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,
219 };
220
221 GST_START_TEST (test_speex_streamable)
222 {
223   GstBuffer *buf;
224   GstMapInfo map = GST_MAP_INFO_INIT;
225
226
227   GstCaps *caps = gst_caps_new_simple ("audio/x-speex",
228       "rate", G_TYPE_INT, 16000,
229       "channels", G_TYPE_INT, 1,
230       NULL);
231
232   const GstClockTime base_time = 123456789;
233   const GstClockTime duration_ms = 20;
234   const GstClockTime duration = duration_ms * GST_MSECOND;
235
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);
239
240   /* push speex header0 */
241   gst_harness_push (h, create_buffer (speex_hdr0,
242           sizeof (speex_hdr0), base_time, 0));
243
244   /* push speex header1 */
245   gst_harness_push (h, create_buffer (speex_hdr1,
246           sizeof (speex_hdr1), base_time, 0));
247
248   /* push speex data */
249   gst_harness_push (h, create_buffer (speex_buf,
250           sizeof (speex_buf), base_time, duration));
251
252   /* push speex data 2 */
253   gst_harness_push (h, create_buffer (speex_buf,
254           sizeof (speex_buf), base_time + duration, duration));
255
256   /* pull out stream-start event */
257   gst_event_unref (gst_harness_pull_event (h));
258
259   /* pull out caps event */
260   gst_event_unref (gst_harness_pull_event (h));
261
262   /* pull out segment event and verify we are using GST_FORMAT_TIME */
263   {
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);
269   }
270
271   /* pull FLV header buffer */
272   buf = gst_harness_pull (h);
273   gst_buffer_unref (buf);
274
275   /* pull Metadata buffer */
276   buf = gst_harness_pull (h);
277   gst_buffer_unref (buf);
278
279   /* pull header0 */
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);
296
297   /* pull header1 */
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);
314
315   /* pull data */
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);
335
336   /* pull data */
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);
356
357   gst_harness_teardown (h);
358 }
359
360 GST_END_TEST;
361
362 static void
363 check_buf_type_timestamp (GstBuffer * buf, gint packet_type, gint timestamp)
364 {
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);
371 }
372
373 GST_START_TEST (test_increasing_timestamp_when_pts_none)
374 {
375   const gint AUDIO = 0x08;
376   const gint VIDEO = 0x09;
377   gint timestamp = 3;
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;
382   GstBuffer *buf;
383
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");
389
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);
394
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);
401
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);
408
409   /* Push audio + video + audio with increasing DTS, but PTS for video is
410    * GST_CLOCK_TIME_NONE
411    */
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);
416
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);
421
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);
426
427   /* Pull two metadata packets out */
428   gst_buffer_unref (gst_harness_pull (h));
429   gst_buffer_unref (gst_harness_pull (h));
430
431   /* Check that we receive the packets in monotonically increasing order and
432    * that their timestamps are correct (should start at 0)
433    */
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);
438
439   /* teardown */
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);
445 }
446
447 GST_END_TEST;
448
449 typedef struct
450 {
451   GstHarness *a_sink;
452   GstHarness *v_sink;
453 } DemuxHarnesses;
454
455 static void
456 flvdemux_pad_added (GstElement * flvdemux, GstPad * srcpad, DemuxHarnesses * h)
457 {
458   GstCaps *caps = gst_pad_get_current_caps (srcpad);
459   const gchar *name = gst_structure_get_name (gst_caps_get_structure (caps, 0));
460
461   if (g_ascii_strncasecmp ("audio", name, 5) == 0)
462     gst_harness_add_element_src_pad (h->a_sink, srcpad);
463   else
464     gst_harness_add_element_src_pad (h->v_sink, srcpad);
465
466   gst_caps_unref (caps);
467 }
468
469 GST_START_TEST (test_video_caps_late)
470 {
471   GstHarness *mux = gst_harness_new_with_padnames ("flvmux", NULL, "src");
472   GstHarness *a_src =
473       gst_harness_new_with_element (mux->element, "audio", NULL);
474   GstHarness *v_src =
475       gst_harness_new_with_element (mux->element, "video", NULL);
476   GstHarness *demux = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
477   GstHarness *a_sink =
478       gst_harness_new_with_element (demux->element, NULL, NULL);
479   GstHarness *v_sink =
480       gst_harness_new_with_element (demux->element, NULL, NULL);
481   DemuxHarnesses harnesses = { a_sink, v_sink };
482   guint i;
483   GstTestClock *tclock;
484
485   g_object_set (mux->element, "streamable", TRUE,
486       "latency", G_GUINT64_CONSTANT (1), NULL);
487   gst_harness_use_testclock (mux);
488
489   g_signal_connect (demux->element, "pad-added",
490       G_CALLBACK (flvdemux_pad_added), &harnesses);
491   gst_harness_add_sink_harness (mux, demux);
492
493   gst_harness_set_src_caps_str (a_src,
494       "audio/x-speex, rate=(int)16000, channels=(int)1");
495
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,
499               NULL)));
500
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,
504               NULL)));
505
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);
512
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");
516
517   gst_harness_crank_single_clock_wait (mux);
518
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,
522               NULL)));
523
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)));
527
528   gst_harness_crank_single_clock_wait (mux);
529   gst_harness_crank_single_clock_wait (mux);
530   gst_harness_crank_single_clock_wait (mux);
531
532
533   /* push from flvmux to demux */
534   for (i = 0; i < 6; i++)
535     gst_harness_push_to_sink (mux);
536
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));
541
542   fail_unless (gst_test_clock_get_next_entry_time (tclock) ==
543       GST_CLOCK_TIME_NONE);
544
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);
551 }
552
553 GST_END_TEST;
554
555 guint8 raw_frame_short[] = {
556   0x27, 0x00, 0x03, 0x20, 0x64, 0x1c
557 };
558
559 GST_START_TEST (test_video_caps_change_streamable)
560 {
561   GstEvent *event;
562   GstCaps *a_caps1, *v_caps1, *v_caps2, *ret_caps;
563   GstHarness *mux = gst_harness_new_with_padnames ("flvmux", NULL, "src");
564   GstHarness *a_src =
565       gst_harness_new_with_element (mux->element, "audio", NULL);
566   GstHarness *v_src =
567       gst_harness_new_with_element (mux->element, "video", NULL);
568   GstHarness *demux = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
569   GstHarness *a_sink =
570       gst_harness_new_with_element (demux->element, NULL, NULL);
571   GstHarness *v_sink =
572       gst_harness_new_with_element (demux->element, NULL, NULL);
573   DemuxHarnesses harnesses = { a_sink, v_sink };
574   guint i;
575
576   const GstClockTime base_time = 123456789;
577   const GstClockTime duration_ms = 20;
578   const GstClockTime duration = duration_ms * GST_MSECOND;
579
580   g_object_set (mux->element, "streamable", TRUE, NULL);
581
582   g_signal_connect (demux->element, "pad-added",
583       G_CALLBACK (flvdemux_pad_added), &harnesses);
584   gst_harness_add_sink_harness (mux, demux);
585
586   a_caps1 =
587       gst_caps_from_string
588       ("audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, "
589       "rate=(int)44100, channels=(int)1, codec_data=(buffer)1208");
590
591   v_caps1 = gst_caps_from_string ("video/x-h264, stream-format=(string)avc, "
592       "codec_data=(buffer)0142c00cffe1000b6742c00c95a7201e1108d401000468ce3c80");
593
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));
596
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,
599               duration)));
600
601   fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (v_src,
602           create_buffer (h264_buf, sizeof (h264_buf), base_time, duration)));
603
604   gst_harness_crank_single_clock_wait (mux);
605
606   /* push from flvmux to demux */
607   for (i = 0; i < 6; i++) {
608     gst_harness_push_to_sink (mux);
609   }
610
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,
616           v_caps1, ret_caps);
617       fail_unless (gst_caps_is_equal (v_caps1, ret_caps));
618     }
619     gst_event_unref (event);
620   }
621
622   /* caps change */
623   v_caps2 = gst_caps_from_string ("video/x-h264, stream-format=(string)avc, "
624       "codec_data=(buffer)0164001fffe1001c6764001facd9405005bb016a02020280000003008000001e478c18cb01000568ebecb22c");
625
626   gst_harness_set_src_caps (v_src, gst_caps_ref (v_caps2));
627
628   fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (v_src,
629           create_buffer (h264_buf, sizeof (h264_buf), base_time + duration,
630               duration)));
631
632   gst_harness_crank_single_clock_wait (mux);
633
634   /* push from flvmux to demux */
635   for (i = 0; i < 2; i++) {
636     gst_harness_push_to_sink (mux);
637   }
638
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,
644           v_caps2, ret_caps);
645       fail_unless (gst_caps_is_equal (v_caps2, ret_caps));
646     }
647     gst_event_unref (event);
648   }
649
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);
657
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);
663 }
664
665 GST_END_TEST;
666
667 GST_START_TEST (test_audio_caps_change_streamable)
668 {
669   GstEvent *event;
670   GstCaps *a_caps1, *a_caps2, *v_caps1, *ret_caps;
671   GstHarness *mux = gst_harness_new_with_padnames ("flvmux", NULL, "src");
672   GstHarness *a_src =
673       gst_harness_new_with_element (mux->element, "audio", NULL);
674   GstHarness *v_src =
675       gst_harness_new_with_element (mux->element, "video", NULL);
676   GstHarness *demux = gst_harness_new_with_padnames ("flvdemux", "sink", NULL);
677   GstHarness *a_sink =
678       gst_harness_new_with_element (demux->element, NULL, NULL);
679   GstHarness *v_sink =
680       gst_harness_new_with_element (demux->element, NULL, NULL);
681   DemuxHarnesses harnesses = { a_sink, v_sink };
682   guint i;
683
684   const GstClockTime base_time = 123456789;
685   const GstClockTime duration_ms = 20;
686   const GstClockTime duration = duration_ms * GST_MSECOND;
687
688   g_object_set (mux->element, "streamable", TRUE, NULL);
689
690   g_signal_connect (demux->element, "pad-added",
691       G_CALLBACK (flvdemux_pad_added), &harnesses);
692   gst_harness_add_sink_harness (mux, demux);
693
694   a_caps1 =
695       gst_caps_from_string
696       ("audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, "
697       "rate=(int)44100, channels=(int)1, codec_data=(buffer)1208");
698
699   v_caps1 = gst_caps_from_string ("video/x-h264, stream-format=(string)avc, "
700       "codec_data=(buffer)0142c00cffe1000b6742c00c95a7201e1108d401000468ce3c80");
701
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));
704
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,
707               duration)));
708
709   fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (v_src,
710           create_buffer (h264_buf, sizeof (h264_buf), base_time, duration)));
711
712   gst_harness_crank_single_clock_wait (mux);
713
714   /* push from flvmux to demux */
715   for (i = 0; i < 6; i++) {
716     gst_harness_push_to_sink (mux);
717   }
718
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,
724           a_caps1, ret_caps);
725       fail_unless (gst_caps_is_equal (a_caps1, ret_caps));
726     }
727     gst_event_unref (event);
728   }
729
730   /* caps change */
731   a_caps2 =
732       gst_caps_from_string
733       ("audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, "
734       "rate=(int)22050, channels=(int)1, codec_data=(buffer)1388");
735
736   gst_harness_set_src_caps (a_src, gst_caps_ref (a_caps2));
737
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)));
741
742   gst_harness_crank_single_clock_wait (mux);
743
744   /* push from flvmux to demux */
745   for (i = 0; i < 2; i++) {
746     gst_harness_push_to_sink (mux);
747   }
748
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,
754           a_caps2, ret_caps);
755       fail_unless (gst_caps_is_equal (a_caps2, ret_caps));
756     }
757     gst_event_unref (event);
758   }
759
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);
767
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);
773 }
774
775 GST_END_TEST;
776
777 static Suite *
778 flvmux_suite (void)
779 {
780   Suite *s = suite_create ("flvmux");
781   TCase *tc_chain = tcase_create ("general");
782   gint loop = 16;
783
784   suite_add_tcase (s, tc_chain);
785
786 #ifdef HAVE_VALGRIND
787   if (RUNNING_ON_VALGRIND) {
788     loop = 1;
789   }
790 #endif
791
792   tcase_add_loop_test (tc_chain, test_index_writing, 0, loop);
793
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);
799
800   return s;
801 }
802
803 GST_CHECK_MAIN (flvmux)