tests: videorate: remove obsolete color-matrix caps field
[platform/upstream/gstreamer.git] / tests / check / elements / decodebin2.c
1 /* GStreamer unit tests for decodebin2
2  *
3  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
4  * Copyright (C) 2011 Hewlett-Packard Development Company, L.P.
5  *   Author: Tim-Philipp Müller <tim.muller@collabora.co.uk>, Collabora Ltd.
6  *           Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #include <gst/check/gstcheck.h>
29 #include <gst/base/gstbaseparse.h>
30 #include <unistd.h>
31
32 static const gchar dummytext[] =
33     "Quick Brown Fox Jumps over a Lazy Frog Quick Brown "
34     "Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick "
35     "Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog "
36     "Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy "
37     "Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a "
38     "Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps "
39     "over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox "
40     "jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown "
41     "Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick "
42     "Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog "
43     "Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy "
44     "Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a "
45     "Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps "
46     "over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox ";
47
48 static void
49 src_handoff_cb (GstElement * src, GstBuffer * buf, GstPad * pad, gpointer data)
50 {
51   GST_BUFFER_DATA (buf) = (guint8 *) dummytext;
52   GST_BUFFER_SIZE (buf) = sizeof (dummytext);
53   GST_BUFFER_OFFSET (buf) = 0;
54   GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
55 }
56
57 static void
58 decodebin_new_decoded_pad_cb (GstElement * decodebin, GstPad * pad,
59     gboolean last, gboolean * p_flag)
60 {
61   /* we should not be reached */
62   fail_unless (decodebin == NULL, "new-decoded-pad should not be emitted");
63 }
64
65 /* make sure that decodebin errors out instead of creating a new decoded pad
66  * if the entire stream is a plain text file */
67 GST_START_TEST (test_text_plain_streams)
68 {
69   GstElement *pipe, *src, *decodebin;
70   GstMessage *msg;
71
72   pipe = gst_pipeline_new (NULL);
73   fail_unless (pipe != NULL, "failed to create pipeline");
74
75   src = gst_element_factory_make ("fakesrc", "src");
76   fail_unless (src != NULL, "Failed to create fakesrc element");
77
78   g_object_set (src, "signal-handoffs", TRUE, NULL);
79   g_object_set (src, "num-buffers", 1, NULL);
80   g_object_set (src, "can-activate-pull", FALSE, NULL);
81   g_signal_connect (src, "handoff", G_CALLBACK (src_handoff_cb), NULL);
82
83   decodebin = gst_element_factory_make ("decodebin2", "decodebin");
84   fail_unless (decodebin != NULL, "Failed to create decodebin element");
85
86   g_signal_connect (decodebin, "new-decoded-pad",
87       G_CALLBACK (decodebin_new_decoded_pad_cb), NULL);
88
89   fail_unless (gst_bin_add (GST_BIN (pipe), src));
90   fail_unless (gst_bin_add (GST_BIN (pipe), decodebin));
91   fail_unless (gst_element_link (src, decodebin), "can't link src<->decodebin");
92
93   fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_READY),
94       GST_STATE_CHANGE_SUCCESS);
95   /* it's push-based, so should be async */
96   fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED),
97       GST_STATE_CHANGE_ASYNC);
98
99   /* it should error out at some point */
100   msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, -1);
101   fail_unless (msg != NULL);
102   fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);
103   gst_message_unref (msg);
104
105   gst_element_set_state (pipe, GST_STATE_NULL);
106   gst_object_unref (pipe);
107 }
108
109 GST_END_TEST;
110
111 static void
112 new_decoded_pad_plug_fakesink_cb (GstElement * decodebin, GstPad * srcpad,
113     gboolean last, GstElement * pipeline)
114 {
115   GstElement *sink;
116   GstPad *sinkpad;
117
118   GST_LOG ("Linking fakesink");
119
120   sink = gst_element_factory_make ("fakesink", "sink");
121   fail_unless (sink != NULL, "Failed to create fakesink element");
122
123   gst_bin_add (GST_BIN (pipeline), sink);
124
125   sinkpad = gst_element_get_static_pad (sink, "sink");
126   fail_unless_equals_int (gst_pad_link (srcpad, sinkpad), GST_PAD_LINK_OK);
127   gst_object_unref (sinkpad);
128
129   gst_element_set_state (sink, GST_STATE_PLAYING);
130 }
131
132 GST_START_TEST (test_reuse_without_decoders)
133 {
134   GstElement *pipe, *src, *decodebin, *sink;
135
136   pipe = gst_pipeline_new (NULL);
137   fail_unless (pipe != NULL, "failed to create pipeline");
138
139   src = gst_element_factory_make ("audiotestsrc", "src");
140   fail_unless (src != NULL, "Failed to create audiotestsrc element");
141
142   decodebin = gst_element_factory_make ("decodebin2", "decodebin");
143   fail_unless (decodebin != NULL, "Failed to create decodebin element");
144
145   g_signal_connect (decodebin, "new-decoded-pad",
146       G_CALLBACK (new_decoded_pad_plug_fakesink_cb), pipe);
147
148   fail_unless (gst_bin_add (GST_BIN (pipe), src));
149   fail_unless (gst_bin_add (GST_BIN (pipe), decodebin));
150   fail_unless (gst_element_link (src, decodebin), "can't link src<->decodebin");
151
152   fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_READY),
153       GST_STATE_CHANGE_SUCCESS);
154   /* it's push-based, so should be async */
155   fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED),
156       GST_STATE_CHANGE_ASYNC);
157
158   /* wait for state change to complete */
159   fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1),
160       GST_STATE_CHANGE_SUCCESS);
161
162   /* there shouldn't be any errors */
163   fail_if (gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, 0) != NULL);
164
165   /* reset */
166   gst_element_set_state (pipe, GST_STATE_READY);
167
168   sink = gst_bin_get_by_name (GST_BIN (pipe), "sink");
169   gst_bin_remove (GST_BIN (pipe), sink);
170   gst_element_set_state (sink, GST_STATE_NULL);
171   gst_object_unref (sink);
172
173   GST_LOG ("second try");
174
175   fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_READY),
176       GST_STATE_CHANGE_SUCCESS);
177   /* it's push-based, so should be async */
178   fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED),
179       GST_STATE_CHANGE_ASYNC);
180
181   /* wait for state change to complete */
182   fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1),
183       GST_STATE_CHANGE_SUCCESS);
184
185   /* there shouldn't be any errors */
186   fail_if (gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, 0) != NULL);
187
188   gst_element_set_state (pipe, GST_STATE_NULL);
189   gst_object_unref (pipe);
190 }
191
192 GST_END_TEST;
193
194 /* Fake mp3 parser for test */
195 typedef GstBaseParse TestMpegAudioParse;
196 typedef GstBaseParseClass TestMpegAudioParseClass;
197
198 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
199     GST_PAD_SRC,
200     GST_PAD_ALWAYS,
201     GST_STATIC_CAPS ("audio/mpeg, mpegversion=1, layer=[1,3], parsed=(b)true")
202     );
203
204 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
205     GST_PAD_SINK,
206     GST_PAD_ALWAYS,
207     GST_STATIC_CAPS ("audio/mpeg, mpegversion=1, parsed=(bool) { false, true }")
208     );
209
210 static GType test_mpeg_audio_parse_get_type (void);
211 static gboolean test_mpeg_audio_parse_start (GstBaseParse * parse);
212 static gboolean test_mpeg_audio_parse_stop (GstBaseParse * parse);
213 static gboolean test_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
214     GstBaseParseFrame * frame, guint * size, gint * skipsize);
215 static GstFlowReturn test_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
216     GstBaseParseFrame * frame);
217
218 GST_BOILERPLATE (TestMpegAudioParse, test_mpeg_audio_parse, GstBaseParse,
219     GST_TYPE_BASE_PARSE);
220
221 static void
222 test_mpeg_audio_parse_base_init (gpointer klass)
223 {
224   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
225
226   gst_element_class_add_pad_template (element_class,
227       gst_static_pad_template_get (&sink_template));
228   gst_element_class_add_pad_template (element_class,
229       gst_static_pad_template_get (&src_template));
230
231   gst_element_class_set_details_simple (element_class, "MPEG1 Audio Parser",
232       "Codec/Parser/Audio", "Pretends to parse mpeg1 audio stream",
233       "Foo Bar <foo@bar.com>");
234 }
235
236 static void
237 test_mpeg_audio_parse_class_init (TestMpegAudioParseClass * klass)
238 {
239   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
240
241   parse_class->start = test_mpeg_audio_parse_start;
242   parse_class->stop = test_mpeg_audio_parse_stop;
243   parse_class->check_valid_frame = test_mpeg_audio_parse_check_valid_frame;
244   parse_class->parse_frame = test_mpeg_audio_parse_parse_frame;
245 }
246
247 static gint num_parse_instances = 0;
248
249 static void
250 test_mpeg_audio_parse_init (TestMpegAudioParse * mp3parse,
251     TestMpegAudioParseClass * klass)
252 {
253   /* catch decodebin plugging parsers in a loop early */
254   fail_unless (++num_parse_instances < 10);
255 }
256
257 static gboolean
258 test_mpeg_audio_parse_start (GstBaseParse * parse)
259 {
260   gst_base_parse_set_min_frame_size (parse, 6);
261   return TRUE;
262 }
263
264 static gboolean
265 test_mpeg_audio_parse_stop (GstBaseParse * parse)
266 {
267   return TRUE;
268 }
269
270 static gboolean
271 test_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
272     GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
273 {
274   const guint8 *data = GST_BUFFER_DATA (frame->buffer);
275
276   if ((GST_READ_UINT16_BE (data) & 0xffe0) == 0xffe0) {
277     /* this framesize is hard-coded for ../test.mp3 */
278     *framesize = 1045;
279     return TRUE;
280   } else {
281     *skipsize = 1;
282     return FALSE;
283   }
284 }
285
286 static GstFlowReturn
287 test_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
288     GstBaseParseFrame * frame)
289 {
290   if (GST_BUFFER_OFFSET (frame->buffer) == 0) {
291     GstCaps *caps;
292
293     caps = gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 1,
294         "mpegaudioversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3,
295         "rate", G_TYPE_INT, 44100, "channels", G_TYPE_INT, 2, NULL);
296     gst_buffer_set_caps (frame->buffer, caps);
297     gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
298     gst_caps_unref (caps);
299   }
300   return GST_FLOW_OK;
301 }
302
303 static gboolean
304 plugin_init (GstPlugin * plugin)
305 {
306   return gst_element_register (plugin, "testmpegaudioparse", GST_RANK_NONE,
307       test_mpeg_audio_parse_get_type ());
308 }
309
310 GST_START_TEST (test_mp3_parser_loop)
311 {
312   GstStateChangeReturn sret;
313   GstPluginFeature *feature;
314   GstMessage *msg;
315   GstElement *pipe, *src, *dec;
316   gchar *path;
317
318   num_parse_instances = 0;
319
320   gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR,
321       "fakemp3parse", "fakemp3parse", plugin_init, VERSION, "LGPL",
322       "gst-plugins-base", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
323
324   feature = gst_default_registry_find_feature ("testmpegaudioparse",
325       GST_TYPE_ELEMENT_FACTORY);
326
327   gst_plugin_feature_set_rank (feature, GST_RANK_PRIMARY + 100);
328
329   pipe = gst_pipeline_new (NULL);
330
331   src = gst_element_factory_make ("filesrc", NULL);
332   fail_unless (src != NULL);
333
334   path = g_build_filename (GST_TEST_FILES_PATH, "test.mp3", NULL);
335   g_object_set (src, "location", path, NULL);
336   g_free (path);
337
338   dec = gst_element_factory_make ("decodebin2", NULL);
339   fail_unless (dec != NULL);
340
341   gst_bin_add_many (GST_BIN (pipe), src, dec, NULL);
342   gst_element_link_many (src, dec, NULL);
343
344   sret = gst_element_set_state (pipe, GST_STATE_PLAYING);
345   fail_unless_equals_int (sret, GST_STATE_CHANGE_ASYNC);
346
347   /* wait for unlinked error */
348   msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe),
349       GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR);
350   gst_message_unref (msg);
351
352   gst_element_set_state (pipe, GST_STATE_NULL);
353   gst_object_unref (pipe);
354
355   /* make sure out parser got plugged at all though */
356   fail_unless_equals_int (num_parse_instances, 1);
357
358   /* don't want to interfere with any other of the other tests */
359   gst_plugin_feature_set_rank (feature, GST_RANK_NONE);
360   gst_object_unref (feature);
361 }
362
363 GST_END_TEST;
364
365 /* Fake parser/decoder for parser_negotiation test */
366 static GType gst_fake_h264_parser_get_type (void);
367 static GType gst_fake_h264_decoder_get_type (void);
368
369 #undef parent_class
370 #define parent_class fake_h264_parser_parent_class
371 typedef struct _GstFakeH264Parser GstFakeH264Parser;
372 typedef GstElementClass GstFakeH264ParserClass;
373
374 struct _GstFakeH264Parser
375 {
376   GstElement parent;
377 };
378
379 GST_BOILERPLATE (GstFakeH264Parser, gst_fake_h264_parser, GstElement,
380     GST_TYPE_ELEMENT);
381
382 static void
383 gst_fake_h264_parser_base_init (gpointer klass)
384 {
385   static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
386       GST_PAD_SINK, GST_PAD_ALWAYS,
387       GST_STATIC_CAPS ("video/x-h264"));
388   static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
389       GST_PAD_SRC, GST_PAD_ALWAYS,
390       GST_STATIC_CAPS ("video/x-h264, "
391           "stream-format=(string) { avc, byte-stream }"));
392   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
393
394   gst_element_class_add_pad_template (element_class,
395       gst_static_pad_template_get (&sink_templ));
396   gst_element_class_add_pad_template (element_class,
397       gst_static_pad_template_get (&src_templ));
398   gst_element_class_set_details_simple (element_class,
399       "FakeH264Parser", "Codec/Parser/Converter/Video", "yep", "me");
400 }
401
402 static void
403 gst_fake_h264_parser_class_init (GstFakeH264ParserClass * klass)
404 {
405 }
406
407 static gboolean
408 gst_fake_h264_parser_sink_setcaps (GstPad * pad, GstCaps * caps)
409 {
410   GstElement *self = GST_ELEMENT (gst_pad_get_parent (pad));
411   GstPad *otherpad = gst_element_get_static_pad (self, "src");
412   GstCaps *accepted_caps;
413   GstStructure *s;
414   const gchar *stream_format;
415
416   accepted_caps = gst_pad_get_allowed_caps (otherpad);
417   accepted_caps = gst_caps_truncate (accepted_caps);
418
419   s = gst_caps_get_structure (accepted_caps, 0);
420   stream_format = gst_structure_get_string (s, "stream-format");
421   if (!stream_format)
422     gst_structure_set (s, "stream-format", G_TYPE_STRING, "avc", NULL);
423
424   gst_pad_set_caps (otherpad, accepted_caps);
425   gst_caps_unref (accepted_caps);
426
427   gst_object_unref (otherpad);
428   gst_object_unref (self);
429
430   return TRUE;
431 }
432
433 static GstFlowReturn
434 gst_fake_h264_parser_sink_chain (GstPad * pad, GstBuffer * buf)
435 {
436   GstElement *self = GST_ELEMENT (gst_pad_get_parent (pad));
437   GstPad *otherpad = gst_element_get_static_pad (self, "src");
438   GstFlowReturn ret = GST_FLOW_OK;
439
440   buf = gst_buffer_make_metadata_writable (buf);
441   gst_buffer_set_caps (buf, GST_PAD_CAPS (otherpad));
442
443   ret = gst_pad_push (otherpad, buf);
444
445   gst_object_unref (otherpad);
446   gst_object_unref (self);
447
448   return ret;
449 }
450
451 static void
452 gst_fake_h264_parser_init (GstFakeH264Parser * self,
453     GstFakeH264ParserClass * klass)
454 {
455   GstPad *pad;
456
457   pad =
458       gst_pad_new_from_template (gst_element_class_get_pad_template
459       (GST_ELEMENT_GET_CLASS (self), "sink"), "sink");
460   gst_pad_set_setcaps_function (pad, gst_fake_h264_parser_sink_setcaps);
461   gst_pad_set_chain_function (pad, gst_fake_h264_parser_sink_chain);
462   gst_element_add_pad (GST_ELEMENT (self), pad);
463
464   pad =
465       gst_pad_new_from_template (gst_element_class_get_pad_template
466       (GST_ELEMENT_GET_CLASS (self), "src"), "src");
467   gst_element_add_pad (GST_ELEMENT (self), pad);
468 }
469
470 #undef parent_class
471 #define parent_class fake_h264_decoder_parent_class
472 typedef struct _GstFakeH264Decoder GstFakeH264Decoder;
473 typedef GstElementClass GstFakeH264DecoderClass;
474
475 struct _GstFakeH264Decoder
476 {
477   GstElement parent;
478 };
479
480 GST_BOILERPLATE (GstFakeH264Decoder, gst_fake_h264_decoder, GstElement,
481     GST_TYPE_ELEMENT);
482
483 static void
484 gst_fake_h264_decoder_base_init (gpointer klass)
485 {
486   static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
487       GST_PAD_SINK, GST_PAD_ALWAYS,
488       GST_STATIC_CAPS ("video/x-h264, " "stream-format=(string) byte-stream"));
489   static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
490       GST_PAD_SRC, GST_PAD_ALWAYS,
491       GST_STATIC_CAPS ("video/x-raw"));
492   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
493
494   gst_element_class_add_pad_template (element_class,
495       gst_static_pad_template_get (&sink_templ));
496   gst_element_class_add_pad_template (element_class,
497       gst_static_pad_template_get (&src_templ));
498   gst_element_class_set_details_simple (element_class,
499       "FakeH264Decoder", "Codec/Decoder/Video", "yep", "me");
500 }
501
502 static void
503 gst_fake_h264_decoder_class_init (GstFakeH264DecoderClass * klass)
504 {
505 }
506
507 static gboolean
508 gst_fake_h264_decoder_sink_setcaps (GstPad * pad, GstCaps * caps)
509 {
510   GstElement *self = GST_ELEMENT (gst_pad_get_parent (pad));
511   GstPad *otherpad = gst_element_get_static_pad (self, "src");
512
513   caps = gst_caps_new_simple ("video/x-raw", NULL);
514   gst_pad_set_caps (otherpad, caps);
515   gst_caps_unref (caps);
516
517   gst_object_unref (otherpad);
518   gst_object_unref (self);
519
520   return TRUE;
521 }
522
523 static GstFlowReturn
524 gst_fake_h264_decoder_sink_chain (GstPad * pad, GstBuffer * buf)
525 {
526   GstElement *self = GST_ELEMENT (gst_pad_get_parent (pad));
527   GstPad *otherpad = gst_element_get_static_pad (self, "src");
528   GstFlowReturn ret = GST_FLOW_OK;
529
530   buf = gst_buffer_make_metadata_writable (buf);
531   gst_buffer_set_caps (buf, GST_PAD_CAPS (otherpad));
532
533   ret = gst_pad_push (otherpad, buf);
534
535   gst_object_unref (otherpad);
536   gst_object_unref (self);
537
538   return ret;
539 }
540
541 static void
542 gst_fake_h264_decoder_init (GstFakeH264Decoder * self,
543     GstFakeH264DecoderClass * klass)
544 {
545   GstPad *pad;
546
547   pad =
548       gst_pad_new_from_template (gst_element_class_get_pad_template
549       (GST_ELEMENT_GET_CLASS (self), "sink"), "sink");
550   gst_pad_set_setcaps_function (pad, gst_fake_h264_decoder_sink_setcaps);
551   gst_pad_set_chain_function (pad, gst_fake_h264_decoder_sink_chain);
552   gst_element_add_pad (GST_ELEMENT (self), pad);
553
554   pad =
555       gst_pad_new_from_template (gst_element_class_get_pad_template
556       (GST_ELEMENT_GET_CLASS (self), "src"), "src");
557   gst_element_add_pad (GST_ELEMENT (self), pad);
558 }
559
560 static void
561 parser_negotiation_pad_added_cb (GstElement * dec, GstPad * pad,
562     gpointer user_data)
563 {
564   GstBin *pipe = user_data;
565   GstElement *sink;
566   GstPad *sinkpad;
567
568   sink = gst_element_factory_make ("fakesink", NULL);
569   gst_bin_add (pipe, sink);
570   gst_element_sync_state_with_parent (sink);
571   sinkpad = gst_element_get_static_pad (sink, "sink");
572   gst_pad_link (pad, sinkpad);
573   gst_object_unref (sinkpad);
574 }
575
576 GST_START_TEST (test_parser_negotiation)
577 {
578   GstStateChangeReturn sret;
579   GstMessage *msg;
580   GstCaps *caps;
581   GstElement *pipe, *src, *filter, *dec;
582
583   gst_element_register (NULL, "fakeh264parse", GST_RANK_PRIMARY + 101,
584       gst_fake_h264_parser_get_type ());
585   gst_element_register (NULL, "fakeh264dec", GST_RANK_PRIMARY + 100,
586       gst_fake_h264_decoder_get_type ());
587
588   pipe = gst_pipeline_new (NULL);
589
590   src = gst_element_factory_make ("fakesrc", NULL);
591   fail_unless (src != NULL);
592   g_object_set (G_OBJECT (src), "num-buffers", 5, "sizetype", 2, "filltype", 2,
593       "can-activate-pull", FALSE, NULL);
594
595   filter = gst_element_factory_make ("capsfilter", NULL);
596   fail_unless (filter != NULL);
597   caps = gst_caps_from_string ("video/x-h264");
598   g_object_set (G_OBJECT (filter), "caps", caps, NULL);
599   gst_caps_unref (caps);
600
601   dec = gst_element_factory_make ("decodebin2", NULL);
602   fail_unless (dec != NULL);
603
604   g_signal_connect (dec, "pad-added",
605       G_CALLBACK (parser_negotiation_pad_added_cb), pipe);
606
607   gst_bin_add_many (GST_BIN (pipe), src, filter, dec, NULL);
608   gst_element_link_many (src, filter, dec, NULL);
609
610   sret = gst_element_set_state (pipe, GST_STATE_PLAYING);
611   fail_unless_equals_int (sret, GST_STATE_CHANGE_ASYNC);
612
613   /* wait for EOS or error */
614   msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe),
615       GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
616   fail_unless (msg != NULL);
617   fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
618   gst_message_unref (msg);
619
620   gst_element_set_state (pipe, GST_STATE_NULL);
621   gst_object_unref (pipe);
622 }
623
624 GST_END_TEST;
625
626 static Suite *
627 decodebin2_suite (void)
628 {
629   Suite *s = suite_create ("decodebin2");
630   TCase *tc_chain = tcase_create ("general");
631
632   suite_add_tcase (s, tc_chain);
633   tcase_add_test (tc_chain, test_text_plain_streams);
634   tcase_add_test (tc_chain, test_reuse_without_decoders);
635   tcase_add_test (tc_chain, test_mp3_parser_loop);
636   tcase_add_test (tc_chain, test_parser_negotiation);
637
638   return s;
639 }
640
641 GST_CHECK_MAIN (decodebin2);