mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2025-01-23 07:28:15 +00:00
examples: overlay-composition: Use cairo's new ImageSurfaceDataOwned
to get rid of unsafe code
This commit is contained in:
parent
fbe6471625
commit
007df43b2f
2 changed files with 74 additions and 98 deletions
|
@ -7,10 +7,6 @@
|
|||
// {videotestsrc} - {overlaycomposition} - {capsfilter} - {videoconvert} - {autovideosink}
|
||||
// The capsfilter element allows us to dictate the video resolution we want for the
|
||||
// videotestsrc and the overlaycomposition element.
|
||||
//
|
||||
// There is a small amount of unsafe code that demonstrates how to work around
|
||||
// Cairo's internal refcounting of the target buffer surface
|
||||
#![allow(clippy::non_send_fields_in_send_ty)]
|
||||
|
||||
use gst::prelude::*;
|
||||
|
||||
|
@ -150,36 +146,13 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
|
|||
let angle = 2.0 * PI * (timestamp % (10 * gst::ClockTime::SECOND)).nseconds() as f64
|
||||
/ (10.0 * gst::ClockTime::SECOND.nseconds() as f64);
|
||||
|
||||
/* Create a gst::Buffer for Cairo to draw into */
|
||||
let frame_width = info.width() as usize;
|
||||
let frame_height = info.height() as usize;
|
||||
let stride = 4 * frame_width;
|
||||
let frame_size = stride * frame_height;
|
||||
|
||||
/* Create an RGBA buffer, and add a video meta that the videooverlaycomposition expects */
|
||||
let mut buffer = gst::Buffer::with_size(frame_size).unwrap();
|
||||
|
||||
gst_video::VideoMeta::add(
|
||||
buffer.get_mut().unwrap(),
|
||||
gst_video::VideoFrameFlags::empty(),
|
||||
gst_video::VideoFormat::Bgra,
|
||||
frame_width as u32,
|
||||
frame_height as u32,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let buffer = buffer.into_mapped_buffer_writable().unwrap();
|
||||
let buffer = {
|
||||
let buffer_ptr = unsafe { buffer.buffer().as_ptr() };
|
||||
let surface = cairo::ImageSurface::create_for_data(
|
||||
buffer,
|
||||
/* Create a Cairo image surface to draw into and the context around it. */
|
||||
let surface = cairo::ImageSurface::create(
|
||||
cairo::Format::ARgb32,
|
||||
frame_width as i32,
|
||||
frame_height as i32,
|
||||
stride as i32,
|
||||
info.width() as i32,
|
||||
info.height() as i32,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cr = cairo::Context::new(&surface).expect("Failed to create cairo context");
|
||||
|
||||
cr.save().expect("Failed to save state");
|
||||
|
@ -233,22 +206,26 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
|
|||
cr.restore().expect("Failed to restore state");
|
||||
}
|
||||
|
||||
// Safety: The surface still owns a mutable reference to the buffer but our reference
|
||||
// to the surface here is the last one. After dropping the surface the buffer would be
|
||||
// freed, so we keep an additional strong reference here before dropping the surface,
|
||||
// which is then returned. As such it's guaranteed that nothing is using the buffer
|
||||
// anymore mutably.
|
||||
/* Drop the Cairo context to release the additional reference to the data and
|
||||
* then take ownership of the data. This only works if we have the one and only
|
||||
* reference to the image surface */
|
||||
drop(cr);
|
||||
unsafe {
|
||||
assert_eq!(
|
||||
cairo::ffi::cairo_surface_get_reference_count(surface.to_raw_none()),
|
||||
1
|
||||
);
|
||||
let buffer = glib::translate::from_glib_none(buffer_ptr);
|
||||
drop(surface);
|
||||
buffer
|
||||
}
|
||||
};
|
||||
let stride = surface.stride();
|
||||
let data = surface.take_data().unwrap();
|
||||
|
||||
/* Create an RGBA buffer, and add a video meta that the videooverlaycomposition expects */
|
||||
let mut buffer = gst::Buffer::from_mut_slice(data);
|
||||
|
||||
gst_video::VideoMeta::add_full(
|
||||
buffer.get_mut().unwrap(),
|
||||
gst_video::VideoFrameFlags::empty(),
|
||||
gst_video::VideoFormat::Bgra,
|
||||
info.width(),
|
||||
info.height(),
|
||||
&[0],
|
||||
&[stride],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
/* Turn the buffer into a VideoOverlayRectangle, then place
|
||||
* that into a VideoOverlayComposition and return it.
|
||||
|
@ -260,8 +237,8 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
|
|||
&buffer,
|
||||
0,
|
||||
0,
|
||||
frame_width as u32,
|
||||
frame_height as u32,
|
||||
info.width(),
|
||||
info.height(),
|
||||
gst_video::VideoOverlayFormatFlags::PREMULTIPLIED_ALPHA,
|
||||
);
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
// {videotestsrc} - {cairooverlay} - {capsfilter} - {videoconvert} - {autovideosink}
|
||||
// The capsfilter element allows us to dictate the video resolution we want for the
|
||||
// videotestsrc and the cairooverlay element.
|
||||
#![allow(clippy::non_send_fields_in_send_ty)]
|
||||
|
||||
use gst::prelude::*;
|
||||
|
||||
|
|
Loading…
Reference in a new issue