mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2025-09-28 12:32:04 +00:00
examples/glupload: Replace separate mpsc channel with winit UserEvent
This commit is contained in:
parent
5e8634e9eb
commit
1609a7c923
1 changed files with 49 additions and 45 deletions
|
@ -13,7 +13,6 @@ use std::ffi::CStr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync;
|
use std::sync;
|
||||||
use std::sync::mpsc;
|
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use derive_more::{Display, Error};
|
use derive_more::{Display, Error};
|
||||||
|
@ -314,12 +313,18 @@ fn load(gl_context: &glutin::WindowedContext<glutin::PossiblyCurrent>) -> Gl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Message {
|
||||||
|
Sample(gst::Sample),
|
||||||
|
BusEvent,
|
||||||
|
}
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
pipeline: gst::Pipeline,
|
pipeline: gst::Pipeline,
|
||||||
appsink: gst_app::AppSink,
|
appsink: gst_app::AppSink,
|
||||||
glupload: gst::Element,
|
glupload: gst::Element,
|
||||||
bus: gst::Bus,
|
bus: gst::Bus,
|
||||||
event_loop: glutin::event_loop::EventLoop<()>,
|
event_loop: glutin::event_loop::EventLoop<Message>,
|
||||||
windowed_context: glutin::WindowedContext<glutin::PossiblyCurrent>,
|
windowed_context: glutin::WindowedContext<glutin::PossiblyCurrent>,
|
||||||
shared_context: gst_gl::GLContext,
|
shared_context: gst_gl::GLContext,
|
||||||
}
|
}
|
||||||
|
@ -333,7 +338,7 @@ impl App {
|
||||||
.get_bus()
|
.get_bus()
|
||||||
.expect("Pipeline without bus. Shouldn't happen!");
|
.expect("Pipeline without bus. Shouldn't happen!");
|
||||||
|
|
||||||
let event_loop = glutin::event_loop::EventLoop::new();
|
let event_loop = glutin::event_loop::EventLoop::with_user_event();
|
||||||
let window = glutin::window::WindowBuilder::new().with_title("GL rendering");
|
let window = glutin::window::WindowBuilder::new().with_title("GL rendering");
|
||||||
let windowed_context = glutin::ContextBuilder::new()
|
let windowed_context = glutin::ContextBuilder::new()
|
||||||
.with_vsync(true)
|
.with_vsync(true)
|
||||||
|
@ -447,7 +452,7 @@ impl App {
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = event_proxy.lock().unwrap().send_event(()) {
|
if let Err(e) = event_proxy.lock().unwrap().send_event(Message::BusEvent) {
|
||||||
eprintln!("Failed to send BusEvent to event proxy: {}", e)
|
eprintln!("Failed to send BusEvent to event proxy: {}", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,12 +473,8 @@ impl App {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(
|
fn setup(&self, event_loop: &glutin::event_loop::EventLoop<Message>) -> Result<(), Error> {
|
||||||
&self,
|
let event_proxy = event_loop.create_proxy();
|
||||||
event_loop: &glutin::event_loop::EventLoop<()>,
|
|
||||||
) -> Result<mpsc::Receiver<gst::Sample>, Error> {
|
|
||||||
let events_proxy = event_loop.create_proxy();
|
|
||||||
let (sender, receiver) = mpsc::channel();
|
|
||||||
self.appsink.set_callbacks(
|
self.appsink.set_callbacks(
|
||||||
gst_app::AppSinkCallbacks::builder()
|
gst_app::AppSinkCallbacks::builder()
|
||||||
.new_sample(move |appsink| {
|
.new_sample(move |appsink| {
|
||||||
|
@ -504,21 +505,25 @@ impl App {
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
sender
|
event_proxy
|
||||||
.send(sample)
|
.send_event(Message::Sample(sample))
|
||||||
.map(|_| gst::FlowSuccess::Ok)
|
.map(|()| gst::FlowSuccess::Ok)
|
||||||
.map_err(|_| gst::FlowError::Error)?;
|
.map_err(|e| {
|
||||||
|
element_error!(
|
||||||
|
appsink,
|
||||||
|
gst::ResourceError::Failed,
|
||||||
|
("Failed to send sample to event loop: {}", e)
|
||||||
|
);
|
||||||
|
|
||||||
let _ = events_proxy.send_event(());
|
gst::FlowError::Error
|
||||||
|
})
|
||||||
Ok(gst::FlowSuccess::Ok)
|
|
||||||
})
|
})
|
||||||
.build(),
|
.build(),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.pipeline.set_state(gst::State::Playing)?;
|
self.pipeline.set_state(gst::State::Playing)?;
|
||||||
|
|
||||||
Ok(receiver)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_gl_api(api: glutin::Api) -> gst_gl::GLAPI {
|
fn map_gl_api(api: glutin::Api) -> gst_gl::GLAPI {
|
||||||
|
@ -601,7 +606,7 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main_loop(app: App) -> Result<(), Error> {
|
fn main_loop(app: App) -> Result<(), Error> {
|
||||||
let receiver = app.setup(&app.event_loop)?;
|
app.setup(&app.event_loop)?;
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Pixel format of the window's GL context {:?}",
|
"Pixel format of the window's GL context {:?}",
|
||||||
|
@ -650,38 +655,37 @@ fn main_loop(app: App) -> Result<(), Error> {
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
glutin::event::Event::RedrawRequested(_) => needs_redraw = true,
|
glutin::event::Event::RedrawRequested(_) => needs_redraw = true,
|
||||||
_ => (),
|
// Receive a frame
|
||||||
}
|
glutin::event::Event::UserEvent(Message::Sample(sample)) => {
|
||||||
|
let buffer = sample.get_buffer_owned().unwrap();
|
||||||
|
let info = sample
|
||||||
|
.get_caps()
|
||||||
|
.and_then(|caps| gst_video::VideoInfo::from_caps(caps).ok())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Handle all pending messages. Whenever there is a message we will
|
{
|
||||||
// wake up the events loop above
|
if gst_gl_context.is_none() {
|
||||||
App::handle_messages(&bus).unwrap();
|
gst_gl_context = glupload
|
||||||
|
.get_property("context")
|
||||||
|
.unwrap()
|
||||||
|
.get::<gst_gl::GLContext>()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// get the last frame in channel
|
let sync_meta = buffer.get_meta::<gst_gl::GLSyncMeta>().unwrap();
|
||||||
if let Some(sample) = receiver.try_iter().last() {
|
sync_meta.set_sync_point(gst_gl_context.as_ref().unwrap());
|
||||||
let buffer = sample.get_buffer_owned().unwrap();
|
|
||||||
let info = sample
|
|
||||||
.get_caps()
|
|
||||||
.and_then(|caps| gst_video::VideoInfo::from_caps(caps).ok())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
{
|
|
||||||
if gst_gl_context.is_none() {
|
|
||||||
gst_gl_context = glupload
|
|
||||||
.get_property("context")
|
|
||||||
.unwrap()
|
|
||||||
.get::<gst_gl::GLContext>()
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sync_meta = buffer.get_meta::<gst_gl::GLSyncMeta>().unwrap();
|
if let Ok(frame) = gst_video::VideoFrame::from_buffer_readable_gl(buffer, &info) {
|
||||||
sync_meta.set_sync_point(gst_gl_context.as_ref().unwrap());
|
curr_frame = Some(frame);
|
||||||
|
needs_redraw = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// Handle all pending messages when we are awaken by set_sync_handler
|
||||||
if let Ok(frame) = gst_video::VideoFrame::from_buffer_readable_gl(buffer, &info) {
|
glutin::event::Event::UserEvent(Message::BusEvent) => {
|
||||||
curr_frame = Some(frame);
|
App::handle_messages(&bus).unwrap();
|
||||||
needs_redraw = true;
|
|
||||||
}
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if needs_redraw {
|
if needs_redraw {
|
||||||
|
|
Loading…
Reference in a new issue