shmsink: Block in preroll_wait on unlock

The correct behaviour of anything stuck in the ->render() function
between ->unlock() and ->unlock_stop() is to call
gst_base_sink_wait_preroll() and only return an error if this returns an
error, otherwise, it must continue where it left off!

https://bugzilla.gnome.org/show_bug.cgi?id=774950
This commit is contained in:
Olivier Crête 2017-12-19 17:35:39 -05:00
parent 536cb12577
commit e19e02db93

View file

@ -666,18 +666,31 @@ gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
GstMemory *memory = NULL; GstMemory *memory = NULL;
GstBuffer *sendbuf = NULL; GstBuffer *sendbuf = NULL;
gsize written_bytes;
GST_OBJECT_LOCK (self); GST_OBJECT_LOCK (self);
while (self->wait_for_connection && !self->clients) { while (self->wait_for_connection && !self->clients) {
g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
if (self->unlock) if (self->unlock) {
goto flushing; GST_OBJECT_UNLOCK (self);
ret = gst_base_sink_wait_preroll (bsink);
if (ret == GST_FLOW_OK)
GST_OBJECT_LOCK (self);
else
return ret;
}
} }
while (!gst_shm_sink_can_render (self, GST_BUFFER_TIMESTAMP (buf))) { while (!gst_shm_sink_can_render (self, GST_BUFFER_TIMESTAMP (buf))) {
g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
if (self->unlock) if (self->unlock) {
goto flushing; GST_OBJECT_UNLOCK (self);
ret = gst_base_sink_wait_preroll (bsink);
if (ret == GST_FLOW_OK)
GST_OBJECT_LOCK (self);
else
return ret;
}
} }
@ -709,16 +722,27 @@ gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
gst_shm_sink_allocator_alloc_locked (self->allocator, gst_shm_sink_allocator_alloc_locked (self->allocator,
gst_buffer_get_size (buf), &self->params)) == NULL) { gst_buffer_get_size (buf), &self->params)) == NULL) {
g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
if (self->unlock) if (self->unlock) {
goto flushing; GST_OBJECT_UNLOCK (self);
ret = gst_base_sink_wait_preroll (bsink);
if (ret == GST_FLOW_OK)
GST_OBJECT_LOCK (self);
else
return ret;
}
} }
while (self->wait_for_connection && !self->clients) { while (self->wait_for_connection && !self->clients) {
g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self)); g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
if (self->unlock) { if (self->unlock) {
GST_OBJECT_UNLOCK (self); GST_OBJECT_UNLOCK (self);
gst_memory_unref (memory); ret = gst_base_sink_wait_preroll (bsink);
return GST_FLOW_FLUSHING; if (ret == GST_FLOW_OK) {
GST_OBJECT_LOCK (self);
} else {
gst_memory_unref (memory);
return ret;
}
} }
} }
@ -731,7 +755,7 @@ gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
GST_DEBUG_OBJECT (self, GST_DEBUG_OBJECT (self,
"Copying %" G_GSIZE_FORMAT " bytes into map of size %" G_GSIZE_FORMAT "Copying %" G_GSIZE_FORMAT " bytes into map of size %" G_GSIZE_FORMAT
" bytes.", gst_buffer_get_size (buf), map.size); " bytes.", gst_buffer_get_size (buf), map.size);
gsize written_bytes = gst_buffer_extract (buf, 0, map.data, map.size); written_bytes = gst_buffer_extract (buf, 0, map.data, map.size);
GST_DEBUG_OBJECT (self, "Copied %" G_GSIZE_FORMAT " bytes.", written_bytes); GST_DEBUG_OBJECT (self, "Copied %" G_GSIZE_FORMAT " bytes.", written_bytes);
gst_memory_unmap (memory, &map); gst_memory_unmap (memory, &map);
@ -776,10 +800,6 @@ gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
return ret; return ret;
flushing:
GST_OBJECT_UNLOCK (self);
return GST_FLOW_FLUSHING;
error: error:
GST_OBJECT_UNLOCK (self); GST_OBJECT_UNLOCK (self);
return GST_FLOW_ERROR; return GST_FLOW_ERROR;