Update for VideoFrame / GLVideoFrame API changes

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1345>
This commit is contained in:
Sebastian Dröge 2023-10-02 13:25:25 +03:00
parent 95581d7fbc
commit 450ffbe452
8 changed files with 85 additions and 36 deletions

View file

@ -9,6 +9,8 @@ use std::ptr;
use byte_slice_cast::*; use byte_slice_cast::*;
use gst_video::prelude::*;
pub fn load() -> Result<(), glib::BoolError> { pub fn load() -> Result<(), glib::BoolError> {
ndisys::load() ndisys::load()
} }

View file

@ -12,6 +12,7 @@ use gst::glib;
use gst::prelude::*; use gst::prelude::*;
use gst::subclass::prelude::*; use gst::subclass::prelude::*;
use gst_base::subclass::prelude::*; use gst_base::subclass::prelude::*;
use gst_video::prelude::*;
use gst_video::subclass::prelude::*; use gst_video::subclass::prelude::*;
use std::sync::Mutex; use std::sync::Mutex;

View file

@ -17,11 +17,53 @@ use gtk::{gdk, glib};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct Frame { enum MappedFrame {
frame: gst_video::VideoFrame<gst_video::video_frame::Readable>, SysMem(gst_video::VideoFrame<gst_video::video_frame::Readable>),
overlays: Vec<Overlay>,
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))] #[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
wrapped_context: Option<gst_gl::GLContext>, GL {
frame: gst_gl::GLVideoFrame<gst_gl::gl_video_frame::Readable>,
wrapped_context: gst_gl::GLContext,
},
}
impl MappedFrame {
fn buffer(&self) -> &gst::BufferRef {
match self {
MappedFrame::SysMem(frame) => frame.buffer(),
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
MappedFrame::GL { frame, .. } => frame.buffer(),
}
}
fn width(&self) -> u32 {
match self {
MappedFrame::SysMem(frame) => frame.width(),
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
MappedFrame::GL { frame, .. } => frame.width(),
}
}
fn height(&self) -> u32 {
match self {
MappedFrame::SysMem(frame) => frame.height(),
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
MappedFrame::GL { frame, .. } => frame.height(),
}
}
fn format_info(&self) -> gst_video::VideoFormatInfo {
match self {
MappedFrame::SysMem(frame) => frame.format_info(),
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
MappedFrame::GL { frame, .. } => frame.format_info(),
}
}
}
#[derive(Debug)]
pub(crate) struct Frame {
frame: MappedFrame,
overlays: Vec<Overlay>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -97,7 +139,7 @@ fn video_frame_to_memory_texture(
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))] #[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
fn video_frame_to_gl_texture( fn video_frame_to_gl_texture(
frame: gst_video::VideoFrame<gst_video::video_frame::Readable>, frame: gst_gl::GLVideoFrame<gst_gl::gl_video_frame::Readable>,
cached_textures: &mut HashMap<usize, gdk::Texture>, cached_textures: &mut HashMap<usize, gdk::Texture>,
used_textures: &mut HashSet<usize>, used_textures: &mut HashSet<usize>,
gdk_context: &gdk::GLContext, gdk_context: &gdk::GLContext,
@ -151,30 +193,28 @@ impl Frame {
let width = self.frame.width(); let width = self.frame.width();
let height = self.frame.height(); let height = self.frame.height();
let has_alpha = self.frame.format_info().has_alpha(); let has_alpha = self.frame.format_info().has_alpha();
let (texture, pixel_aspect_ratio) = { let (texture, pixel_aspect_ratio) = match self.frame {
#[cfg(not(any(target_os = "macos", target_os = "windows", feature = "gst_gl")))] MappedFrame::SysMem(frame) => {
{ video_frame_to_memory_texture(frame, cached_textures, &mut used_textures)
video_frame_to_memory_texture(self.frame, cached_textures, &mut used_textures)
} }
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))] #[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
{ MappedFrame::GL {
if let (Some(gdk_ctx), Some(wrapped_ctx)) = frame,
(gdk_context, self.wrapped_context.as_ref()) wrapped_context,
{ } => {
video_frame_to_gl_texture( let Some(gdk_context) = gdk_context else {
self.frame,
cached_textures,
&mut used_textures,
gdk_ctx,
wrapped_ctx,
)
} else {
// This will fail badly if the video frame was actually mapped as GL texture // This will fail badly if the video frame was actually mapped as GL texture
// but this case can't really happen as we only do that if we actually have a // but this case can't really happen as we only do that if we actually have a
// GDK GL context. // GDK GL context.
assert!(self.wrapped_context.is_none()); unreachable!();
video_frame_to_memory_texture(self.frame, cached_textures, &mut used_textures) };
} video_frame_to_gl_texture(
frame,
cached_textures,
&mut used_textures,
gdk_context,
&wrapped_context,
)
} }
}; };
@ -230,8 +270,10 @@ impl Frame {
#[cfg(not(any(target_os = "macos", target_os = "windows", feature = "gst_gl")))] #[cfg(not(any(target_os = "macos", target_os = "windows", feature = "gst_gl")))]
{ {
frame = Self { frame = Self {
frame: gst_video::VideoFrame::from_buffer_readable(buffer.clone(), info) frame: MappedFrame::SysMem(
.map_err(|_| gst::FlowError::Error)?, gst_video::VideoFrame::from_buffer_readable(buffer.clone(), info)
.map_err(|_| gst::FlowError::Error)?,
),
overlays: vec![], overlays: vec![],
}; };
} }
@ -259,7 +301,7 @@ impl Frame {
// If there is no GLSyncMeta yet then we need to add one here now, which requires // If there is no GLSyncMeta yet then we need to add one here now, which requires
// obtaining a writable buffer. // obtaining a writable buffer.
let mapped_frame = if buffer.meta::<gst_gl::GLSyncMeta>().is_some() { let mapped_frame = if buffer.meta::<gst_gl::GLSyncMeta>().is_some() {
gst_video::VideoFrame::from_buffer_readable_gl(buffer.clone(), info) gst_gl::GLVideoFrame::from_buffer_readable(buffer.clone(), info)
.map_err(|_| gst::FlowError::Error)? .map_err(|_| gst::FlowError::Error)?
} else { } else {
let mut buffer = buffer.clone(); let mut buffer = buffer.clone();
@ -267,7 +309,7 @@ impl Frame {
let buffer = buffer.make_mut(); let buffer = buffer.make_mut();
gst_gl::GLSyncMeta::add(buffer, memory_ctx); gst_gl::GLSyncMeta::add(buffer, memory_ctx);
} }
gst_video::VideoFrame::from_buffer_readable_gl(buffer, info) gst_gl::GLVideoFrame::from_buffer_readable(buffer, info)
.map_err(|_| gst::FlowError::Error)? .map_err(|_| gst::FlowError::Error)?
}; };
@ -278,16 +320,19 @@ impl Frame {
meta.set_sync_point(memory_ctx); meta.set_sync_point(memory_ctx);
frame = Self { frame = Self {
frame: mapped_frame, frame: MappedFrame::GL {
frame: mapped_frame,
wrapped_context: wrapped_context.unwrap().clone(),
},
overlays: vec![], overlays: vec![],
wrapped_context: Some(wrapped_context.unwrap().clone()),
}; };
} else { } else {
frame = Self { frame = Self {
frame: gst_video::VideoFrame::from_buffer_readable(buffer.clone(), info) frame: MappedFrame::SysMem(
.map_err(|_| gst::FlowError::Error)?, gst_video::VideoFrame::from_buffer_readable(buffer.clone(), info)
.map_err(|_| gst::FlowError::Error)?,
),
overlays: vec![], overlays: vec![],
wrapped_context: None,
}; };
} }
} }

View file

@ -14,7 +14,6 @@ use crate::sink::frame::Frame;
use crate::sink::paintable::Paintable; use crate::sink::paintable::Paintable;
use glib::{thread_guard::ThreadGuard, Sender}; use glib::{thread_guard::ThreadGuard, Sender};
use gtk::prelude::GLContextExt;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{gdk, glib}; use gtk::{gdk, glib};

View file

@ -13,6 +13,7 @@ use gst::prelude::*;
use gst::subclass::prelude::*; use gst::subclass::prelude::*;
use gst_base::subclass::prelude::*; use gst_base::subclass::prelude::*;
use gst_video::prelude::*;
use gst_video::subclass::prelude::*; use gst_video::subclass::prelude::*;
use std::sync::Mutex; use std::sync::Mutex;

View file

@ -12,6 +12,7 @@ use gst::glib;
use gst::prelude::*; use gst::prelude::*;
use gst::subclass::prelude::*; use gst::subclass::prelude::*;
use gst_base::subclass::prelude::*; use gst_base::subclass::prelude::*;
use gst_video::prelude::*;
use gst_video::subclass::prelude::*; use gst_video::subclass::prelude::*;
use std::sync::Mutex; use std::sync::Mutex;

View file

@ -9,7 +9,7 @@
use crate::HashAlgorithm; use crate::HashAlgorithm;
#[cfg(feature = "dssim")] #[cfg(feature = "dssim")]
use dssim_core::{Dssim, DssimImage}; use dssim_core::{Dssim, DssimImage};
use gst_video::VideoFormat; use gst_video::{prelude::*, VideoFormat};
use image_hasher::{HashAlg, Hasher, HasherConfig, ImageHash}; use image_hasher::{HashAlg, Hasher, HasherConfig, ImageHash};
#[cfg(feature = "dssim")] #[cfg(feature = "dssim")]
use rgb::FromSlice; use rgb::FromSlice;

View file

@ -14,7 +14,7 @@ use gst::subclass::prelude::*;
use gst::{glib, glib::prelude::*, prelude::*}; use gst::{glib, glib::prelude::*, prelude::*};
use gst_base::prelude::*; use gst_base::prelude::*;
use gst_base::AggregatorPad; use gst_base::AggregatorPad;
use gst_video::prelude::VideoAggregatorPadExtManual; use gst_video::prelude::*;
use gst_video::subclass::prelude::*; use gst_video::subclass::prelude::*;
use gst_video::subclass::AggregateFramesToken; use gst_video::subclass::AggregateFramesToken;
use gst_video::VideoFormat; use gst_video::VideoFormat;