xvimageink: protect buffer_alloc from shutdown

Use the pool_lock in the buffer_alloc function to detect shutdown. Avoids
crashes when the sink is shutdown.
This commit is contained in:
Wim Taymans 2009-02-25 13:16:32 +01:00
parent f5a3387bdb
commit 81b7470ab8
2 changed files with 54 additions and 20 deletions

View file

@ -2209,9 +2209,17 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
gst_xvimagesink_update_colorbalance (xvimagesink); gst_xvimagesink_update_colorbalance (xvimagesink);
break; break;
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED:
g_mutex_lock (xvimagesink->pool_lock);
xvimagesink->pool_invalid = FALSE;
g_mutex_unlock (xvimagesink->pool_lock);
break; break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
g_mutex_lock (xvimagesink->pool_lock);
xvimagesink->pool_invalid = TRUE;
g_mutex_unlock (xvimagesink->pool_lock);
break;
default: default:
break; break;
} }
@ -2336,9 +2344,14 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
GstCaps *intersection = NULL; GstCaps *intersection = NULL;
GstStructure *structure = NULL; GstStructure *structure = NULL;
gint width, height, image_format; gint width, height, image_format;
GstCaps *new_caps;
xvimagesink = GST_XVIMAGESINK (bsink); xvimagesink = GST_XVIMAGESINK (bsink);
g_mutex_lock (xvimagesink->pool_lock);
if (G_UNLIKELY (xvimagesink->pool_invalid))
goto invalid;
if (G_LIKELY (xvimagesink->xcontext->last_caps && if (G_LIKELY (xvimagesink->xcontext->last_caps &&
gst_caps_is_equal (caps, xvimagesink->xcontext->last_caps))) { gst_caps_is_equal (caps, xvimagesink->xcontext->last_caps))) {
GST_DEBUG_OBJECT (xvimagesink, GST_DEBUG_OBJECT (xvimagesink,
@ -2366,7 +2379,7 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
if (gst_caps_is_empty (intersection)) { if (gst_caps_is_empty (intersection)) {
/* So we don't support this kind of buffer, let's define one we'd like */ /* So we don't support this kind of buffer, let's define one we'd like */
GstCaps *new_caps = gst_caps_copy (caps); new_caps = gst_caps_copy (caps);
structure = gst_caps_get_structure (new_caps, 0); structure = gst_caps_get_structure (new_caps, 0);
@ -2392,15 +2405,8 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
gst_caps_unref (intersection); gst_caps_unref (intersection);
intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps); intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps);
if (gst_caps_is_empty (intersection)) { if (gst_caps_is_empty (intersection))
GST_WARNING_OBJECT (xvimagesink, "we were requested a buffer with " goto incompatible;
"caps %" GST_PTR_FORMAT ", but our xcontext caps %" GST_PTR_FORMAT
" are completely incompatible with those caps", new_caps,
xvimagesink->xcontext->caps);
gst_caps_unref (new_caps);
ret = GST_FLOW_UNEXPECTED;
goto beach;
}
} }
/* Clean this copy */ /* Clean this copy */
@ -2424,12 +2430,8 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
structure = gst_caps_get_structure (intersection, 0); structure = gst_caps_get_structure (intersection, 0);
if (!gst_structure_get_int (structure, "width", &width) || if (!gst_structure_get_int (structure, "width", &width) ||
!gst_structure_get_int (structure, "height", &height) || !gst_structure_get_int (structure, "height", &height) ||
image_format == -1) { image_format == -1)
GST_WARNING_OBJECT (xvimagesink, "invalid caps for buffer allocation %" goto invalid_caps;
GST_PTR_FORMAT, intersection);
ret = GST_FLOW_UNEXPECTED;
goto beach;
}
/* Store our caps and format as the last_caps to avoid expensive /* Store our caps and format as the last_caps to avoid expensive
* caps intersection next time */ * caps intersection next time */
@ -2440,8 +2442,6 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
reuse_last_caps: reuse_last_caps:
g_mutex_lock (xvimagesink->pool_lock);
/* Walking through the pool cleaning unusable images and searching for a /* Walking through the pool cleaning unusable images and searching for a
suitable one */ suitable one */
while (xvimagesink->image_pool) { while (xvimagesink->image_pool) {
@ -2466,8 +2466,6 @@ reuse_last_caps:
} }
} }
g_mutex_unlock (xvimagesink->pool_lock);
if (!xvimage) { if (!xvimage) {
/* We found no suitable image in the pool. Creating... */ /* We found no suitable image in the pool. Creating... */
GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage"); GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage");
@ -2480,6 +2478,7 @@ reuse_last_caps:
xvimage = NULL; xvimage = NULL;
} }
} }
g_mutex_unlock (xvimagesink->pool_lock);
if (xvimage) { if (xvimage) {
/* Make sure the buffer is cleared of any previously used flags */ /* Make sure the buffer is cleared of any previously used flags */
@ -2495,6 +2494,34 @@ beach:
} }
return ret; return ret;
/* ERRORS */
invalid:
{
GST_DEBUG_OBJECT (xvimagesink, "the pool is flushing");
ret = GST_FLOW_WRONG_STATE;
g_mutex_unlock (xvimagesink->pool_lock);
goto beach;
}
incompatible:
{
GST_WARNING_OBJECT (xvimagesink, "we were requested a buffer with "
"caps %" GST_PTR_FORMAT ", but our xcontext caps %" GST_PTR_FORMAT
" are completely incompatible with those caps", new_caps,
xvimagesink->xcontext->caps);
gst_caps_unref (new_caps);
ret = GST_FLOW_NOT_NEGOTIATED;
g_mutex_unlock (xvimagesink->pool_lock);
goto beach;
}
invalid_caps:
{
GST_WARNING_OBJECT (xvimagesink, "invalid caps for buffer allocation %"
GST_PTR_FORMAT, intersection);
ret = GST_FLOW_NOT_NEGOTIATED;
g_mutex_unlock (xvimagesink->pool_lock);
goto beach;
}
} }
/* Interfaces stuff */ /* Interfaces stuff */
@ -3136,6 +3163,12 @@ gst_xvimagesink_reset (GstXvImageSink * xvimagesink)
xvimagesink->event_thread = NULL; xvimagesink->event_thread = NULL;
GST_OBJECT_UNLOCK (xvimagesink); GST_OBJECT_UNLOCK (xvimagesink);
/* invalidate the pool, current allocations continue, new buffer_alloc fails
* with wrong_state */
g_mutex_lock (xvimagesink->pool_lock);
xvimagesink->pool_invalid = TRUE;
g_mutex_unlock (xvimagesink->pool_lock);
/* Wait for our event thread to finish before we clean up our stuff. */ /* Wait for our event thread to finish before we clean up our stuff. */
if (thread) if (thread)
g_thread_join (thread); g_thread_join (thread);

View file

@ -250,6 +250,7 @@ struct _GstXvImageSink {
GValue *par; GValue *par;
GMutex *pool_lock; GMutex *pool_lock;
gboolean pool_invalid;
GSList *image_pool; GSList *image_pool;
gboolean synchronous; gboolean synchronous;