mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 11:11:08 +00:00
docs/pwg/advanced-types.xml: Fix description for buffer-frames=0.
Original commit message from CVS: * docs/pwg/advanced-types.xml: Fix description for buffer-frames=0. * docs/gst/tmpl/gstbin.sgml: * gst/gstbin.c: (gst_bin_child_state_change_func), (gst_bin_change_state), (gst_bin_change_state_norecurse): * gst/gstbin.h: * testsuite/threads/Makefile.am: * testsuite/threads/threadi.c: (cb_timeout), (cb_quit), (cb_eos), (cb_state), (cb_play), (main): Fix non-recursive state changes to *really* change the state of the object, and not just call parent_class->state_change. Fix a lot of lockups caused by this. Fixes #132775. Add test for the problem. Also enable test to show #142588 (fixed). * gst/gstthread.c: (gst_thread_change_state), (gst_thread_child_state_change): Don't exit the thread if we go to NULL and are inside thread context. Instead, return control to the main thread context and exit from there. * gst/gstelement.c: (gst_element_disable_threadsafe_properties): Don't unset virtual functions, since those may still be used. That's not necessarily correct, but suffices for now. * configure.ac: * testsuite/Makefile.am: * testsuite/pad/Makefile.am: * testsuite/pad/chainnopull.c: (gst_test_sink_class_init), (gst_test_sink_base_init), (gst_test_sink_chain), (gst_test_sink_init), (main): * testsuite/pad/getnopush.c: (gst_test_src_class_init), (gst_test_src_base_init), (gst_test_src_get), (gst_test_src_init), (main): * testsuite/pad/link.c: (gst_test_element_class_init), (gst_test_element_base_init), (gst_test_src_get), (gst_test_src_loop), (gst_test_src_init), (gst_test_filter_chain), (gst_test_filter_loop), (gst_test_filter_init), (gst_test_sink_chain), (gst_test_sink_loop), (gst_test_sink_init), (cb_error), (main): Add tests to show #150546. Pass, but should fail (currently disabled from the testsuite). * gst/gstscheduler.c: (gst_scheduler_dispose): Dereference child schedulers on dispose (#94464). * testsuite/bytestream/filepadsink.c: (gst_fp_sink_init): Fix typo. * testsuite/threads/thread.c: (main): Add more debug.
This commit is contained in:
parent
10aa48db8d
commit
d8d03b6b98
27 changed files with 1053 additions and 62 deletions
47
ChangeLog
47
ChangeLog
|
@ -1,3 +1,50 @@
|
||||||
|
2005-01-31 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
|
* docs/pwg/advanced-types.xml:
|
||||||
|
Fix description for buffer-frames=0.
|
||||||
|
* docs/gst/tmpl/gstbin.sgml:
|
||||||
|
* gst/gstbin.c: (gst_bin_child_state_change_func),
|
||||||
|
(gst_bin_change_state), (gst_bin_change_state_norecurse):
|
||||||
|
* gst/gstbin.h:
|
||||||
|
* testsuite/threads/Makefile.am:
|
||||||
|
* testsuite/threads/threadi.c: (cb_timeout), (cb_quit), (cb_eos),
|
||||||
|
(cb_state), (cb_play), (main):
|
||||||
|
Fix non-recursive state changes to *really* change the state
|
||||||
|
of the object, and not just call parent_class->state_change.
|
||||||
|
Fix a lot of lockups caused by this. Fixes #132775. Add test
|
||||||
|
for the problem. Also enable test to show #142588 (fixed).
|
||||||
|
* gst/gstthread.c: (gst_thread_change_state),
|
||||||
|
(gst_thread_child_state_change):
|
||||||
|
Don't exit the thread if we go to NULL and are inside thread
|
||||||
|
context. Instead, return control to the main thread context
|
||||||
|
and exit from there.
|
||||||
|
* gst/gstelement.c: (gst_element_disable_threadsafe_properties):
|
||||||
|
Don't unset virtual functions, since those may still be used.
|
||||||
|
That's not necessarily correct, but suffices for now.
|
||||||
|
* configure.ac:
|
||||||
|
* testsuite/Makefile.am:
|
||||||
|
* testsuite/pad/Makefile.am:
|
||||||
|
* testsuite/pad/chainnopull.c: (gst_test_sink_class_init),
|
||||||
|
(gst_test_sink_base_init), (gst_test_sink_chain),
|
||||||
|
(gst_test_sink_init), (main):
|
||||||
|
* testsuite/pad/getnopush.c: (gst_test_src_class_init),
|
||||||
|
(gst_test_src_base_init), (gst_test_src_get), (gst_test_src_init),
|
||||||
|
(main):
|
||||||
|
* testsuite/pad/link.c: (gst_test_element_class_init),
|
||||||
|
(gst_test_element_base_init), (gst_test_src_get),
|
||||||
|
(gst_test_src_loop), (gst_test_src_init), (gst_test_filter_chain),
|
||||||
|
(gst_test_filter_loop), (gst_test_filter_init),
|
||||||
|
(gst_test_sink_chain), (gst_test_sink_loop), (gst_test_sink_init),
|
||||||
|
(cb_error), (main):
|
||||||
|
Add tests to show #150546. Pass, but should fail (currently
|
||||||
|
disabled from the testsuite).
|
||||||
|
* gst/gstscheduler.c: (gst_scheduler_dispose):
|
||||||
|
Dereference child schedulers on dispose (#94464).
|
||||||
|
* testsuite/bytestream/filepadsink.c: (gst_fp_sink_init):
|
||||||
|
Fix typo.
|
||||||
|
* testsuite/threads/thread.c: (main):
|
||||||
|
Add more debug.
|
||||||
|
|
||||||
2005-01-29 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
2005-01-29 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
* gst/gstpad.c: (gst_pad_push):
|
* gst/gstpad.c: (gst_pad_push):
|
||||||
|
|
|
@ -684,6 +684,7 @@ testsuite/elements/Makefile
|
||||||
testsuite/ghostpads/Makefile
|
testsuite/ghostpads/Makefile
|
||||||
testsuite/indexers/Makefile
|
testsuite/indexers/Makefile
|
||||||
testsuite/negotiation/Makefile
|
testsuite/negotiation/Makefile
|
||||||
|
testsuite/pad/Makefile
|
||||||
testsuite/parse/Makefile
|
testsuite/parse/Makefile
|
||||||
testsuite/plugin/Makefile
|
testsuite/plugin/Makefile
|
||||||
testsuite/refcounting/Makefile
|
testsuite/refcounting/Makefile
|
||||||
|
|
|
@ -98,6 +98,7 @@ FALSE.
|
||||||
@GST_BIN_SELF_SCHEDULABLE:
|
@GST_BIN_SELF_SCHEDULABLE:
|
||||||
@GST_BIN_FLAG_PREFER_COTHREADS:
|
@GST_BIN_FLAG_PREFER_COTHREADS:
|
||||||
@GST_BIN_FLAG_FIXED_CLOCK:
|
@GST_BIN_FLAG_FIXED_CLOCK:
|
||||||
|
@GST_BIN_STATE_LOCKED:
|
||||||
@GST_BIN_FLAG_LAST:
|
@GST_BIN_FLAG_LAST:
|
||||||
|
|
||||||
<!-- ##### FUNCTION gst_bin_new ##### -->
|
<!-- ##### FUNCTION gst_bin_new ##### -->
|
||||||
|
|
|
@ -334,14 +334,16 @@ plugin_init (GstPlugin *plugin)
|
||||||
<row>
|
<row>
|
||||||
<entry>buffer-frames</entry>
|
<entry>buffer-frames</entry>
|
||||||
<entry>integer</entry>
|
<entry>integer</entry>
|
||||||
<entry>greater than 0</entry>
|
<entry>Any</entry>
|
||||||
<entry>
|
<entry>
|
||||||
The number of frames per buffer. The reason for this property
|
The number of frames per buffer. The reason for this property
|
||||||
is that the element does not need to reuse buffers or use data
|
is that the element does not need to reuse buffers or use data
|
||||||
spanned over multiple buffers, so this property - when used
|
spanned over multiple buffers, so this property - when used
|
||||||
rightly - will decrease latency. Note that some people think that
|
rightly - will decrease latency. Note that some people think that
|
||||||
this property is very ugly, whereas others think it is vital for
|
this property is very ugly, whereas others think it is vital for
|
||||||
the use of &GStreamer; in professional audio applications.
|
the use of &GStreamer; in professional audio applications. The
|
||||||
|
special value zero is reserved and implies that size is variable
|
||||||
|
between buffers.
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
|
71
gst/gstbin.c
71
gst/gstbin.c
|
@ -705,10 +705,14 @@ gst_bin_child_state_change_func (GstBin * bin, GstElementState oldstate,
|
||||||
bin->child_states[new_idx]++;
|
bin->child_states[new_idx]++;
|
||||||
|
|
||||||
for (i = GST_NUM_STATES - 1; i >= 0; i--) {
|
for (i = GST_NUM_STATES - 1; i >= 0; i--) {
|
||||||
if (bin->child_states[i] != 0) {
|
if (bin->child_states[i] != 0 || i == 0) {
|
||||||
gint state = (1 << i);
|
gint state = (1 << i);
|
||||||
|
|
||||||
if (GST_STATE (bin) != state) {
|
/* We only change state on the parent if the state is not locked.
|
||||||
|
* State locking can occur if the bin itself set state on children,
|
||||||
|
* which should not recurse since it leads to infinite loops. */
|
||||||
|
if (GST_STATE (bin) != state &&
|
||||||
|
!GST_FLAG_IS_SET (bin, GST_BIN_STATE_LOCKED)) {
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
"highest child state is %s, changing bin state accordingly",
|
"highest child state is %s, changing bin state accordingly",
|
||||||
gst_element_state_get_name (state));
|
gst_element_state_get_name (state));
|
||||||
|
@ -832,7 +836,6 @@ gst_bin_change_state (GstElement * element)
|
||||||
GstBin *bin;
|
GstBin *bin;
|
||||||
GstElementStateReturn ret;
|
GstElementStateReturn ret;
|
||||||
GstElementState old_state, pending;
|
GstElementState old_state, pending;
|
||||||
SetKidStateData data;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_BIN (element), GST_STATE_FAILURE);
|
g_return_val_if_fail (GST_IS_BIN (element), GST_STATE_FAILURE);
|
||||||
|
|
||||||
|
@ -849,27 +852,43 @@ gst_bin_change_state (GstElement * element)
|
||||||
if (pending == GST_STATE_VOID_PENDING)
|
if (pending == GST_STATE_VOID_PENDING)
|
||||||
return GST_STATE_SUCCESS;
|
return GST_STATE_SUCCESS;
|
||||||
|
|
||||||
data.pending = pending;
|
/* If we're changing state non-recursively (see _norecurse()),
|
||||||
data.result = GST_STATE_SUCCESS;
|
* this flag is already set and we should not set children states. */
|
||||||
if (!gst_bin_foreach (bin, set_kid_state_func, &data)) {
|
if (!GST_FLAG_IS_SET (bin, GST_BIN_STATE_LOCKED)) {
|
||||||
GST_STATE_PENDING (element) = old_state;
|
SetKidStateData data;
|
||||||
return GST_STATE_FAILURE;
|
|
||||||
|
/* So now we use this flag to make sure that kids don't re-set our
|
||||||
|
* state, which would lead to infinite loops. */
|
||||||
|
GST_FLAG_SET (bin, GST_BIN_STATE_LOCKED);
|
||||||
|
data.pending = pending;
|
||||||
|
data.result = GST_STATE_SUCCESS;
|
||||||
|
if (!gst_bin_foreach (bin, set_kid_state_func, &data)) {
|
||||||
|
GST_FLAG_UNSET (bin, GST_BIN_STATE_LOCKED);
|
||||||
|
GST_STATE_PENDING (element) = old_state;
|
||||||
|
return GST_STATE_FAILURE;
|
||||||
|
}
|
||||||
|
GST_FLAG_UNSET (bin, GST_BIN_STATE_LOCKED);
|
||||||
|
|
||||||
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||||
|
"done changing bin's state from %s to %s, now in %s",
|
||||||
|
gst_element_state_get_name (old_state),
|
||||||
|
gst_element_state_get_name (pending),
|
||||||
|
gst_element_state_get_name (GST_STATE (element)));
|
||||||
|
|
||||||
|
/* if we're async, the kids will change state later (when the
|
||||||
|
* lock-state flag is no longer held) and all will be fine. */
|
||||||
|
if (data.result == GST_STATE_ASYNC)
|
||||||
|
return GST_STATE_ASYNC;
|
||||||
|
} else {
|
||||||
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||||
|
"Not recursing state change onto children");
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
/* FIXME: this should have been done by the children already, no? */
|
||||||
"done changing bin's state from %s to %s, now in %s",
|
if (parent_class->change_state) {
|
||||||
gst_element_state_get_name (old_state),
|
ret = parent_class->change_state (element);
|
||||||
gst_element_state_get_name (pending),
|
} else {
|
||||||
gst_element_state_get_name (GST_STATE (element)));
|
ret = GST_STATE_SUCCESS;
|
||||||
|
|
||||||
if (data.result == GST_STATE_ASYNC)
|
|
||||||
ret = GST_STATE_ASYNC;
|
|
||||||
else {
|
|
||||||
/* FIXME: this should have been done by the children already, no? */
|
|
||||||
if (parent_class->change_state) {
|
|
||||||
ret = parent_class->change_state (element);
|
|
||||||
} else
|
|
||||||
ret = GST_STATE_SUCCESS;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -900,9 +919,13 @@ gst_bin_change_state_norecurse (GstBin * bin)
|
||||||
{
|
{
|
||||||
GstElementStateReturn ret;
|
GstElementStateReturn ret;
|
||||||
|
|
||||||
if (parent_class->change_state) {
|
if (GST_ELEMENT_GET_CLASS (bin)->change_state) {
|
||||||
GST_CAT_LOG_OBJECT (GST_CAT_STATES, bin, "setting bin's own state");
|
GST_CAT_LOG_OBJECT (GST_CAT_STATES, bin, "setting bin's own state");
|
||||||
ret = parent_class->change_state (GST_ELEMENT (bin));
|
|
||||||
|
/* Non-recursive state change flag */
|
||||||
|
GST_FLAG_SET (bin, GST_BIN_STATE_LOCKED);
|
||||||
|
ret = GST_ELEMENT_GET_CLASS (bin)->change_state (GST_ELEMENT (bin));
|
||||||
|
GST_FLAG_UNSET (bin, GST_BIN_STATE_LOCKED);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
} else
|
} else
|
||||||
|
|
26
gst/gstbin.h
26
gst/gstbin.h
|
@ -39,20 +39,30 @@ GST_EXPORT GType _gst_bin_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstBinFlags:
|
* GstBinFlags:
|
||||||
* @GST_BIN_FLAG_MANAGER: This bin has a scheduler and can be used as a toplevel bin.
|
* @GST_BIN_FLAG_MANAGER: this bin is a manager of child elements, i.e.
|
||||||
* @GST_BIN_SELF_SCHEDULABLE: This bin iterates itself, so no calls to gst_bin_iterate() should be made.
|
* a pipeline or thread.
|
||||||
* @GST_BIN_FLAG_PREFER_COTHREADS: This bin preferes to have its elements scheduled with cothreads
|
* @GST_BIN_SELF_SCHEDULABLE: the bin iterates itself.
|
||||||
* @GST_BIN_FLAG_FIXED_CLOCK: This bin uses a fixed clock, possibly the one set with gst_bin_use_clock().
|
* @GST_BIN_FLAG_PREFER_COTHREADS: we prefer to have cothreads when its
|
||||||
* @GST_BIN_FLAG_LAST: id of last for chaining flsg definitions
|
* an option, over chain-based.
|
||||||
*
|
* @GST_BIN_FLAG_FIXED_CLOCK: bin has one clock that cannot be changed.
|
||||||
* Flags for a #GstBin .
|
* @GST_BIN_STATE_LOCKED: indicator that we are in a non-recursive
|
||||||
|
* state-change on the bin, or that kids should not change parent state.
|
||||||
|
* Both are internally used to prevent infinitely recursive loops of
|
||||||
|
* state changes. Since they are mutually exclusive and serve the same
|
||||||
|
* purpose, we use the same flag for them.
|
||||||
|
* @GST_BIN_FLAG_LAST: the last enum in the series of flags in a bin,
|
||||||
|
* derived classes can use this as first value in a list of flags.
|
||||||
|
*
|
||||||
|
* GstBinFlags are a set of flags specific to bins. Most are set/used
|
||||||
|
* internally. They can be checked using the GST_FLAG_IS_SET () macro,
|
||||||
|
* and (un)set using GST_FLAG_SET () and GST_FLAG_UNSET ().
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_BIN_FLAG_MANAGER = GST_ELEMENT_FLAG_LAST,
|
GST_BIN_FLAG_MANAGER = GST_ELEMENT_FLAG_LAST,
|
||||||
GST_BIN_SELF_SCHEDULABLE,
|
GST_BIN_SELF_SCHEDULABLE,
|
||||||
GST_BIN_FLAG_PREFER_COTHREADS,
|
GST_BIN_FLAG_PREFER_COTHREADS,
|
||||||
GST_BIN_FLAG_FIXED_CLOCK,
|
GST_BIN_FLAG_FIXED_CLOCK,
|
||||||
/* padding */
|
GST_BIN_STATE_LOCKED,
|
||||||
GST_BIN_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 5
|
GST_BIN_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 5
|
||||||
} GstBinFlags;
|
} GstBinFlags;
|
||||||
|
|
||||||
|
|
|
@ -398,8 +398,9 @@ gst_element_disable_threadsafe_properties (GstElement * element)
|
||||||
g_return_if_fail (GST_IS_ELEMENT (element));
|
g_return_if_fail (GST_IS_ELEMENT (element));
|
||||||
|
|
||||||
GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
|
GST_FLAG_UNSET (element, GST_ELEMENT_USE_THREADSAFE_PROPERTIES);
|
||||||
element->pre_run_func = NULL;
|
|
||||||
element->post_run_func = NULL;
|
//element->pre_run_func = NULL;
|
||||||
|
//element->post_run_func = NULL;
|
||||||
/* let's keep around that async queue */
|
/* let's keep around that async queue */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,12 @@ gst_scheduler_dispose (GObject * object)
|
||||||
gst_object_replace ((GstObject **) & sched->current_clock, NULL);
|
gst_object_replace ((GstObject **) & sched->current_clock, NULL);
|
||||||
gst_object_replace ((GstObject **) & sched->clock, NULL);
|
gst_object_replace ((GstObject **) & sched->clock, NULL);
|
||||||
|
|
||||||
|
/* kids are held reference to, so dereference here. */
|
||||||
|
while (sched->schedulers != NULL) {
|
||||||
|
gst_scheduler_remove_scheduler (sched,
|
||||||
|
GST_SCHEDULER (sched->schedulers->data));
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -508,24 +508,10 @@ gst_thread_change_state (GstElement * element)
|
||||||
if (thread->thread_id != NULL) {
|
if (thread->thread_id != NULL) {
|
||||||
thread->thread_id = NULL;
|
thread->thread_id = NULL;
|
||||||
if (is_self) {
|
if (is_self) {
|
||||||
/* or should we continue? */
|
|
||||||
GST_LOG_OBJECT (thread,
|
GST_LOG_OBJECT (thread,
|
||||||
"Thread %s is destroying itself. Function call will not return!",
|
"Thread %s is destroying itself. Returning to mainloop ASAP!",
|
||||||
GST_ELEMENT_NAME (thread));
|
GST_ELEMENT_NAME (thread));
|
||||||
gst_scheduler_reset (GST_ELEMENT_SCHED (thread));
|
break;
|
||||||
|
|
||||||
/* unlock and signal - we are out */
|
|
||||||
GST_DEBUG_OBJECT (thread, "signal");
|
|
||||||
g_cond_signal (thread->cond);
|
|
||||||
GST_DEBUG_OBJECT (thread, "unlock");
|
|
||||||
g_mutex_unlock (thread->lock);
|
|
||||||
|
|
||||||
GST_INFO_OBJECT (thread, "GThread %p is exiting", g_thread_self ());
|
|
||||||
|
|
||||||
g_signal_emit (G_OBJECT (thread), gst_thread_signals[SHUTDOWN], 0);
|
|
||||||
|
|
||||||
g_thread_exit (NULL);
|
|
||||||
return GST_STATE_SUCCESS;
|
|
||||||
} else {
|
} else {
|
||||||
/* now wait for the thread to destroy itself */
|
/* now wait for the thread to destroy itself */
|
||||||
GST_DEBUG_OBJECT (thread, "signal");
|
GST_DEBUG_OBJECT (thread, "signal");
|
||||||
|
@ -548,6 +534,17 @@ gst_thread_change_state (GstElement * element)
|
||||||
} else {
|
} else {
|
||||||
ret = GST_STATE_SUCCESS;
|
ret = GST_STATE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_mutex_lock (thread->lock);
|
||||||
|
if (GST_STATE (thread) == GST_STATE_PLAYING &&
|
||||||
|
GST_FLAG_IS_SET (thread, GST_THREAD_STATE_WAITING)) {
|
||||||
|
GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
|
||||||
|
if (!is_self) {
|
||||||
|
g_cond_signal (thread->cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_mutex_unlock (thread->lock);
|
||||||
|
|
||||||
if (!is_self)
|
if (!is_self)
|
||||||
g_mutex_unlock (thread->iterate_lock);
|
g_mutex_unlock (thread->iterate_lock);
|
||||||
|
|
||||||
|
@ -595,6 +592,13 @@ gst_thread_child_state_change (GstBin * bin, GstElementState oldstate,
|
||||||
if (parent_class->child_state_change)
|
if (parent_class->child_state_change)
|
||||||
parent_class->child_state_change (bin, oldstate, newstate, element);
|
parent_class->child_state_change (bin, oldstate, newstate, element);
|
||||||
|
|
||||||
|
/* if we're changing from playing to paused, kids will one-by-one go
|
||||||
|
* to paused while we're playing, which is bad if we execute the code
|
||||||
|
* below. We should only do that when a child explicitely changed
|
||||||
|
* state outside our own context. */
|
||||||
|
if (GST_FLAG_IS_SET (bin, GST_BIN_STATE_LOCKED))
|
||||||
|
return;
|
||||||
|
|
||||||
/* see if we have to wake up the thread now. */
|
/* see if we have to wake up the thread now. */
|
||||||
if (is_self) {
|
if (is_self) {
|
||||||
GST_LOG_OBJECT (element, "we are in the thread context");
|
GST_LOG_OBJECT (element, "we are in the thread context");
|
||||||
|
|
|
@ -17,7 +17,7 @@ SUBDIRS = \
|
||||||
bins bytestream caps cleanup clock \
|
bins bytestream caps cleanup clock \
|
||||||
$(GST_DEBUG_DIRS) \
|
$(GST_DEBUG_DIRS) \
|
||||||
dlopen dynparams \
|
dlopen dynparams \
|
||||||
elements ghostpads indexers negotiation \
|
elements ghostpads indexers negotiation pad \
|
||||||
$(GST_PARSE_DIRS) \
|
$(GST_PARSE_DIRS) \
|
||||||
plugin refcounting schedulers states tags threads
|
plugin refcounting schedulers states tags threads
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ DIST_SUBDIRS = \
|
||||||
bins bytestream caps cleanup clock \
|
bins bytestream caps cleanup clock \
|
||||||
debug \
|
debug \
|
||||||
dlopen dynparams \
|
dlopen dynparams \
|
||||||
elements ghostpads indexers negotiation \
|
elements ghostpads indexers negotiation pad \
|
||||||
parse \
|
parse \
|
||||||
plugin refcounting schedulers states tags threads
|
plugin refcounting schedulers states tags threads
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ gst_fp_sink_init (GstFpSink * fp)
|
||||||
|
|
||||||
fp->sinkpad =
|
fp->sinkpad =
|
||||||
GST_FILE_PAD (gst_file_pad_new (gst_static_pad_template_get (&template),
|
GST_FILE_PAD (gst_file_pad_new (gst_static_pad_template_get (&template),
|
||||||
"src"));
|
"sink"));
|
||||||
gst_file_pad_set_iterate_function (fp->sinkpad, do_tests);
|
gst_file_pad_set_iterate_function (fp->sinkpad, do_tests);
|
||||||
gst_element_add_pad (GST_ELEMENT (fp), GST_PAD (fp->sinkpad));
|
gst_element_add_pad (GST_ELEMENT (fp), GST_PAD (fp->sinkpad));
|
||||||
}
|
}
|
||||||
|
|
5
tests/old/testsuite/pad/Makefile.am
Normal file
5
tests/old/testsuite/pad/Makefile.am
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
include ../Rules
|
||||||
|
|
||||||
|
tests_pass = link
|
||||||
|
tests_fail =
|
||||||
|
tests_ignore = chainnopull getnopush
|
66
tests/old/testsuite/pad/chainnopull.c
Normal file
66
tests/old/testsuite/pad/chainnopull.c
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* this tests that chain-based pads don't pull.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
typedef struct _GstTestSink
|
||||||
|
{
|
||||||
|
GstElement parent;
|
||||||
|
GstPad *sinkpad;
|
||||||
|
} GstTestSink;
|
||||||
|
|
||||||
|
typedef GstElementClass GstTestSinkClass;
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_class_init (GstTestSinkClass * klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_chain (GstPad * pad, GstData * data)
|
||||||
|
{
|
||||||
|
data = gst_pad_pull (pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_init (GstTestSink * sink)
|
||||||
|
{
|
||||||
|
sink->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||||
|
gst_pad_set_chain_function (sink->sinkpad, gst_test_sink_chain);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (sink), sink->sinkpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_BOILERPLATE (GstTestSink, gst_test_sink, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GstElement *pipeline, *fakesrc, *testsink;
|
||||||
|
gint n;
|
||||||
|
|
||||||
|
gst_init (&argc, &argv);
|
||||||
|
|
||||||
|
pipeline = gst_pipeline_new ("p");
|
||||||
|
fakesrc = gst_element_factory_make ("fakesrc", "src");
|
||||||
|
testsink = g_object_new (gst_test_sink_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (testsink), "sink");
|
||||||
|
gst_bin_add_many (GST_BIN (pipeline), fakesrc, testsink, NULL);
|
||||||
|
gst_element_link (fakesrc, testsink);
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
|
|
||||||
|
for (n = 0; n < 100; n++) {
|
||||||
|
if (!gst_bin_iterate (GST_BIN (pipeline)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref (GST_OBJECT (pipeline));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
71
tests/old/testsuite/pad/getnopush.c
Normal file
71
tests/old/testsuite/pad/getnopush.c
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* this tests that get-based pads don't push.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
typedef struct _GstTestSrc
|
||||||
|
{
|
||||||
|
GstElement parent;
|
||||||
|
GstPad *srcpad;
|
||||||
|
} GstTestSrc;
|
||||||
|
|
||||||
|
typedef GstElementClass GstTestSrcClass;
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_src_class_init (GstTestSrcClass * klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
gst_test_src_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstData *
|
||||||
|
gst_test_src_get (GstPad * pad)
|
||||||
|
{
|
||||||
|
GstEvent *event;
|
||||||
|
|
||||||
|
event = gst_event_new (GST_EVENT_INTERRUPT);
|
||||||
|
gst_event_ref (event);
|
||||||
|
gst_pad_push (pad, GST_DATA (event));
|
||||||
|
|
||||||
|
return GST_DATA (event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_src_init (GstTestSrc * src)
|
||||||
|
{
|
||||||
|
src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
|
gst_pad_set_get_function (src->srcpad, gst_test_src_get);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_BOILERPLATE (GstTestSrc, gst_test_src, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GstElement *pipeline, *testsrc, *fakesink;
|
||||||
|
gint n;
|
||||||
|
|
||||||
|
gst_init (&argc, &argv);
|
||||||
|
|
||||||
|
pipeline = gst_pipeline_new ("p");
|
||||||
|
testsrc = g_object_new (gst_test_src_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (testsrc), "src");
|
||||||
|
fakesink = gst_element_factory_make ("fakesink", "sink");
|
||||||
|
gst_bin_add_many (GST_BIN (pipeline), testsrc, fakesink, NULL);
|
||||||
|
gst_element_link (testsrc, fakesink);
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
|
|
||||||
|
for (n = 0; n < 100; n++) {
|
||||||
|
if (!gst_bin_iterate (GST_BIN (pipeline)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref (GST_OBJECT (pipeline));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
194
tests/old/testsuite/pad/link.c
Normal file
194
tests/old/testsuite/pad/link.c
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
* Test that:
|
||||||
|
* - get-based sources can return data, loop-based sources can push.
|
||||||
|
* - chain-based filters receive/push, loop-based filters can pull/push.
|
||||||
|
* - chain-based sinks receive, loop-based sinks pull.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scary type code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct _GstTestElement
|
||||||
|
{
|
||||||
|
GstElement parent;
|
||||||
|
GstPad *srcpad, *sinkpad;
|
||||||
|
} GstTestSrc, GstTestFilter, GstTestSink, GstTestElement;
|
||||||
|
|
||||||
|
typedef GstElementClass GstTestSrcClass, GstTestFilterClass, GstTestSinkClass,
|
||||||
|
GstTestElementClass;
|
||||||
|
|
||||||
|
#define gst_test_src_class_init gst_test_element_class_init
|
||||||
|
#define gst_test_filter_class_init gst_test_element_class_init
|
||||||
|
#define gst_test_sink_class_init gst_test_element_class_init
|
||||||
|
|
||||||
|
#define gst_test_src_base_init gst_test_element_base_init
|
||||||
|
#define gst_test_filter_base_init gst_test_element_base_init
|
||||||
|
#define gst_test_sink_base_init gst_test_element_base_init
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_element_class_init (GstTestElementClass * klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
gst_test_element_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actual element code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
gboolean loop = FALSE;
|
||||||
|
|
||||||
|
static GstData *
|
||||||
|
gst_test_src_get (GstPad * pad)
|
||||||
|
{
|
||||||
|
return GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_src_loop (GstElement * element)
|
||||||
|
{
|
||||||
|
GstTestSrc *src = (GstTestElement *) element;
|
||||||
|
|
||||||
|
gst_pad_push (src->srcpad, gst_test_src_get (src->srcpad));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_src_init (GstTestElement * src)
|
||||||
|
{
|
||||||
|
src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
|
if (loop) {
|
||||||
|
gst_element_set_loop_function (GST_ELEMENT (src), gst_test_src_loop);
|
||||||
|
} else {
|
||||||
|
gst_pad_set_get_function (src->srcpad, gst_test_src_get);
|
||||||
|
}
|
||||||
|
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
|
||||||
|
|
||||||
|
GST_FLAG_SET (src, GST_ELEMENT_EVENT_AWARE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_filter_chain (GstPad * pad, GstData * data)
|
||||||
|
{
|
||||||
|
GstTestFilter *filter = (GstTestElement *) gst_pad_get_parent (pad);
|
||||||
|
|
||||||
|
gst_pad_push (filter->srcpad, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_filter_loop (GstElement * element)
|
||||||
|
{
|
||||||
|
GstTestFilter *filter = (GstTestElement *) element;
|
||||||
|
|
||||||
|
gst_test_filter_chain (filter->sinkpad, gst_pad_pull (filter->sinkpad));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_filter_init (GstTestElement * filter)
|
||||||
|
{
|
||||||
|
filter->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||||
|
if (loop) {
|
||||||
|
gst_element_set_loop_function (GST_ELEMENT (filter), gst_test_filter_loop);
|
||||||
|
} else {
|
||||||
|
gst_pad_set_chain_function (filter->sinkpad, gst_test_filter_chain);
|
||||||
|
}
|
||||||
|
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
|
||||||
|
|
||||||
|
filter->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
|
||||||
|
|
||||||
|
GST_FLAG_SET (filter, GST_ELEMENT_EVENT_AWARE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_chain (GstPad * pad, GstData * data)
|
||||||
|
{
|
||||||
|
gst_data_unref (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_loop (GstElement * element)
|
||||||
|
{
|
||||||
|
GstTestSink *sink = (GstTestElement *) element;
|
||||||
|
|
||||||
|
gst_test_sink_chain (sink->sinkpad, gst_pad_pull (sink->sinkpad));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_init (GstTestElement * sink)
|
||||||
|
{
|
||||||
|
sink->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||||
|
if (loop) {
|
||||||
|
gst_element_set_loop_function (GST_ELEMENT (sink), gst_test_sink_loop);
|
||||||
|
} else {
|
||||||
|
gst_pad_set_chain_function (sink->sinkpad, gst_test_sink_chain);
|
||||||
|
}
|
||||||
|
gst_element_add_pad (GST_ELEMENT (sink), sink->sinkpad);
|
||||||
|
|
||||||
|
GST_FLAG_SET (sink, GST_ELEMENT_EVENT_AWARE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define parent_class src_parent_class
|
||||||
|
GST_BOILERPLATE (GstTestSrc, gst_test_src, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
#undef parent_class
|
||||||
|
#define parent_class filter_parent_class
|
||||||
|
GST_BOILERPLATE (GstTestFilter, gst_test_filter, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
#undef parent_class
|
||||||
|
#define parent_class sink_parent_class
|
||||||
|
GST_BOILERPLATE (GstTestSink, gst_test_sink, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
#undef parent_class
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actual test.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
cb_error (GstElement * element)
|
||||||
|
{
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GstElement *pipeline, *src, *filter, *sink;
|
||||||
|
gint n, r;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
gst_init (&argc, &argv);
|
||||||
|
|
||||||
|
for (r = 0; r < 2; r++) {
|
||||||
|
pipeline = gst_pipeline_new ("p");
|
||||||
|
g_signal_connect (pipeline, "error", G_CALLBACK (cb_error), NULL);
|
||||||
|
src = g_object_new (gst_test_src_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (src), "src");
|
||||||
|
filter = g_object_new (gst_test_filter_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (filter), "filter");
|
||||||
|
sink = g_object_new (gst_test_sink_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (sink), "sink");
|
||||||
|
gst_bin_add_many (GST_BIN (pipeline), src, filter, sink, NULL);
|
||||||
|
res = gst_element_link (src, filter);
|
||||||
|
g_assert (res);
|
||||||
|
res = gst_element_link (filter, sink);
|
||||||
|
g_assert (res);
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
|
|
||||||
|
for (n = 0; n < 100; n++) {
|
||||||
|
if (!gst_bin_iterate (GST_BIN (pipeline)))
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref (GST_OBJECT (pipeline));
|
||||||
|
|
||||||
|
/* switch element types */
|
||||||
|
g_print ("Loop=%s done\n", loop ? "true" : "false");
|
||||||
|
loop = !loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
include ../Rules
|
include ../Rules
|
||||||
|
|
||||||
tests_pass = thread1 thread2 thread3 thread4 thread5 threade threadf signal1 159852
|
tests_pass = thread1 thread2 thread3 thread4 thread5 threade threadf signal1 159852 threadg threadi
|
||||||
tests_fail = 159566 signal2 signal3
|
tests_fail = 159566 signal2 signal3
|
||||||
|
|
||||||
# threadh
|
# threadh
|
||||||
|
|
||||||
tests_ignore = queue threadb threadc threadd staticrec threadg
|
tests_ignore = queue threadb threadc threadd staticrec
|
||||||
|
|
||||||
thread1_SOURCES = thread.c
|
thread1_SOURCES = thread.c
|
||||||
thread1_CFLAGS = -DTESTNUM=1 $(AM_CFLAGS)
|
thread1_CFLAGS = -DTESTNUM=1 $(AM_CFLAGS)
|
||||||
|
|
|
@ -95,6 +95,7 @@ main (gint argc, gchar * argv[])
|
||||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
g_print ("running ...\n");
|
g_print ("running ...\n");
|
||||||
while (gst_bin_iterate (GST_BIN (pipeline)));
|
while (gst_bin_iterate (GST_BIN (pipeline)));
|
||||||
|
g_print ("done ...\n");
|
||||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
}
|
}
|
||||||
if (TESTNUM == 4) {
|
if (TESTNUM == 4) {
|
||||||
|
|
111
tests/old/testsuite/threads/threadi.c
Normal file
111
tests/old/testsuite/threads/threadi.c
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Test two ways of going non-lineairly to PLAYING. Both tests have a thread
|
||||||
|
* containing a fakesrc/sink and a containing thread.
|
||||||
|
*
|
||||||
|
* Test 1 tests by adding fakesrc, putting thread to PLAYING, adding
|
||||||
|
* fakesink, syncing state and see if it iterates.
|
||||||
|
*
|
||||||
|
* Test2 tests by adding fakesrc/fakesink, setting fakesrc to PLAYING
|
||||||
|
* (which should increment the container state) and then synchronizing
|
||||||
|
* state. This reflects bug #123775.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
static GstElement *pipeline, *fakesrc, *fakesink;
|
||||||
|
gboolean bug = FALSE;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cb_timeout (gpointer data)
|
||||||
|
{
|
||||||
|
g_assert_not_reached ();
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cb_quit (gpointer data)
|
||||||
|
{
|
||||||
|
gst_main_quit ();
|
||||||
|
|
||||||
|
g_print ("Quit mainloop\n");
|
||||||
|
|
||||||
|
/* once */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cb_eos (gpointer data)
|
||||||
|
{
|
||||||
|
g_print ("Received EOS\n");
|
||||||
|
|
||||||
|
g_idle_add ((GSourceFunc) cb_quit, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cb_state (GstElement * element, GstElementState old_state,
|
||||||
|
GstElementState new_state, gpointer data)
|
||||||
|
{
|
||||||
|
g_print ("Changed state from %d to %d\n", old_state, new_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cb_play (gpointer data)
|
||||||
|
{
|
||||||
|
GstElementStateReturn res;
|
||||||
|
|
||||||
|
if (bug) {
|
||||||
|
g_print ("Setting state\n");
|
||||||
|
gst_element_set_state (fakesrc, GST_STATE_PLAYING);
|
||||||
|
g_print ("Done\n");
|
||||||
|
} else {
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
|
gst_bin_add (GST_BIN (pipeline), fakesink);
|
||||||
|
}
|
||||||
|
g_print ("Syncing state\n");
|
||||||
|
res = gst_bin_sync_children_state (GST_BIN (data));
|
||||||
|
g_assert (res == GST_STATE_SUCCESS);
|
||||||
|
|
||||||
|
g_print ("Set to playing correctly: %d\n", GST_STATE (pipeline));
|
||||||
|
|
||||||
|
/* once */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
main (gint argc, gchar * argv[])
|
||||||
|
{
|
||||||
|
gint n, id;
|
||||||
|
|
||||||
|
gst_init (&argc, &argv);
|
||||||
|
|
||||||
|
for (n = 0; n < 2; n++) {
|
||||||
|
pipeline = gst_thread_new ("p");
|
||||||
|
g_signal_connect (pipeline, "state-change", G_CALLBACK (cb_state), NULL);
|
||||||
|
fakesrc = gst_element_factory_make ("fakesrc", "src");
|
||||||
|
g_object_set (G_OBJECT (fakesrc), "num-buffers", 1, NULL);
|
||||||
|
fakesink = gst_element_factory_make ("fakesink", "sink");
|
||||||
|
if (bug) {
|
||||||
|
gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
|
||||||
|
} else {
|
||||||
|
gst_bin_add (GST_BIN (pipeline), fakesrc);
|
||||||
|
}
|
||||||
|
gst_element_link (fakesrc, fakesink);
|
||||||
|
g_signal_connect (pipeline, "eos", G_CALLBACK (cb_eos), NULL);
|
||||||
|
g_idle_add ((GSourceFunc) cb_play, pipeline);
|
||||||
|
|
||||||
|
/* give 5 seconds */
|
||||||
|
id = g_timeout_add (5000, (GSourceFunc) cb_timeout, NULL);
|
||||||
|
g_print ("Enter mainloop\n");
|
||||||
|
gst_main ();
|
||||||
|
g_source_remove (id);
|
||||||
|
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref (GST_OBJECT (pipeline));
|
||||||
|
|
||||||
|
g_print ("Done with reproduce-bug-123775=%s\n", bug ? "true" : "false");
|
||||||
|
bug = !bug;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ SUBDIRS = \
|
||||||
bins bytestream caps cleanup clock \
|
bins bytestream caps cleanup clock \
|
||||||
$(GST_DEBUG_DIRS) \
|
$(GST_DEBUG_DIRS) \
|
||||||
dlopen dynparams \
|
dlopen dynparams \
|
||||||
elements ghostpads indexers negotiation \
|
elements ghostpads indexers negotiation pad \
|
||||||
$(GST_PARSE_DIRS) \
|
$(GST_PARSE_DIRS) \
|
||||||
plugin refcounting schedulers states tags threads
|
plugin refcounting schedulers states tags threads
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ DIST_SUBDIRS = \
|
||||||
bins bytestream caps cleanup clock \
|
bins bytestream caps cleanup clock \
|
||||||
debug \
|
debug \
|
||||||
dlopen dynparams \
|
dlopen dynparams \
|
||||||
elements ghostpads indexers negotiation \
|
elements ghostpads indexers negotiation pad \
|
||||||
parse \
|
parse \
|
||||||
plugin refcounting schedulers states tags threads
|
plugin refcounting schedulers states tags threads
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ gst_fp_sink_init (GstFpSink * fp)
|
||||||
|
|
||||||
fp->sinkpad =
|
fp->sinkpad =
|
||||||
GST_FILE_PAD (gst_file_pad_new (gst_static_pad_template_get (&template),
|
GST_FILE_PAD (gst_file_pad_new (gst_static_pad_template_get (&template),
|
||||||
"src"));
|
"sink"));
|
||||||
gst_file_pad_set_iterate_function (fp->sinkpad, do_tests);
|
gst_file_pad_set_iterate_function (fp->sinkpad, do_tests);
|
||||||
gst_element_add_pad (GST_ELEMENT (fp), GST_PAD (fp->sinkpad));
|
gst_element_add_pad (GST_ELEMENT (fp), GST_PAD (fp->sinkpad));
|
||||||
}
|
}
|
||||||
|
|
5
testsuite/pad/Makefile.am
Normal file
5
testsuite/pad/Makefile.am
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
include ../Rules
|
||||||
|
|
||||||
|
tests_pass = link
|
||||||
|
tests_fail =
|
||||||
|
tests_ignore = chainnopull getnopush
|
66
testsuite/pad/chainnopull.c
Normal file
66
testsuite/pad/chainnopull.c
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* this tests that chain-based pads don't pull.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
typedef struct _GstTestSink
|
||||||
|
{
|
||||||
|
GstElement parent;
|
||||||
|
GstPad *sinkpad;
|
||||||
|
} GstTestSink;
|
||||||
|
|
||||||
|
typedef GstElementClass GstTestSinkClass;
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_class_init (GstTestSinkClass * klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_chain (GstPad * pad, GstData * data)
|
||||||
|
{
|
||||||
|
data = gst_pad_pull (pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_init (GstTestSink * sink)
|
||||||
|
{
|
||||||
|
sink->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||||
|
gst_pad_set_chain_function (sink->sinkpad, gst_test_sink_chain);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (sink), sink->sinkpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_BOILERPLATE (GstTestSink, gst_test_sink, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GstElement *pipeline, *fakesrc, *testsink;
|
||||||
|
gint n;
|
||||||
|
|
||||||
|
gst_init (&argc, &argv);
|
||||||
|
|
||||||
|
pipeline = gst_pipeline_new ("p");
|
||||||
|
fakesrc = gst_element_factory_make ("fakesrc", "src");
|
||||||
|
testsink = g_object_new (gst_test_sink_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (testsink), "sink");
|
||||||
|
gst_bin_add_many (GST_BIN (pipeline), fakesrc, testsink, NULL);
|
||||||
|
gst_element_link (fakesrc, testsink);
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
|
|
||||||
|
for (n = 0; n < 100; n++) {
|
||||||
|
if (!gst_bin_iterate (GST_BIN (pipeline)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref (GST_OBJECT (pipeline));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
71
testsuite/pad/getnopush.c
Normal file
71
testsuite/pad/getnopush.c
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* this tests that get-based pads don't push.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
typedef struct _GstTestSrc
|
||||||
|
{
|
||||||
|
GstElement parent;
|
||||||
|
GstPad *srcpad;
|
||||||
|
} GstTestSrc;
|
||||||
|
|
||||||
|
typedef GstElementClass GstTestSrcClass;
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_src_class_init (GstTestSrcClass * klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
gst_test_src_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstData *
|
||||||
|
gst_test_src_get (GstPad * pad)
|
||||||
|
{
|
||||||
|
GstEvent *event;
|
||||||
|
|
||||||
|
event = gst_event_new (GST_EVENT_INTERRUPT);
|
||||||
|
gst_event_ref (event);
|
||||||
|
gst_pad_push (pad, GST_DATA (event));
|
||||||
|
|
||||||
|
return GST_DATA (event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_src_init (GstTestSrc * src)
|
||||||
|
{
|
||||||
|
src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
|
gst_pad_set_get_function (src->srcpad, gst_test_src_get);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_BOILERPLATE (GstTestSrc, gst_test_src, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GstElement *pipeline, *testsrc, *fakesink;
|
||||||
|
gint n;
|
||||||
|
|
||||||
|
gst_init (&argc, &argv);
|
||||||
|
|
||||||
|
pipeline = gst_pipeline_new ("p");
|
||||||
|
testsrc = g_object_new (gst_test_src_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (testsrc), "src");
|
||||||
|
fakesink = gst_element_factory_make ("fakesink", "sink");
|
||||||
|
gst_bin_add_many (GST_BIN (pipeline), testsrc, fakesink, NULL);
|
||||||
|
gst_element_link (testsrc, fakesink);
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
|
|
||||||
|
for (n = 0; n < 100; n++) {
|
||||||
|
if (!gst_bin_iterate (GST_BIN (pipeline)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref (GST_OBJECT (pipeline));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
194
testsuite/pad/link.c
Normal file
194
testsuite/pad/link.c
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
* Test that:
|
||||||
|
* - get-based sources can return data, loop-based sources can push.
|
||||||
|
* - chain-based filters receive/push, loop-based filters can pull/push.
|
||||||
|
* - chain-based sinks receive, loop-based sinks pull.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scary type code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct _GstTestElement
|
||||||
|
{
|
||||||
|
GstElement parent;
|
||||||
|
GstPad *srcpad, *sinkpad;
|
||||||
|
} GstTestSrc, GstTestFilter, GstTestSink, GstTestElement;
|
||||||
|
|
||||||
|
typedef GstElementClass GstTestSrcClass, GstTestFilterClass, GstTestSinkClass,
|
||||||
|
GstTestElementClass;
|
||||||
|
|
||||||
|
#define gst_test_src_class_init gst_test_element_class_init
|
||||||
|
#define gst_test_filter_class_init gst_test_element_class_init
|
||||||
|
#define gst_test_sink_class_init gst_test_element_class_init
|
||||||
|
|
||||||
|
#define gst_test_src_base_init gst_test_element_base_init
|
||||||
|
#define gst_test_filter_base_init gst_test_element_base_init
|
||||||
|
#define gst_test_sink_base_init gst_test_element_base_init
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_element_class_init (GstTestElementClass * klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
gst_test_element_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actual element code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
gboolean loop = FALSE;
|
||||||
|
|
||||||
|
static GstData *
|
||||||
|
gst_test_src_get (GstPad * pad)
|
||||||
|
{
|
||||||
|
return GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_src_loop (GstElement * element)
|
||||||
|
{
|
||||||
|
GstTestSrc *src = (GstTestElement *) element;
|
||||||
|
|
||||||
|
gst_pad_push (src->srcpad, gst_test_src_get (src->srcpad));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_src_init (GstTestElement * src)
|
||||||
|
{
|
||||||
|
src->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
|
if (loop) {
|
||||||
|
gst_element_set_loop_function (GST_ELEMENT (src), gst_test_src_loop);
|
||||||
|
} else {
|
||||||
|
gst_pad_set_get_function (src->srcpad, gst_test_src_get);
|
||||||
|
}
|
||||||
|
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
|
||||||
|
|
||||||
|
GST_FLAG_SET (src, GST_ELEMENT_EVENT_AWARE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_filter_chain (GstPad * pad, GstData * data)
|
||||||
|
{
|
||||||
|
GstTestFilter *filter = (GstTestElement *) gst_pad_get_parent (pad);
|
||||||
|
|
||||||
|
gst_pad_push (filter->srcpad, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_filter_loop (GstElement * element)
|
||||||
|
{
|
||||||
|
GstTestFilter *filter = (GstTestElement *) element;
|
||||||
|
|
||||||
|
gst_test_filter_chain (filter->sinkpad, gst_pad_pull (filter->sinkpad));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_filter_init (GstTestElement * filter)
|
||||||
|
{
|
||||||
|
filter->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||||
|
if (loop) {
|
||||||
|
gst_element_set_loop_function (GST_ELEMENT (filter), gst_test_filter_loop);
|
||||||
|
} else {
|
||||||
|
gst_pad_set_chain_function (filter->sinkpad, gst_test_filter_chain);
|
||||||
|
}
|
||||||
|
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
|
||||||
|
|
||||||
|
filter->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
|
||||||
|
|
||||||
|
GST_FLAG_SET (filter, GST_ELEMENT_EVENT_AWARE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_chain (GstPad * pad, GstData * data)
|
||||||
|
{
|
||||||
|
gst_data_unref (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_loop (GstElement * element)
|
||||||
|
{
|
||||||
|
GstTestSink *sink = (GstTestElement *) element;
|
||||||
|
|
||||||
|
gst_test_sink_chain (sink->sinkpad, gst_pad_pull (sink->sinkpad));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_test_sink_init (GstTestElement * sink)
|
||||||
|
{
|
||||||
|
sink->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||||
|
if (loop) {
|
||||||
|
gst_element_set_loop_function (GST_ELEMENT (sink), gst_test_sink_loop);
|
||||||
|
} else {
|
||||||
|
gst_pad_set_chain_function (sink->sinkpad, gst_test_sink_chain);
|
||||||
|
}
|
||||||
|
gst_element_add_pad (GST_ELEMENT (sink), sink->sinkpad);
|
||||||
|
|
||||||
|
GST_FLAG_SET (sink, GST_ELEMENT_EVENT_AWARE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define parent_class src_parent_class
|
||||||
|
GST_BOILERPLATE (GstTestSrc, gst_test_src, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
#undef parent_class
|
||||||
|
#define parent_class filter_parent_class
|
||||||
|
GST_BOILERPLATE (GstTestFilter, gst_test_filter, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
#undef parent_class
|
||||||
|
#define parent_class sink_parent_class
|
||||||
|
GST_BOILERPLATE (GstTestSink, gst_test_sink, GstElement, GST_TYPE_ELEMENT);
|
||||||
|
#undef parent_class
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actual test.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
cb_error (GstElement * element)
|
||||||
|
{
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GstElement *pipeline, *src, *filter, *sink;
|
||||||
|
gint n, r;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
gst_init (&argc, &argv);
|
||||||
|
|
||||||
|
for (r = 0; r < 2; r++) {
|
||||||
|
pipeline = gst_pipeline_new ("p");
|
||||||
|
g_signal_connect (pipeline, "error", G_CALLBACK (cb_error), NULL);
|
||||||
|
src = g_object_new (gst_test_src_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (src), "src");
|
||||||
|
filter = g_object_new (gst_test_filter_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (filter), "filter");
|
||||||
|
sink = g_object_new (gst_test_sink_get_type (), NULL);
|
||||||
|
gst_object_set_name (GST_OBJECT (sink), "sink");
|
||||||
|
gst_bin_add_many (GST_BIN (pipeline), src, filter, sink, NULL);
|
||||||
|
res = gst_element_link (src, filter);
|
||||||
|
g_assert (res);
|
||||||
|
res = gst_element_link (filter, sink);
|
||||||
|
g_assert (res);
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
|
|
||||||
|
for (n = 0; n < 100; n++) {
|
||||||
|
if (!gst_bin_iterate (GST_BIN (pipeline)))
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref (GST_OBJECT (pipeline));
|
||||||
|
|
||||||
|
/* switch element types */
|
||||||
|
g_print ("Loop=%s done\n", loop ? "true" : "false");
|
||||||
|
loop = !loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
include ../Rules
|
include ../Rules
|
||||||
|
|
||||||
tests_pass = thread1 thread2 thread3 thread4 thread5 threade threadf signal1 159852
|
tests_pass = thread1 thread2 thread3 thread4 thread5 threade threadf signal1 159852 threadg threadi
|
||||||
tests_fail = 159566 signal2 signal3
|
tests_fail = 159566 signal2 signal3
|
||||||
|
|
||||||
# threadh
|
# threadh
|
||||||
|
|
||||||
tests_ignore = queue threadb threadc threadd staticrec threadg
|
tests_ignore = queue threadb threadc threadd staticrec
|
||||||
|
|
||||||
thread1_SOURCES = thread.c
|
thread1_SOURCES = thread.c
|
||||||
thread1_CFLAGS = -DTESTNUM=1 $(AM_CFLAGS)
|
thread1_CFLAGS = -DTESTNUM=1 $(AM_CFLAGS)
|
||||||
|
|
|
@ -95,6 +95,7 @@ main (gint argc, gchar * argv[])
|
||||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
g_print ("running ...\n");
|
g_print ("running ...\n");
|
||||||
while (gst_bin_iterate (GST_BIN (pipeline)));
|
while (gst_bin_iterate (GST_BIN (pipeline)));
|
||||||
|
g_print ("done ...\n");
|
||||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
}
|
}
|
||||||
if (TESTNUM == 4) {
|
if (TESTNUM == 4) {
|
||||||
|
|
111
testsuite/threads/threadi.c
Normal file
111
testsuite/threads/threadi.c
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Test two ways of going non-lineairly to PLAYING. Both tests have a thread
|
||||||
|
* containing a fakesrc/sink and a containing thread.
|
||||||
|
*
|
||||||
|
* Test 1 tests by adding fakesrc, putting thread to PLAYING, adding
|
||||||
|
* fakesink, syncing state and see if it iterates.
|
||||||
|
*
|
||||||
|
* Test2 tests by adding fakesrc/fakesink, setting fakesrc to PLAYING
|
||||||
|
* (which should increment the container state) and then synchronizing
|
||||||
|
* state. This reflects bug #123775.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
static GstElement *pipeline, *fakesrc, *fakesink;
|
||||||
|
gboolean bug = FALSE;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cb_timeout (gpointer data)
|
||||||
|
{
|
||||||
|
g_assert_not_reached ();
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cb_quit (gpointer data)
|
||||||
|
{
|
||||||
|
gst_main_quit ();
|
||||||
|
|
||||||
|
g_print ("Quit mainloop\n");
|
||||||
|
|
||||||
|
/* once */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cb_eos (gpointer data)
|
||||||
|
{
|
||||||
|
g_print ("Received EOS\n");
|
||||||
|
|
||||||
|
g_idle_add ((GSourceFunc) cb_quit, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cb_state (GstElement * element, GstElementState old_state,
|
||||||
|
GstElementState new_state, gpointer data)
|
||||||
|
{
|
||||||
|
g_print ("Changed state from %d to %d\n", old_state, new_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cb_play (gpointer data)
|
||||||
|
{
|
||||||
|
GstElementStateReturn res;
|
||||||
|
|
||||||
|
if (bug) {
|
||||||
|
g_print ("Setting state\n");
|
||||||
|
gst_element_set_state (fakesrc, GST_STATE_PLAYING);
|
||||||
|
g_print ("Done\n");
|
||||||
|
} else {
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||||
|
gst_bin_add (GST_BIN (pipeline), fakesink);
|
||||||
|
}
|
||||||
|
g_print ("Syncing state\n");
|
||||||
|
res = gst_bin_sync_children_state (GST_BIN (data));
|
||||||
|
g_assert (res == GST_STATE_SUCCESS);
|
||||||
|
|
||||||
|
g_print ("Set to playing correctly: %d\n", GST_STATE (pipeline));
|
||||||
|
|
||||||
|
/* once */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
main (gint argc, gchar * argv[])
|
||||||
|
{
|
||||||
|
gint n, id;
|
||||||
|
|
||||||
|
gst_init (&argc, &argv);
|
||||||
|
|
||||||
|
for (n = 0; n < 2; n++) {
|
||||||
|
pipeline = gst_thread_new ("p");
|
||||||
|
g_signal_connect (pipeline, "state-change", G_CALLBACK (cb_state), NULL);
|
||||||
|
fakesrc = gst_element_factory_make ("fakesrc", "src");
|
||||||
|
g_object_set (G_OBJECT (fakesrc), "num-buffers", 1, NULL);
|
||||||
|
fakesink = gst_element_factory_make ("fakesink", "sink");
|
||||||
|
if (bug) {
|
||||||
|
gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
|
||||||
|
} else {
|
||||||
|
gst_bin_add (GST_BIN (pipeline), fakesrc);
|
||||||
|
}
|
||||||
|
gst_element_link (fakesrc, fakesink);
|
||||||
|
g_signal_connect (pipeline, "eos", G_CALLBACK (cb_eos), NULL);
|
||||||
|
g_idle_add ((GSourceFunc) cb_play, pipeline);
|
||||||
|
|
||||||
|
/* give 5 seconds */
|
||||||
|
id = g_timeout_add (5000, (GSourceFunc) cb_timeout, NULL);
|
||||||
|
g_print ("Enter mainloop\n");
|
||||||
|
gst_main ();
|
||||||
|
g_source_remove (id);
|
||||||
|
|
||||||
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref (GST_OBJECT (pipeline));
|
||||||
|
|
||||||
|
g_print ("Done with reproduce-bug-123775=%s\n", bug ? "true" : "false");
|
||||||
|
bug = !bug;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue