servo_media/
lib.rs

1pub extern crate servo_media_audio as audio;
2pub extern crate servo_media_player as player;
3pub extern crate servo_media_streams as streams;
4pub extern crate servo_media_traits as traits;
5pub extern crate servo_media_webrtc as webrtc;
6
7extern crate once_cell;
8
9pub use traits::*;
10
11use std::ops::Deref;
12use std::sync::{Arc, Mutex};
13use std::thread;
14
15use audio::{
16    context::{AudioContext, AudioContextOptions},
17    sink::AudioSinkError,
18};
19use player::audio::AudioRenderer;
20use player::context::PlayerGLContext;
21use player::ipc_channel::ipc::IpcSender;
22use player::video::VideoFrameRenderer;
23use player::{Player, PlayerEvent, StreamType};
24use streams::capture::MediaTrackConstraintSet;
25use streams::device_monitor::MediaDeviceMonitor;
26use streams::registry::MediaStreamId;
27use streams::{MediaOutput, MediaSocket, MediaStreamType};
28use webrtc::{WebRtcController, WebRtcSignaller};
29
30use once_cell::sync::OnceCell;
31
32pub struct ServoMedia(Box<dyn Backend>);
33
34static INSTANCE: OnceCell<Arc<ServoMedia>> = OnceCell::new();
35
36pub trait BackendInit {
37    fn init() -> Box<dyn Backend>;
38}
39
40pub trait BackendDeInit {
41    fn deinit(&self) {}
42}
43
44pub trait Backend: Send + Sync {
45    fn create_player(
46        &self,
47        id: &ClientContextId,
48        stream_type: StreamType,
49        sender: IpcSender<PlayerEvent>,
50        video_renderer: Option<Arc<Mutex<dyn VideoFrameRenderer>>>,
51        audio_renderer: Option<Arc<Mutex<dyn AudioRenderer>>>,
52        gl_context: Box<dyn PlayerGLContext>,
53    ) -> Arc<Mutex<dyn Player>>;
54    fn create_audiostream(&self) -> MediaStreamId;
55    fn create_videostream(&self) -> MediaStreamId;
56    fn create_stream_output(&self) -> Box<dyn MediaOutput>;
57    fn create_stream_and_socket(
58        &self,
59        ty: MediaStreamType,
60    ) -> (Box<dyn MediaSocket>, MediaStreamId);
61    fn create_audioinput_stream(&self, set: MediaTrackConstraintSet) -> Option<MediaStreamId>;
62    fn create_videoinput_stream(&self, set: MediaTrackConstraintSet) -> Option<MediaStreamId>;
63    fn create_audio_context(
64        &self,
65        id: &ClientContextId,
66        options: AudioContextOptions,
67    ) -> Result<Arc<Mutex<AudioContext>>, AudioSinkError>;
68    fn create_webrtc(&self, signaller: Box<dyn WebRtcSignaller>) -> WebRtcController;
69    fn can_play_type(&self, media_type: &str) -> SupportsMediaType;
70    fn set_capture_mocking(&self, _mock: bool) {}
71    /// Allow muting/unmuting the media instances associated with the given client context identifier.
72    /// Backend implementations are responsible for keeping a match between client contexts
73    /// and the media instances created for these contexts.
74    /// The client context identifier is currently an abstraction of Servo's PipelineId.
75    fn mute(&self, _id: &ClientContextId, _val: bool) {}
76    /// Allow suspending the activity of all media instances associated with the given client
77    /// context identifier.
78    /// Note that suspending does not involve releasing any resources, so media playback can
79    /// be restarted.
80    /// Backend implementations are responsible for keeping a match between client contexts
81    /// and the media instances created for these contexts.
82    /// The client context identifier is currently an abstraction of Servo's PipelineId.
83    fn suspend(&self, _id: &ClientContextId) {}
84    /// Allow resuming the activity of all the media instances associated with the given client
85    /// context identifier.
86    /// Backend implementations are responsible for keeping a match between client contexts
87    /// and the media instances created for these contexts.
88    /// The client context identifier is currently an abstraction of Servo's PipelineId.
89    fn resume(&self, _id: &ClientContextId) {}
90
91    fn get_device_monitor(&self) -> Box<dyn MediaDeviceMonitor>;
92}
93
94#[derive(Clone, Copy, Debug, PartialEq)]
95pub enum SupportsMediaType {
96    Maybe,
97    No,
98    Probably,
99}
100
101impl ServoMedia {
102    pub fn init<B: BackendInit>() {
103        thread::spawn(|| INSTANCE.get_or_init(|| Arc::new(ServoMedia(B::init()))));
104    }
105
106    pub fn init_with_backend<F>(backend_factory: F)
107    where
108        F: Fn() -> Box<dyn Backend> + Send + 'static,
109    {
110        thread::spawn(move || INSTANCE.get_or_init(|| Arc::new(ServoMedia(backend_factory()))));
111    }
112
113    pub fn get() -> Arc<ServoMedia> {
114        INSTANCE.wait().clone()
115    }
116}
117
118impl Deref for ServoMedia {
119    type Target = dyn Backend + 'static;
120    fn deref(&self) -> &(dyn Backend + 'static) {
121        &*self.0
122    }
123}