video/gtk4: Copy non-contiguous sysmem buffers

As the texture builder only supports contiguous buffers. This follows
the gtkgstsink implementation.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2271>
This commit is contained in:
Robert Mader 2025-07-03 03:42:24 +02:00 committed by GStreamer Marge Bot
parent d2308a964e
commit 7b561354eb
2 changed files with 45 additions and 11 deletions

View file

@ -9,9 +9,10 @@
// //
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use gst_video::prelude::*; use crate::sink::imp::PaintableSink;
use crate::sink::imp::CAT;
use gst_gl::prelude::*; use gst_gl::prelude::*;
use gst_video::subclass::prelude::*;
use gtk::{gdk, glib}; use gtk::{gdk, glib};
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
@ -692,6 +693,7 @@ impl Frame {
impl Frame { impl Frame {
pub(crate) fn new( pub(crate) fn new(
dbg_obj: &PaintableSink,
buffer: &gst::Buffer, buffer: &gst::Buffer,
info: &VideoInfo, info: &VideoInfo,
orientation: Orientation, orientation: Orientation,
@ -809,11 +811,44 @@ impl Frame {
let mut frame = Self { let mut frame = Self {
frame: match frame { frame: match frame {
Some(frame) => frame, Some(frame) => frame,
None => MappedFrame::SysMem { None => {
frame: gst_video::VideoFrame::from_buffer_readable(buffer.clone(), info) let readable_frame = match buffer.n_memory() {
1 => buffer.clone(),
_ => {
gst::debug!(CAT, imp = dbg_obj, "Buffer is not contiguous, copying");
let mut copy_buffer = gst::Buffer::with_size(info.size()).unwrap();
{
let copy_buffer = copy_buffer.get_mut().unwrap();
buffer
.copy_into(copy_buffer, gst::BUFFER_COPY_METADATA, 0..0)
.unwrap();
let frame = gst_video::VideoFrameRef::from_buffer_ref_readable(
buffer, info,
)
.unwrap();
let mut copy_frame =
gst_video::VideoFrameRef::from_buffer_ref_writable(
copy_buffer,
info,
)
.unwrap();
frame.copy(&mut copy_frame).unwrap();
}
copy_buffer
}
};
MappedFrame::SysMem {
frame: gst_video::VideoFrame::from_buffer_readable(readable_frame, info)
.map_err(|_| gst::FlowError::Error)?, .map_err(|_| gst::FlowError::Error)?,
orientation, orientation,
}, }
}
}, },
overlays: vec![], overlays: vec![],
}; };

View file

@ -719,11 +719,10 @@ impl VideoSinkImpl for PaintableSink {
} }
} }
}; };
let frame = Frame::new(buffer, info, orientation, wrapped_context.as_ref()).inspect_err( let frame = Frame::new(self, buffer, info, orientation, wrapped_context.as_ref())
|_err| { .inspect_err(|_err| {
gst::error!(CAT, imp = self, "Failed to map video frame"); gst::error!(CAT, imp = self, "Failed to map video frame");
}, })?;
)?;
self.pending_frame.lock().unwrap().replace(frame); self.pending_frame.lock().unwrap().replace(frame);
let sender = self.sender.lock().unwrap(); let sender = self.sender.lock().unwrap();