[libcamera-devel] [PATCH v6 1/1] gstreamer: Provide multiple colorimetry support for libcamerasrc
Umang Jain
umang.jain at ideasonboard.com
Mon Sep 19 20:48:36 CEST 2022
Hi Laurent,
Thank you for the comments
On 9/19/22 11:22 PM, Laurent Pinchart wrote:
> Hi Rishikesh,
>
> Thank you for the patch.
>
> On Mon, Sep 19, 2022 at 08:27:09AM +0530, Rishikesh Donadkar wrote:
>> Iterate over each GValue in the colorimetry list,
>> retrieve the colorimetry string, convert to colorspace,
>> set the colorspace in the stream_cfg and validate the camera configuration.
>> Retrieve the colorspace after validation, convert to colorimetry and
>> check if it is same as the colorimetry requested.
>>
>> If none of the colorimetry requested is supported by the camera (i.e. not
>> the same after validation) then set the stream_cfg to the previous
>> configuration that was present before trying new colorimetry.
>>
>> Signed-off-by: Rishikesh Donadkar <rishikeshdonadkar at gmail.com>
>> Reviewed-by: Nicolas Dufresne <nicolas.dufresne at collabora.com>
>> ---
>> src/gstreamer/gstlibcamera-utils.cpp | 49 +++++++++++++++++++++++-----
>> src/gstreamer/gstlibcamera-utils.h | 4 ++-
>> src/gstreamer/gstlibcamerasrc.cpp | 2 +-
>> 3 files changed, 44 insertions(+), 11 deletions(-)
>>
>> diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp
>> index 244a4a79..f73b6349 100644
>> --- a/src/gstreamer/gstlibcamera-utils.cpp
>> +++ b/src/gstreamer/gstlibcamera-utils.cpp
>> @@ -316,9 +316,9 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg
>> return caps;
>> }
>>
>> -void
>> -gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,
>> - GstCaps *caps)
>> +void gst_libcamera_configure_stream_from_caps(std::unique_ptr<CameraConfiguration> &cam_cfg,
>> + StreamConfiguration &stream_cfg,
>> + GstCaps *caps)
>> {
>> GstVideoFormat gst_format = pixel_format_to_gst_format(stream_cfg.pixelFormat);
>> guint i;
>> @@ -395,15 +395,46 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,
>> stream_cfg.size.width = width;
>> stream_cfg.size.height = height;
>>
>> - /* Configure colorimetry */
>> - if (gst_structure_has_field(s, "colorimetry")) {
>> - const gchar *colorimetry_str = gst_structure_get_string(s, "colorimetry");
>> - GstVideoColorimetry colorimetry;
>> + const GValue *colorimetry_ = gst_structure_get_value(s, "colorimetry");
> Trailing underscores are reserved for class members.
>
>> + if (!colorimetry_)
>> + return;
>>
>> - if (!gst_video_colorimetry_from_string(&colorimetry, colorimetry_str))
>> - g_critical("Invalid colorimetry %s", colorimetry_str);
>> + /* Configure Colorimetry */
>> + GstVideoColorimetry colorimetry;
>> + if (GST_VALUE_HOLDS_LIST(colorimetry_)) {
>> + StreamConfiguration pristine_stream_cfg = stream_cfg;
>> + for (i = 0; i < gst_value_list_get_size(colorimetry_); i++) {
>> + const GValue *val = gst_value_list_get_value(colorimetry_, i);
>> +
>> + if (!gst_video_colorimetry_from_string(&colorimetry, g_value_get_string(val))) {
>> + g_warning("Invalid colorimetry %s, trying next option", g_value_get_string(val));
>> + continue;
>> + }
>> +
>> + std::optional<ColorSpace> clrSpace = colorspace_from_colorimetry(colorimetry);
>> + stream_cfg.colorSpace = clrSpace;
>> +
>> + /* Validate the configuration and check if the requested
> Wrong style. On this topic, lines are too long. Line wraps can help, but
> it may also indicate that some code could be split to separate functions
> (I haven't checked).
>
>> + * colorimetry can be applied to the sensor. Otherwise,
>> + * restore the configuration back to pristine one.
>> + */
>> + if (cam_cfg->validate() != CameraConfiguration::Invalid) {
> The RPi pipeline handler (and other pipeline handlers) requires the same
> color space to be used for all streams, and it will pick (if I recall
> correctly) the color space of the largest non-raw stream and apply it to
> all other streams. For multi-stream use cases, validating the color
> space on streams individually will probably not work as you're
> expecting. You'll need a more complex logic.
We indeed had a discussion around it I think but I think it was my idea
to develop on top of this actually.
Rishikesh, what do you think about handling this? We can have a
exploratory session together as I think I haven't been much exposed to
multi-stream usage via gstreamer plugin.
>
>> + /* Check the colorspace returned after validation, with the colorspace before validation */
>> + if (stream_cfg.colorSpace == clrSpace) {
>> + g_print("Selected colorimetry %s\n", gst_video_colorimetry_to_string(&colorimetry));
>> + break;
>> + } else {
>> + stream_cfg = pristine_stream_cfg;
>> + }
>> + }
>> + }
>> + } else if (G_VALUE_HOLDS_STRING(colorimetry_)) {
>> + if (!gst_video_colorimetry_from_string(&colorimetry, g_value_get_string(colorimetry_)))
>> + g_critical("Invalid colorimetry %s", g_value_get_string(colorimetry_));
>>
>> stream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry);
> Why does this not use validate() ? The asymmetry between the two makes
> me think something is wrong.
For single colorimetry, the validate happens right after the function's
call in src/gstreamer/gstlibcamerasrc.cpp and then whatever is returned
back, is exposed as caps. If the user-defined colorimetry as whatever is
exposed in caps, negotiation shall pass.
For multiple colorimetry, we need to "select" a supported colorspace
candidate from the user-provided list, hence need to run through
validate() to see what sensor agrees on any-one of them. Which is found
to be suitable, is set in the stream configuration and re-validated
(although futile) in
src/gstreamer/gstlibcamerasrc.cpp::gst_libcamera_src_task_enter() and
then exposed through caps.
Hence, an extra validation is not required for the single-colorimetry
case (which currently is the behaviour on master as well). Does that
makes sense?
>
>> + } else {
>> + GST_WARNING("colorimetry field type should only be string or list.");
>> }
>> }
>>
>> diff --git a/src/gstreamer/gstlibcamera-utils.h b/src/gstreamer/gstlibcamera-utils.h
>> index 164189a2..7afad576 100644
>> --- a/src/gstreamer/gstlibcamera-utils.h
>> +++ b/src/gstreamer/gstlibcamera-utils.h
>> @@ -8,6 +8,7 @@
>>
>> #pragma once
>>
>> +#include <libcamera/camera.h>
>> #include <libcamera/camera_manager.h>
>> #include <libcamera/stream.h>
>>
>> @@ -16,7 +17,8 @@
>>
>> GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &formats);
>> GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg);
>> -void gst_libcamera_configure_stream_from_caps(libcamera::StreamConfiguration &stream_cfg,
>> +void gst_libcamera_configure_stream_from_caps(std::unique_ptr<libcamera::CameraConfiguration> &cam_cfg,
> Let's pass a normal reference to the function:
>
> void gst_libcamera_configure_stream_from_caps(libcamera::CameraConfiguration &cam_cfg,
ah good point, ack
>
>> + libcamera::StreamConfiguration &stream_cfg,
>> GstCaps *caps);
>> #if !GST_CHECK_VERSION(1, 17, 1)
>> gboolean gst_task_resume(GstTask *task);
>> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
>> index 16d70fea..25059914 100644
>> --- a/src/gstreamer/gstlibcamerasrc.cpp
>> +++ b/src/gstreamer/gstlibcamerasrc.cpp
>> @@ -503,7 +503,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,
>>
>> /* Fixate caps and configure the stream. */
>> caps = gst_caps_make_writable(caps);
>> - gst_libcamera_configure_stream_from_caps(stream_cfg, caps);
>> + gst_libcamera_configure_stream_from_caps(state->config_, stream_cfg, caps);
> gst_libcamera_configure_stream_from_caps(*state->config_, stream_cfg, caps);
>
>> }
>>
>> if (flow_ret != GST_FLOW_OK)
More information about the libcamera-devel
mailing list