feat: video publishing (#42)
- Prepare webrtc abstraction ( for future wasm support ) - Added track publish support for videos - Added LogoTrack example to simple_room demo - Lot of cleanup - There are compiler warnings I'll solve on our v1 release
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
use core::str;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::{MessageEvent, RtcDataChannelEvent, RtcDataChannelState};
|
||||
|
||||
use crate::data_channel::{
|
||||
DataChannelError, DataChannelTrait, DataState, OnBufferedAmountChange, OnMessage, OnStateChange,
|
||||
};
|
||||
|
||||
impl From<RtcDataChannelState> for DataState {
|
||||
fn from(value: RtcDataChannelState) -> Self {
|
||||
match value {
|
||||
RtcDataChannelState::Connecting => Self::Connecting,
|
||||
RtcDataChannelState::Open => Self::Open,
|
||||
RtcDataChannelState::Closing => Self::Closing,
|
||||
RtcDataChannelState::Closed => Self::Closed,
|
||||
_ => panic!("unknown data channel state"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DataChannel {
|
||||
sys_handle: web_sys::RtcDataChannel,
|
||||
on_closing: Rc<RefCell<Option<JsValue>>>,
|
||||
}
|
||||
|
||||
impl DataChannelTrait for DataChannel {
|
||||
fn send(&self, data: &[u8], binary: bool) -> Result<(), DataChannelError> {
|
||||
if binary {
|
||||
self.sys_handle
|
||||
.send_with_u8_array(data)
|
||||
.map_err(|_| DataChannelError::Send)
|
||||
} else {
|
||||
let utf8 = str::from_utf8(data)?;
|
||||
self.sys_handle
|
||||
.send_with_str(utf8)
|
||||
.map_err(|_| DataChannelError::Send)
|
||||
}
|
||||
}
|
||||
|
||||
fn label(&self) -> String {
|
||||
self.sys_handle.label()
|
||||
}
|
||||
|
||||
fn state(&self) -> DataState {
|
||||
self.sys_handle.ready_state().into()
|
||||
}
|
||||
|
||||
fn close(&self) {
|
||||
self.sys_handle.close();
|
||||
}
|
||||
|
||||
fn on_state_change(&self, callback: Option<OnStateChange>) {
|
||||
if let Some(mut callback) = callback {
|
||||
let dc = self.clone();
|
||||
let js_callback = Closure::new(move |_: RtcDataChannelEvent| {
|
||||
callback(dc.state());
|
||||
});
|
||||
let js_callback = js_callback.into_js_value();
|
||||
self.sys_handle
|
||||
.set_onopen(Some(js_callback.unchecked_ref()));
|
||||
self.sys_handle
|
||||
.set_onclose(Some(js_callback.unchecked_ref()));
|
||||
self.sys_handle
|
||||
.add_event_listener_with_callback("closing", js_callback.unchecked_ref())
|
||||
.unwrap();
|
||||
|
||||
self.on_closing.replace(Some(js_callback));
|
||||
} else {
|
||||
self.sys_handle.set_onopen(None);
|
||||
self.sys_handle.set_onclose(None);
|
||||
if let Some(on_closing) = self.on_closing.take() {
|
||||
self.sys_handle
|
||||
.remove_event_listener_with_callback("closing", on_closing.unchecked_ref())
|
||||
.unwrap();
|
||||
}
|
||||
self.on_closing.replace(None);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_message(&self, callback: Option<OnMessage>) {
|
||||
let js_callback = callback.map(|mut callback| {
|
||||
Closure::new(move |event: MessageEvent| {
|
||||
if let Some(str) = event.as_string() {
|
||||
callback(str.as_bytes(), false);
|
||||
}
|
||||
})
|
||||
.into_js_value()
|
||||
});
|
||||
|
||||
self.sys_handle.set_onmessage(
|
||||
js_callback
|
||||
.as_ref()
|
||||
.map(|callback| callback.unchecked_ref()),
|
||||
);
|
||||
}
|
||||
|
||||
fn on_buffered_amount_change(&self, _callback: Option<OnBufferedAmountChange>) {
|
||||
todo!("onbufferedamountlow instead?")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
use super::VideoTrack;
|
||||
use crate::{
|
||||
media_stream::{
|
||||
BiplanarYuv8Buffer, BiplanarYuvBuffer, PlanarYuv16BBuffer, PlanarYuv8Buffer,
|
||||
PlanarYuvBuffer, VideoFrameBuffer,
|
||||
},
|
||||
video_frame::{BiplanarYuv8Buffer, I420Buffer, SinkError, VideoFrame, VideoFrameBuffer},
|
||||
I010Buffer, I420ABuffer, I422Buffer, I444Buffer, NV12Buffer,
|
||||
};
|
||||
use std::sync::mpsc;
|
||||
use web_sys::{WebGlRenderingContext, WebGlTexture};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WebGlVideoSink {
|
||||
track: Arc<VideoTrack>,
|
||||
gl_ctx: WebGlRenderingContext,
|
||||
tex: WebGlTexture,
|
||||
}
|
||||
|
||||
/// Create a new WebGL texture and update it inside requestAnimationFrame
|
||||
impl WebGlVideoSink {
|
||||
pub fn new(
|
||||
track: Arc<VideoTrack>,
|
||||
gl_ctx: WebGlRenderingContext,
|
||||
) -> Result<(Self, mpsc::Receiver<VideoFrame<WebGlBuffer>>), SinkError> {
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
let tex = gl_ctx.create_texture()?;
|
||||
Ok((Self { track, gl_ctx, tex }, receiver))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WebGlBuffer {
|
||||
width: i32,
|
||||
height: i32,
|
||||
tex: WebGlTexture,
|
||||
}
|
||||
|
||||
impl VideoFrameBuffer for WebGlBuffer {
|
||||
fn width(&self) -> i32 {
|
||||
self.width
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
self.height
|
||||
}
|
||||
}
|
||||
|
||||
/// The following types could be implemented if we want
|
||||
/// to support VideoFrame with WebCodecs
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct I420Buffer {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct I420ABuffer {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct I422Buffer {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct I444Buffer {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct I010Buffer {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NV12Buffer {}
|
||||
|
||||
impl VideoFrameBuffer for I420Buffer {
|
||||
fn width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoFrameBuffer for I420ABuffer {
|
||||
fn width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoFrameBuffer for I422Buffer {
|
||||
fn width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoFrameBuffer for I444Buffer {
|
||||
fn width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoFrameBuffer for I010Buffer {
|
||||
fn width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoFrameBuffer for NV12Buffer {
|
||||
fn width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuvBuffer for I420Buffer {
|
||||
fn chroma_width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn chroma_height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_y(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_u(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_v(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuvBuffer for I420ABuffer {
|
||||
fn chroma_width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn chroma_height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_y(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_u(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_v(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuvBuffer for I422Buffer {
|
||||
fn chroma_width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn chroma_height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_y(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_u(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_v(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuvBuffer for I444Buffer {
|
||||
fn chroma_width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn chroma_height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_y(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_u(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_v(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuvBuffer for I010Buffer {
|
||||
fn chroma_width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn chroma_height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_y(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_u(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_v(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuvBuffer for NV12Buffer {
|
||||
fn chroma_width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn chroma_height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_y(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_u(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_v(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuv8Buffer for I420Buffer {
|
||||
fn data_y(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_u(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_v(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuv8Buffer for I420ABuffer {
|
||||
fn data_y(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_u(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_v(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuv8Buffer for I422Buffer {
|
||||
fn data_y(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_u(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_v(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuv8Buffer for I444Buffer {
|
||||
fn data_y(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_u(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_v(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PlanarYuv16BBuffer for I010Buffer {
|
||||
fn data_y(&self) -> &[u16] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_u(&self) -> &[u16] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_v(&self) -> &[u16] {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl BiplanarYuvBuffer for NV12Buffer {
|
||||
fn chroma_width(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn chroma_height(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_y(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn stride_uv(&self) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl BiplanarYuv8Buffer for NV12Buffer {
|
||||
fn data_y(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn data_uv(&self) -> &[u8] {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
unimplemented!()
|
||||
Reference in New Issue
Block a user