From bb1d9b398e418d3c4cc8552c4a73556c4241ff8e Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Thu, 4 Feb 2021 14:13:32 -0500 Subject: [PATCH] v4l2bufferpool: Handle resolution change event This patch adds the detection, dequeuing and reporting of the SOURCE_CHANGE event when the CH_RESOLUTION flag is set. The acquire function will now return a new custom success called GST_V4L2_FLOW_RESOLUTION_CHANGE. In order to use this new feature, elements must enable it by calling: gst_v4l2_buffer_pool_enable_resolution_change (pool); Part-of: --- sys/v4l2/gstv4l2bufferpool.c | 49 +++++++++++++++++++++++++++++++++++- sys/v4l2/gstv4l2bufferpool.h | 11 +++++--- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index 21efd35728..8d24819026 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -1115,6 +1115,22 @@ again: if (gst_poll_fd_has_error (pool->poll, &pool->pollfd)) goto select_error; + /* PRI is used to signal that events are available */ + if (gst_poll_fd_has_pri (pool->poll, &pool->pollfd)) { + struct v4l2_event event = { 0, }; + + if (!gst_v4l2_dequeue_event (pool->obj, &event)) + goto dqevent_failed; + + if (event.type != V4L2_EVENT_SOURCE_CHANGE || + (event.u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION) == 0) { + GST_INFO_OBJECT (pool, "Received unhandled event, ignoring."); + goto again; + } + + return GST_V4L2_FLOW_RESOLUTION_CHANGE; + } + if (ret == 0) goto no_buffers; @@ -1134,7 +1150,15 @@ select_error: return GST_FLOW_ERROR; } no_buffers: - return GST_V4L2_FLOW_LAST_BUFFER; + { + return GST_V4L2_FLOW_LAST_BUFFER; + } +dqevent_failed: + { + GST_ELEMENT_ERROR (pool->obj->element, RESOURCE, READ, (NULL), + ("dqevent error: %s (%d)", g_strerror (errno), errno)); + return GST_FLOW_ERROR; + } } static GstFlowReturn @@ -1241,6 +1265,11 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer, goto done; } + if (res == GST_V4L2_FLOW_RESOLUTION_CHANGE) { + GST_INFO_OBJECT (pool, "Resolution change detected."); + goto done; + } + GST_LOG_OBJECT (pool, "dequeueing a buffer"); res = gst_v4l2_allocator_dqbuf (pool->vallocator, &group); @@ -2159,3 +2188,21 @@ gst_v4l2_buffer_pool_flush (GstBufferPool * bpool) return ret; } + +/** + * gst_v4l2_buffer_pool_enable_resolution_change: + * @pool: a #GstBufferPool + * + * When this is called, the pool will subscribe to the + * %V4L2_EVENT_SOURCE_CHANGE. Upon receiving this event, it will notify + * the element acquiring buffer with the special flow return + * %GST_V4L2_FLOW_RESOLUTION_CHANGE. + */ +void +gst_v4l2_buffer_pool_enable_resolution_change (GstV4l2BufferPool * pool) +{ + g_return_if_fail (!gst_buffer_pool_is_active (GST_BUFFER_POOL (pool))); + + if (gst_v4l2_subscribe_event (pool->obj, V4L2_EVENT_SOURCE_CHANGE)) + gst_poll_fd_ctl_pri (pool->poll, &pool->pollfd, TRUE); +} diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h index f8972b6417..b61a6ea821 100644 --- a/sys/v4l2/gstv4l2bufferpool.h +++ b/sys/v4l2/gstv4l2bufferpool.h @@ -41,9 +41,8 @@ G_BEGIN_DECLS #define GST_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER_POOL, GstV4l2BufferPool)) #define GST_V4L2_BUFFER_POOL_CAST(obj) ((GstV4l2BufferPool*)(obj)) -/* This flow return is used to indicated that the last buffer of a - * drain or a resoltuion change has been found. This should normally - * only occur for mem-2-mem devices. */ +/* This flow return is used to indicate that the last buffer has been dequeued + * during draining. This should normally only occur for mem-2-mem devices. */ #define GST_V4L2_FLOW_LAST_BUFFER GST_FLOW_CUSTOM_SUCCESS /* This flow return is used to indicated that the returned buffer was marked @@ -51,6 +50,10 @@ G_BEGIN_DECLS * simply waiting for next buffer. */ #define GST_V4L2_FLOW_CORRUPTED_BUFFER GST_FLOW_CUSTOM_SUCCESS_1 +/* This flow return is used to indicate that a SOURCE_CHANGE event with the + * resolution change flag set was received. */ +#define GST_V4L2_FLOW_RESOLUTION_CHANGE GST_FLOW_CUSTOM_SUCCESS_2 + struct _GstV4l2BufferPool { GstBufferPool parent; @@ -114,6 +117,8 @@ gboolean gst_v4l2_buffer_pool_flush (GstBufferPool *pool); gboolean gst_v4l2_buffer_pool_orphan (GstBufferPool ** pool); +void gst_v4l2_buffer_pool_enable_resolution_change (GstV4l2BufferPool *self); + G_END_DECLS #endif /*__GST_V4L2_BUFFER_POOL_H__ */