summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnl/gnlcomposition.c65
-rw-r--r--tests/check/complex.c245
-rw-r--r--tests/check/gnloperation.c219
3 files changed, 507 insertions, 22 deletions
diff --git a/gnl/gnlcomposition.c b/gnl/gnlcomposition.c
index 4c34eaf..cf2b4c0 100644
--- a/gnl/gnlcomposition.c
+++ b/gnl/gnlcomposition.c
@@ -96,7 +96,8 @@ struct _GnlCompositionPrivate
96 /* current stack, list of GnlObject* */ 96 /* current stack, list of GnlObject* */
97 GNode *current; 97 GNode *current;
98 98
99 GnlObject *defaultobject; 99 /* List of GnlObject whose start/duration will be the same as the composition */
100 GList *expandables;
100 101
101 /* TRUE if the stack is valid. 102 /* TRUE if the stack is valid.
102 * This is meant to prevent the top-level pad to be unblocked before the stack 103 * This is meant to prevent the top-level pad to be unblocked before the stack
@@ -328,8 +329,6 @@ gnl_composition_init (GnlComposition * comp,
328 329
329 comp->private->waitingpads = 0; 330 comp->private->waitingpads = 0;
330 331
331 comp->private->defaultobject = NULL;
332
333 comp->private->objects_hash = g_hash_table_new_full 332 comp->private->objects_hash = g_hash_table_new_full
334 (g_direct_hash, 333 (g_direct_hash,
335 g_direct_equal, NULL, (GDestroyNotify) hash_value_destroy); 334 g_direct_equal, NULL, (GDestroyNotify) hash_value_destroy);
@@ -366,6 +365,11 @@ gnl_composition_dispose (GObject * object)
366 comp->private->current = NULL; 365 comp->private->current = NULL;
367 } 366 }
368 367
368 if (comp->private->expandables) {
369 g_list_free (comp->private->expandables);
370 comp->private->expandables = NULL;
371 }
372
369 G_OBJECT_CLASS (parent_class)->dispose (object); 373 G_OBJECT_CLASS (parent_class)->dispose (object);
370} 374}
371 375
@@ -917,7 +921,7 @@ handle_seek_event (GnlComposition * comp, GstEvent * event)
917 921
918 /* crop the segment start/stop values */ 922 /* crop the segment start/stop values */
919 /* Only crop segment start value if we don't have a default object */ 923 /* Only crop segment start value if we don't have a default object */
920 if (comp->private->defaultobject == NULL) 924 if (comp->private->expandables == NULL)
921 comp->private->segment->start = MAX (comp->private->segment->start, 925 comp->private->segment->start = MAX (comp->private->segment->start,
922 ((GnlObject *) comp)->start); 926 ((GnlObject *) comp)->start);
923 comp->private->segment->stop = MIN (comp->private->segment->stop, 927 comp->private->segment->stop = MIN (comp->private->segment->stop,
@@ -1262,9 +1266,14 @@ get_stack_list (GnlComposition * comp, GstClockTime timestamp,
1262 } 1266 }
1263 } 1267 }
1264 1268
1265 /* append the default source if we have one */ 1269 /* Insert the expandables */
1266 if ((timestamp < ((GnlObject *) comp)->stop) && comp->private->defaultobject) 1270 if (G_LIKELY (timestamp < ((GnlObject *) comp)->stop))
1267 stack = g_list_append (stack, comp->private->defaultobject); 1271 for (tmp = comp->private->expandables; tmp; tmp = g_list_next (tmp)) {
1272 GST_DEBUG_OBJECT (comp, "Adding expandable %s sorted to the list",
1273 GST_OBJECT_NAME (tmp->data));
1274 stack = g_list_insert_sorted (stack, tmp->data,
1275 (GCompareFunc) priority_comp);
1276 }
1268 1277
1269 /* convert that list to a stack */ 1278 /* convert that list to a stack */
1270 tmp = stack; 1279 tmp = stack;
@@ -1529,7 +1538,7 @@ update_start_stop_duration (GnlComposition * comp)
1529 } 1538 }
1530 1539
1531 /* If we have a default object, the start position is 0 */ 1540 /* If we have a default object, the start position is 0 */
1532 if (comp->private->defaultobject) { 1541 if (comp->private->expandables) {
1533 GST_LOG_OBJECT (cobj, 1542 GST_LOG_OBJECT (cobj,
1534 "Setting start to 0 because we have a default object"); 1543 "Setting start to 0 because we have a default object");
1535 if (cobj->start != 0) { 1544 if (cobj->start != 0) {
@@ -1551,10 +1560,13 @@ update_start_stop_duration (GnlComposition * comp)
1551 if (obj->stop != cobj->stop) { 1560 if (obj->stop != cobj->stop) {
1552 GST_LOG_OBJECT (obj, "setting stop from %s to %" GST_TIME_FORMAT, 1561 GST_LOG_OBJECT (obj, "setting stop from %s to %" GST_TIME_FORMAT,
1553 GST_OBJECT_NAME (obj), GST_TIME_ARGS (obj->stop)); 1562 GST_OBJECT_NAME (obj), GST_TIME_ARGS (obj->stop));
1554 if (comp->private->defaultobject) { 1563 if (comp->private->expandables) {
1555 g_object_set (comp->private->defaultobject, "duration", obj->stop, NULL); 1564 GList *tmp = comp->private->expandables;
1556 g_object_set (comp->private->defaultobject, "media-duration", obj->stop, 1565 while (tmp) {
1557 NULL); 1566 g_object_set (tmp->data, "duration", obj->stop, NULL);
1567 g_object_set (tmp->data, "media-duration", obj->stop, NULL);
1568 tmp = g_list_next (tmp);
1569 }
1558 } 1570 }
1559 comp->private->segment->stop = obj->stop; 1571 comp->private->segment->stop = obj->stop;
1560 cobj->stop = obj->stop; 1572 cobj->stop = obj->stop;
@@ -1730,7 +1742,8 @@ compare_relink_single_node (GnlComposition * comp, GNode * node,
1730 guint nbchilds = g_node_n_children (node); 1742 guint nbchilds = g_node_n_children (node);
1731 GnlOperation *oper = (GnlOperation *) newobj; 1743 GnlOperation *oper = (GnlOperation *) newobj;
1732 1744
1733 GST_LOG_OBJECT (newobj, "is operation, analyzing the %d childs", nbchilds); 1745 GST_LOG_OBJECT (newobj, "is a %s operation, analyzing the %d childs",
1746 oper->dynamicsinks ? "dynamic" : "regular", nbchilds);
1734 if (oper->dynamicsinks) 1747 if (oper->dynamicsinks)
1735 g_object_set (G_OBJECT (newobj), "sinks", nbchilds, NULL); 1748 g_object_set (G_OBJECT (newobj), "sinks", nbchilds, NULL);
1736 for (child = node->children; child; child = child->next) 1749 for (child = node->children; child; child = child->next)
@@ -2330,10 +2343,11 @@ gnl_composition_add_object (GstBin * bin, GstElement * element)
2330 2343
2331 COMP_OBJECTS_LOCK (comp); 2344 COMP_OBJECTS_LOCK (comp);
2332 2345
2333 if ((((GnlObject *) element)->priority == G_MAXUINT32) 2346 if (((((GnlObject *) element)->priority == G_MAXUINT32) ||
2334 && comp->private->defaultobject) { 2347 GNL_OBJECT_IS_EXPANDABLE (element)) &&
2348 g_list_find (comp->private->expandables, element)) {
2335 GST_WARNING_OBJECT (comp, 2349 GST_WARNING_OBJECT (comp,
2336 "We already have a default source, remove it before adding new one"); 2350 "We already have an expandable, remove it before adding new one");
2337 ret = FALSE; 2351 ret = FALSE;
2338 goto chiringuito; 2352 goto chiringuito;
2339 } 2353 }
@@ -2352,7 +2366,8 @@ gnl_composition_add_object (GstBin * bin, GstElement * element)
2352 /* wrap new element in a GnlCompositionEntry ... */ 2366 /* wrap new element in a GnlCompositionEntry ... */
2353 entry = g_new0 (GnlCompositionEntry, 1); 2367 entry = g_new0 (GnlCompositionEntry, 1);
2354 entry->object = (GnlObject *) element; 2368 entry->object = (GnlObject *) element;
2355 if ((((GnlObject *) element)->priority != G_MAXUINT32)) { 2369 if (G_LIKELY ((((GnlObject *) element)->priority != G_MAXUINT32) &&
2370 !GNL_OBJECT_IS_EXPANDABLE (element))) {
2356 /* Only react on non-default objects properties */ 2371 /* Only react on non-default objects properties */
2357 entry->starthandler = g_signal_connect (G_OBJECT (element), 2372 entry->starthandler = g_signal_connect (G_OBJECT (element),
2358 "notify::start", G_CALLBACK (object_start_stop_priority_changed), comp); 2373 "notify::start", G_CALLBACK (object_start_stop_priority_changed), comp);
@@ -2380,9 +2395,11 @@ gnl_composition_add_object (GstBin * bin, GstElement * element)
2380 g_hash_table_insert (comp->private->objects_hash, element, entry); 2395 g_hash_table_insert (comp->private->objects_hash, element, entry);
2381 2396
2382 /* Special case for default source. */ 2397 /* Special case for default source. */
2383 if (((GnlObject *) element)->priority == G_MAXUINT32) { 2398 if ((((GnlObject *) element)->priority == G_MAXUINT32) ||
2399 GNL_OBJECT_IS_EXPANDABLE (element)) {
2384 /* It doesn't get added to objects_start and objects_stop. */ 2400 /* It doesn't get added to objects_start and objects_stop. */
2385 comp->private->defaultobject = ((GnlObject *) element); 2401 comp->private->expandables = g_list_prepend (comp->private->expandables,
2402 element);
2386 goto chiringuito; 2403 goto chiringuito;
2387 } 2404 }
2388 2405
@@ -2470,8 +2487,11 @@ gnl_composition_remove_object (GstBin * bin, GstElement * element)
2470 gst_element_set_locked_state (element, FALSE); 2487 gst_element_set_locked_state (element, FALSE);
2471 2488
2472 /* handle default source */ 2489 /* handle default source */
2473 if (((GnlObject *) element)->priority == G_MAXUINT32) { 2490 if ((((GnlObject *) element)->priority == G_MAXUINT32) ||
2474 comp->private->defaultobject = NULL; 2491 GNL_OBJECT_IS_EXPANDABLE (element)) {
2492 /* Find it in the list */
2493 comp->private->expandables =
2494 g_list_remove (comp->private->expandables, element);
2475 } else { 2495 } else {
2476 /* remove it from the objects list and resort the lists */ 2496 /* remove it from the objects list and resort the lists */
2477 comp->private->objects_start = g_list_remove 2497 comp->private->objects_start = g_list_remove
@@ -2487,7 +2507,8 @@ gnl_composition_remove_object (GstBin * bin, GstElement * element)
2487 goto chiringuito; 2507 goto chiringuito;
2488 2508
2489 update_required = OBJECT_IN_ACTIVE_SEGMENT (comp, element) || 2509 update_required = OBJECT_IN_ACTIVE_SEGMENT (comp, element) ||
2490 ((GnlObject *) element)->priority == G_MAXUINT32; 2510 (((GnlObject *) element)->priority == G_MAXUINT32) ||
2511 GNL_OBJECT_IS_EXPANDABLE (element);
2491 2512
2492 if (update_required && comp->private->can_update) { 2513 if (update_required && comp->private->can_update) {
2493 curpos = get_current_position (comp); 2514 curpos = get_current_position (comp);
diff --git a/tests/check/complex.c b/tests/check/complex.c
index 06eca9e..ae9db2a 100644
--- a/tests/check/complex.c
+++ b/tests/check/complex.c
@@ -442,6 +442,250 @@ GST_START_TEST (test_one_default_another)
442 442
443GST_END_TEST; 443GST_END_TEST;
444 444
445GST_START_TEST (test_one_expandable_another)
446{
447 GstElement *pipeline;
448 GstElement *comp, *sink, *source1, *source2, *source3, *defaultsrc;
449 CollectStructure *collect;
450 GstBus *bus;
451 GstMessage *message;
452 gboolean carry_on = TRUE;
453 guint64 start, stop;
454 gint64 duration;
455 GstPad *sinkpad;
456
457 pipeline = gst_pipeline_new ("test_pipeline");
458 comp =
459 gst_element_factory_make_or_warn ("gnlcomposition", "test_composition");
460 fail_if (comp == NULL);
461
462 /*
463 defaultsrc source
464 Start : 0s
465 Duration : 5s
466 Priority : 1000
467 */
468
469 defaultsrc = videotest_gnl_src ("defaultsrc", 0, 5 * GST_SECOND, 2, 1000);
470 g_object_set (defaultsrc, "expandable", TRUE, NULL);
471 fail_if (defaultsrc == NULL);
472 check_start_stop_duration (defaultsrc, 0, 5 * GST_SECOND, 5 * GST_SECOND);
473
474 /*
475 Source 1
476 Start : 1s
477 Duration : 1s
478 Priority : 1
479 */
480 source1 = videotest_gnl_src ("source1", 1 * GST_SECOND, 1 * GST_SECOND, 1, 1);
481 fail_if (source1 == NULL);
482 check_start_stop_duration (source1, GST_SECOND, 2 * GST_SECOND,
483 1 * GST_SECOND);
484
485 /*
486 Source 2
487 Start : 3s
488 Duration : 1s
489 Priority : 1
490 */
491 source2 = videotest_gnl_src ("source2", 3 * GST_SECOND, 1 * GST_SECOND, 2, 1);
492 fail_if (source2 == NULL);
493 check_start_stop_duration (source2, 3 * GST_SECOND, 4 * GST_SECOND,
494 1 * GST_SECOND);
495
496 /*
497 Source 3
498 Start : 4s
499 Duration : 1s
500 Priority : 1
501 */
502 source3 = videotest_gnl_src ("source3", 4 * GST_SECOND, 1 * GST_SECOND, 2, 1);
503 fail_if (source3 == NULL);
504 check_start_stop_duration (source3, 4 * GST_SECOND, 5 * GST_SECOND,
505 1 * GST_SECOND);
506
507
508 /* Add one source */
509
510 gst_bin_add (GST_BIN (comp), source1);
511 check_start_stop_duration (comp, GST_SECOND, 2 * GST_SECOND, 1 * GST_SECOND);
512
513 ASSERT_OBJECT_REFCOUNT (source1, "source1", 1);
514
515 /* defaultsrc source */
516
517 gst_bin_add (GST_BIN (comp), defaultsrc);
518 check_start_stop_duration (comp, 0, 2 * GST_SECOND, 2 * GST_SECOND);
519 check_start_stop_duration (defaultsrc, 0, 2 * GST_SECOND, 2 * GST_SECOND);
520
521 ASSERT_OBJECT_REFCOUNT (defaultsrc, "defaultsrc", 1);
522
523 /* Second source */
524
525 gst_bin_add (GST_BIN (comp), source2);
526 check_start_stop_duration (comp, 0, 4 * GST_SECOND, 4 * GST_SECOND);
527 check_start_stop_duration (defaultsrc, 0, 4 * GST_SECOND, 4 * GST_SECOND);
528
529 ASSERT_OBJECT_REFCOUNT (source2, "source2", 1);
530
531
532 /* Third source */
533
534 gst_bin_add (GST_BIN (comp), source3);
535 check_start_stop_duration (comp, 0, 5 * GST_SECOND, 5 * GST_SECOND);
536 check_start_stop_duration (defaultsrc, 0, 5 * GST_SECOND, 5 * GST_SECOND);
537
538 ASSERT_OBJECT_REFCOUNT (source3, "source3", 1);
539
540
541 sink = gst_element_factory_make_or_warn ("fakesink", "sink");
542 fail_if (sink == NULL);
543
544 gst_bin_add_many (GST_BIN (pipeline), comp, sink, NULL);
545
546 /* Shared data */
547 collect = g_new0 (CollectStructure, 1);
548 collect->comp = comp;
549 collect->sink = sink;
550
551 /* Expected segments */
552 collect->expected_segments = g_list_append (collect->expected_segments,
553 segment_new (1.0, GST_FORMAT_TIME, 0, 1 * GST_SECOND, 0));
554 collect->expected_segments = g_list_append (collect->expected_segments,
555 segment_new (1.0, GST_FORMAT_TIME,
556 1 * GST_SECOND, 2 * GST_SECOND, 1 * GST_SECOND));
557 collect->expected_segments = g_list_append (collect->expected_segments,
558 segment_new (1.0, GST_FORMAT_TIME,
559 2 * GST_SECOND, 3 * GST_SECOND, 2 * GST_SECOND));
560 collect->expected_segments = g_list_append (collect->expected_segments,
561 segment_new (1.0, GST_FORMAT_TIME,
562 3 * GST_SECOND, 4 * GST_SECOND, 3 * GST_SECOND));
563 collect->expected_segments = g_list_append (collect->expected_segments,
564 segment_new (1.0, GST_FORMAT_TIME,
565 4 * GST_SECOND, 5 * GST_SECOND, 4 * GST_SECOND));
566
567 g_signal_connect (G_OBJECT (comp), "pad-added",
568 G_CALLBACK (composition_pad_added_cb), collect);
569
570 sinkpad = gst_element_get_pad (sink, "sink");
571 gst_pad_add_event_probe (sinkpad, G_CALLBACK (sinkpad_event_probe), collect);
572 gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (sinkpad_buffer_probe),
573 collect);
574
575 bus = gst_element_get_bus (GST_ELEMENT (pipeline));
576
577 GST_DEBUG ("Setting pipeline to PLAYING");
578 ASSERT_OBJECT_REFCOUNT (source1, "source1", 1);
579
580 fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
581 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
582
583 GST_DEBUG ("Let's poll the bus");
584
585 while (carry_on) {
586 message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
587 if (message) {
588 switch (GST_MESSAGE_TYPE (message)) {
589 case GST_MESSAGE_EOS:
590 /* we should check if we really finished here */
591 GST_WARNING ("Got an EOS");
592 carry_on = FALSE;
593 break;
594 case GST_MESSAGE_SEGMENT_START:
595 case GST_MESSAGE_SEGMENT_DONE:
596 /* We shouldn't see any segement messages, since we didn't do a segment seek */
597 GST_WARNING ("Saw a Segment start/stop");
598 fail_if (TRUE);
599 break;
600 case GST_MESSAGE_ERROR:
601 GST_WARNING ("Saw an ERROR");
602 fail_if (TRUE);
603 default:
604 break;
605 }
606 gst_mini_object_unref (GST_MINI_OBJECT (message));
607 }
608 }
609
610 GST_DEBUG ("Setting pipeline to NULL");
611
612 fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
613 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
614
615 fail_if (collect->expected_segments != NULL);
616
617 GST_DEBUG ("Resetted pipeline to READY");
618
619 /* Expected segments */
620 /* Expected segments */
621 collect->expected_segments = g_list_append (collect->expected_segments,
622 segment_new (1.0, GST_FORMAT_TIME, 0, 1 * GST_SECOND, 0));
623 collect->expected_segments = g_list_append (collect->expected_segments,
624 segment_new (1.0, GST_FORMAT_TIME,
625 1 * GST_SECOND, 2 * GST_SECOND, 1 * GST_SECOND));
626 collect->expected_segments = g_list_append (collect->expected_segments,
627 segment_new (1.0, GST_FORMAT_TIME,
628 2 * GST_SECOND, 3 * GST_SECOND, 2 * GST_SECOND));
629 collect->expected_segments = g_list_append (collect->expected_segments,
630 segment_new (1.0, GST_FORMAT_TIME,
631 3 * GST_SECOND, 4 * GST_SECOND, 3 * GST_SECOND));
632 collect->expected_segments = g_list_append (collect->expected_segments,
633 segment_new (1.0, GST_FORMAT_TIME,
634 4 * GST_SECOND, 5 * GST_SECOND, 4 * GST_SECOND));
635 collect->gotsegment = FALSE;
636
637
638 GST_DEBUG ("Setting pipeline to PLAYING again");
639
640 fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
641 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
642
643 carry_on = TRUE;
644
645 GST_DEBUG ("Let's poll the bus");
646
647 while (carry_on) {
648 message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
649 if (message) {
650 switch (GST_MESSAGE_TYPE (message)) {
651 case GST_MESSAGE_EOS:
652 /* we should check if we really finished here */
653 carry_on = FALSE;
654 break;
655 case GST_MESSAGE_SEGMENT_START:
656 case GST_MESSAGE_SEGMENT_DONE:
657 /* We shouldn't see any segement messages, since we didn't do a segment seek */
658 GST_WARNING ("Saw a Segment start/stop");
659 fail_if (TRUE);
660 break;
661 case GST_MESSAGE_ERROR:
662 GST_ERROR ("Saw an ERROR");
663 fail_if (TRUE);
664 default:
665 break;
666 }
667 gst_mini_object_unref (GST_MINI_OBJECT (message));
668 } else {
669 GST_DEBUG ("bus_poll responded, but there wasn't any message...");
670 }
671 }
672
673 fail_if (collect->expected_segments != NULL);
674
675 fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
676 GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE);
677
678 gst_object_unref (GST_OBJECT (sinkpad));
679 ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "main pipeline", 1, 2);
680 gst_object_unref (pipeline);
681 ASSERT_OBJECT_REFCOUNT_BETWEEN (bus, "main bus", 1, 2);
682 gst_object_unref (bus);
683
684 g_free (collect);
685}
686
687GST_END_TEST;
688
445 689
446 690
447GST_START_TEST (test_renegotiation) 691GST_START_TEST (test_renegotiation)
@@ -934,6 +1178,7 @@ gnonlin_suite (void)
934 1178
935 tcase_add_test (tc_chain, test_one_space_another); 1179 tcase_add_test (tc_chain, test_one_space_another);
936 tcase_add_test (tc_chain, test_one_default_another); 1180 tcase_add_test (tc_chain, test_one_default_another);
1181 tcase_add_test (tc_chain, test_one_expandable_another);
937 tcase_add_test (tc_chain, test_renegotiation); 1182 tcase_add_test (tc_chain, test_renegotiation);
938 tcase_add_test (tc_chain, test_one_bin_space_another); 1183 tcase_add_test (tc_chain, test_one_bin_space_another);
939 tcase_add_test (tc_chain, test_one_above_another); 1184 tcase_add_test (tc_chain, test_one_above_another);
diff --git a/tests/check/gnloperation.c b/tests/check/gnloperation.c
index aa668f0..4e3b74f 100644
--- a/tests/check/gnloperation.c
+++ b/tests/check/gnloperation.c
@@ -655,6 +655,224 @@ GST_START_TEST (test_pyramid_operations2)
655 655
656GST_END_TEST; 656GST_END_TEST;
657 657
658GST_START_TEST (test_pyramid_operations_expandable)
659{
660 GstElement *pipeline;
661 guint64 start, stop;
662 gint64 duration;
663 GstElement *comp, *oper, *source1, *source2, *def, *sink;
664 CollectStructure *collect;
665 GstBus *bus;
666 GstMessage *message;
667 gboolean carry_on = TRUE;
668 GstPad *sinkpad;
669
670 pipeline = gst_pipeline_new ("test_pipeline");
671 comp =
672 gst_element_factory_make_or_warn ("gnlcomposition", "test_composition");
673
674 /*
675 source1
676 Start : 0s
677 Duration : 2s
678 Priority : 2
679 */
680
681 source1 = videotest_gnl_src ("source1", 0, 2 * GST_SECOND, 1, 2);
682 check_start_stop_duration (source1, 0, 2 * GST_SECOND, 2 * GST_SECOND);
683
684 /*
685 operation (expandable)
686 Start : XX
687 Duration : XX
688 Priority : 1
689 */
690
691 oper = new_operation ("oper", "identity", 1 * GST_SECOND, 4 * GST_SECOND, 1);
692 g_object_set (oper, "expandable", TRUE, NULL);
693 check_start_stop_duration (oper, 1 * GST_SECOND, 5 * GST_SECOND,
694 4 * GST_SECOND);
695
696 /*
697 source2
698 Start : 4s
699 Duration : 2s
700 Priority : 2
701 */
702
703 source2 = videotest_gnl_src ("source2", 4 * GST_SECOND, 2 * GST_SECOND, 1, 2);
704 check_start_stop_duration (source2, 4 * GST_SECOND, 6 * GST_SECOND,
705 2 * GST_SECOND);
706
707 /*
708 def (default source)
709 Priority = G_MAXUINT32
710 */
711 def =
712 videotest_gnl_src ("default", 0 * GST_SECOND, 0 * GST_SECOND, 1,
713 G_MAXUINT32);
714
715 ASSERT_OBJECT_REFCOUNT (source1, "source1", 1);
716 ASSERT_OBJECT_REFCOUNT (source2, "source2", 1);
717 ASSERT_OBJECT_REFCOUNT (oper, "oper", 1);
718 ASSERT_OBJECT_REFCOUNT (def, "default", 1);
719
720 /* Add source 1 */
721
722 gst_bin_add (GST_BIN (comp), source1);
723 check_start_stop_duration (comp, 0, 2 * GST_SECOND, 2 * GST_SECOND);
724
725 /* Add source 2 */
726
727 gst_bin_add (GST_BIN (comp), source2);
728 check_start_stop_duration (comp, 0, 6 * GST_SECOND, 6 * GST_SECOND);
729
730 /* Add operation */
731
732 gst_bin_add (GST_BIN (comp), oper);
733 check_start_stop_duration (comp, 0, 6 * GST_SECOND, 6 * GST_SECOND);
734
735 /* Add default */
736
737 gst_bin_add (GST_BIN (comp), def);
738 check_start_stop_duration (comp, 0, 6 * GST_SECOND, 6 * GST_SECOND);
739
740
741
742 sink = gst_element_factory_make_or_warn ("fakesink", "sink");
743 gst_bin_add_many (GST_BIN (pipeline), comp, sink, NULL);
744
745 /* Shared data */
746 collect = g_new0 (CollectStructure, 1);
747 collect->comp = comp;
748 collect->sink = sink;
749
750 /* Expected segments */
751 collect->expected_segments = g_list_append (collect->expected_segments,
752 segment_new (1.0, GST_FORMAT_TIME, 0, 2 * GST_SECOND, 0));
753 collect->expected_segments = g_list_append (collect->expected_segments,
754 segment_new (1.0, GST_FORMAT_TIME,
755 2 * GST_SECOND, 4 * GST_SECOND, 2 * GST_SECOND));
756 collect->expected_segments = g_list_append (collect->expected_segments,
757 segment_new (1.0, GST_FORMAT_TIME,
758 4 * GST_SECOND, 6 * GST_SECOND, 4 * GST_SECOND));
759
760 g_signal_connect (G_OBJECT (comp), "pad-added",
761 G_CALLBACK (composition_pad_added_cb), collect);
762
763 sinkpad = gst_element_get_pad (sink, "sink");
764 gst_pad_add_event_probe (sinkpad, G_CALLBACK (sinkpad_event_probe), collect);
765 gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (sinkpad_buffer_probe),
766 collect);
767
768 bus = gst_element_get_bus (GST_ELEMENT (pipeline));
769
770 GST_DEBUG ("Setting pipeline to PLAYING");
771 ASSERT_OBJECT_REFCOUNT (source1, "source1", 1);
772
773 fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
774 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
775
776 GST_DEBUG ("Let's poll the bus");
777
778 while (carry_on) {
779 message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
780 if (message) {
781 switch (GST_MESSAGE_TYPE (message)) {
782 case GST_MESSAGE_EOS:
783 /* we should check if we really finished here */
784 GST_WARNING ("Got an EOS");
785 carry_on = FALSE;
786 break;
787 case GST_MESSAGE_SEGMENT_START:
788 case GST_MESSAGE_SEGMENT_DONE:
789 /* We shouldn't see any segement messages, since we didn't do a segment seek */
790 GST_WARNING ("Saw a Segment start/stop");
791 fail_if (TRUE);
792 break;
793 case GST_MESSAGE_ERROR:
794 GST_WARNING ("Saw an ERROR");
795 fail_if (TRUE);
796 default:
797 break;
798 }
799 gst_mini_object_unref (GST_MINI_OBJECT (message));
800 }
801 }
802
803 GST_DEBUG ("Setting pipeline to NULL");
804
805 fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
806 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
807
808 fail_if (collect->expected_segments != NULL);
809
810 GST_DEBUG ("Resetted pipeline to READY");
811
812 /* Expected segments */
813 collect->expected_segments = g_list_append (collect->expected_segments,
814 segment_new (1.0, GST_FORMAT_TIME, 0, 2 * GST_SECOND, 0));
815 collect->expected_segments = g_list_append (collect->expected_segments,
816 segment_new (1.0, GST_FORMAT_TIME,
817 2 * GST_SECOND, 4 * GST_SECOND, 2 * GST_SECOND));
818 collect->expected_segments = g_list_append (collect->expected_segments,
819 segment_new (1.0, GST_FORMAT_TIME,
820 4 * GST_SECOND, 6 * GST_SECOND, 4 * GST_SECOND));
821
822 collect->gotsegment = FALSE;
823
824
825 GST_DEBUG ("Setting pipeline to PLAYING again");
826
827 fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
828 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
829
830 carry_on = TRUE;
831
832 GST_DEBUG ("Let's poll the bus");
833
834 while (carry_on) {
835 message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
836 if (message) {
837 switch (GST_MESSAGE_TYPE (message)) {
838 case GST_MESSAGE_EOS:
839 /* we should check if we really finished here */
840 carry_on = FALSE;
841 break;
842 case GST_MESSAGE_SEGMENT_START:
843 case GST_MESSAGE_SEGMENT_DONE:
844 /* We shouldn't see any segement messages, since we didn't do a segment seek */
845 GST_WARNING ("Saw a Segment start/stop");
846 fail_if (TRUE);
847 break;
848 case GST_MESSAGE_ERROR:
849 GST_ERROR ("Saw an ERROR");
850 fail_if (TRUE);
851 default:
852 break;
853 }
854 gst_mini_object_unref (GST_MINI_OBJECT (message));
855 } else {
856 GST_DEBUG ("bus_poll responded, but there wasn't any message...");
857 }
858 }
859
860 fail_if (collect->expected_segments != NULL);
861
862 fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
863 GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE);
864
865 gst_object_unref (GST_OBJECT (sinkpad));
866 ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "main pipeline", 1, 2);
867 gst_object_unref (pipeline);
868 ASSERT_OBJECT_REFCOUNT_BETWEEN (bus, "main bus", 1, 2);
869 gst_object_unref (bus);
870
871 g_free (collect);
872}
873
874GST_END_TEST;
875
658 876
659 877
660 878
@@ -888,6 +1106,7 @@ gnonlin_suite (void)
888 tcase_add_test (tc_chain, test_simple_operation); 1106 tcase_add_test (tc_chain, test_simple_operation);
889 tcase_add_test (tc_chain, test_pyramid_operations); 1107 tcase_add_test (tc_chain, test_pyramid_operations);
890 tcase_add_test (tc_chain, test_pyramid_operations2); 1108 tcase_add_test (tc_chain, test_pyramid_operations2);
1109 tcase_add_test (tc_chain, test_pyramid_operations_expandable);
891 tcase_add_test (tc_chain, test_complex_operations); 1110 tcase_add_test (tc_chain, test_complex_operations);
892 1111
893 return s; 1112 return s;