gstreamer: keep same transfer with that in negotiated caps
The conversions back and forth between GStreamer colorimetry and libcamera color space are not invariant for the bt601 colorimetry. The reason is that Rec709 transfer function defined in GStreamer as GST_VIDEO_TRANSFER_BT709 (5), is to be replaced by its alias GST_VIDEO_TRANSFER_BT601 (16) only for the case of bt601 (aka 2:4:16:4) colorimetry - see [1]. Currently the composition of the GStreamer/libcamera conversions: colorimetry_from_colorspace (colorspace_from_colorimetry (bt601)) returns 2:4:5:4 instead of the expected 2:4:16:4 (bt601). This causes negotiation error when the downstream element explicitly expects bt601 colorimetry. Minimal example to reproduce the issue is with a pipeline handler that do not set the optional color space in the stream configuration, for instance vimc or imx8-isi: export LIBCAMERA_PIPELINES_MATCH_LIST="vimc,imx8-isi" gst-launch-1.0 -v libcamerasrc ! video/x-raw,colorimetry=bt601 ! fakesink Above pipeline fails to start. This change memorizes downstream required transfer function when mapped libcamera transfer is Rec709 in gst_libcamera_configure_stream_from_caps(), and restores the transfer function in gst_libcamera_stream_formats_to_caps(). [1] https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/724 Bug: https://bugs.libcamera.org/show_bug.cgi?id=150 Signed-off-by: Hou Qi <qi.hou@nxp.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
a7aab7da8a
commit
e9a876acc6
3 changed files with 19 additions and 12 deletions
|
@ -85,7 +85,7 @@ static struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
static GstVideoColorimetry
|
static GstVideoColorimetry
|
||||||
colorimetry_from_colorspace(const ColorSpace &colorSpace)
|
colorimetry_from_colorspace(const ColorSpace &colorSpace, GstVideoTransferFunction transfer)
|
||||||
{
|
{
|
||||||
GstVideoColorimetry colorimetry;
|
GstVideoColorimetry colorimetry;
|
||||||
|
|
||||||
|
@ -113,6 +113,8 @@ colorimetry_from_colorspace(const ColorSpace &colorSpace)
|
||||||
break;
|
break;
|
||||||
case ColorSpace::TransferFunction::Rec709:
|
case ColorSpace::TransferFunction::Rec709:
|
||||||
colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
|
colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
|
||||||
|
if (transfer != GST_VIDEO_TRANSFER_UNKNOWN)
|
||||||
|
colorimetry.transfer = transfer;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +146,8 @@ colorimetry_from_colorspace(const ColorSpace &colorSpace)
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<ColorSpace>
|
static std::optional<ColorSpace>
|
||||||
colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry)
|
colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry,
|
||||||
|
GstVideoTransferFunction *transfer)
|
||||||
{
|
{
|
||||||
std::optional<ColorSpace> colorspace = ColorSpace::Raw;
|
std::optional<ColorSpace> colorspace = ColorSpace::Raw;
|
||||||
|
|
||||||
|
@ -188,6 +191,7 @@ colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry)
|
||||||
case GST_VIDEO_TRANSFER_BT2020_12:
|
case GST_VIDEO_TRANSFER_BT2020_12:
|
||||||
case GST_VIDEO_TRANSFER_BT709:
|
case GST_VIDEO_TRANSFER_BT709:
|
||||||
colorspace->transferFunction = ColorSpace::TransferFunction::Rec709;
|
colorspace->transferFunction = ColorSpace::TransferFunction::Rec709;
|
||||||
|
*transfer = colorimetry.transfer;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GST_WARNING("Colorimetry transfer function %d not mapped in gstlibcamera",
|
GST_WARNING("Colorimetry transfer function %d not mapped in gstlibcamera",
|
||||||
|
@ -379,7 +383,8 @@ gst_libcamera_stream_formats_to_caps(const StreamFormats &formats)
|
||||||
}
|
}
|
||||||
|
|
||||||
GstCaps *
|
GstCaps *
|
||||||
gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg)
|
gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg,
|
||||||
|
GstVideoTransferFunction transfer)
|
||||||
{
|
{
|
||||||
GstCaps *caps = gst_caps_new_empty();
|
GstCaps *caps = gst_caps_new_empty();
|
||||||
GstStructure *s = bare_structure_from_format(stream_cfg.pixelFormat);
|
GstStructure *s = bare_structure_from_format(stream_cfg.pixelFormat);
|
||||||
|
@ -390,7 +395,7 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
if (stream_cfg.colorSpace) {
|
if (stream_cfg.colorSpace) {
|
||||||
GstVideoColorimetry colorimetry = colorimetry_from_colorspace(stream_cfg.colorSpace.value());
|
GstVideoColorimetry colorimetry = colorimetry_from_colorspace(stream_cfg.colorSpace.value(), transfer);
|
||||||
g_autofree gchar *colorimetry_str = gst_video_colorimetry_to_string(&colorimetry);
|
g_autofree gchar *colorimetry_str = gst_video_colorimetry_to_string(&colorimetry);
|
||||||
|
|
||||||
if (colorimetry_str)
|
if (colorimetry_str)
|
||||||
|
@ -405,9 +410,8 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,
|
||||||
gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,
|
GstCaps *caps, GstVideoTransferFunction *transfer)
|
||||||
GstCaps *caps)
|
|
||||||
{
|
{
|
||||||
GstVideoFormat gst_format = pixel_format_to_gst_format(stream_cfg.pixelFormat);
|
GstVideoFormat gst_format = pixel_format_to_gst_format(stream_cfg.pixelFormat);
|
||||||
guint i;
|
guint i;
|
||||||
|
@ -495,7 +499,7 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,
|
||||||
if (!gst_video_colorimetry_from_string(&colorimetry, colorimetry_str))
|
if (!gst_video_colorimetry_from_string(&colorimetry, colorimetry_str))
|
||||||
g_critical("Invalid colorimetry %s", colorimetry_str);
|
g_critical("Invalid colorimetry %s", colorimetry_str);
|
||||||
|
|
||||||
stream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry);
|
stream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry, transfer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,10 @@
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
|
||||||
GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &formats);
|
GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &formats);
|
||||||
GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg);
|
GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg,
|
||||||
|
GstVideoTransferFunction transfer);
|
||||||
void gst_libcamera_configure_stream_from_caps(libcamera::StreamConfiguration &stream_cfg,
|
void gst_libcamera_configure_stream_from_caps(libcamera::StreamConfiguration &stream_cfg,
|
||||||
GstCaps *caps);
|
GstCaps *caps, GstVideoTransferFunction *transfer);
|
||||||
void gst_libcamera_get_framerate_from_caps(GstCaps *caps, GstStructure *element_caps);
|
void gst_libcamera_get_framerate_from_caps(GstCaps *caps, GstStructure *element_caps);
|
||||||
void gst_libcamera_clamp_and_set_frameduration(libcamera::ControlList &controls,
|
void gst_libcamera_clamp_and_set_frameduration(libcamera::ControlList &controls,
|
||||||
const libcamera::ControlInfoMap &camera_controls,
|
const libcamera::ControlInfoMap &camera_controls,
|
||||||
|
|
|
@ -433,6 +433,8 @@ static bool
|
||||||
gst_libcamera_src_negotiate(GstLibcameraSrc *self)
|
gst_libcamera_src_negotiate(GstLibcameraSrc *self)
|
||||||
{
|
{
|
||||||
GstLibcameraSrcState *state = self->state;
|
GstLibcameraSrcState *state = self->state;
|
||||||
|
std::vector<GstVideoTransferFunction> transfer(state->srcpads_.size(),
|
||||||
|
GST_VIDEO_TRANSFER_UNKNOWN);
|
||||||
|
|
||||||
g_autoptr(GstStructure) element_caps = gst_structure_new_empty("caps");
|
g_autoptr(GstStructure) element_caps = gst_structure_new_empty("caps");
|
||||||
|
|
||||||
|
@ -448,7 +450,7 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)
|
||||||
|
|
||||||
/* Fixate caps and configure the stream. */
|
/* Fixate caps and configure the stream. */
|
||||||
caps = gst_caps_make_writable(caps);
|
caps = gst_caps_make_writable(caps);
|
||||||
gst_libcamera_configure_stream_from_caps(stream_cfg, caps);
|
gst_libcamera_configure_stream_from_caps(stream_cfg, caps, &transfer[i]);
|
||||||
gst_libcamera_get_framerate_from_caps(caps, element_caps);
|
gst_libcamera_get_framerate_from_caps(caps, element_caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +478,7 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)
|
||||||
GstPad *srcpad = state->srcpads_[i];
|
GstPad *srcpad = state->srcpads_[i];
|
||||||
const StreamConfiguration &stream_cfg = state->config_->at(i);
|
const StreamConfiguration &stream_cfg = state->config_->at(i);
|
||||||
|
|
||||||
g_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg);
|
g_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg, transfer[i]);
|
||||||
gst_libcamera_framerate_to_caps(caps, element_caps);
|
gst_libcamera_framerate_to_caps(caps, element_caps);
|
||||||
|
|
||||||
if (!gst_pad_push_event(srcpad, gst_event_new_caps(caps)))
|
if (!gst_pad_push_event(srcpad, gst_event_new_caps(caps)))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue