gstpad.c 33.3 KB
Newer Older
Wim Taymans's avatar
Wim Taymans committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/* GStreamer
 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
 *
 * gstpad.c: Unit test for GstPad
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

22
#include <gst/check/gstcheck.h>
Wim Taymans's avatar
Wim Taymans committed
23

24
GST_START_TEST (test_link)
Wim Taymans's avatar
Wim Taymans committed
25 26
{
  GstPad *src, *sink;
27
  GstPadTemplate *srct;
Wim Taymans's avatar
Wim Taymans committed
28 29 30 31 32 33

  GstPadLinkReturn ret;
  gchar *name;

  src = gst_pad_new ("source", GST_PAD_SRC);
  fail_if (src == NULL);
34
  ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
Wim Taymans's avatar
Wim Taymans committed
35 36 37

  name = gst_pad_get_name (src);
  fail_unless (strcmp (name, "source") == 0);
38 39
  ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
  g_free (name);
Wim Taymans's avatar
Wim Taymans committed
40 41 42 43

  sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_if (sink == NULL);

44
  /* linking without templates or caps should fail */
Wim Taymans's avatar
Wim Taymans committed
45
  ret = gst_pad_link (src, sink);
46 47
  ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
  ASSERT_OBJECT_REFCOUNT (sink, "sink pad", 1);
Wim Taymans's avatar
Wim Taymans committed
48 49 50 51 52 53
  fail_unless (ret == GST_PAD_LINK_NOFORMAT);

  ASSERT_CRITICAL (gst_pad_get_pad_template (NULL));

  srct = gst_pad_get_pad_template (src);
  fail_unless (srct == NULL);
54 55 56 57 58 59
  ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);

  /* clean up */
  ASSERT_OBJECT_REFCOUNT (src, "source pad", 1);
  gst_object_unref (src);
  gst_object_unref (sink);
Wim Taymans's avatar
Wim Taymans committed
60 61
}

62
GST_END_TEST;
63

Wim Taymans's avatar
Wim Taymans committed
64 65
/* threaded link/unlink */
/* use globals */
66
static GstPad *src, *sink;
Wim Taymans's avatar
Wim Taymans committed
67

68
static void
Wim Taymans's avatar
Wim Taymans committed
69 70 71 72 73 74 75 76 77 78 79
thread_link_unlink (gpointer data)
{
  THREAD_START ();

  while (THREAD_TEST_RUNNING ()) {
    gst_pad_link (src, sink);
    gst_pad_unlink (src, sink);
    THREAD_SWITCH ();
  }
}

80
GST_START_TEST (test_link_unlink_threaded)
Wim Taymans's avatar
Wim Taymans committed
81 82 83 84 85 86 87 88 89
{
  GstCaps *caps;
  int i;

  src = gst_pad_new ("source", GST_PAD_SRC);
  fail_if (src == NULL);
  sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_if (sink == NULL);

90
  caps = gst_caps_from_string ("foo/bar");
Wim Taymans's avatar
Wim Taymans committed
91
  gst_pad_set_caps (src, caps);
Wim Taymans's avatar
Wim Taymans committed
92
  gst_pad_set_active (sink, TRUE);
Wim Taymans's avatar
Wim Taymans committed
93
  gst_pad_set_caps (sink, caps);
94
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
Wim Taymans's avatar
Wim Taymans committed
95 96 97 98 99 100 101 102

  MAIN_START_THREADS (5, thread_link_unlink, NULL);
  for (i = 0; i < 1000; ++i) {
    gst_pad_is_linked (src);
    gst_pad_is_linked (sink);
    THREAD_SWITCH ();
  }
  MAIN_STOP_THREADS ();
103

104
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
105 106
  gst_caps_unref (caps);

107
  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
108 109
  gst_object_unref (src);
  gst_object_unref (sink);
Wim Taymans's avatar
Wim Taymans committed
110
}
111

112
GST_END_TEST;
113

114
GST_START_TEST (test_refcount)
115 116 117 118 119 120 121 122 123 124 125
{
  GstPad *src, *sink;
  GstCaps *caps;
  GstPadLinkReturn plr;

  sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_if (sink == NULL);

  src = gst_pad_new ("src", GST_PAD_SRC);
  fail_if (src == NULL);

126
  caps = gst_caps_from_string ("foo/bar");
127 128 129
  /* one for me */
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);

130
  /* can't set caps on flushing sinkpad */
131
  fail_if (gst_pad_set_caps (src, caps) == TRUE);
Wim Taymans's avatar
Wim Taymans committed
132
  fail_if (gst_pad_set_caps (sink, caps) == TRUE);
133
  /* one for me and one for each set_caps */
134 135 136 137 138
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);

  gst_pad_set_active (src, TRUE);
  fail_unless (gst_pad_set_caps (src, caps) == TRUE);
  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
Wim Taymans's avatar
Wim Taymans committed
139 140 141

  gst_pad_set_active (sink, TRUE);
  fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
142
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
143 144 145

  plr = gst_pad_link (src, sink);
  fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
146 147
  /* src caps added to pending caps on sink */
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
148 149

  gst_pad_unlink (src, sink);
150
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
151 152

  /* cleanup */
153 154
  gst_object_unref (src);
  gst_object_unref (sink);
155 156 157 158 159
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);

  gst_caps_unref (caps);
}

160
GST_END_TEST;
161

162
GST_START_TEST (test_get_allowed_caps)
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
{
  GstPad *src, *sink;
  GstCaps *caps, *gotcaps;
  GstBuffer *buffer;
  GstPadLinkReturn plr;

  ASSERT_CRITICAL (gst_pad_get_allowed_caps (NULL));

  buffer = gst_buffer_new ();
  ASSERT_CRITICAL (gst_pad_get_allowed_caps ((GstPad *) buffer));
  gst_buffer_unref (buffer);

  src = gst_pad_new ("src", GST_PAD_SRC);
  fail_if (src == NULL);
  caps = gst_pad_get_allowed_caps (src);
  fail_unless (caps == NULL);

180
  caps = gst_caps_from_string ("foo/bar");
181

182
  sink = gst_pad_new ("sink", GST_PAD_SINK);
183
  fail_unless (gst_pad_set_caps (src, caps) == TRUE);
Wim Taymans's avatar
Wim Taymans committed
184
  fail_if (gst_pad_set_caps (sink, caps) == TRUE);
185
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
Wim Taymans's avatar
Wim Taymans committed
186 187 188

  gst_pad_set_active (sink, TRUE);
  fail_unless (gst_pad_set_caps (sink, caps) == TRUE);
189 190 191 192 193 194 195
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);

  plr = gst_pad_link (src, sink);
  fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));

  gotcaps = gst_pad_get_allowed_caps (src);
  fail_if (gotcaps == NULL);
196
#if 0
197 198
  /* FIXME, does not work, caps events are different so the sinkpad loses caps
   * when linking */
199
  fail_unless (gst_caps_is_equal (gotcaps, caps));
200
#endif
201 202 203 204 205 206 207

  ASSERT_CAPS_REFCOUNT (gotcaps, "gotcaps", 1);
  gst_caps_unref (gotcaps);

  gst_pad_unlink (src, sink);

  /* cleanup */
208
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);
209 210 211
  ASSERT_OBJECT_REFCOUNT (src, "src", 1);
  ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);

212 213
  gst_object_unref (src);
  gst_object_unref (sink);
214 215 216 217 218

  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
  gst_caps_unref (caps);
}

219
GST_END_TEST;
220

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
static GstCaps *event_caps = NULL;

static gboolean
sticky_event (GstPad * pad, GstEvent * event)
{
  GstCaps *caps;

  fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);

  /* Ensure we get here just once: */
  fail_unless (event_caps == NULL);

  /* The event must arrive before any buffer: */
  fail_unless_equals_int (g_list_length (buffers), 0);

  gst_event_parse_caps (event, &caps);
  event_caps = gst_caps_ref (caps);

  gst_event_unref (event);

  return TRUE;
}

GST_START_TEST (test_sticky_caps_unlinked)
{
  GstCaps *caps;
  GstPadTemplate *src_template, *sink_template;
  GstPad *src, *sink;
  GstEvent *event;

  caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
  src_template = gst_pad_template_new ("src", GST_PAD_SRC,
      GST_PAD_ALWAYS, caps);
  sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
      GST_PAD_ALWAYS, caps);
  gst_caps_unref (caps);

  src = gst_pad_new_from_template (src_template, "src");
  fail_if (src == NULL);
  sink = gst_pad_new_from_template (sink_template, "sink");
  fail_if (sink == NULL);
  gst_pad_set_event_function (sink, sticky_event);
  gst_pad_set_chain_function (sink, gst_check_chain_func);

  gst_object_unref (src_template);
  gst_object_unref (sink_template);

  caps = gst_caps_from_string ("foo/bar, dummy=(int)1");
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);

  event = gst_event_new_caps (caps);
  /* Pad is still inactive but the event gets stored sticky, so push is
   * successful: */
  fail_unless (gst_pad_push_event (src, event) == TRUE);
  fail_unless (event_caps == NULL);

  /* Linking and activating will not forward the sticky event yet... */
  fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));
  gst_pad_set_active (src, TRUE);
  gst_pad_set_active (sink, TRUE);
  fail_unless (event_caps == NULL);

  /* ...but the first buffer will: */
  fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
  fail_unless (event_caps == caps);
  fail_unless_equals_int (g_list_length (buffers), 1);

  gst_caps_replace (&caps, NULL);
  gst_caps_replace (&event_caps, NULL);

  ASSERT_OBJECT_REFCOUNT (src, "src", 1);
  ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
  gst_object_unref (src);
  gst_object_unref (sink);
}

GST_END_TEST;

/* Like test_sticky_caps_unlinked, but link before caps: */

GST_START_TEST (test_sticky_caps_flushing)
{
  GstCaps *caps;
  GstPadTemplate *src_template, *sink_template;
  GstPad *src, *sink;
  GstEvent *event;

  caps = gst_caps_from_string ("foo/bar, dummy=(int){1, 2}");
  src_template = gst_pad_template_new ("src", GST_PAD_SRC,
      GST_PAD_ALWAYS, caps);
  sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
      GST_PAD_ALWAYS, caps);
  gst_caps_unref (caps);

  src = gst_pad_new_from_template (src_template, "src");
  fail_if (src == NULL);
  sink = gst_pad_new_from_template (sink_template, "sink");
  fail_if (sink == NULL);
  gst_pad_set_event_function (sink, sticky_event);
  gst_pad_set_chain_function (sink, gst_check_chain_func);

  gst_object_unref (src_template);
  gst_object_unref (sink_template);

  fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (src, sink)));

  caps = gst_caps_from_string ("foo/bar, dummy=(int)1");
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);

  event = gst_event_new_caps (caps);
  /* Pads are still inactive but event gets stored sticky, so push is
   * successful: */
  fail_unless (gst_pad_push_event (src, event) == TRUE);
  fail_unless (event_caps == NULL);

  /* Activating will not forward the sticky event yet... */
  gst_pad_set_active (src, TRUE);
  gst_pad_set_active (sink, TRUE);
  fail_unless (event_caps == NULL);

  /* ...but the first buffer will: */
  fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK);
  fail_unless (event_caps == caps);
  fail_unless_equals_int (g_list_length (buffers), 1);

  gst_caps_replace (&caps, NULL);
  gst_caps_replace (&event_caps, NULL);

  ASSERT_OBJECT_REFCOUNT (src, "src", 1);
  ASSERT_OBJECT_REFCOUNT (sink, "sink", 1);
  gst_object_unref (src);
  gst_object_unref (sink);
}

GST_END_TEST;

357 358 359 360
static gboolean
name_is_valid (const gchar * name, GstPadPresence presence)
{
  GstPadTemplate *new;
Edward Hervey's avatar
Edward Hervey committed
361
  GstCaps *any = gst_caps_new_any ();
362

363
  new = gst_pad_template_new (name, GST_PAD_SRC, presence, any);
Edward Hervey's avatar
Edward Hervey committed
364
  gst_caps_unref (any);
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
  if (new) {
    gst_object_unref (GST_OBJECT (new));
    return TRUE;
  }
  return FALSE;
}

GST_START_TEST (test_name_is_valid)
{
  gboolean result = FALSE;

  fail_unless (name_is_valid ("src", GST_PAD_ALWAYS));
  ASSERT_WARNING (name_is_valid ("src%", GST_PAD_ALWAYS));
  ASSERT_WARNING (result = name_is_valid ("src%d", GST_PAD_ALWAYS));
  fail_if (result);

  fail_unless (name_is_valid ("src", GST_PAD_REQUEST));
  ASSERT_WARNING (name_is_valid ("src%s%s", GST_PAD_REQUEST));
  ASSERT_WARNING (name_is_valid ("src%c", GST_PAD_REQUEST));
  ASSERT_WARNING (name_is_valid ("src%", GST_PAD_REQUEST));
  ASSERT_WARNING (name_is_valid ("src%dsrc", GST_PAD_REQUEST));

  fail_unless (name_is_valid ("src", GST_PAD_SOMETIMES));
  fail_unless (name_is_valid ("src%c", GST_PAD_SOMETIMES));
}

GST_END_TEST;

393
static GstPadProbeReturn
Wim Taymans's avatar
Wim Taymans committed
394
_probe_handler (GstPad * pad, GstPadProbeInfo * info, gpointer userdata)
395 396 397 398
{
  gint ret = GPOINTER_TO_INT (userdata);

  if (ret == 1)
399
    return GST_PAD_PROBE_OK;
400

401
  return GST_PAD_PROBE_DROP;
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
}

GST_START_TEST (test_push_unlinked)
{
  GstPad *src;
  GstCaps *caps;
  GstBuffer *buffer;
  gulong id;

  src = gst_pad_new ("src", GST_PAD_SRC);
  fail_if (src == NULL);
  caps = gst_pad_get_allowed_caps (src);
  fail_unless (caps == NULL);

  caps = gst_caps_from_string ("foo/bar");

  gst_pad_set_caps (src, caps);
419
  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
420

421 422 423 424 425 426 427 428 429
  /* pushing on an inactive pad will return wrong state */
  buffer = gst_buffer_new ();
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
  gst_buffer_unref (buffer);

  gst_pad_set_active (src, TRUE);

430 431 432 433 434 435 436
  /* pushing on an unlinked pad will drop the buffer */
  buffer = gst_buffer_new ();
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
  gst_buffer_unref (buffer);

Wim Taymans's avatar
Wim Taymans committed
437
  /* adding a probe that returns _DROP will drop the buffer without trying
438
   * to chain */
439
  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
Wim Taymans's avatar
Wim Taymans committed
440
      _probe_handler, GINT_TO_POINTER (0), NULL);
441 442 443 444 445
  buffer = gst_buffer_new ();
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
  gst_buffer_unref (buffer);
446
  gst_pad_remove_probe (src, id);
447

Wim Taymans's avatar
Wim Taymans committed
448
  /* adding a probe that returns _OK will still chain the buffer,
449
   * and hence drop because pad is unlinked */
450
  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
Wim Taymans's avatar
Wim Taymans committed
451
      _probe_handler, GINT_TO_POINTER (1), NULL);
452 453 454 455 456
  buffer = gst_buffer_new ();
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_LINKED);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
  gst_buffer_unref (buffer);
457
  gst_pad_remove_probe (src, id);
458 459 460


  /* cleanup */
461
  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
  ASSERT_OBJECT_REFCOUNT (src, "src", 1);

  gst_object_unref (src);

  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
  gst_caps_unref (caps);
}

GST_END_TEST;

GST_START_TEST (test_push_linked)
{
  GstPad *src, *sink;
  GstPadLinkReturn plr;
  GstCaps *caps;
  GstBuffer *buffer;
478
  gulong id;
479 480 481 482 483 484 485 486 487 488 489 490 491 492

  /* setup */
  sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_if (sink == NULL);
  gst_pad_set_chain_function (sink, gst_check_chain_func);

  src = gst_pad_new ("src", GST_PAD_SRC);
  fail_if (src == NULL);

  caps = gst_caps_from_string ("foo/bar");
  /* one for me */
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);

  gst_pad_set_caps (src, caps);
493
  gst_pad_set_active (sink, TRUE);
494 495 496 497 498 499 500 501
  gst_pad_set_caps (sink, caps);
  /* one for me and one for each set_caps */
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);

  plr = gst_pad_link (src, sink);
  fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);

502 503 504 505 506 507 508 509 510 511 512 513 514
  buffer = gst_buffer_new ();
#if 0
  /* FIXME, new pad should be flushing */
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_chain (sink, buffer) == GST_FLOW_WRONG_STATE);
#endif

  /* activate pads */
  gst_pad_set_active (src, TRUE);
  gst_pad_set_active (sink, TRUE);

515 516 517 518 519 520 521 522 523
  /* test */
  /* pushing on a linked pad will drop the ref to the buffer */
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
  gst_buffer_unref (buffer);
  fail_unless_equals_int (g_list_length (buffers), 1);
  buffer = GST_BUFFER (buffers->data);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
524
  gst_buffer_unref (buffer);
525 526 527 528 529
  g_list_free (buffers);
  buffers = NULL;

  /* adding a probe that returns FALSE will drop the buffer without trying
   * to chain */
530
  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
Wim Taymans's avatar
Wim Taymans committed
531
      _probe_handler, GINT_TO_POINTER (0), NULL);
532 533 534 535 536
  buffer = gst_buffer_new ();
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
  gst_buffer_unref (buffer);
537
  gst_pad_remove_probe (src, id);
538 539 540
  fail_unless_equals_int (g_list_length (buffers), 0);

  /* adding a probe that returns TRUE will still chain the buffer */
541
  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER,
Wim Taymans's avatar
Wim Taymans committed
542
      _probe_handler, GINT_TO_POINTER (1), NULL);
543 544 545
  buffer = gst_buffer_new ();
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
546
  gst_pad_remove_probe (src, id);
547 548 549 550 551 552

  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 2);
  gst_buffer_unref (buffer);
  fail_unless_equals_int (g_list_length (buffers), 1);
  buffer = GST_BUFFER (buffers->data);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
553
  gst_buffer_unref (buffer);
554 555 556 557 558
  g_list_free (buffers);
  buffers = NULL;

  /* teardown */
  gst_pad_unlink (src, sink);
Wim Taymans's avatar
Wim Taymans committed
559
  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
560 561 562 563 564 565 566 567 568
  gst_object_unref (src);
  gst_object_unref (sink);
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);

  gst_caps_unref (caps);
}

GST_END_TEST;

569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
GST_START_TEST (test_push_linked_flushing)
{
  GstPad *src, *sink;
  GstCaps *caps;
  GstPadLinkReturn plr;
  GstBuffer *buffer;
  gulong id;

  /* setup */
  src = gst_pad_new ("src", GST_PAD_SRC);
  fail_if (src == NULL);
  sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_if (sink == NULL);
  gst_pad_set_chain_function (sink, gst_check_chain_func);

  caps = gst_pad_get_allowed_caps (src);
  fail_unless (caps == NULL);
  caps = gst_pad_get_allowed_caps (sink);
  fail_unless (caps == NULL);

  caps = gst_caps_from_string ("foo/bar");
  /* one for me */
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);

  gst_pad_set_caps (src, caps);
Wim Taymans's avatar
Wim Taymans committed
594 595
  /* need to activate to make it accept the caps */
  gst_pad_set_active (sink, TRUE);
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
  gst_pad_set_caps (sink, caps);
  /* one for me and one for each set_caps */
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);

  plr = gst_pad_link (src, sink);
  fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
  ASSERT_CAPS_REFCOUNT (caps, "caps", 3);

  /* not activating the pads here, which keeps them flushing */

  /* pushing on a flushing pad will drop the buffer */
  buffer = gst_buffer_new ();
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
  fail_unless_equals_int (g_list_length (buffers), 0);
  gst_buffer_unref (buffer);

Wim Taymans's avatar
Wim Taymans committed
614 615 616
  gst_pad_set_active (src, TRUE);
  gst_pad_set_active (sink, FALSE);

617 618
  /* adding a probe that returns FALSE will drop the buffer without trying
   * to chain */
Wim Taymans's avatar
Wim Taymans committed
619 620
  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler,
      GINT_TO_POINTER (0), NULL);
621 622 623 624 625 626
  buffer = gst_buffer_new ();
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_OK);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
  fail_unless_equals_int (g_list_length (buffers), 0);
  gst_buffer_unref (buffer);
Wim Taymans's avatar
Wim Taymans committed
627
  gst_pad_remove_probe (src, id);
628 629 630

  /* adding a probe that returns TRUE will still chain the buffer,
   * and hence drop because pad is flushing */
Wim Taymans's avatar
Wim Taymans committed
631 632
  id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BUFFER, _probe_handler,
      GINT_TO_POINTER (1), NULL);
633 634 635 636 637 638
  buffer = gst_buffer_new ();
  gst_buffer_ref (buffer);
  fail_unless (gst_pad_push (src, buffer) == GST_FLOW_WRONG_STATE);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
  fail_unless_equals_int (g_list_length (buffers), 0);
  gst_buffer_unref (buffer);
Wim Taymans's avatar
Wim Taymans committed
639
  gst_pad_remove_probe (src, id);
640 641

  /* cleanup */
Wim Taymans's avatar
Wim Taymans committed
642
  ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
643 644 645 646 647 648 649 650 651 652
  ASSERT_OBJECT_REFCOUNT (src, "src", 1);
  gst_pad_link (src, sink);
  gst_object_unref (src);
  gst_object_unref (sink);
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
  gst_caps_unref (caps);
}

GST_END_TEST;

653
static GstBuffer *
Benjamin Otte's avatar
Benjamin Otte committed
654
buffer_from_string (const gchar * str)
655 656 657
{
  guint size;
  GstBuffer *buf;
Wim Taymans's avatar
Wim Taymans committed
658
  gpointer data;
659 660 661

  size = strlen (str);
  buf = gst_buffer_new_and_alloc (size);
Wim Taymans's avatar
Wim Taymans committed
662 663 664 665

  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
  memcpy (data, str, size);
  gst_buffer_unmap (buf, data, size);
666 667 668 669

  return buf;
}

Wim Taymans's avatar
Wim Taymans committed
670 671 672 673 674 675
static gboolean
buffer_compare (GstBuffer * buf, const gchar * str, gsize size)
{
  gboolean res;
  gpointer data;

676
  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_READ);
Wim Taymans's avatar
Wim Taymans committed
677
  res = memcmp (data, str, size) == 0;
Wim Taymans's avatar
Wim Taymans committed
678
  GST_DEBUG ("%s <-> %s: %d", (gchar *) data, str, res);
Wim Taymans's avatar
Wim Taymans committed
679 680 681 682 683
  gst_buffer_unmap (buf, data, size);

  return res;
}

684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
GST_START_TEST (test_push_buffer_list_compat)
{
  GstPad *src, *sink;
  GstPadLinkReturn plr;
  GstCaps *caps;
  GstBufferList *list;
  GstBuffer *buffer;

  /* setup */
  sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_if (sink == NULL);
  gst_pad_set_chain_function (sink, gst_check_chain_func);
  /* leave chainlistfunc unset */

  src = gst_pad_new ("src", GST_PAD_SRC);
  fail_if (src == NULL);

  caps = gst_caps_from_string ("foo/bar");

  gst_pad_set_caps (src, caps);
Wim Taymans's avatar
Wim Taymans committed
704
  gst_pad_set_active (sink, TRUE);
705 706 707 708 709 710 711 712 713 714 715 716 717
  gst_pad_set_caps (sink, caps);

  plr = gst_pad_link (src, sink);
  fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));

  list = gst_buffer_list_new ();

  /* activate pads */
  gst_pad_set_active (src, TRUE);
  gst_pad_set_active (sink, TRUE);

  /* test */
  /* adding to a buffer list will drop the ref to the buffer */
Wim Taymans's avatar
Wim Taymans committed
718 719 720
  gst_buffer_list_add (list, buffer_from_string ("ListGroup"));
  gst_buffer_list_add (list, buffer_from_string ("AnotherListGroup"));

721 722 723 724
  fail_unless (gst_pad_push_list (src, list) == GST_FLOW_OK);
  fail_unless_equals_int (g_list_length (buffers), 2);
  buffer = GST_BUFFER (buffers->data);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
Wim Taymans's avatar
Wim Taymans committed
725
  fail_unless (buffer_compare (buffer, "ListGroup", 9));
726 727 728 729
  gst_buffer_unref (buffer);
  buffers = g_list_delete_link (buffers, buffers);
  buffer = GST_BUFFER (buffers->data);
  ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
Wim Taymans's avatar
Wim Taymans committed
730
  fail_unless (buffer_compare (buffer, "AnotherListGroup", 16));
731 732 733 734 735 736 737 738 739 740 741 742 743 744
  gst_buffer_unref (buffer);
  buffers = g_list_delete_link (buffers, buffers);
  fail_unless (buffers == NULL);

  /* teardown */
  gst_pad_unlink (src, sink);
  gst_object_unref (src);
  gst_object_unref (sink);
  ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
  gst_caps_unref (caps);
}

GST_END_TEST;

745 746 747 748 749 750
GST_START_TEST (test_flowreturn)
{
  GstFlowReturn ret;
  GQuark quark;

  /* test some of the macros */
751 752
  ret = GST_FLOW_EOS;
  fail_if (strcmp (gst_flow_get_name (ret), "eos"));
753
  quark = gst_flow_to_quark (ret);
754
  fail_if (strcmp (g_quark_to_string (quark), "eos"));
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790

  ret = GST_FLOW_RESEND;
  fail_if (strcmp (gst_flow_get_name (ret), "resend"));
  quark = gst_flow_to_quark (ret);
  fail_if (strcmp (g_quark_to_string (quark), "resend"));

  /* custom returns */
  ret = GST_FLOW_CUSTOM_SUCCESS;
  fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
  quark = gst_flow_to_quark (ret);
  fail_if (strcmp (g_quark_to_string (quark), "custom-success"));

  ret = GST_FLOW_CUSTOM_ERROR;
  fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
  quark = gst_flow_to_quark (ret);
  fail_if (strcmp (g_quark_to_string (quark), "custom-error"));

  /* custom returns clamping */
  ret = GST_FLOW_CUSTOM_SUCCESS + 2;
  fail_if (strcmp (gst_flow_get_name (ret), "custom-success"));
  quark = gst_flow_to_quark (ret);
  fail_if (strcmp (g_quark_to_string (quark), "custom-success"));

  ret = GST_FLOW_CUSTOM_ERROR - 2;
  fail_if (strcmp (gst_flow_get_name (ret), "custom-error"));
  quark = gst_flow_to_quark (ret);
  fail_if (strcmp (g_quark_to_string (quark), "custom-error"));

  /* unknown values */
  ret = GST_FLOW_CUSTOM_ERROR + 2;
  fail_if (strcmp (gst_flow_get_name (ret), "unknown"));
  quark = gst_flow_to_quark (ret);
  fail_unless (quark == 0);
}

GST_END_TEST;
791

792 793 794 795
GST_START_TEST (test_push_negotiation)
{
  GstPad *src, *sink;
  GstPadLinkReturn plr;
796 797 798 799 800 801
  GstCaps *srccaps =
      gst_caps_from_string ("audio/x-raw-int,width={16,32},depth={16,32}");
  GstCaps *sinkcaps =
      gst_caps_from_string ("audio/x-raw-int,width=32,depth={16,32}");
  GstPadTemplate *src_template;
  GstPadTemplate *sink_template;
802 803 804
  GstCaps *caps;

  /* setup */
805 806 807 808
  src_template = gst_pad_template_new ("src", GST_PAD_SRC,
      GST_PAD_ALWAYS, srccaps);
  sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
      GST_PAD_ALWAYS, sinkcaps);
809 810
  gst_caps_unref (srccaps);
  gst_caps_unref (sinkcaps);
811

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
  sink = gst_pad_new_from_template (sink_template, "sink");
  fail_if (sink == NULL);
  gst_pad_set_chain_function (sink, gst_check_chain_func);

  src = gst_pad_new_from_template (src_template, "src");
  fail_if (src == NULL);

  plr = gst_pad_link (src, sink);
  fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));

  /* activate pads */
  gst_pad_set_active (src, TRUE);
  gst_pad_set_active (sink, TRUE);

  caps = gst_caps_from_string ("audio/x-raw-int,width=16,depth=16");

  /* Should fail if src pad caps are incompatible with sink pad caps */
  gst_pad_set_caps (src, caps);
Wim Taymans's avatar
Wim Taymans committed
830
  fail_unless (gst_pad_set_caps (sink, caps) == FALSE);
831 832 833 834 835 836 837 838 839 840 841 842

  /* teardown */
  gst_pad_unlink (src, sink);
  gst_object_unref (src);
  gst_object_unref (sink);
  gst_caps_unref (caps);
  gst_object_unref (sink_template);
  gst_object_unref (src_template);
}

GST_END_TEST;

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
/* see that an unref also unlinks the pads */
GST_START_TEST (test_src_unref_unlink)
{
  GstPad *src, *sink;
  GstCaps *caps;
  GstPadLinkReturn plr;

  sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_if (sink == NULL);

  src = gst_pad_new ("src", GST_PAD_SRC);
  fail_if (src == NULL);

  caps = gst_caps_from_string ("foo/bar");

  gst_pad_set_caps (src, caps);
Wim Taymans's avatar
Wim Taymans committed
859
  gst_pad_set_active (sink, TRUE);
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
  gst_pad_set_caps (sink, caps);

  plr = gst_pad_link (src, sink);
  fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));

  /* unref the srcpad */
  gst_object_unref (src);

  /* sink should be unlinked now */
  fail_if (gst_pad_is_linked (sink));

  /* cleanup */
  gst_object_unref (sink);
  gst_caps_unref (caps);
}

GST_END_TEST;

/* see that an unref also unlinks the pads */
GST_START_TEST (test_sink_unref_unlink)
{
  GstPad *src, *sink;
  GstCaps *caps;
  GstPadLinkReturn plr;

  sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_if (sink == NULL);

  src = gst_pad_new ("src", GST_PAD_SRC);
  fail_if (src == NULL);

  caps = gst_caps_from_string ("foo/bar");

  gst_pad_set_caps (src, caps);
Wim Taymans's avatar
Wim Taymans committed
894
  gst_pad_set_active (sink, TRUE);
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
  gst_pad_set_caps (sink, caps);

  plr = gst_pad_link (src, sink);
  fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));

  /* unref the sinkpad */
  gst_object_unref (sink);

  /* src should be unlinked now */
  fail_if (gst_pad_is_linked (src));

  /* cleanup */
  gst_object_unref (src);
  gst_caps_unref (caps);
}

GST_END_TEST;
912

913 914
static gulong id;

915
static GstPadProbeReturn
Wim Taymans's avatar
Wim Taymans committed
916
block_async_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
917 918 919
{
  gboolean *bool_user_data = (gboolean *) user_data;

Wim Taymans's avatar
Wim Taymans committed
920
  fail_unless ((info->type & GST_PAD_PROBE_TYPE_BLOCK) != 0);
921 922 923 924 925

  /* here we should have blocked == 0 unblocked == 0 */
  fail_unless (bool_user_data[0] == FALSE);
  fail_unless (bool_user_data[1] == FALSE);

926
  bool_user_data[0] = TRUE;
927

928
  gst_pad_remove_probe (pad, id);
929
  bool_user_data[1] = TRUE;
930

931
  return GST_PAD_PROBE_OK;
932 933 934 935 936 937 938 939 940 941 942 943 944
}

GST_START_TEST (test_block_async)
{
  GstPad *pad;
  /* we set data[0] = TRUE when the pad is blocked, data[1] = TRUE when it's
   * unblocked */
  gboolean data[2] = { FALSE, FALSE };

  pad = gst_pad_new ("src", GST_PAD_SRC);
  fail_unless (pad != NULL);

  gst_pad_set_active (pad, TRUE);
945
  id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_cb, &data,
946
      NULL);
947

948 949
  fail_unless (data[0] == FALSE);
  fail_unless (data[1] == FALSE);
950 951 952 953 954 955 956 957 958 959 960
  gst_pad_push (pad, gst_buffer_new ());

  gst_object_unref (pad);
}

GST_END_TEST;

#if 0
static void
block_async_second (GstPad * pad, gboolean blocked, gpointer user_data)
{
961
  gst_pad_set_blocked (pad, FALSE, unblock_async_cb, NULL, NULL);
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
}

static void
block_async_first (GstPad * pad, gboolean blocked, gpointer user_data)
{
  static int n_calls = 0;
  gboolean *bool_user_data = (gboolean *) user_data;

  if (++n_calls > 1)
    /* we expect this callback to be called only once */
    g_warn_if_reached ();

  *bool_user_data = blocked;

  /* replace block_async_first with block_async_second so next time the pad is
   * blocked the latter should be called */
978
  gst_pad_set_blocked (pad, TRUE, block_async_second, NULL, NULL);
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993

  /* unblock temporarily, in the next push block_async_second should be called
   */
  gst_pad_push_event (pad, gst_event_new_flush_start ());
}

GST_START_TEST (test_block_async_replace_callback)
{
  GstPad *pad;
  gboolean blocked;

  pad = gst_pad_new ("src", GST_PAD_SRC);
  fail_unless (pad != NULL);
  gst_pad_set_active (pad, TRUE);

994
  gst_pad_set_blocked (pad, TRUE, block_async_first, &blocked, NULL);
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
  blocked = FALSE;

  gst_pad_push (pad, gst_buffer_new ());
  fail_unless (blocked == TRUE);
  /* block_async_first flushes to unblock */
  gst_pad_push_event (pad, gst_event_new_flush_stop ());

  /* push again, this time block_async_second should be called */
  gst_pad_push (pad, gst_buffer_new ());
  fail_unless (blocked == TRUE);

  gst_object_unref (pad);
}

GST_END_TEST;
#endif

static void
block_async_full_destroy (gpointer user_data)
{
  gint *state = (gint *) user_data;

  fail_unless (*state < 2);

1019
  GST_DEBUG ("setting state to 2");
1020 1021 1022
  *state = 2;
}

1023
static GstPadProbeReturn
Wim Taymans's avatar
Wim Taymans committed
1024
block_async_full_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
1025
{
1026
  *(gint *) user_data = (gint) TRUE;
1027 1028

  gst_pad_push_event (pad, gst_event_new_flush_start ());
1029
  GST_DEBUG ("setting state to 1");
1030

1031
  return GST_PAD_PROBE_OK;
1032 1033 1034 1035 1036 1037 1038
}

GST_START_TEST (test_block_async_full_destroy)
{
  GstPad *pad;
  /* 0 = unblocked, 1 = blocked, 2 = destroyed */
  gint state = 0;
1039
  gulong id;
1040 1041 1042 1043 1044

  pad = gst_pad_new ("src", GST_PAD_SRC);
  fail_unless (pad != NULL);
  gst_pad_set_active (pad, TRUE);

1045
  id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1046
      &state, block_async_full_destroy);
1047
  fail_unless (state == 0);
1048 1049 1050 1051

  gst_pad_push (pad, gst_buffer_new ());
  /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
   */
1052
  fail_unless (state == 1);
1053
  gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1054

1055
  /* unblock callback is called */
1056
  gst_pad_remove_probe (pad, id);
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
  fail_unless (state == 2);

  gst_object_unref (pad);
}

GST_END_TEST;

GST_START_TEST (test_block_async_full_destroy_dispose)
{
  GstPad *pad;
  /* 0 = unblocked, 1 = blocked, 2 = destroyed */
  gint state = 0;

  pad = gst_pad_new ("src", GST_PAD_SRC);
  fail_unless (pad != NULL);
  gst_pad_set_active (pad, TRUE);

1074
  (void) gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, block_async_full_cb,
1075 1076 1077 1078 1079
      &state, block_async_full_destroy);

  gst_pad_push (pad, gst_buffer_new ());
  /* block_async_full_cb sets state to 1 and then flushes to unblock temporarily
   */
1080
  fail_unless_equals_int (state, 1);
1081
  gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
1082

1083
  /* gst_BLOCK calls the destroy_notify function if necessary */
1084 1085 1086 1087 1088 1089 1090
  gst_object_unref (pad);

  fail_unless_equals_int (state, 2);
}

GST_END_TEST;

1091

1092
#if 0
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
static void
unblock_async_no_flush_cb (GstPad * pad, gboolean blocked, gpointer user_data)
{
  gboolean *bool_user_data = (gboolean *) user_data;

  /* here we should have blocked == 1 unblocked == 0 */

  fail_unless (blocked == FALSE);

  fail_unless (bool_user_data[0] == TRUE);
  fail_unless (bool_user_data[1] == TRUE);
  fail_unless (bool_user_data[2] == FALSE);

  bool_user_data[2] = TRUE;
}
1108
#endif
1109 1110


1111
#if 0
1112 1113 1114 1115 1116
static void
unblock_async_not_called (GstPad * pad, gboolean blocked, gpointer user_data)
{
  g_warn_if_reached ();
}
1117
#endif
1118

1119
static GstPadProbeReturn
Wim Taymans's avatar
Wim Taymans committed
1120 1121
block_async_second_no_flush (GstPad * pad, GstPadProbeInfo * info,
    gpointer user_data)
1122 1123 1124
{
  gboolean *bool_user_data = (gboolean *) user_data;

1125 1126
  GST_DEBUG ("second probe called");

Wim Taymans's avatar
Wim Taymans committed
1127
  fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1128 1129 1130 1131 1132 1133 1134

  fail_unless (bool_user_data[0] == TRUE);
  fail_unless (bool_user_data[1] == FALSE);
  fail_unless (bool_user_data[2] == FALSE);

  bool_user_data[1] = TRUE;

1135
  GST_DEBUG ("removing second probe with id %lu", id);
1136 1137
  gst_pad_remove_probe (pad, id);

1138
  return GST_PAD_PROBE_OK;
1139 1140
}

1141
static GstPadProbeReturn
Wim Taymans's avatar
Wim Taymans committed
1142 1143
block_async_first_no_flush (GstPad * pad, GstPadProbeInfo * info,
    gpointer user_data)
1144 1145 1146 1147
{
  static int n_calls = 0;
  gboolean *bool_user_data = (gboolean *) user_data;

Wim Taymans's avatar
Wim Taymans committed
1148
  fail_unless (info->type & GST_PAD_PROBE_TYPE_BLOCK);
1149

1150 1151
  GST_DEBUG ("first probe called");

1152 1153 1154 1155
  if (++n_calls > 1)
    /* we expect this callback to be called only once */
    g_warn_if_reached ();

1156
  *bool_user_data = TRUE;
1157 1158 1159 1160 1161

  fail_unless (bool_user_data[0] == TRUE);
  fail_unless (bool_user_data[1] == FALSE);
  fail_unless (bool_user_data[2] == FALSE);

1162
  GST_DEBUG ("removing first probe with id %lu", id);
1163
  gst_pad_remove_probe (pad, id);
1164

1165
  GST_DEBUG ("adding second probe");
1166 1167
  /* replace block_async_first with block_async_second so next time the pad is
   * blocked the latter should be called */
1168
  id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1169
      block_async_second_no_flush, user_data, NULL);
1170
  GST_DEBUG ("added probe with id %lu", id);
1171

1172
  return GST_PAD_PROBE_OK;
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
}

GST_START_TEST (test_block_async_replace_callback_no_flush)
{
  GstPad *pad;
  gboolean bool_user_data[3] = { FALSE, FALSE, FALSE };

  pad = gst_pad_new ("src", GST_PAD_SRC);
  fail_unless (pad != NULL);
  gst_pad_set_active (pad, TRUE);

1184
  GST_DEBUG ("adding probe");
1185
  id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK,
1186
      block_async_first_no_flush, bool_user_data, NULL);
1187
  GST_DEBUG ("added probe with id %lu", id);
1188
  fail_if (id == 0);
1189

1190
  GST_DEBUG ("pushing buffer");
1191 1192 1193
  gst_pad_push (pad, gst_buffer_new ());
  fail_unless (bool_user_data[0] == TRUE);
  fail_unless