Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add trait PlayerGLContext #241

Merged
merged 2 commits into from Apr 30, 2019
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

Next

Add trait PlayerGLContext

PlayerGLContext will provide the GL context paratemers required to
create a Render object. If those parameters are supported by the
Render, it will setup a GL rendering pipeline and will handle the
frames in form of GL Textures.

The PlayerGLContext is passed to the player at its instantiation.
  • Loading branch information...
ceyusa authored and ferjm committed Apr 21, 2019
commit 8a8dc95bac22a6edb4f6d73397ff81213c1abe39
@@ -15,7 +15,8 @@ use servo_media_audio::decoder::{AudioDecoder, AudioDecoderCallbacks, AudioDecod
use servo_media_audio::render_thread::AudioRenderThreadMsg;
use servo_media_audio::sink::{AudioSink, AudioSinkError};
use servo_media_audio::AudioBackend;
use servo_media_player::{frame, GlContext, Player, PlayerError, PlayerEvent, StreamType};
use servo_media_player::context::PlayerGLContext;
use servo_media_player::{frame, Player, PlayerError, PlayerEvent, StreamType};
use servo_media_streams::capture::MediaTrackConstraintSet;
use servo_media_streams::registry::{register_stream, unregister_stream, MediaStreamId};
use servo_media_streams::{MediaOutput, MediaStream};
@@ -65,7 +66,7 @@ impl Backend for DummyBackend {
}))))
}

fn create_player(&self, _: StreamType) -> Box<Player> {
fn create_player(&self, _: StreamType, _: Box<PlayerGLContext>) -> Box<Player> {
Box::new(DummyPlayer)
}

@@ -135,9 +136,6 @@ impl Player for DummyPlayer {
fn buffered(&self) -> Result<Vec<Range<f64>>, PlayerError> {
Ok(vec![])
}
fn set_gl_params(&self, _: GlContext, _: usize) -> Result<(), ()> {
Err(())
}

fn shutdown(&self) -> Result<(), PlayerError> {
Ok(())
@@ -146,6 +144,10 @@ impl Player for DummyPlayer {
fn set_stream(&self, _: &MediaStreamId) -> Result<(), PlayerError> {
Ok(())
}

fn render_use_gl(&self) -> bool {
false
}
}

impl WebRtcBackend for DummyBackend {
@@ -51,6 +51,7 @@ use servo_media_audio::context::{AudioContext, AudioContextOptions};
use servo_media_audio::decoder::AudioDecoder;
use servo_media_audio::sink::AudioSinkError;
use servo_media_audio::AudioBackend;
use servo_media_player::context::PlayerGLContext;
use servo_media_player::{Player, StreamType};
use servo_media_streams::capture::MediaTrackConstraintSet;
use servo_media_streams::registry::MediaStreamId;
@@ -64,8 +65,12 @@ lazy_static! {
pub struct GStreamerBackend;

impl Backend for GStreamerBackend {
fn create_player(&self, stream_type: StreamType) -> Box<Player> {
Box::new(player::GStreamerPlayer::new(stream_type))
fn create_player(
&self,
stream_type: StreamType,
gl_context: Box<PlayerGLContext>,
) -> Box<Player> {
Box::new(player::GStreamerPlayer::new(stream_type, gl_context))
}

fn create_audio_context(&self, options: AudioContextOptions) -> AudioContext {
@@ -10,9 +10,10 @@ use ipc_channel::ipc::IpcSender;
use media_stream::GStreamerMediaStream;
use media_stream_source::{register_servo_media_stream_src, ServoMediaStreamSrc};
use render::GStreamerRender;
use servo_media_player::context::PlayerGLContext;
use servo_media_player::frame::{Frame, FrameRenderer};
use servo_media_player::metadata::Metadata;
use servo_media_player::{GlContext, PlaybackState, Player, PlayerError, PlayerEvent, StreamType};
use servo_media_player::{PlaybackState, Player, PlayerError, PlayerEvent, StreamType};
use servo_media_streams::registry::{get_stream, MediaStreamId};
use source::{register_servo_src, ServoSrc};
use std::cell::RefCell;
@@ -346,18 +347,19 @@ pub struct GStreamerPlayer {
is_ready: Arc<Once>,
/// Indicates whether the type of media stream to be played is a live stream.
stream_type: StreamType,
render: RefCell<Option<GStreamerRender>>,
/// Decorator used to setup the video sink and process the produced frames
render: Arc<Mutex<GStreamerRender>>,
}

impl GStreamerPlayer {
pub fn new(stream_type: StreamType) -> GStreamerPlayer {
pub fn new(stream_type: StreamType, gl_context: Box<PlayerGLContext>) -> GStreamerPlayer {
Self {
inner: RefCell::new(None),
observers: Arc::new(Mutex::new(PlayerEventObserverList::new())),
renderers: Arc::new(Mutex::new(FrameRendererList::new())),
is_ready: Arc::new(Once::new()),
stream_type,
render: RefCell::new(None),
render: Arc::new(Mutex::new(GStreamerRender::new(gl_context))),
}
}

@@ -429,11 +431,7 @@ impl GStreamerPlayer {
.set_config(config)
.map_err(|e| PlayerError::Backend(e.to_string()))?;

let render = self
.render
.replace(None)
.unwrap_or(GStreamerRender::new(GlContext::Unknown, 0));
let appsink = render.setup_video_sink(&pipeline)?;
let appsink = self.render.lock().unwrap().setup_video_sink(&pipeline)?;

// There's a known bug in gstreamer that may cause a wrong transition
// to the ready state while setting the uri property:
@@ -614,6 +612,7 @@ impl GStreamerPlayer {
}
});

let render = self.render.clone();
let observers = self.observers.clone();
let renderers = self.renderers.clone();
// Set appsink callbacks.
@@ -623,6 +622,8 @@ impl GStreamerPlayer {
.new_sample(move |appsink| {
let sample = appsink.pull_sample().ok_or(gst::FlowError::Eos)?;
let frame = render
.lock()
.unwrap()
.get_frame_from_sample(&sample)
.or_else(|_| Err(gst::FlowError::Error))?;
renderers
@@ -803,20 +804,13 @@ impl Player for GStreamerPlayer {
self.renderers.lock().unwrap().register(renderer);
}

fn set_gl_params(&self, context: GlContext, display: usize) -> Result<(), ()> {
let render = GStreamerRender::new(context, display);
let ret = render.is_gl();
*self.render.borrow_mut() = Some(render);
if ret {
Ok(())
} else {
Err(())
}
}

fn shutdown(&self) -> Result<(), PlayerError> {
self.observers.lock().unwrap().clear();
self.renderers.lock().unwrap().clear();
self.stop()
}

fn render_use_gl(&self) -> bool {
self.render.lock().unwrap().is_gl()
}
}
@@ -26,8 +26,9 @@ extern crate servo_media_player as sm_player;
use gst::prelude::*;
use gst_gl::prelude::*;
use sm_gst_render::Render;
use sm_player::context::{GlContext, NativeDisplay, PlayerGLContext};
use sm_player::frame::{Buffer, Frame, FrameData};
use sm_player::{GlContext, PlayerError};
use sm_player::PlayerError;
use std::sync::{Arc, Mutex};

struct GStreamerBuffer {
@@ -58,24 +59,29 @@ impl RenderUnix {
///
/// # Arguments
///
/// * `gl_context` - is the living pointer to the GL context,
/// which might be Egl or Glx (right now only the first one is
/// supported).
///
/// * `display_native` - is the living pointer to the native
/// display structure. It migth be the EGLDisplay, the XDisplay or
/// the wl_display (right now only the first one is supported)
pub fn new(gl_context: GlContext, display_native: usize) -> Option<RenderUnix> {
/// * `context` - is the PlayerContext trait object from
/// application.
pub fn new(context: Box<PlayerGLContext>) -> Option<RenderUnix> {
// Check that we actually have the elements that we
// need to make this work.
if gst::ElementFactory::find("glsinkbin").is_none() {
return None;
}

let display_native = context.get_native_display();
let gl_context = context.get_gl_context();

match gl_context {
GlContext::Egl(context) => {
let display = unsafe { gst_gl::GLDisplayEGL::new_with_egl_display(display_native) };
if let Some(display) = display {
let display = match display_native {
NativeDisplay::Egl(display_native) => unsafe {
gst_gl::GLDisplayEGL::new_with_egl_display(display_native)
},
_ => None, // XXX(victor): Add wayland
}
.and_then(|display| Some(display.upcast()));

let render = if let Some(display) = display {
let context = unsafe {
gst_gl::GLContext::new_wrapped(
&display,
@@ -85,23 +91,29 @@ impl RenderUnix {
)
};

if let Some(context) = context {
let render = if let Some(context) = context {
if !(context.activate(true).is_ok() && context.fill_info().is_ok()) {
let cat = gst::DebugCategory::get("default").unwrap();
gst_warning!(cat, "Couldn't fill the wrapped app GL context")
}
return Some(RenderUnix {
display: display.upcast(),
Some(RenderUnix {
display: display,
app_context: context,
gst_context: Arc::new(Mutex::new(None)),
gl_upload: Arc::new(Mutex::new(None)),
});
}
}
})
} else {
None
};

render
} else {
None
};

None
render
}
_ => None,
_ => None, // XXX(victor): add GLX with X11 display
}
}
}
@@ -6,8 +6,9 @@ use gst_video;
use std::sync::Arc;

use servo_media_gstreamer_render::Render;
use servo_media_player::context::PlayerGLContext;
use servo_media_player::frame::{Buffer, Frame, FrameData};
use servo_media_player::{GlContext, PlayerError};
use servo_media_player::PlayerError;

#[cfg(any(
target_os = "linux",
@@ -22,8 +23,8 @@ mod platform {

use super::*;

pub fn create_render(context: GlContext, display: usize) -> Option<Render> {
Render::new(context, display)
pub fn create_render(gl_context: Box<PlayerGLContext>) -> Option<Render> {
Render::new(gl_context)
}
}

@@ -36,13 +37,14 @@ mod platform {
)))]
mod platform {
use servo_media_gstreamer_render::Render as RenderTrait;
use servo_media_player::context::PlayerGLContext;
use servo_media_player::frame::Frame;
use servo_media_player::{GlContext, PlayerError};
use servo_media_player::PlayerError;

pub struct RenderDummy();
pub type Render = RenderDummy;

pub fn create_render(_: GlContext, _: usize) -> Option<RenderDummy> {
pub fn create_render(_: Box<PlayerGLContext>) -> Option<RenderDummy> {
None
}

@@ -79,9 +81,9 @@ pub struct GStreamerRender {
}

impl GStreamerRender {
pub fn new(gl_context: GlContext, display_native: usize) -> Self {
pub fn new(gl_context: Box<PlayerGLContext>) -> Self {
GStreamerRender {
render: platform::create_render(gl_context, display_native),
render: platform::create_render(gl_context),
}
}

@@ -3,12 +3,26 @@ extern crate servo_media;
extern crate servo_media_auto;

use ipc_channel::ipc;
use servo_media::player::context::{GlContext, NativeDisplay, PlayerGLContext};
use servo_media::player::{PlayerEvent, StreamType};
use servo_media::ServoMedia;
use std::sync::{Arc, Mutex};

struct PlayerContextDummy();
impl PlayerGLContext for PlayerContextDummy {
fn get_gl_context(&self) -> GlContext {
return GlContext::Unknown;
}

fn get_native_display(&self) -> NativeDisplay {
return NativeDisplay::Unknown;
}
}

fn run_example(servo_media: Arc<ServoMedia>) {
let player = Arc::new(Mutex::new(servo_media.create_player(StreamType::Stream)));
let player = Arc::new(Mutex::new(
servo_media.create_player(StreamType::Stream, Box::new(PlayerContextDummy())),
));

let (sender, receiver) = ipc::channel().unwrap();
player.lock().unwrap().register_event_handler(sender);
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.