mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
omx: Don't hold any locks while calling OMX_SendCommand()
It might call into one of the callbacks and lead to deadlocks, e.g. with the Qualcomm OMX implementation.
This commit is contained in:
parent
0bb345a16d
commit
9dcaf5c2bb
1 changed files with 43 additions and 6 deletions
49
omx/gstomx.c
49
omx/gstomx.c
|
@ -503,7 +503,6 @@ gst_omx_component_set_state (GstOMXComponent * comp, OMX_STATETYPE state)
|
||||||
}
|
}
|
||||||
|
|
||||||
comp->pending_state = state;
|
comp->pending_state = state;
|
||||||
err = OMX_SendCommand (comp->handle, OMX_CommandStateSet, state, NULL);
|
|
||||||
|
|
||||||
/* Reset some things */
|
/* Reset some things */
|
||||||
if (old_state == OMX_StateExecuting && state < old_state) {
|
if (old_state == OMX_StateExecuting && state < old_state) {
|
||||||
|
@ -514,6 +513,13 @@ gst_omx_component_set_state (GstOMXComponent * comp, OMX_STATETYPE state)
|
||||||
g_cond_broadcast (comp->state_cond);
|
g_cond_broadcast (comp->state_cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Release lock because the command could call into the callbacks,
|
||||||
|
* which take the lock again */
|
||||||
|
g_mutex_unlock (comp->state_lock);
|
||||||
|
err = OMX_SendCommand (comp->handle, OMX_CommandStateSet, state, NULL);
|
||||||
|
g_mutex_lock (comp->state_lock);
|
||||||
|
/* No need to check if anything has changed here */
|
||||||
|
|
||||||
done:
|
done:
|
||||||
g_mutex_unlock (comp->state_lock);
|
g_mutex_unlock (comp->state_lock);
|
||||||
|
|
||||||
|
@ -1106,8 +1112,14 @@ gst_omx_port_set_flushing (GstOMXPort * port, gboolean flush)
|
||||||
g_cond_broadcast (comp->state_cond);
|
g_cond_broadcast (comp->state_cond);
|
||||||
g_mutex_unlock (comp->state_lock);
|
g_mutex_unlock (comp->state_lock);
|
||||||
|
|
||||||
|
/* Now flush the port */
|
||||||
port->flushed = FALSE;
|
port->flushed = FALSE;
|
||||||
|
/* Unlock because this could call one of the callbacks which
|
||||||
|
* also take the lock */
|
||||||
|
g_mutex_unlock (port->port_lock);
|
||||||
err = OMX_SendCommand (comp->handle, OMX_CommandFlush, port->index, NULL);
|
err = OMX_SendCommand (comp->handle, OMX_CommandFlush, port->index, NULL);
|
||||||
|
g_mutex_lock (port->port_lock);
|
||||||
|
|
||||||
if (err != OMX_ErrorNone) {
|
if (err != OMX_ErrorNone) {
|
||||||
GST_ERROR_OBJECT (comp->parent,
|
GST_ERROR_OBJECT (comp->parent,
|
||||||
"Error sending flush command to port %u: %s (0x%08x)", port->index,
|
"Error sending flush command to port %u: %s (0x%08x)", port->index,
|
||||||
|
@ -1115,6 +1127,18 @@ gst_omx_port_set_flushing (GstOMXPort * port, gboolean flush)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = gst_omx_component_get_last_error (comp)) != OMX_ErrorNone) {
|
||||||
|
GST_ERROR_OBJECT (comp->parent,
|
||||||
|
"Component is in error state: %s (0x%08x)",
|
||||||
|
gst_omx_error_to_string (err), err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! !port->flushing != ! !flush) {
|
||||||
|
GST_ERROR_OBJECT (comp->parent, "Another flush happened in the meantime");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
g_get_current_time (&abstimeout);
|
g_get_current_time (&abstimeout);
|
||||||
g_time_val_add (&abstimeout, 5 * G_USEC_PER_SEC);
|
g_time_val_add (&abstimeout, 5 * G_USEC_PER_SEC);
|
||||||
timeval = &abstimeout;
|
timeval = &abstimeout;
|
||||||
|
@ -1123,12 +1147,14 @@ gst_omx_port_set_flushing (GstOMXPort * port, gboolean flush)
|
||||||
/* Retry until timeout or until an error happend or
|
/* Retry until timeout or until an error happend or
|
||||||
* until all buffers were released by the component and
|
* until all buffers were released by the component and
|
||||||
* the flush command completed */
|
* the flush command completed */
|
||||||
do {
|
signalled = TRUE;
|
||||||
|
last_error = OMX_ErrorNone;
|
||||||
|
while (signalled && last_error == OMX_ErrorNone && !port->flushed
|
||||||
|
&& port->buffers->len != g_queue_get_length (port->pending_buffers)) {
|
||||||
signalled = g_cond_timed_wait (port->port_cond, port->port_lock, timeval);
|
signalled = g_cond_timed_wait (port->port_cond, port->port_lock, timeval);
|
||||||
|
|
||||||
last_error = gst_omx_component_get_last_error (comp);
|
last_error = gst_omx_component_get_last_error (comp);
|
||||||
} while (signalled && last_error == OMX_ErrorNone && !port->flushed
|
}
|
||||||
&& port->buffers->len != g_queue_get_length (port->pending_buffers));
|
|
||||||
port->flushed = FALSE;
|
port->flushed = FALSE;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (comp->parent, "Port %d flushed", port->index);
|
GST_DEBUG_OBJECT (comp->parent, "Port %d flushed", port->index);
|
||||||
|
@ -1433,6 +1459,7 @@ gst_omx_port_set_enabled_unlocked (GstOMXPort * port, gboolean enabled)
|
||||||
|
|
||||||
port->enabled_changed = FALSE;
|
port->enabled_changed = FALSE;
|
||||||
|
|
||||||
|
g_mutex_unlock (port->port_lock);
|
||||||
if (enabled)
|
if (enabled)
|
||||||
err =
|
err =
|
||||||
OMX_SendCommand (comp->handle, OMX_CommandPortEnable, port->index,
|
OMX_SendCommand (comp->handle, OMX_CommandPortEnable, port->index,
|
||||||
|
@ -1441,6 +1468,7 @@ gst_omx_port_set_enabled_unlocked (GstOMXPort * port, gboolean enabled)
|
||||||
err =
|
err =
|
||||||
OMX_SendCommand (comp->handle, OMX_CommandPortDisable,
|
OMX_SendCommand (comp->handle, OMX_CommandPortDisable,
|
||||||
port->index, NULL);
|
port->index, NULL);
|
||||||
|
g_mutex_lock (port->port_lock);
|
||||||
|
|
||||||
if (err != OMX_ErrorNone) {
|
if (err != OMX_ErrorNone) {
|
||||||
GST_ERROR_OBJECT (comp->parent,
|
GST_ERROR_OBJECT (comp->parent,
|
||||||
|
@ -1449,6 +1477,17 @@ gst_omx_port_set_enabled_unlocked (GstOMXPort * port, gboolean enabled)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = gst_omx_component_get_last_error (comp)) != OMX_ErrorNone) {
|
||||||
|
GST_ERROR_OBJECT (comp->parent, "Component in error state: %s (0x%08x)",
|
||||||
|
gst_omx_error_to_string (err), err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port->enabled_changed) {
|
||||||
|
GST_ERROR_OBJECT (comp->parent, "Port enabled/disabled in the meantime");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
g_get_current_time (&abstimeout);
|
g_get_current_time (&abstimeout);
|
||||||
g_time_val_add (&abstimeout, 5 * G_USEC_PER_SEC);
|
g_time_val_add (&abstimeout, 5 * G_USEC_PER_SEC);
|
||||||
timeval = &abstimeout;
|
timeval = &abstimeout;
|
||||||
|
@ -1505,8 +1544,6 @@ gst_omx_port_set_enabled_unlocked (GstOMXPort * port, gboolean enabled)
|
||||||
&port->port_def);
|
&port->port_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
port->enabled_changed = FALSE;
|
|
||||||
|
|
||||||
if (!signalled) {
|
if (!signalled) {
|
||||||
GST_ERROR_OBJECT (comp->parent,
|
GST_ERROR_OBJECT (comp->parent,
|
||||||
"Timeout waiting for port %u to be %s", port->index,
|
"Timeout waiting for port %u to be %s", port->index,
|
||||||
|
|
Loading…
Reference in a new issue