examples/glupload: Clean up considerably and port to glutin 0.21

This commit is contained in:
Sebastian Dröge 2019-04-24 16:07:15 +03:00
parent d460310ed1
commit 4af06f0dd2
2 changed files with 56 additions and 56 deletions

View file

@ -46,7 +46,7 @@ gst-rtsp-server = ["gstreamer-rtsp-server"]
gst-rtsp-server-record = ["gstreamer-rtsp-server-sys", "gstreamer-rtsp-server", "gstreamer-rtsp", "gio"] gst-rtsp-server-record = ["gstreamer-rtsp-server-sys", "gstreamer-rtsp-server", "gstreamer-rtsp", "gio"]
v1_10 = ["gstreamer/v1_10"] v1_10 = ["gstreamer/v1_10"]
pango-cairo = ["pango", "pangocairo", "cairo-rs"] pango-cairo = ["pango", "pangocairo", "cairo-rs"]
gl = ["gl_generator", "glutin"] gl = ["gstreamer-gl", "gl_generator", "glutin"]
gl-egl = ["gstreamer-gl/egl"] gl-egl = ["gstreamer-gl/egl"]
gl-x11 = ["gstreamer-gl/x11"] gl-x11 = ["gstreamer-gl/x11"]
gl-wayland = ["gstreamer-gl/wayland"] gl-wayland = ["gstreamer-gl/wayland"]
@ -142,3 +142,4 @@ required-features = ["ges"]
name = "glupload" name = "glupload"
required-features = ["gl"] required-features = ["gl"]
features = ["gl-egl", "gl-x11", "gl-wayland"] features = ["gl-egl", "gl-x11", "gl-wayland"]
edition = "2018"

View file

@ -19,8 +19,7 @@ use std::error::Error as StdError;
use std::ffi::CStr; use std::ffi::CStr;
use std::mem; use std::mem;
use std::ptr; use std::ptr;
use std::sync::{mpsc, Arc, Mutex}; use std::sync::mpsc;
use std::thread;
extern crate failure; extern crate failure;
use failure::Error; use failure::Error;
@ -29,7 +28,6 @@ use failure::Error;
extern crate failure_derive; extern crate failure_derive;
extern crate glutin; extern crate glutin;
use glutin::ContextTrait;
#[path = "../examples-common.rs"] #[path = "../examples-common.rs"]
mod examples_common; mod examples_common;
@ -209,7 +207,7 @@ impl Gl {
} }
} }
fn load(gl_context: &glutin::Context) -> Gl { fn load(gl_context: &glutin::WindowedContext<glutin::PossiblyCurrent>) -> Gl {
let gl = gl::Gl::load_with(|ptr| gl_context.get_proc_address(ptr) as *const _); let gl = gl::Gl::load_with(|ptr| gl_context.get_proc_address(ptr) as *const _);
let version = unsafe { let version = unsafe {
@ -329,8 +327,8 @@ struct App {
appsink: gst_app::AppSink, appsink: gst_app::AppSink,
glupload: gst::Element, glupload: gst::Element,
bus: gst::Bus, bus: gst::Bus,
events_loop: Arc<glutin::EventsLoop>, events_loop: glutin::EventsLoop,
windowed_context: Arc<glutin::WindowedContext>, windowed_context: glutin::WindowedContext<glutin::PossiblyCurrent>,
shared_context: gst_gl::GLContext, shared_context: gst_gl::GLContext,
} }
@ -345,19 +343,14 @@ impl App {
let events_loop = glutin::EventsLoop::new(); let events_loop = glutin::EventsLoop::new();
let window = glutin::WindowBuilder::new().with_title("GL rendering"); let window = glutin::WindowBuilder::new().with_title("GL rendering");
let windowed_context = Arc::new( let windowed_context = glutin::ContextBuilder::new()
glutin::ContextBuilder::new()
.with_vsync(true) .with_vsync(true)
.build_windowed(window, &events_loop)?, .build_windowed(window, &events_loop)?;
);
unsafe { windowed_context.make_current()? }; let windowed_context = unsafe { windowed_context.make_current().map_err(|(_, err)| err)? };
let windowed_context_ = windowed_context.clone();
let context = windowed_context_.context();
#[cfg(any(feature = "gl-x11", feature = "gl-wayland"))] #[cfg(any(feature = "gl-x11", feature = "gl-wayland"))]
let inner_window = windowed_context_.window(); let inner_window = windowed_context.window();
let shared_context: gst_gl::GLContext; let shared_context: gst_gl::GLContext;
if cfg!(target_os = "linux") { if cfg!(target_os = "linux") {
@ -366,13 +359,15 @@ impl App {
use glutin::os::unix::WindowExt; use glutin::os::unix::WindowExt;
use glutin::os::ContextTraitExt; use glutin::os::ContextTraitExt;
let api = App::map_gl_api(context.get_api()); let api = App::map_gl_api(windowed_context.get_api());
let (gl_context, gl_display, platform) = match unsafe { context.raw_handle() } { let (gl_context, gl_display, platform) = match unsafe { windowed_context.raw_handle() }
{
#[cfg(any(feature = "gl-egl", feature = "gl-wayland"))] #[cfg(any(feature = "gl-egl", feature = "gl-wayland"))]
RawHandle::Egl(egl_context) => { RawHandle::Egl(egl_context) => {
#[cfg(feature = "gl-egl")] #[cfg(feature = "gl-egl")]
let gl_display = if let Some(display) = unsafe { context.get_egl_display() } { let gl_display =
if let Some(display) = unsafe { windowed_context.get_egl_display() } {
unsafe { gst_gl::GLDisplayEGL::new_with_egl_display(display as usize) } unsafe { gst_gl::GLDisplayEGL::new_with_egl_display(display as usize) }
.unwrap() .unwrap()
} else { } else {
@ -421,6 +416,7 @@ impl App {
shared_context.fill_info()?; shared_context.fill_info()?;
let gl_context = shared_context.clone(); let gl_context = shared_context.clone();
let events_proxy = events_loop.create_proxy();
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
bus.set_sync_handler(move |_, msg| { bus.set_sync_handler(move |_, msg| {
@ -443,7 +439,7 @@ impl App {
let mut context = gst::Context::new(context_type, true); let mut context = gst::Context::new(context_type, true);
{ {
let context = context.get_mut().unwrap(); let context = context.get_mut().unwrap();
let mut s = context.get_mut_structure(); let s = context.get_mut_structure();
s.set_value("context", gl_context.to_send_value()); s.set_value("context", gl_context.to_send_value());
} }
el.set_context(&context); el.set_context(&context);
@ -453,6 +449,8 @@ impl App {
_ => (), _ => (),
} }
let _ = events_proxy.wakeup();
gst::BusSyncReply::Pass gst::BusSyncReply::Pass
}); });
} else { } else {
@ -464,23 +462,18 @@ impl App {
appsink, appsink,
glupload, glupload,
bus, bus,
events_loop: Arc::new(events_loop), events_loop: events_loop,
windowed_context, windowed_context: windowed_context,
shared_context, shared_context,
}) })
} }
fn setup(&self) -> Result<(thread::JoinHandle<()>, mpsc::Receiver<gst::Sample>), Error> { fn setup(
let bus = self.bus.clone(); &self,
let bus_handler = thread::spawn(move || { events_loop: &glutin::EventsLoop,
let ret = App::gst_loop(bus); ) -> Result<mpsc::Receiver<gst::Sample>, Error> {
if ret.is_err() { let events_proxy = events_loop.create_proxy();
eprintln!("ERROR! {:?}", ret);
}
});
let (sender, receiver) = mpsc::channel(); let (sender, receiver) = mpsc::channel();
let sender_clone = Mutex::new(sender.clone());
self.appsink.set_callbacks( self.appsink.set_callbacks(
gst_app::AppSinkCallbacks::new() gst_app::AppSinkCallbacks::new()
.new_sample(move |appsink| { .new_sample(move |appsink| {
@ -511,19 +504,21 @@ impl App {
})?; })?;
} }
sender_clone sender
.lock()
.unwrap()
.send(sample) .send(sample)
.map(|_| gst::FlowSuccess::Ok) .map(|_| gst::FlowSuccess::Ok)
.map_err(|_| gst::FlowError::Error) .map_err(|_| gst::FlowError::Error)?;
let _ = events_proxy.wakeup();
Ok(gst::FlowSuccess::Ok)
}) })
.build(), .build(),
); );
self.pipeline.set_state(gst::State::Playing)?; self.pipeline.set_state(gst::State::Playing)?;
Ok((bus_handler, receiver)) Ok(receiver)
} }
fn map_gl_api(api: glutin::Api) -> gst_gl::GLAPI { fn map_gl_api(api: glutin::Api) -> gst_gl::GLAPI {
@ -579,10 +574,10 @@ impl App {
Ok((pipeline, appsink, glupload.unwrap())) Ok((pipeline, appsink, glupload.unwrap()))
} }
fn gst_loop(bus: gst::Bus) -> Result<(), Error> { fn handle_messages(bus: &gst::Bus) -> Result<(), Error> {
use gst::MessageView; use gst::MessageView;
for msg in bus.iter_timed(gst::CLOCK_TIME_NONE) { for msg in bus.iter() {
match msg.view() { match msg.view() {
MessageView::Eos(..) => break, MessageView::Eos(..) => break,
MessageView::Error(err) => { MessageView::Error(err) => {
@ -610,15 +605,16 @@ fn main_loop(mut app: App) -> Result<(), Error> {
app.windowed_context.get_pixel_format() app.windowed_context.get_pixel_format()
); );
let gl = load(&app.windowed_context.context()); let gl = load(&app.windowed_context);
let (bus_handler, receiver) = app.setup()?; let receiver = app.setup(&app.events_loop)?;
let mut curr_frame: Option<Arc<gst_video::VideoFrame<gst_video::video_frame::Readable>>> = None; let mut curr_frame: Option<gst_video::VideoFrame<gst_video::video_frame::Readable>> = None;
let mut running = true; let mut running = true;
let events_loop = Arc::get_mut(&mut app.events_loop).unwrap();
let windowed_context = app.windowed_context.clone();
let mut gst_gl_context: Option<gst_gl::GLContext> = None; let mut gst_gl_context: Option<gst_gl::GLContext> = None;
let events_loop = &mut app.events_loop;
let windowed_context = &mut app.windowed_context;
let bus = &app.bus;
while running { while running {
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
@ -626,7 +622,7 @@ fn main_loop(mut app: App) -> Result<(), Error> {
glutin::Event::WindowEvent { event, .. } => match event { glutin::Event::WindowEvent { event, .. } => match event {
glutin::WindowEvent::CloseRequested => running = false, glutin::WindowEvent::CloseRequested => running = false,
glutin::WindowEvent::Resized(logical_size) => { glutin::WindowEvent::Resized(logical_size) => {
let dpi_factor = windowed_context.get_hidpi_factor(); let dpi_factor = windowed_context.window().get_hidpi_factor();
windowed_context.resize(logical_size.to_physical(dpi_factor)); windowed_context.resize(logical_size.to_physical(dpi_factor));
gl.resize(logical_size.to_physical(dpi_factor)); gl.resize(logical_size.to_physical(dpi_factor));
} }
@ -635,8 +631,12 @@ fn main_loop(mut app: App) -> Result<(), Error> {
_ => (), _ => (),
}); });
// Handle all pending messages. Whenever there is a message we will
// wake up the events loop above
App::handle_messages(&bus)?;
// get the last frame in channel // get the last frame in channel
while let Ok(sample) = receiver.try_recv() { if let Some(sample) = receiver.try_iter().last() {
let buffer = sample.get_buffer().unwrap(); let buffer = sample.get_buffer().unwrap();
let info = sample let info = sample
.get_caps() .get_caps()
@ -659,22 +659,21 @@ fn main_loop(mut app: App) -> Result<(), Error> {
if let Ok(frame) = if let Ok(frame) =
gst_video::VideoFrame::from_buffer_readable_gl(buffer.to_owned(), &info) gst_video::VideoFrame::from_buffer_readable_gl(buffer.to_owned(), &info)
{ {
curr_frame = Some(Arc::new(frame)); curr_frame = Some(frame);
} }
} }
if let Some(frame) = curr_frame.clone() { if let Some(frame) = curr_frame.as_ref() {
let sync_meta = frame.buffer().get_meta::<gst_gl::GLSyncMeta>().unwrap(); let sync_meta = frame.buffer().get_meta::<gst_gl::GLSyncMeta>().unwrap();
sync_meta.wait(&app.shared_context); sync_meta.wait(&app.shared_context);
if let Some(texture) = frame.get_texture_id(0) { if let Some(texture) = frame.get_texture_id(0) {
gl.draw_frame(texture as gl::types::GLuint); gl.draw_frame(texture as gl::types::GLuint);
} }
} }
app.windowed_context.swap_buffers()?; windowed_context.swap_buffers()?;
} }
app.pipeline.send_event(gst::Event::new_eos().build()); app.pipeline.send_event(gst::Event::new_eos().build());
bus_handler.join().expect("Could join bus handler thread");
app.pipeline.set_state(gst::State::Null)?; app.pipeline.set_state(gst::State::Null)?;
Ok(()) Ok(())