2929
3030#include < atomic>
3131#include < queue>
32+ #include < tuple>
33+ #include < utility>
3234#include < vector>
3335
3436#include < libcamera/camera.h>
@@ -285,10 +287,19 @@ gst_libcamera_extrapolate_info(GstVideoInfo *info, guint32 stride)
285287}
286288
287289static GstFlowReturn
288- gst_libcamera_video_frame_copy (GstBuffer *src, GstBuffer *dest, const GstVideoInfo *dest_info, guint32 stride)
290+ gst_libcamera_video_frame_copy (GstBuffer *src, GstBuffer *dest,
291+ const GstVideoInfo *dest_info, guint32 stride)
289292{
290- GstVideoInfo src_info = *dest_info;
293+ /*
294+ * When dropping support for versions earlier than v1.22.0, use
295+ *
296+ * g_auto (GstVideoFrame) src_frame = GST_VIDEO_FRAME_INIT;
297+ * g_auto (GstVideoFrame) dest_frame = GST_VIDEO_FRAME_INIT;
298+ *
299+ * and drop the gst_video_frame_unmap() calls.
300+ */
291301 GstVideoFrame src_frame, dest_frame;
302+ GstVideoInfo src_info = *dest_info;
292303
293304 gst_libcamera_extrapolate_info (&src_info, stride);
294305 src_info.size = gst_buffer_get_size (src);
@@ -298,7 +309,12 @@ gst_libcamera_video_frame_copy(GstBuffer *src, GstBuffer *dest, const GstVideoIn
298309 return GST_FLOW_ERROR;
299310 }
300311
301- if (!gst_video_frame_map (&dest_frame, const_cast <GstVideoInfo *>(dest_info), dest, GST_MAP_WRITE)) {
312+ /*
313+ * When dropping support for versions earlier than 1.20.0, drop the
314+ * const_cast<>().
315+ */
316+ if (!gst_video_frame_map (&dest_frame, const_cast <GstVideoInfo *>(dest_info),
317+ dest, GST_MAP_WRITE)) {
302318 GST_ERROR (" Could not map dest buffer" );
303319 gst_video_frame_unmap (&src_frame);
304320 return GST_FLOW_ERROR;
@@ -352,10 +368,10 @@ int GstLibcameraSrcState::processRequest()
352368
353369 if (video_pool) {
354370 /* Only set video pool when a copy is needed. */
355- GstBuffer *copy = NULL ;
371+ GstBuffer *copy = nullptr ;
356372 const GstVideoInfo info = gst_libcamera_pad_get_video_info (srcpad);
357373
358- ret = gst_buffer_pool_acquire_buffer (video_pool, ©, NULL );
374+ ret = gst_buffer_pool_acquire_buffer (video_pool, ©, nullptr );
359375 if (ret != GST_FLOW_OK) {
360376 gst_buffer_unref (buffer);
361377 GST_ELEMENT_ERROR (src_, RESOURCE, SETTINGS,
@@ -507,6 +523,73 @@ gst_libcamera_src_open(GstLibcameraSrc *self)
507523 return true ;
508524}
509525
526+ /* *
527+ * \brief Create a video pool for a pad
528+ * \param[in] self The libcamerasrc instance
529+ * \param[in] srcpad The pad
530+ * \param[in] caps The pad caps
531+ * \param[in] info The video info for the pad
532+ *
533+ * This function creates and returns a video buffer pool for the given pad if
534+ * needed to accommodate stride mismatch. If the peer element supports stride
535+ * negotiation through the meta API, no pool is needed and the function will
536+ * return a null pool.
537+ *
538+ * \return A tuple containing the video buffers pool pointer and an error code
539+ */
540+ static std::tuple<GstBufferPool *, int >
541+ gst_libcamera_create_video_pool (GstLibcameraSrc *self, GstPad *srcpad,
542+ GstCaps *caps, const GstVideoInfo *info)
543+ {
544+ g_autoptr (GstQuery) query = nullptr ;
545+ g_autoptr (GstBufferPool) pool = nullptr ;
546+ const gboolean need_pool = true ;
547+
548+ /*
549+ * Get the peer allocation hints to check if it supports the meta API.
550+ * If so, the stride will be negotiated, and there's no need to create a
551+ * video pool.
552+ */
553+ query = gst_query_new_allocation (caps, need_pool);
554+
555+ if (!gst_pad_peer_query (srcpad, query))
556+ GST_DEBUG_OBJECT (self, " Didn't get downstream ALLOCATION hints" );
557+ else if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, nullptr ))
558+ return { nullptr , 0 };
559+
560+ GST_WARNING_OBJECT (self, " Downstream doesn't support video meta, need to copy frame." );
561+
562+ /*
563+ * If the allocation query has pools, use the first one. Otherwise,
564+ * create a new pool.
565+ */
566+ if (gst_query_get_n_allocation_pools (query) > 0 )
567+ gst_query_parse_nth_allocation_pool (query, 0 , &pool, nullptr ,
568+ nullptr , nullptr );
569+
570+ if (!pool) {
571+ GstStructure *config;
572+ guint min_buffers = 3 ;
573+
574+ pool = gst_video_buffer_pool_new ();
575+ config = gst_buffer_pool_get_config (pool);
576+ gst_buffer_pool_config_set_params (config, caps, info->size , min_buffers, 0 );
577+
578+ GST_DEBUG_OBJECT (self, " Own pool config is %" GST_PTR_FORMAT, config);
579+
580+ gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), config);
581+ }
582+
583+ if (!gst_buffer_pool_set_active (pool, true )) {
584+ GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
585+ (" Failed to active buffer pool" ),
586+ (" gst_libcamera_src_negotiate() failed." ));
587+ return { nullptr , -EINVAL };
588+ }
589+
590+ return { std::exchange (pool, nullptr ), 0 };
591+ }
592+
510593/* Must be called with stream_lock held. */
511594static bool
512595gst_libcamera_src_negotiate (GstLibcameraSrc *self)
@@ -578,7 +661,7 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)
578661 for (gsize i = 0 ; i < state->srcpads_ .size (); i++) {
579662 GstPad *srcpad = state->srcpads_ [i];
580663 const StreamConfiguration &stream_cfg = state->config_ ->at (i);
581- GstBufferPool *video_pool = NULL ;
664+ GstBufferPool *video_pool = nullptr ;
582665 GstVideoInfo info;
583666
584667 g_autoptr (GstCaps) caps = gst_libcamera_stream_configuration_to_caps (stream_cfg, transfer[i]);
@@ -589,50 +672,13 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)
589672 /* Stride mismatch between camera stride and that calculated by video-info. */
590673 if (static_cast <unsigned int >(info.stride [0 ]) != stream_cfg.stride &&
591674 GST_VIDEO_INFO_FORMAT (&info) != GST_VIDEO_FORMAT_ENCODED) {
592- GstQuery *query = NULL ;
593- const gboolean need_pool = true ;
594- gboolean has_video_meta = false ;
595-
596675 gst_libcamera_extrapolate_info (&info, stream_cfg.stride );
597676
598- query = gst_query_new_allocation (caps, need_pool);
599- if (!gst_pad_peer_query (srcpad, query))
600- GST_DEBUG_OBJECT (self, " Didn't get downstream ALLOCATION hints" );
601- else
602- has_video_meta = gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL );
603-
604- if (!has_video_meta) {
605- GstBufferPool *pool = NULL ;
606-
607- if (gst_query_get_n_allocation_pools (query) > 0 )
608- gst_query_parse_nth_allocation_pool (query, 0 , &pool, NULL , NULL , NULL );
609-
610- if (pool)
611- video_pool = pool;
612- else {
613- GstStructure *config;
614- guint min_buffers = 3 ;
615- video_pool = gst_video_buffer_pool_new ();
616-
617- config = gst_buffer_pool_get_config (video_pool);
618- gst_buffer_pool_config_set_params (config, caps, info.size , min_buffers, 0 );
619-
620- GST_DEBUG_OBJECT (self, " Own pool config is %" GST_PTR_FORMAT, config);
621-
622- gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (video_pool), config);
623- }
624-
625- GST_WARNING_OBJECT (self, " Downstream doesn't support video meta, need to copy frame." );
626-
627- if (!gst_buffer_pool_set_active (video_pool, true )) {
628- gst_caps_unref (caps);
629- GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
630- (" Failed to active buffer pool" ),
631- (" gst_libcamera_src_negotiate() failed." ));
632- return false ;
633- }
634- }
635- gst_query_unref (query);
677+ std::tie (video_pool, ret) =
678+ gst_libcamera_create_video_pool (self, srcpad,
679+ caps, &info);
680+ if (ret)
681+ return false ;
636682 }
637683
638684 GstLibcameraPool *pool = gst_libcamera_pool_new (self->allocator ,
@@ -1020,7 +1066,7 @@ gst_libcamera_src_request_new_pad(GstElement *element, GstPadTemplate *templ,
10201066 const gchar *name, [[maybe_unused]] const GstCaps *caps)
10211067{
10221068 GstLibcameraSrc *self = GST_LIBCAMERA_SRC (element);
1023- g_autoptr (GstPad) pad = NULL ;
1069+ g_autoptr (GstPad) pad = nullptr ;
10241070
10251071 GST_DEBUG_OBJECT (self, " new request pad created" );
10261072
@@ -1034,7 +1080,7 @@ gst_libcamera_src_request_new_pad(GstElement *element, GstPadTemplate *templ,
10341080 GST_ELEMENT_ERROR (element, STREAM, FAILED,
10351081 (" Internal data stream error." ),
10361082 (" Could not add pad to element" ));
1037- return NULL ;
1083+ return nullptr ;
10381084 }
10391085
10401086 gst_child_proxy_child_added (GST_CHILD_PROXY (self), G_OBJECT (pad), GST_OBJECT_NAME (pad));
0 commit comments