Skip to content

Commit 652465e

Browse files
committed
[*] add webrtc whep client demo
1 parent a77e512 commit 652465e

File tree

13 files changed

+663
-998
lines changed

13 files changed

+663
-998
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/mp4-player/src/lib.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,43 @@ pub enum MP4PlayerError {
2828
#[error("Mp4 Player stop error: {0}")]
2929
PlayerStopError(String),
3030
}
31+
32+
pub fn yuv420_to_rgb(
33+
yuv_frame: &openh264::decoder::DecodedYUV,
34+
width: u32,
35+
height: u32,
36+
) -> Result<Vec<u8>> {
37+
use openh264::formats::YUVSource;
38+
use yuv::{YuvPlanarImage, YuvRange, YuvStandardMatrix, yuv420_to_rgb};
39+
40+
let y_plane = yuv_frame.y();
41+
let u_plane = yuv_frame.u();
42+
let v_plane = yuv_frame.v();
43+
let y_plane_len = y_plane.len();
44+
let u_plane_len = u_plane.len();
45+
let v_plane_len = v_plane.len();
46+
47+
let height_usize = height as usize;
48+
let yuv_planar_image = YuvPlanarImage {
49+
y_plane,
50+
y_stride: (y_plane_len / height_usize) as u32, // Calculate actual stride from data length
51+
u_plane,
52+
u_stride: (u_plane_len / (height_usize / 2)) as u32, // U plane stride for 420 format
53+
v_plane,
54+
v_stride: (v_plane_len / (height_usize / 2)) as u32, // V plane stride for 420 format
55+
width,
56+
height,
57+
};
58+
59+
let mut rgb_data = vec![0u8; (width * height * 3) as usize];
60+
yuv420_to_rgb(
61+
&yuv_planar_image,
62+
&mut rgb_data,
63+
width * 3, // RGB stride (3 bytes per pixel)
64+
YuvRange::Limited, // TV range (16-235) - matches encoder
65+
YuvStandardMatrix::Bt601, // BT.601 standard - matches encoder
66+
)
67+
.map_err(|e| MP4PlayerError::FrameError(format!("YUV to RGB conversion failed: {:?}", e)))?;
68+
69+
Ok(rgb_data)
70+
}

lib/mp4-player/src/video_decoder.rs

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
use super::{MP4PlayerError, Result};
1+
use super::{MP4PlayerError, Result, yuv420_to_rgb};
22
use image::{ImageBuffer, Rgb};
3-
use openh264::{
4-
decoder::{DecodedYUV, Decoder},
5-
formats::YUVSource,
6-
};
7-
use yuv::{YuvPlanarImage, YuvRange, YuvStandardMatrix, yuv420_to_rgb};
3+
use openh264::decoder::Decoder;
84

95
pub struct VideoDecoder {
106
decoder: Decoder,
@@ -34,7 +30,7 @@ impl VideoDecoder {
3430
for nal_data in nal_units {
3531
match self.decoder.decode(&nal_data) {
3632
Ok(Some(yuv_frame)) => {
37-
let rgb_data = Self::yuv420_to_rgb(&yuv_frame, self.width, self.height)?;
33+
let rgb_data = yuv420_to_rgb(&yuv_frame, self.width, self.height)?;
3834
return Ok(Some(DecodedFrame {
3935
rgb_data,
4036
width: self.width,
@@ -109,41 +105,6 @@ impl VideoDecoder {
109105

110106
nal_units
111107
}
112-
113-
fn yuv420_to_rgb(yuv_frame: &DecodedYUV, width: u32, height: u32) -> Result<Vec<u8>> {
114-
let y_plane = yuv_frame.y();
115-
let u_plane = yuv_frame.u();
116-
let v_plane = yuv_frame.v();
117-
let y_plane_len = y_plane.len();
118-
let u_plane_len = u_plane.len();
119-
let v_plane_len = v_plane.len();
120-
121-
let height_usize = height as usize;
122-
let yuv_planar_image = YuvPlanarImage {
123-
y_plane,
124-
y_stride: (y_plane_len / height_usize) as u32, // Calculate actual stride from data length
125-
u_plane,
126-
u_stride: (u_plane_len / (height_usize / 2)) as u32, // U plane stride for 420 format
127-
v_plane,
128-
v_stride: (v_plane_len / (height_usize / 2)) as u32, // V plane stride for 420 format
129-
width,
130-
height,
131-
};
132-
133-
let mut rgb_data = vec![0u8; (width * height * 3) as usize];
134-
yuv420_to_rgb(
135-
&yuv_planar_image,
136-
&mut rgb_data,
137-
width * 3, // RGB stride (3 bytes per pixel)
138-
YuvRange::Limited, // TV range (16-235) - matches encoder
139-
YuvStandardMatrix::Bt601, // BT.601 standard - matches encoder
140-
)
141-
.map_err(|e| {
142-
MP4PlayerError::FrameError(format!("YUV to RGB conversion failed: {:?}", e))
143-
})?;
144-
145-
Ok(rgb_data)
146-
}
147108
}
148109

149110
#[derive(Debug, Clone)]

lib/mp4m/src/mp4_processor.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,6 @@ impl Mp4Processor {
421421
) {
422422
self.total_video_frames += 1;
423423

424-
const VIDEO_TIMESCALE: u32 = 90000;
425-
426424
// Calculate duration in 90kHz timescale units (90000 / fps)
427425
let duration = VIDEO_TIMESCALE / self.config.video_config.fps;
428426

lib/video-encoder/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ impl VideoEncoderConfig {
6464
}
6565
}
6666

67+
#[cfg(any(feature = "x264", feature = "openh264", feature = "ffmpeg"))]
6768
pub fn new(config: VideoEncoderConfig) -> Result<Box<dyn VideoEncoder>> {
6869
#[cfg(feature = "x264")]
6970
let ve = ve_x264::X264VideoEncoder::new(config)?;

lib/wrtc/Cargo.toml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,33 @@
11
[package]
22
name = "wrtc"
3-
edition = "2024"
4-
license = "MIT"
5-
version = "0.1.0"
6-
description = "A whip/whep library."
3+
license.workspace = true
4+
edition.workspace = true
5+
version.workspace = true
6+
readme.workspace = true
7+
authors.workspace = true
8+
keywords.workspace = true
9+
homepage.workspace = true
10+
repository.workspace = true
11+
description = "A whep library"
712

813
[dependencies]
914
log.workspace = true
1015
rand.workspace = true
1116
http.workspace = true
1217
bytes.workspace = true
1318
rubato.workspace = true
14-
anyhow.workspace = true
1519
webrtc.workspace = true
1620
bytesio.workspace = true
1721
indexmap.workspace = true
1822
audiopus.workspace = true
1923
openh264.workspace = true
2024
byteorder.workspace = true
25+
crossbeam.workspace = true
2126
thiserror.workspace = true
27+
derivative.workspace = true
2228
serde_json.workspace = true
2329
mp4-player.workspace = true
30+
video-encoder.workspace = true
2431
derive_setters.workspace = true
2532
tokio = { workspace = true, features = ["full"] }
2633
serde = { workspace = true, features = ["derive"] }
@@ -29,6 +36,7 @@ reqwest = { workspace = true, features = ["json"] }
2936
[dev-dependencies]
3037
image.workspace = true
3138
hound.workspace = true
39+
anyhow.workspace = true
3240
once_cell.workspace = true
3341
stunclient.workspace = true
3442
env_logger.workspace = true

0 commit comments

Comments
 (0)