forked from mirrors/gstreamer-rs
parent
9a01bd6202
commit
1e4d63d77f
1 changed files with 51 additions and 6 deletions
|
@ -327,16 +327,18 @@ fn load(gl_context: &glutin::Context) -> Gl {
|
||||||
struct App {
|
struct App {
|
||||||
pipeline: gst::Pipeline,
|
pipeline: gst::Pipeline,
|
||||||
appsink: gst_app::AppSink,
|
appsink: gst_app::AppSink,
|
||||||
|
glupload: gst::Element,
|
||||||
bus: gst::Bus,
|
bus: gst::Bus,
|
||||||
events_loop: Arc<glutin::EventsLoop>,
|
events_loop: Arc<glutin::EventsLoop>,
|
||||||
windowed_context: Arc<glutin::WindowedContext>,
|
windowed_context: Arc<glutin::WindowedContext>,
|
||||||
|
shared_context: gst_gl::GLContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
fn new() -> Result<App, Error> {
|
fn new() -> Result<App, Error> {
|
||||||
gst::init()?;
|
gst::init()?;
|
||||||
|
|
||||||
let (pipeline, appsink) = App::create_pipeline()?;
|
let (pipeline, appsink, glupload) = App::create_pipeline()?;
|
||||||
let bus = pipeline
|
let bus = pipeline
|
||||||
.get_bus()
|
.get_bus()
|
||||||
.expect("Pipeline without bus. Shouldn't happen!");
|
.expect("Pipeline without bus. Shouldn't happen!");
|
||||||
|
@ -349,9 +351,12 @@ impl App {
|
||||||
.build_windowed(window, &events_loop)?,
|
.build_windowed(window, &events_loop)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
unsafe { windowed_context.make_current()? };
|
||||||
|
|
||||||
let windowed_context_ = windowed_context.clone();
|
let windowed_context_ = windowed_context.clone();
|
||||||
let context = windowed_context_.context();
|
let context = windowed_context_.context();
|
||||||
|
|
||||||
|
let shared_context: gst_gl::GLContext;
|
||||||
if cfg!(target_os = "linux") {
|
if cfg!(target_os = "linux") {
|
||||||
use glutin::os::unix::RawHandle;
|
use glutin::os::unix::RawHandle;
|
||||||
use glutin::os::ContextTraitExt;
|
use glutin::os::ContextTraitExt;
|
||||||
|
@ -369,10 +374,18 @@ impl App {
|
||||||
|
|
||||||
let gl_display =
|
let gl_display =
|
||||||
unsafe { gst_gl::GLDisplayEGL::new_with_egl_display(egl_display) }.unwrap();
|
unsafe { gst_gl::GLDisplayEGL::new_with_egl_display(egl_display) }.unwrap();
|
||||||
let gl_context =
|
shared_context =
|
||||||
unsafe { gst_gl::GLContext::new_wrapped(&gl_display, egl_context, platform, api) }
|
unsafe { gst_gl::GLContext::new_wrapped(&gl_display, egl_context, platform, api) }
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
shared_context
|
||||||
|
.activate(true)
|
||||||
|
.expect("Couldn't activate wrapped GL context");
|
||||||
|
|
||||||
|
shared_context.fill_info()?;
|
||||||
|
|
||||||
|
let gl_context = shared_context.clone();
|
||||||
|
|
||||||
#[allow(clippy::single_match)]
|
#[allow(clippy::single_match)]
|
||||||
bus.set_sync_handler(move |_, msg| {
|
bus.set_sync_handler(move |_, msg| {
|
||||||
use gst::MessageView;
|
use gst::MessageView;
|
||||||
|
@ -415,9 +428,11 @@ impl App {
|
||||||
Ok(App {
|
Ok(App {
|
||||||
pipeline,
|
pipeline,
|
||||||
appsink,
|
appsink,
|
||||||
|
glupload,
|
||||||
bus,
|
bus,
|
||||||
events_loop: Arc::new(events_loop),
|
events_loop: Arc::new(events_loop),
|
||||||
windowed_context,
|
windowed_context,
|
||||||
|
shared_context,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +498,7 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_pipeline() -> Result<(gst::Pipeline, gst_app::AppSink), Error> {
|
fn create_pipeline() -> Result<(gst::Pipeline, gst_app::AppSink, gst::Element), Error> {
|
||||||
let pipeline = gst::Pipeline::new(None);
|
let pipeline = gst::Pipeline::new(None);
|
||||||
let src = gst::ElementFactory::make("videotestsrc", None)
|
let src = gst::ElementFactory::make("videotestsrc", None)
|
||||||
.ok_or(MissingElement("videotestsrc"))?;
|
.ok_or(MissingElement("videotestsrc"))?;
|
||||||
|
@ -511,7 +526,21 @@ impl App {
|
||||||
.build();
|
.build();
|
||||||
appsink.set_caps(&caps);
|
appsink.set_caps(&caps);
|
||||||
|
|
||||||
Ok((pipeline, appsink))
|
// get the glupload element to extract later the used context in it
|
||||||
|
let mut iter = sink.dynamic_cast::<gst::Bin>().unwrap().iterate_elements();
|
||||||
|
let glupload = loop {
|
||||||
|
match iter.next() {
|
||||||
|
Ok(Some(element)) => {
|
||||||
|
if "glupload" == element.get_factory().unwrap().get_name() {
|
||||||
|
break Some(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(gst::IteratorError::Resync) => iter.resync(),
|
||||||
|
_ => break None,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((pipeline, appsink, glupload.unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gst_loop(bus: gst::Bus) -> Result<(), Error> {
|
fn gst_loop(bus: gst::Bus) -> Result<(), Error> {
|
||||||
|
@ -540,8 +569,6 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main_loop(mut app: App) -> Result<(), Error> {
|
fn main_loop(mut app: App) -> Result<(), Error> {
|
||||||
unsafe { app.windowed_context.make_current()? };
|
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Pixel format of the window's GL context {:?}",
|
"Pixel format of the window's GL context {:?}",
|
||||||
app.windowed_context.get_pixel_format()
|
app.windowed_context.get_pixel_format()
|
||||||
|
@ -555,6 +582,8 @@ fn main_loop(mut app: App) -> Result<(), Error> {
|
||||||
let mut running = true;
|
let mut running = true;
|
||||||
let events_loop = Arc::get_mut(&mut app.events_loop).unwrap();
|
let events_loop = Arc::get_mut(&mut app.events_loop).unwrap();
|
||||||
let windowed_context = app.windowed_context.clone();
|
let windowed_context = app.windowed_context.clone();
|
||||||
|
let mut gst_gl_context: Option<gst_gl::GLContext> = None;
|
||||||
|
|
||||||
while running {
|
while running {
|
||||||
#[allow(clippy::single_match)]
|
#[allow(clippy::single_match)]
|
||||||
events_loop.poll_events(|event| match event {
|
events_loop.poll_events(|event| match event {
|
||||||
|
@ -577,12 +606,28 @@ fn main_loop(mut app: App) -> Result<(), Error> {
|
||||||
.get_caps()
|
.get_caps()
|
||||||
.and_then(|caps| gst_video::VideoInfo::from_caps(caps.as_ref()))
|
.and_then(|caps| gst_video::VideoInfo::from_caps(caps.as_ref()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
{
|
||||||
|
if gst_gl_context.is_none() {
|
||||||
|
gst_gl_context = app
|
||||||
|
.glupload
|
||||||
|
.get_property("context")
|
||||||
|
.unwrap()
|
||||||
|
.get::<gst_gl::GLContext>();
|
||||||
|
}
|
||||||
|
|
||||||
|
let sync_meta = buffer.as_ref().get_meta::<gst_gl::GLSyncMeta>().unwrap();
|
||||||
|
sync_meta.set_sync_point(gst_gl_context.as_ref().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(frame) = gst_video::VideoFrame::from_buffer_readable_gl(buffer, &info) {
|
if let Ok(frame) = gst_video::VideoFrame::from_buffer_readable_gl(buffer, &info) {
|
||||||
curr_frame = Some(Arc::new(frame));
|
curr_frame = Some(Arc::new(frame));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(frame) = curr_frame.clone() {
|
if let Some(frame) = curr_frame.clone() {
|
||||||
|
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) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue