mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-09-05 19:17:36 +00:00
video/gtk4: Initial colorimetry support
Similar to GtkGstSink. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2022>
This commit is contained in:
parent
85455c937f
commit
6450381017
3 changed files with 109 additions and 20 deletions
|
@ -388,7 +388,7 @@ foreach glib_version : glib_versions
|
|||
endforeach
|
||||
|
||||
if get_option('gtk4').allowed() and gtk_dep.found()
|
||||
gtk4_versions = ['4.16','4.14','4.12','4.10']
|
||||
gtk4_versions = ['4.20','4.18','4.16','4.14','4.12','4.10']
|
||||
foreach gtk4_version : gtk4_versions
|
||||
if gtk_dep.version().version_compare(f'>=@gtk4_version@')
|
||||
found_features += {'gtk': 'gtk_v' + gtk4_version.underscorify()}
|
||||
|
|
|
@ -56,6 +56,8 @@ gtk_v4_10 = ["gtk/v4_10"]
|
|||
gtk_v4_12 = ["gtk/v4_12", "gtk_v4_10"]
|
||||
gtk_v4_14 = ["gtk/v4_14", "gtk_v4_12"]
|
||||
gtk_v4_16 = ["gtk/v4_16", "gtk_v4_14"]
|
||||
gtk_v4_18 = ["gtk/v4_18", "gtk_v4_16"]
|
||||
gtk_v4_20 = ["gtk/v4_20", "gtk_v4_18"]
|
||||
|
||||
[package.metadata.capi]
|
||||
min_version = "0.9.21"
|
||||
|
|
|
@ -241,6 +241,40 @@ fn video_format_to_memory_format(f: gst_video::VideoFormat) -> gdk::MemoryFormat
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gtk_v4_20")]
|
||||
fn colorimetry_to_color_state(colorimetry: gst_video::VideoColorimetry) -> Option<gdk::ColorState> {
|
||||
// Ignore incomplete colorimetries and fall back to format dependent default color states in
|
||||
// GTK. This should make it easier to detect buggy sources and avoid confusing and unexpected
|
||||
// output.
|
||||
if colorimetry.primaries() == gst_video::VideoColorPrimaries::Unknown
|
||||
|| colorimetry.transfer() == gst_video::VideoTransferFunction::Unknown
|
||||
|| colorimetry.matrix() == gst_video::VideoColorMatrix::Unknown
|
||||
|| colorimetry.range() == gst_video::VideoColorRange::Unknown
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
let color_params = gdk::CicpParams::new();
|
||||
|
||||
color_params.set_color_primaries(colorimetry.primaries().to_iso());
|
||||
color_params.set_transfer_function(colorimetry.transfer().to_iso());
|
||||
color_params.set_matrix_coefficients(colorimetry.matrix().to_iso());
|
||||
|
||||
match colorimetry.range() {
|
||||
gst_video::VideoColorRange::Range0_255 => color_params.set_range(gdk::CicpRange::Full),
|
||||
gst_video::VideoColorRange::Range16_235 => color_params.set_range(gdk::CicpRange::Narrow),
|
||||
_ => panic!("Unhandled range"),
|
||||
}
|
||||
|
||||
match color_params.build_color_state() {
|
||||
Ok(color_state) => Some(color_state),
|
||||
Err(error) => {
|
||||
println!("Could not build color state: {}", error);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn video_frame_to_memory_texture(
|
||||
frame: gst_video::VideoFrame<gst_video::video_frame::Readable>,
|
||||
cached_textures: &mut HashMap<TextureCacheId, gdk::Texture>,
|
||||
|
@ -261,14 +295,36 @@ fn video_frame_to_memory_texture(
|
|||
let height = frame.height();
|
||||
let rowstride = frame.plane_stride()[0] as usize;
|
||||
|
||||
let texture = gdk::MemoryTexture::new(
|
||||
width as i32,
|
||||
height as i32,
|
||||
format,
|
||||
&glib::Bytes::from_owned(FrameWrapper(frame)),
|
||||
rowstride,
|
||||
)
|
||||
.upcast::<gdk::Texture>();
|
||||
let texture = {
|
||||
#[cfg(feature = "gtk_v4_20")]
|
||||
{
|
||||
let info = frame.info().clone();
|
||||
|
||||
let mut builder = gdk::MemoryTextureBuilder::new()
|
||||
.set_width(width as i32)
|
||||
.set_height(height as i32)
|
||||
.set_format(format)
|
||||
.set_bytes(Some(&glib::Bytes::from_owned(FrameWrapper(frame))))
|
||||
.set_stride(rowstride);
|
||||
|
||||
if let Some(color_state) = colorimetry_to_color_state(info.colorimetry()) {
|
||||
builder = builder.set_color_state(&color_state);
|
||||
}
|
||||
|
||||
builder.build()
|
||||
}
|
||||
#[cfg(not(feature = "gtk_v4_20"))]
|
||||
{
|
||||
gdk::MemoryTexture::new(
|
||||
width as i32,
|
||||
height as i32,
|
||||
format,
|
||||
&glib::Bytes::from_owned(FrameWrapper(frame)),
|
||||
rowstride,
|
||||
)
|
||||
}
|
||||
.upcast::<gdk::Texture>()
|
||||
};
|
||||
|
||||
cached_textures.insert(TextureCacheId::Memory(ptr), texture.clone());
|
||||
used_textures.insert(TextureCacheId::Memory(ptr));
|
||||
|
@ -345,17 +401,40 @@ fn video_frame_to_gl_texture(
|
|||
};
|
||||
let sync_point = (*sync_meta.as_ptr()).data;
|
||||
|
||||
gdk::GLTextureBuilder::new()
|
||||
.set_context(Some(gdk_context))
|
||||
.set_id(texture_id as u32)
|
||||
.set_width(width as i32)
|
||||
.set_height(height as i32)
|
||||
.set_format(format)
|
||||
.set_sync(Some(sync_point))
|
||||
.build_with_release_func(move || {
|
||||
// Unmap and drop the GStreamer GL texture once GTK is done with it and not earlier
|
||||
drop(frame);
|
||||
})
|
||||
let builder = {
|
||||
#[cfg(feature = "gtk_v4_20")]
|
||||
{
|
||||
let mut mut_builder = gdk::GLTextureBuilder::new()
|
||||
.set_context(Some(gdk_context))
|
||||
.set_id(texture_id as u32)
|
||||
.set_width(width as i32)
|
||||
.set_height(height as i32)
|
||||
.set_format(format)
|
||||
.set_sync(Some(sync_point));
|
||||
|
||||
if let Some(color_state) =
|
||||
colorimetry_to_color_state(frame.info().colorimetry())
|
||||
{
|
||||
mut_builder = mut_builder.set_color_state(&color_state);
|
||||
}
|
||||
mut_builder
|
||||
}
|
||||
#[cfg(not(feature = "gtk_v4_20"))]
|
||||
{
|
||||
gdk::GLTextureBuilder::new()
|
||||
.set_context(Some(gdk_context))
|
||||
.set_id(texture_id as u32)
|
||||
.set_width(width as i32)
|
||||
.set_height(height as i32)
|
||||
.set_format(format)
|
||||
.set_sync(Some(sync_point))
|
||||
}
|
||||
};
|
||||
|
||||
builder.build_with_release_func(move || {
|
||||
// Unmap and drop the GStreamer GL texture once GTK is done with it and not earlier
|
||||
drop(frame);
|
||||
})
|
||||
}
|
||||
#[cfg(not(feature = "gtk_v4_12"))]
|
||||
{
|
||||
|
@ -409,6 +488,14 @@ fn video_frame_to_dmabuf_texture(
|
|||
.set_width(width)
|
||||
.set_height(height)
|
||||
.set_n_planes(n_planes);
|
||||
|
||||
#[cfg(feature = "gtk_v4_20")]
|
||||
{
|
||||
if let Some(color_state) = colorimetry_to_color_state(info.colorimetry()) {
|
||||
builder = builder.set_color_state(Some(color_state).as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
for plane in 0..(n_planes as usize) {
|
||||
unsafe {
|
||||
builder = builder.set_fd(plane as u32, fds[plane]);
|
||||
|
|
Loading…
Reference in a new issue