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"]
v1_10 = ["gstreamer/v1_10"]
pango-cairo = ["pango", "pangocairo", "cairo-rs"]
gl = ["gl_generator", "glutin"]
gl = ["gstreamer-gl", "gl_generator", "glutin"]
gl-egl = ["gstreamer-gl/egl"]
gl-x11 = ["gstreamer-gl/x11"]
gl-wayland = ["gstreamer-gl/wayland"]
@ -142,3 +142,4 @@ required-features = ["ges"]
name = "glupload"
required-features = ["gl"]
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::mem;
use std::ptr;
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use std::sync::mpsc;
extern crate failure;
use failure::Error;
@ -29,7 +28,6 @@ use failure::Error;
extern crate failure_derive;
extern crate glutin;
use glutin::ContextTrait;
#[path = "../examples-common.rs"]
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 version = unsafe {
@ -329,8 +327,8 @@ struct App {
appsink: gst_app::AppSink,
glupload: gst::Element,
bus: gst::Bus,
events_loop: Arc<glutin::EventsLoop>,
windowed_context: Arc<glutin::WindowedContext>,
events_loop: glutin::EventsLoop,
windowed_context: glutin::WindowedContext<glutin::PossiblyCurrent>,
shared_context: gst_gl::GLContext,
}
@ -345,19 +343,14 @@ impl App {
let events_loop = glutin::EventsLoop::new();
let window = glutin::WindowBuilder::new().with_title("GL rendering");
let windowed_context = Arc::new(
glutin::ContextBuilder::new()
let windowed_context = glutin::ContextBuilder::new()
.with_vsync(true)
.build_windowed(window, &events_loop)?,
);
.build_windowed(window, &events_loop)?;
unsafe { windowed_context.make_current()? };
let windowed_context_ = windowed_context.clone();
let context = windowed_context_.context();
let windowed_context = unsafe { windowed_context.make_current().map_err(|(_, err)| err)? };
#[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;
if cfg!(target_os = "linux") {
@ -366,13 +359,15 @@ impl App {
use glutin::os::unix::WindowExt;
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"))]
RawHandle::Egl(egl_context) => {
#[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) }
.unwrap()
} else {
@ -421,6 +416,7 @@ impl App {
shared_context.fill_info()?;
let gl_context = shared_context.clone();
let events_proxy = events_loop.create_proxy();
#[allow(clippy::single_match)]
bus.set_sync_handler(move |_, msg| {
@ -443,7 +439,7 @@ impl App {
let mut context = gst::Context::new(context_type, true);
{
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());
}
el.set_context(&context);
@ -453,6 +449,8 @@ impl App {
_ => (),
}
let _ = events_proxy.wakeup();
gst::BusSyncReply::Pass
});
} else {
@ -464,23 +462,18 @@ impl App {
appsink,
glupload,
bus,
events_loop: Arc::new(events_loop),
windowed_context,
events_loop: events_loop,
windowed_context: windowed_context,
shared_context,
})
}
fn setup(&self) -> Result<(thread::JoinHandle<()>, mpsc::Receiver<gst::Sample>), Error> {
let bus = self.bus.clone();
let bus_handler = thread::spawn(move || {
let ret = App::gst_loop(bus);
if ret.is_err() {
eprintln!("ERROR! {:?}", ret);
}
});
fn setup(
&self,
events_loop: &glutin::EventsLoop,
) -> Result<mpsc::Receiver<gst::Sample>, Error> {
let events_proxy = events_loop.create_proxy();
let (sender, receiver) = mpsc::channel();
let sender_clone = Mutex::new(sender.clone());
self.appsink.set_callbacks(
gst_app::AppSinkCallbacks::new()
.new_sample(move |appsink| {
@ -511,19 +504,21 @@ impl App {
})?;
}
sender_clone
.lock()
.unwrap()
sender
.send(sample)
.map(|_| gst::FlowSuccess::Ok)
.map_err(|_| gst::FlowError::Error)
.map_err(|_| gst::FlowError::Error)?;
let _ = events_proxy.wakeup();
Ok(gst::FlowSuccess::Ok)
})
.build(),
);
self.pipeline.set_state(gst::State::Playing)?;
Ok((bus_handler, receiver))
Ok(receiver)
}
fn map_gl_api(api: glutin::Api) -> gst_gl::GLAPI {
@ -579,10 +574,10 @@ impl App {
Ok((pipeline, appsink, glupload.unwrap()))
}
fn gst_loop(bus: gst::Bus) -> Result<(), Error> {
fn handle_messages(bus: &gst::Bus) -> Result<(), Error> {
use gst::MessageView;
for msg in bus.iter_timed(gst::CLOCK_TIME_NONE) {
for msg in bus.iter() {
match msg.view() {
MessageView::Eos(..) => break,
MessageView::Error(err) => {
@ -610,15 +605,16 @@ fn main_loop(mut app: App) -> Result<(), Error> {
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 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 events_loop = &mut app.events_loop;
let windowed_context = &mut app.windowed_context;
let bus = &app.bus;
while running {
#[allow(clippy::single_match)]
@ -626,7 +622,7 @@ fn main_loop(mut app: App) -> Result<(), Error> {
glutin::Event::WindowEvent { event, .. } => match event {
glutin::WindowEvent::CloseRequested => running = false,
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));
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
while let Ok(sample) = receiver.try_recv() {
if let Some(sample) = receiver.try_iter().last() {
let buffer = sample.get_buffer().unwrap();
let info = sample
.get_caps()
@ -659,22 +659,21 @@ fn main_loop(mut app: App) -> Result<(), Error> {
if let Ok(frame) =
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();
sync_meta.wait(&app.shared_context);
if let Some(texture) = frame.get_texture_id(0) {
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());
bus_handler.join().expect("Could join bus handler thread");
app.pipeline.set_state(gst::State::Null)?;
Ok(())