mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 21:21:12 +00:00
v4l2: Fix SIGSEGV on 'change state' during 'format change'
Ensure all access to v4l2object->pool imply taking a lock and a hard ref on the pool Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3481>
This commit is contained in:
parent
0841e846a3
commit
94ba019397
9 changed files with 279 additions and 107 deletions
|
@ -1024,21 +1024,25 @@ gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_buffer_pool_orphan (GstBufferPool ** bpool)
|
gst_v4l2_buffer_pool_orphan (GstV4l2Object * v4l2object)
|
||||||
{
|
{
|
||||||
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (*bpool);
|
GstBufferPool *bpool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||||
|
GstV4l2BufferPool *pool;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
|
||||||
g_return_val_if_fail (pool->orphaned == FALSE, FALSE);
|
g_return_val_if_fail (bpool, FALSE);
|
||||||
|
|
||||||
if (!GST_V4L2_ALLOCATOR_CAN_ORPHAN_BUFS (pool->vallocator))
|
pool = GST_V4L2_BUFFER_POOL (bpool);
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (g_getenv ("GST_V4L2_FORCE_DRAIN"))
|
if (pool->orphaned != FALSE
|
||||||
|
|| !GST_V4L2_ALLOCATOR_CAN_ORPHAN_BUFS (pool->vallocator)
|
||||||
|
|| g_getenv ("GST_V4L2_FORCE_DRAIN")) {
|
||||||
|
gst_object_unref (bpool);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pool, "orphaning pool");
|
GST_DEBUG_OBJECT (pool, "orphaning pool");
|
||||||
gst_buffer_pool_set_active (*bpool, FALSE);
|
gst_buffer_pool_set_active (bpool, FALSE);
|
||||||
|
|
||||||
/* We lock to prevent racing with a return buffer in QBuf, and has a
|
/* We lock to prevent racing with a return buffer in QBuf, and has a
|
||||||
* workaround of not being able to use the pool hidden activation lock. */
|
* workaround of not being able to use the pool hidden activation lock. */
|
||||||
|
@ -1052,10 +1056,17 @@ gst_v4l2_buffer_pool_orphan (GstBufferPool ** bpool)
|
||||||
GST_OBJECT_UNLOCK (pool);
|
GST_OBJECT_UNLOCK (pool);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
gst_object_unref (*bpool);
|
GstBufferPool *old_pool;
|
||||||
*bpool = NULL;
|
GST_OBJECT_LOCK (v4l2object->element);
|
||||||
|
old_pool = v4l2object->pool;
|
||||||
|
v4l2object->pool = NULL;
|
||||||
|
GST_OBJECT_UNLOCK (v4l2object->element);
|
||||||
|
if (old_pool)
|
||||||
|
gst_object_unref (old_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_object_unref (bpool);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2288,16 +2299,23 @@ gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool * pool, gboolean copy)
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_buffer_pool_flush (GstBufferPool * bpool)
|
gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object)
|
||||||
{
|
{
|
||||||
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
|
GstBufferPool *bpool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||||
|
GstV4l2BufferPool *pool;
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
|
|
||||||
|
if (!bpool)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pool = GST_V4L2_BUFFER_POOL (bpool);
|
||||||
|
|
||||||
gst_v4l2_buffer_pool_streamoff (pool);
|
gst_v4l2_buffer_pool_streamoff (pool);
|
||||||
|
|
||||||
if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type))
|
if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type))
|
||||||
ret = gst_v4l2_buffer_pool_streamon (pool);
|
ret = gst_v4l2_buffer_pool_streamon (pool);
|
||||||
|
|
||||||
|
gst_object_unref (bpool);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,9 +118,9 @@ void gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * poo
|
||||||
void gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool * pool,
|
void gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool * pool,
|
||||||
gboolean copy);
|
gboolean copy);
|
||||||
|
|
||||||
gboolean gst_v4l2_buffer_pool_flush (GstBufferPool *pool);
|
gboolean gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object);
|
||||||
|
|
||||||
gboolean gst_v4l2_buffer_pool_orphan (GstBufferPool ** pool);
|
gboolean gst_v4l2_buffer_pool_orphan (GstV4l2Object * v4l2object);
|
||||||
|
|
||||||
void gst_v4l2_buffer_pool_enable_resolution_change (GstV4l2BufferPool *self);
|
void gst_v4l2_buffer_pool_enable_resolution_change (GstV4l2BufferPool *self);
|
||||||
|
|
||||||
|
|
|
@ -3172,8 +3172,14 @@ gst_v4l2_object_setup_pool (GstV4l2Object * v4l2object, GstCaps * caps)
|
||||||
/* Map the buffers */
|
/* Map the buffers */
|
||||||
GST_LOG_OBJECT (v4l2object->dbg_obj, "initiating buffer pool");
|
GST_LOG_OBJECT (v4l2object->dbg_obj, "initiating buffer pool");
|
||||||
|
|
||||||
if (!(v4l2object->pool = gst_v4l2_buffer_pool_new (v4l2object, caps)))
|
{
|
||||||
|
GstBufferPool *pool = gst_v4l2_buffer_pool_new (v4l2object, caps);
|
||||||
|
GST_OBJECT_LOCK (v4l2object->element);
|
||||||
|
v4l2object->pool = pool;
|
||||||
|
GST_OBJECT_UNLOCK (v4l2object->element);
|
||||||
|
if (!pool)
|
||||||
goto buffer_pool_new_failed;
|
goto buffer_pool_new_failed;
|
||||||
|
}
|
||||||
|
|
||||||
GST_V4L2_SET_ACTIVE (v4l2object);
|
GST_V4L2_SET_ACTIVE (v4l2object);
|
||||||
|
|
||||||
|
@ -4515,17 +4521,19 @@ gst_v4l2_object_caps_equal (GstV4l2Object * v4l2object, GstCaps * caps)
|
||||||
GstStructure *config;
|
GstStructure *config;
|
||||||
GstCaps *oldcaps;
|
GstCaps *oldcaps;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||||
|
|
||||||
if (!v4l2object->pool)
|
if (!pool)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
config = gst_buffer_pool_get_config (v4l2object->pool);
|
config = gst_buffer_pool_get_config (pool);
|
||||||
gst_buffer_pool_config_get_params (config, &oldcaps, NULL, NULL, NULL);
|
gst_buffer_pool_config_get_params (config, &oldcaps, NULL, NULL, NULL);
|
||||||
|
|
||||||
ret = oldcaps && gst_caps_is_equal (caps, oldcaps);
|
ret = oldcaps && gst_caps_is_equal (caps, oldcaps);
|
||||||
|
|
||||||
gst_structure_free (config);
|
gst_structure_free (config);
|
||||||
|
|
||||||
|
gst_object_unref (pool);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4535,17 +4543,19 @@ gst_v4l2_object_caps_is_subset (GstV4l2Object * v4l2object, GstCaps * caps)
|
||||||
GstStructure *config;
|
GstStructure *config;
|
||||||
GstCaps *oldcaps;
|
GstCaps *oldcaps;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||||
|
|
||||||
if (!v4l2object->pool)
|
if (!pool)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
config = gst_buffer_pool_get_config (v4l2object->pool);
|
config = gst_buffer_pool_get_config (pool);
|
||||||
gst_buffer_pool_config_get_params (config, &oldcaps, NULL, NULL, NULL);
|
gst_buffer_pool_config_get_params (config, &oldcaps, NULL, NULL, NULL);
|
||||||
|
|
||||||
ret = oldcaps && gst_caps_is_subset (oldcaps, caps);
|
ret = oldcaps && gst_caps_is_subset (oldcaps, caps);
|
||||||
|
|
||||||
gst_structure_free (config);
|
gst_structure_free (config);
|
||||||
|
|
||||||
|
gst_object_unref (pool);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4554,11 +4564,12 @@ gst_v4l2_object_get_current_caps (GstV4l2Object * v4l2object)
|
||||||
{
|
{
|
||||||
GstStructure *config;
|
GstStructure *config;
|
||||||
GstCaps *oldcaps;
|
GstCaps *oldcaps;
|
||||||
|
GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||||
|
|
||||||
if (!v4l2object->pool)
|
if (!pool)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
config = gst_buffer_pool_get_config (v4l2object->pool);
|
config = gst_buffer_pool_get_config (pool);
|
||||||
gst_buffer_pool_config_get_params (config, &oldcaps, NULL, NULL, NULL);
|
gst_buffer_pool_config_get_params (config, &oldcaps, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (oldcaps)
|
if (oldcaps)
|
||||||
|
@ -4566,6 +4577,7 @@ gst_v4l2_object_get_current_caps (GstV4l2Object * v4l2object)
|
||||||
|
|
||||||
gst_structure_free (config);
|
gst_structure_free (config);
|
||||||
|
|
||||||
|
gst_object_unref (pool);
|
||||||
return oldcaps;
|
return oldcaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4573,12 +4585,17 @@ gboolean
|
||||||
gst_v4l2_object_unlock (GstV4l2Object * v4l2object)
|
gst_v4l2_object_unlock (GstV4l2Object * v4l2object)
|
||||||
{
|
{
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
|
GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||||
|
|
||||||
GST_LOG_OBJECT (v4l2object->dbg_obj, "start flushing");
|
GST_LOG_OBJECT (v4l2object->dbg_obj, "start flushing");
|
||||||
|
|
||||||
if (v4l2object->pool && gst_buffer_pool_is_active (v4l2object->pool))
|
if (!pool)
|
||||||
gst_buffer_pool_set_flushing (v4l2object->pool, TRUE);
|
return ret;
|
||||||
|
|
||||||
|
if (gst_buffer_pool_is_active (pool))
|
||||||
|
gst_buffer_pool_set_flushing (pool, TRUE);
|
||||||
|
|
||||||
|
gst_object_unref (pool);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4586,18 +4603,24 @@ gboolean
|
||||||
gst_v4l2_object_unlock_stop (GstV4l2Object * v4l2object)
|
gst_v4l2_object_unlock_stop (GstV4l2Object * v4l2object)
|
||||||
{
|
{
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
|
GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||||
|
|
||||||
GST_LOG_OBJECT (v4l2object->dbg_obj, "stop flushing");
|
GST_LOG_OBJECT (v4l2object->dbg_obj, "stop flushing");
|
||||||
|
|
||||||
if (v4l2object->pool && gst_buffer_pool_is_active (v4l2object->pool))
|
if (!pool)
|
||||||
gst_buffer_pool_set_flushing (v4l2object->pool, FALSE);
|
return ret;
|
||||||
|
|
||||||
|
if (gst_buffer_pool_is_active (pool))
|
||||||
|
gst_buffer_pool_set_flushing (pool, FALSE);
|
||||||
|
|
||||||
|
gst_object_unref (pool);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_v4l2_object_stop (GstV4l2Object * v4l2object)
|
gst_v4l2_object_stop (GstV4l2Object * v4l2object)
|
||||||
{
|
{
|
||||||
|
GstBufferPool *pool;
|
||||||
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "stopping");
|
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "stopping");
|
||||||
|
|
||||||
if (!GST_V4L2_IS_OPEN (v4l2object))
|
if (!GST_V4L2_IS_OPEN (v4l2object))
|
||||||
|
@ -4605,13 +4628,23 @@ gst_v4l2_object_stop (GstV4l2Object * v4l2object)
|
||||||
if (!GST_V4L2_IS_ACTIVE (v4l2object))
|
if (!GST_V4L2_IS_ACTIVE (v4l2object))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (v4l2object->pool) {
|
pool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||||
if (!gst_v4l2_buffer_pool_orphan (&v4l2object->pool)) {
|
if (pool) {
|
||||||
|
if (!gst_v4l2_buffer_pool_orphan (v4l2object)) {
|
||||||
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "deactivating pool");
|
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "deactivating pool");
|
||||||
gst_buffer_pool_set_active (v4l2object->pool, FALSE);
|
gst_buffer_pool_set_active (pool, FALSE);
|
||||||
gst_object_unref (v4l2object->pool);
|
|
||||||
}
|
{
|
||||||
|
GstBufferPool *old_pool;
|
||||||
|
GST_OBJECT_LOCK (v4l2object->element);
|
||||||
|
old_pool = v4l2object->pool;
|
||||||
v4l2object->pool = NULL;
|
v4l2object->pool = NULL;
|
||||||
|
GST_OBJECT_UNLOCK (v4l2object->element);
|
||||||
|
if (old_pool)
|
||||||
|
gst_object_unref (old_pool);
|
||||||
|
}
|
||||||
|
gst_object_unref (pool);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_V4L2_SET_INACTIVE (v4l2object);
|
GST_V4L2_SET_INACTIVE (v4l2object);
|
||||||
|
@ -4958,7 +4991,7 @@ gboolean
|
||||||
gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstBufferPool *pool = NULL, *other_pool = NULL;
|
GstBufferPool *pool = NULL, *other_pool = NULL, *obj_pool = NULL;
|
||||||
GstStructure *config;
|
GstStructure *config;
|
||||||
guint size, min, max, own_min = 0;
|
guint size, min, max, own_min = 0;
|
||||||
gboolean update;
|
gboolean update;
|
||||||
|
@ -4975,9 +5008,13 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
|
|
||||||
gst_query_parse_allocation (query, &caps, NULL);
|
gst_query_parse_allocation (query, &caps, NULL);
|
||||||
|
|
||||||
if (obj->pool == NULL) {
|
obj_pool = gst_v4l2_object_get_buffer_pool (obj);
|
||||||
|
if (obj_pool == NULL) {
|
||||||
if (!gst_v4l2_object_setup_pool (obj, caps))
|
if (!gst_v4l2_object_setup_pool (obj, caps))
|
||||||
goto pool_failed;
|
goto pool_failed;
|
||||||
|
obj_pool = gst_v4l2_object_get_buffer_pool (obj);
|
||||||
|
if (obj_pool == NULL)
|
||||||
|
goto pool_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_query_get_n_allocation_params (query) > 0)
|
if (gst_query_get_n_allocation_params (query) > 0)
|
||||||
|
@ -5031,7 +5068,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
/* no downstream pool, use our own then */
|
/* no downstream pool, use our own then */
|
||||||
GST_DEBUG_OBJECT (obj->dbg_obj,
|
GST_DEBUG_OBJECT (obj->dbg_obj,
|
||||||
"read/write mode: no downstream pool, using our own");
|
"read/write mode: no downstream pool, using our own");
|
||||||
pool = gst_object_ref (obj->pool);
|
pool = gst_object_ref (obj_pool);
|
||||||
size = obj->info.size;
|
size = obj->info.size;
|
||||||
pushing_from_our_pool = TRUE;
|
pushing_from_our_pool = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -5043,11 +5080,11 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
* our own, so it can serve itself */
|
* our own, so it can serve itself */
|
||||||
if (pool == NULL)
|
if (pool == NULL)
|
||||||
goto no_downstream_pool;
|
goto no_downstream_pool;
|
||||||
gst_v4l2_buffer_pool_set_other_pool (GST_V4L2_BUFFER_POOL (obj->pool),
|
gst_v4l2_buffer_pool_set_other_pool (GST_V4L2_BUFFER_POOL (obj_pool),
|
||||||
pool);
|
pool);
|
||||||
other_pool = pool;
|
other_pool = pool;
|
||||||
gst_object_unref (pool);
|
gst_object_unref (pool);
|
||||||
pool = gst_object_ref (obj->pool);
|
pool = gst_object_ref (obj_pool);
|
||||||
size = obj->info.size;
|
size = obj->info.size;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -5058,7 +5095,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
if (can_share_own_pool) {
|
if (can_share_own_pool) {
|
||||||
if (pool)
|
if (pool)
|
||||||
gst_object_unref (pool);
|
gst_object_unref (pool);
|
||||||
pool = gst_object_ref (obj->pool);
|
pool = gst_object_ref (obj_pool);
|
||||||
size = obj->info.size;
|
size = obj->info.size;
|
||||||
GST_DEBUG_OBJECT (obj->dbg_obj,
|
GST_DEBUG_OBJECT (obj->dbg_obj,
|
||||||
"streaming mode: using our own pool %" GST_PTR_FORMAT, pool);
|
"streaming mode: using our own pool %" GST_PTR_FORMAT, pool);
|
||||||
|
@ -5116,7 +5153,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
min = MAX (min, GST_V4L2_MIN_BUFFERS (obj));
|
min = MAX (min, GST_V4L2_MIN_BUFFERS (obj));
|
||||||
|
|
||||||
/* To import we need the other pool to hold at least own_min */
|
/* To import we need the other pool to hold at least own_min */
|
||||||
if (obj->pool == pool)
|
if (obj_pool == pool)
|
||||||
min += own_min;
|
min += own_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5125,7 +5162,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
max = MAX (min, max);
|
max = MAX (min, max);
|
||||||
|
|
||||||
/* First step, configure our own pool */
|
/* First step, configure our own pool */
|
||||||
config = gst_buffer_pool_get_config (obj->pool);
|
config = gst_buffer_pool_get_config (obj_pool);
|
||||||
|
|
||||||
if (obj->need_video_meta || has_video_meta) {
|
if (obj->need_video_meta || has_video_meta) {
|
||||||
GST_DEBUG_OBJECT (obj->dbg_obj, "activate Video Meta");
|
GST_DEBUG_OBJECT (obj->dbg_obj, "activate Video Meta");
|
||||||
|
@ -5140,19 +5177,19 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
GST_PTR_FORMAT, config);
|
GST_PTR_FORMAT, config);
|
||||||
|
|
||||||
/* Our pool often need to adjust the value */
|
/* Our pool often need to adjust the value */
|
||||||
if (!gst_buffer_pool_set_config (obj->pool, config)) {
|
if (!gst_buffer_pool_set_config (obj_pool, config)) {
|
||||||
config = gst_buffer_pool_get_config (obj->pool);
|
config = gst_buffer_pool_get_config (obj_pool);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (obj->dbg_obj, "own pool config changed to %"
|
GST_DEBUG_OBJECT (obj->dbg_obj, "own pool config changed to %"
|
||||||
GST_PTR_FORMAT, config);
|
GST_PTR_FORMAT, config);
|
||||||
|
|
||||||
/* our pool will adjust the maximum buffer, which we are fine with */
|
/* our pool will adjust the maximum buffer, which we are fine with */
|
||||||
if (!gst_buffer_pool_set_config (obj->pool, config))
|
if (!gst_buffer_pool_set_config (obj_pool, config))
|
||||||
goto config_failed;
|
goto config_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now configure the other pool if different */
|
/* Now configure the other pool if different */
|
||||||
if (obj->pool != pool)
|
if (obj_pool != pool)
|
||||||
other_pool = pool;
|
other_pool = pool;
|
||||||
|
|
||||||
if (other_pool) {
|
if (other_pool) {
|
||||||
|
@ -5203,6 +5240,9 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
if (pool)
|
if (pool)
|
||||||
gst_object_unref (pool);
|
gst_object_unref (pool);
|
||||||
|
|
||||||
|
if (obj_pool)
|
||||||
|
gst_object_unref (obj_pool);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
pool_failed:
|
pool_failed:
|
||||||
|
@ -5222,6 +5262,13 @@ no_size:
|
||||||
(_("Video device did not suggest any buffer size.")), (NULL));
|
(_("Video device did not suggest any buffer size.")), (NULL));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
no_downstream_pool:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (obj->element, RESOURCE, SETTINGS,
|
||||||
|
(_("No downstream pool to import from.")),
|
||||||
|
("When importing DMABUF or USERPTR, we need a pool to import from"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
cleanup:
|
cleanup:
|
||||||
{
|
{
|
||||||
if (allocator)
|
if (allocator)
|
||||||
|
@ -5229,13 +5276,9 @@ cleanup:
|
||||||
|
|
||||||
if (pool)
|
if (pool)
|
||||||
gst_object_unref (pool);
|
gst_object_unref (pool);
|
||||||
return FALSE;
|
|
||||||
}
|
if (obj_pool)
|
||||||
no_downstream_pool:
|
gst_object_unref (obj_pool);
|
||||||
{
|
|
||||||
GST_ELEMENT_ERROR (obj->element, RESOURCE, SETTINGS,
|
|
||||||
(_("No downstream pool to import from.")),
|
|
||||||
("When importing DMABUF or USERPTR, we need a pool to import from"));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5262,9 +5305,14 @@ gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query)
|
||||||
switch (obj->mode) {
|
switch (obj->mode) {
|
||||||
case GST_V4L2_IO_MMAP:
|
case GST_V4L2_IO_MMAP:
|
||||||
case GST_V4L2_IO_DMABUF:
|
case GST_V4L2_IO_DMABUF:
|
||||||
if (need_pool && obj->pool) {
|
if (need_pool) {
|
||||||
if (!gst_buffer_pool_is_active (obj->pool))
|
GstBufferPool *obj_pool = gst_v4l2_object_get_buffer_pool (obj);
|
||||||
pool = gst_object_ref (obj->pool);
|
if (obj_pool) {
|
||||||
|
if (!gst_buffer_pool_is_active (obj_pool))
|
||||||
|
pool = gst_object_ref (obj_pool);
|
||||||
|
|
||||||
|
gst_object_unref (obj_pool);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -5377,3 +5425,25 @@ gst_v4l2_object_try_import (GstV4l2Object * obj, GstBuffer * buffer)
|
||||||
/* for the remaining, only the kernel driver can tell */
|
/* for the remaining, only the kernel driver can tell */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_v4l2_object_get_buffer_pool:
|
||||||
|
* @src: a #GstV4l2Object
|
||||||
|
*
|
||||||
|
* Returns: (nullable) (transfer full): the instance of the #GstBufferPool used
|
||||||
|
* by the v4l2object; unref it after usage.
|
||||||
|
*/
|
||||||
|
GstBufferPool *
|
||||||
|
gst_v4l2_object_get_buffer_pool (GstV4l2Object * v4l2object)
|
||||||
|
{
|
||||||
|
GstBufferPool *ret = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (v4l2object != NULL, NULL);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (v4l2object->element);
|
||||||
|
if (v4l2object->pool)
|
||||||
|
ret = gst_object_ref (v4l2object->pool);
|
||||||
|
GST_OBJECT_UNLOCK (v4l2object->element);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -311,6 +311,8 @@ gboolean gst_v4l2_object_decide_allocation (GstV4l2Object * v4l2object, GstQ
|
||||||
|
|
||||||
gboolean gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query);
|
gboolean gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query);
|
||||||
|
|
||||||
|
GstBufferPool * gst_v4l2_object_get_buffer_pool (GstV4l2Object * v4l2object);
|
||||||
|
|
||||||
GstStructure * gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc);
|
GstStructure * gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc);
|
||||||
|
|
||||||
/* crop / compose */
|
/* crop / compose */
|
||||||
|
|
|
@ -587,11 +587,11 @@ gst_v4l2sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstV4l2Sink *v4l2sink = GST_V4L2SINK (vsink);
|
GstV4l2Sink *v4l2sink = GST_V4L2SINK (vsink);
|
||||||
GstV4l2Object *obj = v4l2sink->v4l2object;
|
GstV4l2Object *obj = v4l2sink->v4l2object;
|
||||||
GstBufferPool *bpool = GST_BUFFER_POOL (obj->pool);
|
GstBufferPool *bpool = gst_v4l2_object_get_buffer_pool (obj);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (v4l2sink, "render buffer: %p", buf);
|
GST_DEBUG_OBJECT (v4l2sink, "render buffer: %p", buf);
|
||||||
|
|
||||||
if (G_UNLIKELY (obj->pool == NULL))
|
if (G_UNLIKELY (bpool == NULL))
|
||||||
goto not_negotiated;
|
goto not_negotiated;
|
||||||
|
|
||||||
if (G_UNLIKELY (!gst_buffer_pool_is_active (bpool))) {
|
if (G_UNLIKELY (!gst_buffer_pool_is_active (bpool))) {
|
||||||
|
@ -611,7 +611,7 @@ gst_v4l2sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||||
|
|
||||||
gst_buffer_ref (buf);
|
gst_buffer_ref (buf);
|
||||||
again:
|
again:
|
||||||
ret = gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL_CAST (obj->pool),
|
ret = gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL_CAST (bpool),
|
||||||
&buf, NULL);
|
&buf, NULL);
|
||||||
if (ret == GST_FLOW_FLUSHING) {
|
if (ret == GST_FLOW_FLUSHING) {
|
||||||
ret = gst_base_sink_wait_preroll (GST_BASE_SINK (vsink));
|
ret = gst_base_sink_wait_preroll (GST_BASE_SINK (vsink));
|
||||||
|
@ -619,6 +619,8 @@ again:
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
|
if (bpool)
|
||||||
|
gst_object_unref (bpool);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -633,6 +635,8 @@ activate_failed:
|
||||||
GST_ELEMENT_ERROR (v4l2sink, RESOURCE, SETTINGS,
|
GST_ELEMENT_ERROR (v4l2sink, RESOURCE, SETTINGS,
|
||||||
(_("Failed to allocated required memory.")),
|
(_("Failed to allocated required memory.")),
|
||||||
("Buffer pool activation failed"));
|
("Buffer pool activation failed"));
|
||||||
|
if (bpool)
|
||||||
|
gst_object_unref (bpool);
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -647,6 +647,7 @@ gst_v4l2src_query_preferred_dv_timings (GstV4l2Src * v4l2src,
|
||||||
GstV4l2Object *obj = v4l2src->v4l2object;
|
GstV4l2Object *obj = v4l2src->v4l2object;
|
||||||
struct v4l2_dv_timings dv_timings = { 0, };
|
struct v4l2_dv_timings dv_timings = { 0, };
|
||||||
const struct v4l2_bt_timings *bt = &dv_timings.bt;
|
const struct v4l2_bt_timings *bt = &dv_timings.bt;
|
||||||
|
gboolean not_streaming;
|
||||||
gint tot_width, tot_height;
|
gint tot_width, tot_height;
|
||||||
gint gcd;
|
gint gcd;
|
||||||
|
|
||||||
|
@ -673,7 +674,14 @@ gst_v4l2src_query_preferred_dv_timings (GstV4l2Src * v4l2src,
|
||||||
|
|
||||||
/* If are are not streaming (e.g. we received source-change event), lock the
|
/* If are are not streaming (e.g. we received source-change event), lock the
|
||||||
* new timing immediatly so that TRY_FMT can properly work */
|
* new timing immediatly so that TRY_FMT can properly work */
|
||||||
if (!obj->pool || !GST_V4L2_BUFFER_POOL_IS_STREAMING (obj->pool)) {
|
{
|
||||||
|
GstBufferPool *obj_pool = gst_v4l2_object_get_buffer_pool (obj);
|
||||||
|
not_streaming = !obj_pool || !GST_V4L2_BUFFER_POOL_IS_STREAMING (obj_pool);
|
||||||
|
if (obj_pool)
|
||||||
|
gst_object_unref (obj_pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not_streaming) {
|
||||||
gst_v4l2_set_dv_timings (obj, &dv_timings);
|
gst_v4l2_set_dv_timings (obj, &dv_timings);
|
||||||
/* Setting a new DV timings invalidates the probed caps. */
|
/* Setting a new DV timings invalidates the probed caps. */
|
||||||
gst_caps_replace (&obj->probed_caps, NULL);
|
gst_caps_replace (&obj->probed_caps, NULL);
|
||||||
|
@ -892,6 +900,7 @@ static gboolean
|
||||||
gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
|
gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
|
||||||
{
|
{
|
||||||
GstV4l2Src *src = GST_V4L2SRC (bsrc);
|
GstV4l2Src *src = GST_V4L2SRC (bsrc);
|
||||||
|
GstBufferPool *bpool = gst_v4l2_object_get_buffer_pool (src->v4l2object);
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
|
|
||||||
if (src->pending_set_fmt) {
|
if (src->pending_set_fmt) {
|
||||||
|
@ -902,7 +911,7 @@ gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
|
||||||
|
|
||||||
ret = gst_v4l2src_set_format (src, caps, &error);
|
ret = gst_v4l2src_set_format (src, caps, &error);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (src->v4l2object->pool);
|
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
|
||||||
gst_v4l2_buffer_pool_enable_resolution_change (pool);
|
gst_v4l2_buffer_pool_enable_resolution_change (pool);
|
||||||
} else {
|
} else {
|
||||||
gst_v4l2_error (src, &error);
|
gst_v4l2_error (src, &error);
|
||||||
|
@ -910,7 +919,7 @@ gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
src->pending_set_fmt = FALSE;
|
src->pending_set_fmt = FALSE;
|
||||||
} else if (gst_buffer_pool_is_active (src->v4l2object->pool)) {
|
} else if (gst_buffer_pool_is_active (bpool)) {
|
||||||
/* Trick basesrc into not deactivating the active pool. Renegotiating here
|
/* Trick basesrc into not deactivating the active pool. Renegotiating here
|
||||||
* would otherwise turn off and on the camera. */
|
* would otherwise turn off and on the camera. */
|
||||||
GstAllocator *allocator;
|
GstAllocator *allocator;
|
||||||
|
@ -936,6 +945,8 @@ gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
|
||||||
gst_object_unref (pool);
|
gst_object_unref (pool);
|
||||||
if (allocator)
|
if (allocator)
|
||||||
gst_object_unref (allocator);
|
gst_object_unref (allocator);
|
||||||
|
if (bpool)
|
||||||
|
gst_object_unref (bpool);
|
||||||
|
|
||||||
return GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query);
|
return GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query);
|
||||||
}
|
}
|
||||||
|
@ -947,10 +958,12 @@ gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (!gst_buffer_pool_set_active (src->v4l2object->pool, TRUE))
|
if (!gst_buffer_pool_set_active (bpool, TRUE))
|
||||||
goto activate_failed;
|
goto activate_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bpool)
|
||||||
|
gst_object_unref (bpool);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
activate_failed:
|
activate_failed:
|
||||||
|
@ -958,6 +971,8 @@ activate_failed:
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS,
|
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS,
|
||||||
(_("Failed to allocate required memory.")),
|
(_("Failed to allocate required memory.")),
|
||||||
("Buffer pool activation failed"));
|
("Buffer pool activation failed"));
|
||||||
|
if (bpool)
|
||||||
|
gst_object_unref (bpool);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1002,8 +1017,13 @@ gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
|
||||||
min_latency /= 2;
|
min_latency /= 2;
|
||||||
|
|
||||||
/* max latency is total duration of the frame buffer */
|
/* max latency is total duration of the frame buffer */
|
||||||
if (obj->pool != NULL)
|
{
|
||||||
num_buffers = GST_V4L2_BUFFER_POOL_CAST (obj->pool)->max_latency;
|
GstBufferPool *obj_pool = gst_v4l2_object_get_buffer_pool (obj);
|
||||||
|
if (obj_pool != NULL) {
|
||||||
|
num_buffers = GST_V4L2_BUFFER_POOL_CAST (obj_pool)->max_latency;
|
||||||
|
gst_object_unref (obj_pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (num_buffers == 0)
|
if (num_buffers == 0)
|
||||||
max_latency = -1;
|
max_latency = -1;
|
||||||
|
@ -1136,8 +1156,6 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
|
||||||
gboolean half_frame;
|
gboolean half_frame;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL_CAST (obj->pool);
|
|
||||||
|
|
||||||
ret = GST_BASE_SRC_CLASS (parent_class)->alloc (GST_BASE_SRC (src), 0,
|
ret = GST_BASE_SRC_CLASS (parent_class)->alloc (GST_BASE_SRC (src), 0,
|
||||||
obj->info.size, buf);
|
obj->info.size, buf);
|
||||||
|
|
||||||
|
@ -1164,7 +1182,13 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
|
||||||
goto alloc_failed;
|
goto alloc_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gst_v4l2_buffer_pool_process (pool, buf, NULL);
|
{
|
||||||
|
GstV4l2BufferPool *obj_pool =
|
||||||
|
GST_V4L2_BUFFER_POOL_CAST (gst_v4l2_object_get_buffer_pool (obj));
|
||||||
|
ret = gst_v4l2_buffer_pool_process (obj_pool, buf, NULL);
|
||||||
|
if (obj_pool)
|
||||||
|
gst_object_unref (obj_pool);
|
||||||
|
}
|
||||||
|
|
||||||
} while (ret == GST_V4L2_FLOW_CORRUPTED_BUFFER ||
|
} while (ret == GST_V4L2_FLOW_CORRUPTED_BUFFER ||
|
||||||
ret == GST_V4L2_FLOW_RESOLUTION_CHANGE);
|
ret == GST_V4L2_FLOW_RESOLUTION_CHANGE);
|
||||||
|
|
|
@ -318,12 +318,16 @@ gst_v4l2_transform_decide_allocation (GstBaseTransform * trans,
|
||||||
GST_DEBUG_OBJECT (self, "called");
|
GST_DEBUG_OBJECT (self, "called");
|
||||||
|
|
||||||
if (gst_v4l2_object_decide_allocation (self->v4l2capture, query)) {
|
if (gst_v4l2_object_decide_allocation (self->v4l2capture, query)) {
|
||||||
GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2capture->pool);
|
gboolean pool_active;
|
||||||
|
GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
|
||||||
|
|
||||||
ret = GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans,
|
ret = GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans,
|
||||||
query);
|
query);
|
||||||
|
|
||||||
if (!gst_buffer_pool_set_active (pool, TRUE))
|
pool_active = gst_buffer_pool_set_active (pool, TRUE);
|
||||||
|
if (pool)
|
||||||
|
gst_object_unref (pool);
|
||||||
|
if (!pool_active)
|
||||||
goto activate_failed;
|
goto activate_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,7 +887,7 @@ gst_v4l2_transform_prepare_output_buffer (GstBaseTransform * trans,
|
||||||
GstBuffer * inbuf, GstBuffer ** outbuf)
|
GstBuffer * inbuf, GstBuffer ** outbuf)
|
||||||
{
|
{
|
||||||
GstV4l2Transform *self = GST_V4L2_TRANSFORM (trans);
|
GstV4l2Transform *self = GST_V4L2_TRANSFORM (trans);
|
||||||
GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
|
GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (self->v4l2output);
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_CLASS (parent_class);
|
GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_CLASS (parent_class);
|
||||||
|
|
||||||
|
@ -932,6 +936,8 @@ gst_v4l2_transform_prepare_output_buffer (GstBaseTransform * trans,
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
if (pool)
|
||||||
|
g_object_unref (pool);
|
||||||
pool = gst_base_transform_get_buffer_pool (trans);
|
pool = gst_base_transform_get_buffer_pool (trans);
|
||||||
|
|
||||||
if (!gst_buffer_pool_set_active (pool, TRUE))
|
if (!gst_buffer_pool_set_active (pool, TRUE))
|
||||||
|
@ -944,7 +950,7 @@ gst_v4l2_transform_prepare_output_buffer (GstBaseTransform * trans,
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto alloc_failed;
|
goto alloc_failed;
|
||||||
|
|
||||||
pool = self->v4l2capture->pool;
|
pool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
|
||||||
ret =
|
ret =
|
||||||
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool), outbuf,
|
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool), outbuf,
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -964,6 +970,8 @@ gst_v4l2_transform_prepare_output_buffer (GstBaseTransform * trans,
|
||||||
}
|
}
|
||||||
|
|
||||||
beach:
|
beach:
|
||||||
|
if (pool)
|
||||||
|
g_object_unref (pool);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
activate_failed:
|
activate_failed:
|
||||||
|
@ -1014,10 +1022,8 @@ gst_v4l2_transform_sink_event (GstBaseTransform * trans, GstEvent * event)
|
||||||
GST_DEBUG_OBJECT (self, "flush stop");
|
GST_DEBUG_OBJECT (self, "flush stop");
|
||||||
gst_v4l2_object_unlock_stop (self->v4l2capture);
|
gst_v4l2_object_unlock_stop (self->v4l2capture);
|
||||||
gst_v4l2_object_unlock_stop (self->v4l2output);
|
gst_v4l2_object_unlock_stop (self->v4l2output);
|
||||||
if (self->v4l2output->pool)
|
gst_v4l2_buffer_pool_flush (self->v4l2output);
|
||||||
gst_v4l2_buffer_pool_flush (self->v4l2output->pool);
|
gst_v4l2_buffer_pool_flush (self->v4l2capture);
|
||||||
if (self->v4l2capture->pool)
|
|
||||||
gst_v4l2_buffer_pool_flush (self->v4l2capture->pool);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -286,8 +286,7 @@ gst_v4l2_video_dec_set_format (GstVideoDecoder * decoder,
|
||||||
* the complexity and should not have much impact in performance since the
|
* the complexity and should not have much impact in performance since the
|
||||||
* following allocation query will happen on a drained pipeline and won't
|
* following allocation query will happen on a drained pipeline and won't
|
||||||
* block. */
|
* block. */
|
||||||
if (self->v4l2capture->pool &&
|
if (!gst_v4l2_buffer_pool_orphan (self->v4l2capture)) {
|
||||||
!gst_v4l2_buffer_pool_orphan (&self->v4l2capture->pool)) {
|
|
||||||
GstCaps *caps = gst_pad_get_current_caps (decoder->srcpad);
|
GstCaps *caps = gst_pad_get_current_caps (decoder->srcpad);
|
||||||
if (caps) {
|
if (caps) {
|
||||||
GstQuery *query = gst_query_new_allocation (caps, FALSE);
|
GstQuery *query = gst_query_new_allocation (caps, FALSE);
|
||||||
|
@ -351,14 +350,12 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
|
||||||
gst_v4l2_object_unlock_stop (self->v4l2output);
|
gst_v4l2_object_unlock_stop (self->v4l2output);
|
||||||
gst_v4l2_object_unlock_stop (self->v4l2capture);
|
gst_v4l2_object_unlock_stop (self->v4l2capture);
|
||||||
|
|
||||||
if (self->v4l2output->pool)
|
gst_v4l2_buffer_pool_flush (self->v4l2output);
|
||||||
gst_v4l2_buffer_pool_flush (self->v4l2output->pool);
|
|
||||||
|
|
||||||
/* gst_v4l2_buffer_pool_flush() calls streamon the capture pool and must be
|
/* gst_v4l2_buffer_pool_flush() calls streamon the capture pool and must be
|
||||||
* called after gst_v4l2_object_unlock_stop() stopped flushing the buffer
|
* called after gst_v4l2_object_unlock_stop() stopped flushing the buffer
|
||||||
* pool. */
|
* pool. */
|
||||||
if (self->v4l2capture->pool)
|
gst_v4l2_buffer_pool_flush (self->v4l2capture);
|
||||||
gst_v4l2_buffer_pool_flush (self->v4l2capture->pool);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -369,9 +366,15 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
|
||||||
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
|
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
|
||||||
|
|
||||||
/* We don't allow renegotiation without careful disabling the pool */
|
/* We don't allow renegotiation without careful disabling the pool */
|
||||||
if (self->v4l2capture->pool &&
|
{
|
||||||
gst_buffer_pool_is_active (GST_BUFFER_POOL (self->v4l2capture->pool)))
|
GstBufferPool *cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
|
||||||
|
if (cpool) {
|
||||||
|
gboolean is_active = gst_buffer_pool_is_active (cpool);
|
||||||
|
gst_object_unref (cpool);
|
||||||
|
if (is_active)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||||
}
|
}
|
||||||
|
@ -444,15 +447,18 @@ gst_v4l2_video_dec_finish (GstVideoDecoder * decoder)
|
||||||
gst_object_unref (task);
|
gst_object_unref (task);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
GstBufferPool *opool = gst_v4l2_object_get_buffer_pool (self->v4l2output);
|
||||||
/* otherwise keep queuing empty buffers until the processing thread has
|
/* otherwise keep queuing empty buffers until the processing thread has
|
||||||
* stopped, _pool_process() will return FLUSHING when that happened */
|
* stopped, _pool_process() will return FLUSHING when that happened */
|
||||||
while (ret == GST_FLOW_OK) {
|
while (ret == GST_FLOW_OK) {
|
||||||
buffer = gst_buffer_new ();
|
buffer = gst_buffer_new ();
|
||||||
ret =
|
ret =
|
||||||
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
|
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (opool), &buffer,
|
||||||
v4l2output->pool), &buffer, NULL);
|
NULL);
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
}
|
}
|
||||||
|
if (opool)
|
||||||
|
gst_object_unref (opool);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* and ensure the processing thread has stopped in case another error
|
/* and ensure the processing thread has stopped in case another error
|
||||||
|
@ -566,6 +572,8 @@ gst_v4l2_video_dec_setup_capture (GstVideoDecoder * decoder)
|
||||||
GstVideoCodecState *output_state;
|
GstVideoCodecState *output_state;
|
||||||
GstCaps *acquired_caps, *available_caps, *caps, *filter;
|
GstCaps *acquired_caps, *available_caps, *caps, *filter;
|
||||||
GstStructure *st;
|
GstStructure *st;
|
||||||
|
GstBufferPool *cpool;
|
||||||
|
gboolean active;
|
||||||
|
|
||||||
if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
|
if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
|
||||||
/* init capture fps according to output */
|
/* init capture fps according to output */
|
||||||
|
@ -635,10 +643,14 @@ gst_v4l2_video_dec_setup_capture (GstVideoDecoder * decoder)
|
||||||
output_state->info.interlace_mode = info.interlace_mode;
|
output_state->info.interlace_mode = info.interlace_mode;
|
||||||
output_state->info.colorimetry = info.colorimetry;
|
output_state->info.colorimetry = info.colorimetry;
|
||||||
gst_video_codec_state_unref (output_state);
|
gst_video_codec_state_unref (output_state);
|
||||||
|
|
||||||
|
cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
|
||||||
gst_v4l2_buffer_pool_enable_resolution_change (GST_V4L2_BUFFER_POOL
|
gst_v4l2_buffer_pool_enable_resolution_change (GST_V4L2_BUFFER_POOL
|
||||||
(self->v4l2capture->pool));
|
(cpool));
|
||||||
|
|
||||||
if (!gst_video_decoder_negotiate (decoder)) {
|
if (!gst_video_decoder_negotiate (decoder)) {
|
||||||
|
if (cpool)
|
||||||
|
gst_object_unref (cpool);
|
||||||
if (GST_PAD_IS_FLUSHING (decoder->srcpad))
|
if (GST_PAD_IS_FLUSHING (decoder->srcpad))
|
||||||
goto flushing;
|
goto flushing;
|
||||||
else
|
else
|
||||||
|
@ -646,8 +658,10 @@ gst_v4l2_video_dec_setup_capture (GstVideoDecoder * decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure our internal pool is activated */
|
/* Ensure our internal pool is activated */
|
||||||
if (!gst_buffer_pool_set_active (GST_BUFFER_POOL (self->v4l2capture->pool),
|
active = gst_buffer_pool_set_active (cpool, TRUE);
|
||||||
TRUE))
|
if (cpool)
|
||||||
|
gst_object_unref (cpool);
|
||||||
|
if (!active)
|
||||||
goto activate_failed;
|
goto activate_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,7 +684,6 @@ static void
|
||||||
gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
|
gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
|
||||||
{
|
{
|
||||||
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
|
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
|
||||||
GstV4l2BufferPool *v4l2_pool;
|
|
||||||
GstBufferPool *pool;
|
GstBufferPool *pool;
|
||||||
GstVideoCodecFrame *frame;
|
GstVideoCodecFrame *frame;
|
||||||
GstBuffer *buffer = NULL;
|
GstBuffer *buffer = NULL;
|
||||||
|
@ -701,7 +714,6 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
|
||||||
|
|
||||||
GST_LOG_OBJECT (decoder, "Allocate output buffer");
|
GST_LOG_OBJECT (decoder, "Allocate output buffer");
|
||||||
|
|
||||||
v4l2_pool = GST_V4L2_BUFFER_POOL (self->v4l2capture->pool);
|
|
||||||
self->output_flow = GST_FLOW_OK;
|
self->output_flow = GST_FLOW_OK;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -730,7 +742,14 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
GST_LOG_OBJECT (decoder, "Process output buffer");
|
GST_LOG_OBJECT (decoder, "Process output buffer");
|
||||||
ret = gst_v4l2_buffer_pool_process (v4l2_pool, &buffer, NULL);
|
{
|
||||||
|
GstV4l2BufferPool *cpool =
|
||||||
|
GST_V4L2_BUFFER_POOL (gst_v4l2_object_get_buffer_pool
|
||||||
|
(self->v4l2capture));
|
||||||
|
ret = gst_v4l2_buffer_pool_process (cpool, &buffer, NULL);
|
||||||
|
if (cpool)
|
||||||
|
gst_object_unref (cpool);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == GST_V4L2_FLOW_RESOLUTION_CHANGE) {
|
if (ret == GST_V4L2_FLOW_RESOLUTION_CHANGE) {
|
||||||
GST_INFO_OBJECT (decoder, "Received resolution change");
|
GST_INFO_OBJECT (decoder, "Received resolution change");
|
||||||
|
@ -825,7 +844,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||||
{
|
{
|
||||||
GstV4l2Error error = GST_V4L2_ERROR_INIT;
|
GstV4l2Error error = GST_V4L2_ERROR_INIT;
|
||||||
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
|
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
|
||||||
GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
|
GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (self->v4l2output);
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
gboolean processed = FALSE;
|
gboolean processed = FALSE;
|
||||||
GstBuffer *tmp;
|
GstBuffer *tmp;
|
||||||
|
@ -900,8 +919,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||||
GST_LOG_OBJECT (decoder, "Passing buffer with system frame number %u",
|
GST_LOG_OBJECT (decoder, "Passing buffer with system frame number %u",
|
||||||
processed ? frame->system_frame_number : 0);
|
processed ? frame->system_frame_number : 0);
|
||||||
ret =
|
ret =
|
||||||
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
|
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool), &codec_data,
|
||||||
v4l2output->pool), &codec_data,
|
|
||||||
processed ? &frame->system_frame_number : &dummy_frame_number);
|
processed ? &frame->system_frame_number : &dummy_frame_number);
|
||||||
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
|
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
|
||||||
|
|
||||||
|
@ -933,8 +951,8 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||||
GST_LOG_OBJECT (decoder, "Passing buffer with system frame number %u",
|
GST_LOG_OBJECT (decoder, "Passing buffer with system frame number %u",
|
||||||
frame->system_frame_number);
|
frame->system_frame_number);
|
||||||
ret =
|
ret =
|
||||||
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->v4l2output->
|
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (pool),
|
||||||
pool), &frame->input_buffer, &frame->system_frame_number);
|
&frame->input_buffer, &frame->system_frame_number);
|
||||||
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
|
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
|
||||||
|
|
||||||
if (ret == GST_FLOW_FLUSHING) {
|
if (ret == GST_FLOW_FLUSHING) {
|
||||||
|
@ -956,6 +974,8 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
|
||||||
gst_buffer_unref (tmp);
|
gst_buffer_unref (tmp);
|
||||||
|
|
||||||
gst_video_codec_frame_unref (frame);
|
gst_video_codec_frame_unref (frame);
|
||||||
|
if (pool)
|
||||||
|
gst_object_unref (pool);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
@ -997,6 +1017,8 @@ process_failed:
|
||||||
}
|
}
|
||||||
drop:
|
drop:
|
||||||
{
|
{
|
||||||
|
if (pool)
|
||||||
|
gst_object_unref (pool);
|
||||||
gst_video_decoder_drop_frame (decoder, frame);
|
gst_video_decoder_drop_frame (decoder, frame);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -652,10 +652,14 @@ gst_v4l2_video_enc_loop (GstVideoEncoder * encoder)
|
||||||
/* FIXME Check if buffer isn't the last one here */
|
/* FIXME Check if buffer isn't the last one here */
|
||||||
|
|
||||||
GST_LOG_OBJECT (encoder, "Process output buffer");
|
GST_LOG_OBJECT (encoder, "Process output buffer");
|
||||||
ret =
|
{
|
||||||
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL
|
GstV4l2BufferPool *cpool =
|
||||||
(self->v4l2capture->pool), &buffer, NULL);
|
GST_V4L2_BUFFER_POOL (gst_v4l2_object_get_buffer_pool
|
||||||
|
(self->v4l2capture));
|
||||||
|
ret = gst_v4l2_buffer_pool_process (cpool, &buffer, NULL);
|
||||||
|
if (cpool)
|
||||||
|
gst_object_unref (cpool);
|
||||||
|
}
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
|
@ -741,6 +745,7 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
|
||||||
GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
|
GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstTaskState task_state;
|
GstTaskState task_state;
|
||||||
|
gboolean active;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
|
GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
|
||||||
|
|
||||||
|
@ -749,7 +754,7 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
|
||||||
|
|
||||||
task_state = gst_pad_get_task_state (GST_VIDEO_ENCODER_SRC_PAD (self));
|
task_state = gst_pad_get_task_state (GST_VIDEO_ENCODER_SRC_PAD (self));
|
||||||
if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED) {
|
if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED) {
|
||||||
GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
|
GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (self->v4l2output);
|
||||||
|
|
||||||
/* It is possible that the processing thread stopped due to an error or
|
/* It is possible that the processing thread stopped due to an error or
|
||||||
* when the last buffer has been met during the draining process. */
|
* when the last buffer has been met during the draining process. */
|
||||||
|
@ -759,6 +764,8 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
|
||||||
GST_DEBUG_OBJECT (self, "Processing loop stopped with error: %s, leaving",
|
GST_DEBUG_OBJECT (self, "Processing loop stopped with error: %s, leaving",
|
||||||
gst_flow_get_name (self->output_flow));
|
gst_flow_get_name (self->output_flow));
|
||||||
ret = self->output_flow;
|
ret = self->output_flow;
|
||||||
|
if (pool)
|
||||||
|
gst_object_unref (pool);
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,15 +779,29 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
|
||||||
self->v4l2output->info.size, min, min);
|
self->v4l2output->info.size, min, min);
|
||||||
|
|
||||||
/* There is no reason to refuse this config */
|
/* There is no reason to refuse this config */
|
||||||
if (!gst_buffer_pool_set_config (pool, config))
|
if (!gst_buffer_pool_set_config (pool, config)) {
|
||||||
goto activate_failed;
|
if (pool)
|
||||||
|
gst_object_unref (pool);
|
||||||
if (!gst_buffer_pool_set_active (pool, TRUE))
|
|
||||||
goto activate_failed;
|
goto activate_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_buffer_pool_set_active
|
if (!gst_buffer_pool_set_active (pool, TRUE)) {
|
||||||
(GST_BUFFER_POOL (self->v4l2capture->pool), TRUE)) {
|
if (pool)
|
||||||
|
gst_object_unref (pool);
|
||||||
|
goto activate_failed;
|
||||||
|
}
|
||||||
|
if (pool)
|
||||||
|
gst_object_unref (pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
GstBufferPool *cpool =
|
||||||
|
gst_v4l2_object_get_buffer_pool (self->v4l2capture);
|
||||||
|
active = gst_buffer_pool_set_active (cpool, TRUE);
|
||||||
|
if (cpool)
|
||||||
|
gst_object_unref (cpool);
|
||||||
|
}
|
||||||
|
if (!active) {
|
||||||
GST_WARNING_OBJECT (self, "Could not activate capture buffer pool.");
|
GST_WARNING_OBJECT (self, "Could not activate capture buffer pool.");
|
||||||
goto activate_failed;
|
goto activate_failed;
|
||||||
}
|
}
|
||||||
|
@ -799,10 +820,15 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
|
||||||
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
|
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
|
||||||
GST_LOG_OBJECT (encoder, "Passing buffer with frame number %u",
|
GST_LOG_OBJECT (encoder, "Passing buffer with frame number %u",
|
||||||
frame->system_frame_number);
|
frame->system_frame_number);
|
||||||
ret =
|
|
||||||
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
|
{
|
||||||
v4l2output->pool), &frame->input_buffer,
|
GstBufferPool *opool = gst_v4l2_object_get_buffer_pool (self->v4l2output);
|
||||||
&frame->system_frame_number);
|
ret = gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (opool),
|
||||||
|
&frame->input_buffer, &frame->system_frame_number);
|
||||||
|
if (opool)
|
||||||
|
gst_object_unref (opool);
|
||||||
|
}
|
||||||
|
|
||||||
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
|
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
|
||||||
|
|
||||||
if (ret == GST_FLOW_FLUSHING) {
|
if (ret == GST_FLOW_FLUSHING) {
|
||||||
|
|
Loading…
Reference in a new issue