Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions web-codecs/src/audio/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ impl AudioData {
self.0.format()
}

pub fn sample_rate(&self) -> f32 {
self.0.sample_rate()
pub fn sample_rate(&self) -> u32 {
self.0.sample_rate() as u32
}

pub fn number_of_frames(&self) -> u32 {
pub fn frame_count(&self) -> u32 {
self.0.number_of_frames()
}

pub fn number_of_channels(&self) -> u32 {
pub fn channel_count(&self) -> u32 {
self.0.number_of_channels()
}

Expand Down
10 changes: 5 additions & 5 deletions web-codecs/src/audio/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ pub struct AudioDecoderConfig {
pub description: Option<Bytes>,

/// The number of channels in the audio.
pub channels: u32,
pub channel_count: u32,

/// The sample rate of the audio.
pub sample_rate: u32,
}

impl AudioDecoderConfig {
pub fn new<T: Into<String>>(codec: T, channels: u32, sample_rate: u32) -> Self {
pub fn new<T: Into<String>>(codec: T, channel_count: u32, sample_rate: u32) -> Self {
Self {
codec: codec.into(),
channels,
channel_count,
sample_rate,
..Default::default()
}
Expand Down Expand Up @@ -83,7 +83,7 @@ impl AudioDecoderConfig {

impl From<&AudioDecoderConfig> for web_sys::AudioDecoderConfig {
fn from(this: &AudioDecoderConfig) -> Self {
let config = web_sys::AudioDecoderConfig::new(&this.codec, this.channels, this.sample_rate);
let config = web_sys::AudioDecoderConfig::new(&this.codec, this.channel_count, this.sample_rate);

if let Some(description) = &this.description {
config.set_description(&js_sys::Uint8Array::from(description.as_ref()));
Expand Down Expand Up @@ -113,7 +113,7 @@ impl From<web_sys::AudioDecoderConfig> for AudioDecoderConfig {
Self {
codec: this.get_codec(),
description,
channels,
channel_count: channels,
sample_rate,
}
}
Expand Down
40 changes: 19 additions & 21 deletions web-codecs/src/audio/encoder.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
use std::{cell::RefCell, rc::Rc};

use tokio::sync::{mpsc, watch};
use wasm_bindgen::prelude::*;

use crate::{EncodedFrame, Error};

use super::{AudioData, AudioDecoderConfig};

// TODO support the full specification: https://developer.mozilla.org/en-US/docs/Web/API/AudioEncoder/configure
#[derive(Debug, Default, Clone)]
pub struct AudioEncoderConfig {
pub codec: String,
pub channels: Option<u32>,
pub channel_count: Option<u32>,
pub sample_rate: Option<u32>,
pub bit_rate: Option<f64>, // bits per second
pub bitrate: Option<u32>, // bits per second
}

impl AudioEncoderConfig {
pub fn new<T: Into<String>>(codec: T) -> Self {
Self {
codec: codec.into(),
channels: None,
channel_count: None,
sample_rate: None,
bit_rate: None,
bitrate: None,
}
}

Expand All @@ -38,10 +41,10 @@ impl AudioEncoderConfig {
pub fn init(self) -> Result<(AudioEncoder, AudioEncoded), Error> {
let (frames_tx, frames_rx) = mpsc::unbounded_channel();
let (closed_tx, closed_rx) = watch::channel(Ok(()));
let (config_tx, config_rx) = watch::channel(None);
let config = Rc::new(RefCell::new(None));

let decoder = AudioEncoder::new(self, config_tx, frames_tx, closed_tx)?;
let decoded = AudioEncoded::new(config_rx, frames_rx, closed_rx);
let decoder = AudioEncoder::new(self, config.clone(), frames_tx, closed_tx)?;
let decoded = AudioEncoded::new(config, frames_rx, closed_rx);

Ok((decoder, decoded))
}
Expand All @@ -51,16 +54,16 @@ impl From<&AudioEncoderConfig> for web_sys::AudioEncoderConfig {
fn from(this: &AudioEncoderConfig) -> Self {
let config = web_sys::AudioEncoderConfig::new(&this.codec);

if let Some(channels) = this.channels {
if let Some(channels) = this.channel_count {
config.set_number_of_channels(channels);
}

if let Some(sample_rate) = this.sample_rate {
config.set_sample_rate(sample_rate);
}

if let Some(bit_rate) = this.bit_rate {
config.set_bitrate(bit_rate);
if let Some(bit_rate) = this.bitrate {
config.set_bitrate(bit_rate as f64);
}

config
Expand All @@ -81,7 +84,7 @@ pub struct AudioEncoder {
impl AudioEncoder {
fn new(
config: AudioEncoderConfig,
on_config: watch::Sender<Option<AudioDecoderConfig>>,
on_config: Rc<RefCell<Option<AudioDecoderConfig>>>,
on_frame: mpsc::UnboundedSender<EncodedFrame>,
on_error: watch::Sender<Result<(), Error>>,
) -> Result<Self, Error> {
Expand All @@ -101,7 +104,7 @@ impl AudioEncoder {
if !config.is_falsy() {
let config: web_sys::AudioDecoderConfig = config.unchecked_into();
let config = AudioDecoderConfig::from(config);
on_config.send_replace(Some(config));
on_config.borrow_mut().replace(config);
}
}
}
Expand Down Expand Up @@ -149,14 +152,14 @@ impl Drop for AudioEncoder {
}

pub struct AudioEncoded {
config: watch::Receiver<Option<AudioDecoderConfig>>,
config: Rc<RefCell<Option<AudioDecoderConfig>>>,
frames: mpsc::UnboundedReceiver<EncodedFrame>,
closed: watch::Receiver<Result<(), Error>>,
}

impl AudioEncoded {
fn new(
config: watch::Receiver<Option<AudioDecoderConfig>>,
config: Rc<RefCell<Option<AudioDecoderConfig>>>,
frames: mpsc::UnboundedReceiver<EncodedFrame>,
closed: watch::Receiver<Result<(), Error>>,
) -> Self {
Expand All @@ -171,12 +174,7 @@ impl AudioEncoded {
}
}

pub async fn config(&self) -> Option<AudioDecoderConfig> {
self.config
.clone()
.wait_for(|config| config.is_some())
.await
.ok()?
.clone()
pub fn config(&self) -> Option<AudioDecoderConfig> {
self.config.borrow().clone()
}
}
20 changes: 8 additions & 12 deletions web-codecs/src/video/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ impl VideoDecoderConfig {
/// Check if the configuration is supported by this browser.
/// Returns an error if the configuration is invalid, and false if just unsupported.
pub async fn is_supported(&self) -> Result<bool, Error> {
if self.resolution.is_none_or(|d| d.width == 0 || d.height == 0) {
return Err(Error::InvalidDimensions);
}

if self.display.is_none_or(|d| d.width == 0 || d.height == 0) {
return Err(Error::InvalidDimensions);
}

let res =
wasm_bindgen_futures::JsFuture::from(web_sys::VideoDecoder::is_config_supported(&self.into())).await?;

Expand All @@ -56,18 +64,6 @@ impl VideoDecoderConfig {
Ok(supported)
}

pub fn is_valid(&self) -> Result<(), Error> {
if self.resolution.is_none_or(|d| d.width == 0 || d.height == 0) {
return Err(Error::InvalidDimensions);
}

if self.display.is_none_or(|d| d.width == 0 || d.height == 0) {
return Err(Error::InvalidDimensions);
}

Ok(())
}

pub fn build(self) -> Result<(VideoDecoder, VideoDecoded), Error> {
let (frames_tx, frames_rx) = mpsc::unbounded_channel();
let (closed_tx, closed_rx) = watch::channel(Ok(()));
Expand Down
42 changes: 19 additions & 23 deletions web-codecs/src/video/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use super::{Dimensions, VideoDecoderConfig, VideoFrame};
use derive_more::Display;

#[derive(Debug, Display, Clone, Copy)]
pub enum VideoEncoderBitrate {
pub enum VideoBitrateMode {
#[display("constant")]
Constant,

Expand All @@ -28,11 +28,11 @@ pub struct VideoEncoderConfig {
pub display: Option<Dimensions>,
pub hardware_acceleration: Option<bool>,
pub latency_optimized: Option<bool>,
pub bit_rate: Option<f64>, // bits per second
pub frame_rate: Option<f64>, // frames per second
pub bitrate: Option<u32>, // bits per second
pub framerate: Option<f64>, // frames per second
pub alpha_preserved: Option<bool>, // keep alpha channel
pub scalability_mode: Option<String>,
pub bitrate_mode: Option<VideoEncoderBitrate>,
pub bitrate_mode: Option<VideoBitrateMode>,

// NOTE: This is a custom configuration
/// The maximum duration of a Group of Pictures (GOP) before forcing a new keyframe.
Expand All @@ -47,8 +47,8 @@ impl VideoEncoderConfig {
display: None,
hardware_acceleration: None,
latency_optimized: None,
bit_rate: None,
frame_rate: None,
bitrate: None,
framerate: None,
alpha_preserved: None,
scalability_mode: None,
bitrate_mode: None,
Expand Down Expand Up @@ -85,10 +85,10 @@ impl VideoEncoderConfig {
pub fn init(self) -> Result<(VideoEncoder, VideoEncoded), Error> {
let (frames_tx, frames_rx) = mpsc::unbounded_channel();
let (closed_tx, closed_rx) = watch::channel(Ok(()));
let (config_tx, config_rx) = watch::channel(None);
let config = Rc::new(RefCell::new(None));

let decoder = VideoEncoder::new(self, config_tx, frames_tx, closed_tx)?;
let decoded = VideoEncoded::new(config_rx, frames_rx, closed_rx);
let decoder = VideoEncoder::new(self, config.clone(), frames_tx, closed_tx)?;
let decoded = VideoEncoded::new(config, frames_rx, closed_rx);

Ok((decoder, decoded))
}
Expand Down Expand Up @@ -117,11 +117,11 @@ impl From<&VideoEncoderConfig> for web_sys::VideoEncoderConfig {
});
}

if let Some(value) = this.bit_rate {
config.set_bitrate(value);
if let Some(value) = this.bitrate {
config.set_bitrate(value as f64);
}

if let Some(value) = this.frame_rate {
if let Some(value) = this.framerate {
config.set_framerate(value);
}

Expand Down Expand Up @@ -168,7 +168,7 @@ pub struct VideoEncoder {
impl VideoEncoder {
fn new(
config: VideoEncoderConfig,
on_config: watch::Sender<Option<VideoDecoderConfig>>,
on_config: Rc<RefCell<Option<VideoDecoderConfig>>>,
on_frame: mpsc::UnboundedSender<EncodedFrame>,
on_error: watch::Sender<Result<(), Error>>,
) -> Result<Self, Error> {
Expand All @@ -191,7 +191,7 @@ impl VideoEncoder {
if !config.is_falsy() {
let config: web_sys::VideoDecoderConfig = config.unchecked_into();
let config = VideoDecoderConfig::from(config);
on_config.send_replace(Some(config));
on_config.borrow_mut().replace(config);
}
}
}
Expand Down Expand Up @@ -264,14 +264,14 @@ impl Drop for VideoEncoder {
}

pub struct VideoEncoded {
config: watch::Receiver<Option<VideoDecoderConfig>>,
config: Rc<RefCell<Option<VideoDecoderConfig>>>,
frames: mpsc::UnboundedReceiver<EncodedFrame>,
closed: watch::Receiver<Result<(), Error>>,
}

impl VideoEncoded {
fn new(
config: watch::Receiver<Option<VideoDecoderConfig>>,
config: Rc<RefCell<Option<VideoDecoderConfig>>>,
frames: mpsc::UnboundedReceiver<EncodedFrame>,
closed: watch::Receiver<Result<(), Error>>,
) -> Self {
Expand All @@ -286,12 +286,8 @@ impl VideoEncoded {
}
}

pub async fn config(&self) -> Option<VideoDecoderConfig> {
self.config
.clone()
.wait_for(|config| config.is_some())
.await
.ok()?
.clone()
/// Returns the decoder config, after the first frame has been encoded.
pub fn config(&self) -> Option<VideoDecoderConfig> {
self.config.borrow().clone()
}
}
Loading