mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 07:47:17 +00:00
- Reclaim cothread state even if the cothread was never activated after the free.
Original commit message from CVS: - Reclaim cothread state even if the cothread was never activated after the free. - fix the bin state change when there are no more children. - use a real method to signal the parent bin of a state change. - move the state change policy in the scheduler. - remove the unused and ridiculous state change event - don't free the cothread state when the element is disabled. only free it when the element is removed from the scheduler.
This commit is contained in:
parent
a8b1346857
commit
f5affde61c
12 changed files with 63 additions and 135 deletions
|
@ -40,6 +40,8 @@
|
|||
#define COTHREAD_MAXTHREADS 16
|
||||
#define COTHREAD_STACKSIZE (STACK_SIZE/COTHREAD_MAXTHREADS)
|
||||
|
||||
static void cothread_destroy (cothread_state *thread);
|
||||
|
||||
struct _cothread_context
|
||||
{
|
||||
cothread_state *threads[COTHREAD_MAXTHREADS];
|
||||
|
@ -116,6 +118,8 @@ cothread_context_free (cothread_context *ctx)
|
|||
{
|
||||
gint i;
|
||||
|
||||
GST_INFO (GST_CAT_COTHREADS, "free cothread context");
|
||||
|
||||
for (i = 0; i < ctx->nthreads; i++) {
|
||||
#ifndef COTHREAD_ATOMIC
|
||||
if (ctx->threads[i]) {
|
||||
|
@ -158,6 +162,11 @@ cothread_create (cothread_context *ctx)
|
|||
for (slot = 1; slot < ctx->nthreads; slot++) {
|
||||
if (ctx->threads[slot] == NULL)
|
||||
break;
|
||||
else if (ctx->threads[slot]->flags & COTHREAD_DESTROYED) {
|
||||
cothread_destroy (ctx->threads[slot]);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sp = CURRENT_STACK_FRAME;
|
||||
|
@ -209,6 +218,8 @@ cothread_free (cothread_state *thread)
|
|||
{
|
||||
g_return_if_fail (thread != NULL);
|
||||
|
||||
GST_INFO (GST_CAT_COTHREADS, "flag cothread for destruction");
|
||||
|
||||
/* we simply flag the cothread for destruction here */
|
||||
thread->flags |= COTHREAD_DESTROYED;
|
||||
}
|
||||
|
@ -220,6 +231,8 @@ cothread_destroy (cothread_state *thread)
|
|||
|
||||
g_return_if_fail (thread != NULL);
|
||||
|
||||
GST_INFO (GST_CAT_COTHREADS, "destroy cothread");
|
||||
|
||||
ctx = thread->ctx;
|
||||
#ifndef COTHREAD_ATOMIC
|
||||
g_mutex_free (thread->lock);
|
||||
|
|
26
gst/gstbin.c
26
gst/gstbin.c
|
@ -46,8 +46,6 @@ static GstElementStateReturn gst_bin_change_state_norecurse (GstBin *bin);
|
|||
static gboolean gst_bin_change_state_type (GstBin *bin,
|
||||
GstElementState state,
|
||||
GType type);
|
||||
static void gst_bin_child_state_change (GstBin *bin, GstElementState old,
|
||||
GstElementState new, GstElement *child);
|
||||
static void gst_bin_send_event (GstElement *element, GstEvent *event);
|
||||
|
||||
static gboolean gst_bin_iterate_func (GstBin * bin);
|
||||
|
@ -359,11 +357,13 @@ gst_bin_remove (GstBin * bin, GstElement * element)
|
|||
gst_object_unparent (GST_OBJECT (element));
|
||||
|
||||
/* if we're down to zero children, force state to NULL */
|
||||
if (bin->numchildren == 0 && GST_ELEMENT_SCHED (bin) != NULL)
|
||||
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
|
||||
if (bin->numchildren == 0 && GST_ELEMENT_SCHED (bin) != NULL) {
|
||||
GST_STATE_PENDING (bin) = GST_STATE_NULL;
|
||||
gst_bin_change_state_norecurse (bin);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
gst_bin_child_state_change (GstBin * bin, GstElementState old, GstElementState new,
|
||||
GstElement * child)
|
||||
{
|
||||
|
@ -401,21 +401,7 @@ gst_bin_send_event (GstElement *element, GstEvent *event)
|
|||
gst_element_get_name (GST_ELEMENT (GST_EVENT_SRC (event))),
|
||||
gst_element_get_name (element));
|
||||
|
||||
if (GST_ELEMENT (GST_EVENT_SRC (event)) == element) {
|
||||
GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_STATE_CHANGE:
|
||||
gst_bin_child_state_change (GST_BIN (element), GST_EVENT_STATE_OLD (event),
|
||||
GST_EVENT_STATE_NEW (event), GST_ELEMENT (GST_EVENT_SRC (event)));
|
||||
gst_event_free (event);
|
||||
break;
|
||||
default:
|
||||
GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
|
||||
break;
|
||||
}
|
||||
GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
|
|
|
@ -110,6 +110,10 @@ gboolean gst_bin_set_state_type (GstBin *bin, GstElementState state, GType type
|
|||
|
||||
gboolean gst_bin_iterate (GstBin *bin);
|
||||
|
||||
/* internal */
|
||||
void gst_bin_child_state_change (GstBin *bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement *child);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -831,9 +831,6 @@ gst_element_send_event_func (GstElement *element, GstEvent *event)
|
|||
}
|
||||
else {
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_STATE_CHANGE:
|
||||
g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE], 0,
|
||||
GST_EVENT_STATE_OLD (event), GST_EVENT_STATE_NEW (event));
|
||||
default:
|
||||
g_signal_emit (G_OBJECT (element), gst_element_signals[EVENT], 0, event);
|
||||
}
|
||||
|
@ -968,6 +965,7 @@ static GstElementStateReturn
|
|||
gst_element_change_state (GstElement *element)
|
||||
{
|
||||
GstElementState old_state;
|
||||
//GstEvent *event;
|
||||
|
||||
g_return_val_if_fail (element != NULL, GST_STATE_FAILURE);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
|
||||
|
@ -984,24 +982,9 @@ gst_element_change_state (GstElement *element)
|
|||
gst_element_statename (GST_STATE_PENDING (element)),
|
||||
GST_STATE_TRANSITION (element));
|
||||
|
||||
if (GST_STATE_TRANSITION (element) == GST_STATE_PAUSED_TO_PLAYING) {
|
||||
g_return_val_if_fail (GST_ELEMENT_SCHED (element), GST_STATE_FAILURE);
|
||||
|
||||
if (GST_ELEMENT_PARENT (element)) {
|
||||
GST_DEBUG (GST_CAT_STATES, "PAUSED->PLAYING: element \"%s\" has parent \"%s\" and sched %p\n",
|
||||
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (GST_ELEMENT_PARENT (element)),
|
||||
GST_ELEMENT_SCHED (element));
|
||||
}
|
||||
gst_scheduler_enable_element (element->sched, element);
|
||||
}
|
||||
else if (GST_STATE_TRANSITION (element) == GST_STATE_PLAYING_TO_PAUSED) {
|
||||
if (GST_ELEMENT_PARENT (element)) {
|
||||
GST_DEBUG (GST_CAT_STATES, "PLAYING->PAUSED: element \"%s\" has parent \"%s\" and sched %p\n",
|
||||
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (GST_ELEMENT_PARENT (element)),
|
||||
GST_ELEMENT_SCHED (element));
|
||||
}
|
||||
gst_scheduler_disable_element (element->sched, element);
|
||||
}
|
||||
/* tell the scheduler if we have one */
|
||||
if (element->sched)
|
||||
gst_scheduler_state_transition (element->sched, element, GST_STATE_TRANSITION (element));
|
||||
|
||||
GST_STATE (element) = GST_STATE_PENDING (element);
|
||||
GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
|
||||
|
@ -1010,11 +993,11 @@ gst_element_change_state (GstElement *element)
|
|||
g_cond_signal (element->state_cond);
|
||||
g_mutex_unlock (element->state_mutex);
|
||||
|
||||
{
|
||||
GstEvent *event = gst_event_new_state_change (old_state, GST_STATE (element));
|
||||
|
||||
gst_element_send_event (element, event);
|
||||
if (GST_ELEMENT_PARENT (element)) {
|
||||
gst_bin_child_state_change (GST_BIN (GST_ELEMENT_PARENT (element)), old_state, GST_STATE (element), element);
|
||||
}
|
||||
//event = gst_event_new_state_change (old_state, GST_STATE (element));
|
||||
//gst_element_send_event (element, event);
|
||||
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -153,25 +153,5 @@ gst_event_new_info (const gchar *firstname, ...)
|
|||
|
||||
return event;
|
||||
}
|
||||
/**
|
||||
* gst_event_new_state_change:
|
||||
* @old: The old state
|
||||
* @state: The new state
|
||||
*
|
||||
* Allocate a new state change event with the given props.
|
||||
*
|
||||
* Returns: A new state change event.
|
||||
*/
|
||||
GstEvent*
|
||||
gst_event_new_state_change (GstElementState old, GstElementState state)
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
event = gst_event_new (GST_EVENT_STATE_CHANGE);
|
||||
GST_EVENT_STATE_OLD (event) = old;
|
||||
GST_EVENT_STATE_NEW (event) = state;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ typedef enum {
|
|||
/* vertical events */
|
||||
GST_EVENT_INFO,
|
||||
GST_EVENT_ERROR,
|
||||
GST_EVENT_STATE_CHANGE,
|
||||
} GstEventType;
|
||||
|
||||
extern GType _gst_event_type;
|
||||
|
@ -71,10 +70,6 @@ typedef enum {
|
|||
|
||||
#define GST_EVENT_INFO_PROPS(event) (GST_EVENT(event)->event_data.info.props)
|
||||
|
||||
#define GST_EVENT_STATE_OLD(event) (GST_EVENT(event)->event_data.state.old_state)
|
||||
#define GST_EVENT_STATE_NEW(event) (GST_EVENT(event)->event_data.state.new_state)
|
||||
|
||||
|
||||
struct _GstEvent {
|
||||
GstData data;
|
||||
|
||||
|
@ -112,9 +107,6 @@ GstEvent* gst_event_new_seek (GstSeekType type, guint64 offset, gboolean flush);
|
|||
/* info events */
|
||||
GstEvent* gst_event_new_info (const gchar *firstname, ...);
|
||||
|
||||
/* state change events */
|
||||
GstEvent* gst_event_new_state_change (GstElementState old, GstElementState state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -331,8 +331,7 @@ restart:
|
|||
while (queue->level_buffers == queue->size_buffers) {
|
||||
/* if there's a pending state change for this queue or its manager, switch */
|
||||
/* back to iterator so bottom half of state change executes */
|
||||
while (GST_STATE (queue) != GST_STATE_PLAYING) {
|
||||
//while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||
while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!\n");
|
||||
g_mutex_unlock (queue->qlock);
|
||||
cothread_switch(cothread_current_main());
|
||||
|
@ -400,8 +399,7 @@ restart:
|
|||
/* if there's a pending state change for this queue or its manager, switch
|
||||
* back to iterator so bottom half of state change executes
|
||||
*/
|
||||
while (GST_STATE (queue) != GST_STATE_PLAYING) {
|
||||
//while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||
while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!\n");
|
||||
g_mutex_unlock (queue->qlock);
|
||||
cothread_switch(cothread_current_main());
|
||||
|
|
|
@ -154,31 +154,18 @@ gst_scheduler_add_element (GstScheduler *sched, GstElement *element)
|
|||
}
|
||||
|
||||
/**
|
||||
* gst_scheduler_enable_element:
|
||||
* gst_scheduler_state_transition:
|
||||
* @sched: the schedulerr
|
||||
* @element: the element to enable
|
||||
* @element: the element with the state transition
|
||||
* @transition: the state transition
|
||||
*
|
||||
* Enable an element for scheduling.
|
||||
* Tell the scheduler that an element changed its state.
|
||||
*/
|
||||
void
|
||||
gst_scheduler_enable_element (GstScheduler *sched, GstElement *element)
|
||||
gst_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition)
|
||||
{
|
||||
if (CLASS (sched)->enable_element)
|
||||
CLASS (sched)->enable_element (sched, element);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_scheduler_disable_element:
|
||||
* @sched: the schedulerr
|
||||
* @element: the element to disable
|
||||
*
|
||||
* Disable an element for scheduling.
|
||||
*/
|
||||
void
|
||||
gst_scheduler_disable_element (GstScheduler *sched, GstElement *element)
|
||||
{
|
||||
if (CLASS (sched)->disable_element)
|
||||
CLASS (sched)->disable_element (sched, element);
|
||||
if (CLASS (sched)->state_transition)
|
||||
CLASS (sched)->state_transition (sched, element, transition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -69,8 +69,7 @@ struct _GstSchedulerClass {
|
|||
void (*reset) (GstScheduler *sched);
|
||||
void (*add_element) (GstScheduler *sched, GstElement *element);
|
||||
void (*remove_element) (GstScheduler *sched, GstElement *element);
|
||||
void (*enable_element) (GstScheduler *sched, GstElement *element);
|
||||
void (*disable_element) (GstScheduler *sched, GstElement *element);
|
||||
void (*state_transition) (GstScheduler *sched, GstElement *element, gint transition);
|
||||
void (*lock_element) (GstScheduler *sched, GstElement *element);
|
||||
void (*unlock_element) (GstScheduler *sched, GstElement *element);
|
||||
void (*pad_connect) (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
|
||||
|
@ -90,8 +89,7 @@ void gst_scheduler_setup (GstScheduler *sched);
|
|||
void gst_scheduler_reset (GstScheduler *sched);
|
||||
void gst_scheduler_add_element (GstScheduler *sched, GstElement *element);
|
||||
void gst_scheduler_remove_element (GstScheduler *sched, GstElement *element);
|
||||
void gst_scheduler_enable_element (GstScheduler *sched, GstElement *element);
|
||||
void gst_scheduler_disable_element (GstScheduler *sched, GstElement *element);
|
||||
void gst_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition);
|
||||
void gst_scheduler_lock_element (GstScheduler *sched, GstElement *element);
|
||||
void gst_scheduler_unlock_element (GstScheduler *sched, GstElement *element);
|
||||
void gst_scheduler_pad_connect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
|
||||
|
|
|
@ -324,13 +324,18 @@ gst_thread_change_state (GstElement * element)
|
|||
THR_DEBUG (" element \"%s\"\n", GST_ELEMENT_NAME (element));
|
||||
elements = g_list_next (elements);
|
||||
if (GST_IS_QUEUE (element)) {
|
||||
GstQueue *queue = GST_QUEUE (element);
|
||||
/* FIXME make this more efficient by only waking queues that are asleep
|
||||
* FIXME and only waking the appropriate condition (depending on if it's
|
||||
* FIXME on up- or down-stream side)
|
||||
* FIXME also make this more efficient by keeping list of managed queues
|
||||
*/
|
||||
THR_DEBUG ("waking queue \"%s\"\n", GST_ELEMENT_NAME (element));
|
||||
gst_element_set_state (element, GST_STATE_PAUSED);
|
||||
g_mutex_lock (queue->qlock);
|
||||
GST_STATE_PENDING (element) = GST_STATE_PAUSED;
|
||||
g_cond_signal (queue->not_full);
|
||||
g_cond_signal (queue->not_empty);
|
||||
g_mutex_unlock (queue->qlock);
|
||||
}
|
||||
else {
|
||||
GList *pads = GST_ELEMENT_PADS (element);
|
||||
|
|
|
@ -50,8 +50,7 @@ static void gst_basic_scheduler_setup (GstScheduler *sched);
|
|||
static void gst_basic_scheduler_reset (GstScheduler *sched);
|
||||
static void gst_basic_scheduler_add_element (GstScheduler *sched, GstElement *element);
|
||||
static void gst_basic_scheduler_remove_element (GstScheduler *sched, GstElement *element);
|
||||
static void gst_basic_scheduler_enable_element (GstScheduler *sched, GstElement *element);
|
||||
static void gst_basic_scheduler_disable_element (GstScheduler *sched, GstElement *element);
|
||||
static void gst_basic_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition);
|
||||
static void gst_basic_scheduler_lock_element (GstScheduler *sched, GstElement *element);
|
||||
static void gst_basic_scheduler_unlock_element (GstScheduler *sched, GstElement *element);
|
||||
static void gst_basic_scheduler_pad_connect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad);
|
||||
|
@ -102,8 +101,7 @@ gst_basic_scheduler_class_init (GstSchedulerClass * klass)
|
|||
klass->reset = GST_DEBUG_FUNCPTR (gst_basic_scheduler_reset);
|
||||
klass->add_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_add_element);
|
||||
klass->remove_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_remove_element);
|
||||
klass->enable_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_enable_element);
|
||||
klass->disable_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_disable_element);
|
||||
klass->state_transition = GST_DEBUG_FUNCPTR (gst_basic_scheduler_state_transition);
|
||||
klass->lock_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_lock_element);
|
||||
klass->unlock_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_unlock_element);
|
||||
klass->pad_connect = GST_DEBUG_FUNCPTR (gst_basic_scheduler_pad_connect);
|
||||
|
@ -622,12 +620,6 @@ gst_basic_scheduler_chain_disable_element (GstSchedulerChain * chain, GstElement
|
|||
/* reschedule the chain */
|
||||
/* FIXME this should be done only if manager state != NULL */
|
||||
/* gst_basic_scheduler_cothreaded_chain(GST_BIN(chain->sched->parent),chain); */
|
||||
/* FIXME is this right? */
|
||||
/* we have to check for a threadstate here because a queue doesn't have one */
|
||||
if (element->threadstate) {
|
||||
cothread_free (element->threadstate);
|
||||
element->threadstate = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -640,6 +632,11 @@ gst_basic_scheduler_chain_remove_element (GstSchedulerChain * chain, GstElement
|
|||
if (g_list_find (chain->elements, element)) {
|
||||
gst_basic_scheduler_chain_disable_element (chain, element);
|
||||
}
|
||||
/* we have to check for a threadstate here because a queue doesn't have one */
|
||||
if (element->threadstate) {
|
||||
cothread_free (element->threadstate);
|
||||
element->threadstate = NULL;
|
||||
}
|
||||
|
||||
/* remove the element from the list of elements */
|
||||
chain->disabled = g_list_remove (chain->disabled, element);
|
||||
|
@ -907,23 +904,7 @@ gst_basic_scheduler_remove_element (GstScheduler * sched, GstElement * element)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_basic_scheduler_enable_element (GstScheduler *sched, GstElement *element)
|
||||
{
|
||||
GstSchedulerChain *chain;
|
||||
|
||||
/* find the chain the element's in */
|
||||
chain = gst_basic_scheduler_find_chain (sched, element);
|
||||
|
||||
if (chain) {
|
||||
gst_basic_scheduler_chain_enable_element (chain, element);
|
||||
}
|
||||
else {
|
||||
GST_INFO (GST_CAT_SCHEDULING, "element \"%s\" not found in any chain, not enabling", GST_ELEMENT_NAME (element));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_basic_scheduler_disable_element (GstScheduler *sched, GstElement *element)
|
||||
gst_basic_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition)
|
||||
{
|
||||
GstSchedulerChain *chain;
|
||||
|
||||
|
@ -932,10 +913,13 @@ gst_basic_scheduler_disable_element (GstScheduler *sched, GstElement *element)
|
|||
|
||||
/* remove it from the chain */
|
||||
if (chain) {
|
||||
gst_basic_scheduler_chain_disable_element (chain, element);
|
||||
if (transition == GST_STATE_PLAYING_TO_PAUSED)
|
||||
gst_basic_scheduler_chain_disable_element (chain, element);
|
||||
if (transition == GST_STATE_PAUSED_TO_PLAYING)
|
||||
gst_basic_scheduler_chain_enable_element (chain, element);
|
||||
}
|
||||
else {
|
||||
GST_INFO (GST_CAT_SCHEDULING, "element \"%s\" not found in any chain, not disabling", GST_ELEMENT_NAME (element));
|
||||
GST_INFO (GST_CAT_SCHEDULING, "element \"%s\" not found in any chain, no state change", GST_ELEMENT_NAME (element));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -331,8 +331,7 @@ restart:
|
|||
while (queue->level_buffers == queue->size_buffers) {
|
||||
/* if there's a pending state change for this queue or its manager, switch */
|
||||
/* back to iterator so bottom half of state change executes */
|
||||
while (GST_STATE (queue) != GST_STATE_PLAYING) {
|
||||
//while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||
while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!\n");
|
||||
g_mutex_unlock (queue->qlock);
|
||||
cothread_switch(cothread_current_main());
|
||||
|
@ -400,8 +399,7 @@ restart:
|
|||
/* if there's a pending state change for this queue or its manager, switch
|
||||
* back to iterator so bottom half of state change executes
|
||||
*/
|
||||
while (GST_STATE (queue) != GST_STATE_PLAYING) {
|
||||
//while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||
while (GST_STATE_PENDING (queue) != GST_STATE_VOID_PENDING) {
|
||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, queue, "interrupted!!\n");
|
||||
g_mutex_unlock (queue->qlock);
|
||||
cothread_switch(cothread_current_main());
|
||||
|
|
Loading…
Reference in a new issue