Skip to content

Commit ce4dfe0

Browse files
committed
vp8 whip input
1 parent 0e1e13b commit ce4dfe0

File tree

4 files changed

+196
-43
lines changed

4 files changed

+196
-43
lines changed

compositor_api/src/types/from_register_input.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@ impl TryFrom<WhipInput> for pipeline::RegisterInputOptions {
200200
VideoDecoder::FfmpegH264 => decoder::VideoDecoderOptions {
201201
decoder: pipeline::VideoDecoder::FFmpegH264,
202202
},
203-
VideoDecoder::FfmpegVp8 => unimplemented!("WHIP VP8 input"),
203+
VideoDecoder::FfmpegVp8 => decoder::VideoDecoderOptions {
204+
decoder: pipeline::VideoDecoder::FFmpegVp8,
205+
},
204206
#[cfg(feature = "vk-video")]
205207
VideoDecoder::VulkanVideo => decoder::VideoDecoderOptions {
206208
decoder: pipeline::VideoDecoder::VulkanVideoH264,

compositor_pipeline/src/pipeline/input/whip/depayloader.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{mem, time::Duration};
33
use bytes::Bytes;
44
use log::error;
55
use rtp::{
6-
codecs::{h264::H264Packet, opus::OpusPacket},
6+
codecs::{h264::H264Packet, opus::OpusPacket, vp8::Vp8Packet},
77
packetizer::Depacketizer,
88
};
99
use webrtc::rtp_transceiver::rtp_codec::RTPCodecType;
@@ -74,6 +74,11 @@ pub enum VideoDepayloader {
7474
buffer: Vec<Bytes>,
7575
rollover_state: RolloverState,
7676
},
77+
VP8 {
78+
depayloader: Vp8Packet,
79+
buffer: Vec<Bytes>,
80+
rollover_state: RolloverState,
81+
},
7782
}
7883

7984
impl VideoDepayloader {
@@ -85,7 +90,11 @@ impl VideoDepayloader {
8590
rollover_state: RolloverState::default(),
8691
},
8792

88-
VideoDecoder::FFmpegVp8 => unimplemented!(),
93+
VideoDecoder::FFmpegVp8 => VideoDepayloader::VP8 {
94+
depayloader: Vp8Packet::default(),
95+
buffer: vec![],
96+
rollover_state: RolloverState::default(),
97+
},
8998

9099
#[cfg(feature = "vk-video")]
91100
VideoDecoder::VulkanVideoH264 => VideoDepayloader::H264 {
@@ -128,6 +137,35 @@ impl VideoDepayloader {
128137
kind,
129138
};
130139

140+
Ok(vec![new_chunk])
141+
},
142+
VideoDepayloader::VP8 {
143+
depayloader,
144+
buffer,
145+
rollover_state,
146+
} => {
147+
let kind = EncodedChunkKind::Video(VideoCodec::VP8);
148+
let vp8_chunk = depayloader.depacketize(&packet.payload)?;
149+
150+
if vp8_chunk.is_empty() {
151+
return Ok(Vec::new());
152+
}
153+
154+
buffer.push(vp8_chunk);
155+
if !packet.header.marker {
156+
// the marker bit is set on the last packet of an access unit
157+
return Ok(Vec::new());
158+
}
159+
160+
let timestamp = rollover_state.timestamp(packet.header.timestamp);
161+
let new_chunk = EncodedChunk {
162+
data: mem::take(buffer).concat().into(),
163+
pts: Duration::from_secs_f64(timestamp as f64 / 90000.0),
164+
dts: None,
165+
is_keyframe: IsKeyframe::Unknown,
166+
kind,
167+
};
168+
131169
Ok(vec![new_chunk])
132170
}
133171
}

compositor_pipeline/src/pipeline/whip_whep/init_peer_connection.rs

Lines changed: 122 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@ use std::sync::Arc;
33
use webrtc::{
44
api::{
55
interceptor_registry::register_default_interceptors,
6-
media_engine::{MediaEngine, MIME_TYPE_H264, MIME_TYPE_OPUS},
6+
media_engine::{MediaEngine, MIME_TYPE_H264, MIME_TYPE_OPUS, MIME_TYPE_VP8},
77
APIBuilder,
88
},
99
ice_transport::ice_server::RTCIceServer,
1010
interceptor::registry::Registry,
1111
peer_connection::{configuration::RTCConfiguration, RTCPeerConnection},
1212
rtp_transceiver::{
13-
rtp_codec::{RTCRtpCodecCapability, RTCRtpCodecParameters, RTPCodecType},
14-
rtp_transceiver_direction::RTCRtpTransceiverDirection,
15-
RTCRtpTransceiverInit,
13+
rtp_codec::{RTCRtpCodecCapability, RTCRtpCodecParameters, RTPCodecType}, rtp_transceiver_direction::RTCRtpTransceiverDirection, RTCPFeedback, RTCRtpTransceiverInit
1614
},
1715
};
1816

@@ -25,35 +23,7 @@ pub async fn init_peer_connection(
2523
) -> Result<Arc<RTCPeerConnection>, WhipServerError> {
2624
let mut media_engine = MediaEngine::default();
2725

28-
media_engine.register_codec(
29-
RTCRtpCodecParameters {
30-
capability: RTCRtpCodecCapability {
31-
mime_type: MIME_TYPE_H264.to_owned(),
32-
clock_rate: 90000,
33-
channels: 0,
34-
sdp_fmtp_line: "".to_owned(),
35-
rtcp_feedback: vec![],
36-
},
37-
payload_type: 96,
38-
..Default::default()
39-
},
40-
RTPCodecType::Video,
41-
)?;
42-
43-
media_engine.register_codec(
44-
RTCRtpCodecParameters {
45-
capability: RTCRtpCodecCapability {
46-
mime_type: MIME_TYPE_OPUS.to_owned(),
47-
clock_rate: 48000,
48-
channels: 2,
49-
sdp_fmtp_line: "".to_owned(),
50-
rtcp_feedback: vec![],
51-
},
52-
payload_type: 97,
53-
..Default::default()
54-
},
55-
RTPCodecType::Audio,
56-
)?;
26+
register_codecs(&mut media_engine)?;
5727

5828
let mut registry = Registry::new();
5929

@@ -98,3 +68,122 @@ pub async fn init_peer_connection(
9868

9969
Ok(peer_connection)
10070
}
71+
72+
fn register_codecs(media_engine: &mut MediaEngine) -> webrtc::error::Result<()> {
73+
media_engine.register_codec(
74+
RTCRtpCodecParameters {
75+
capability: RTCRtpCodecCapability {
76+
mime_type: MIME_TYPE_OPUS.to_owned(),
77+
clock_rate: 48000,
78+
channels: 2,
79+
sdp_fmtp_line: "minptime=10;useinbandfec=1".to_owned(),
80+
rtcp_feedback: vec![],
81+
},
82+
payload_type: 111,
83+
..Default::default()
84+
},
85+
RTPCodecType::Audio,
86+
)?;
87+
88+
let video_rtcp_feedback = vec![
89+
RTCPFeedback {
90+
typ: "goog-remb".to_owned(),
91+
parameter: "".to_owned(),
92+
},
93+
RTCPFeedback {
94+
typ: "ccm".to_owned(),
95+
parameter: "fir".to_owned(),
96+
},
97+
RTCPFeedback {
98+
typ: "nack".to_owned(),
99+
parameter: "".to_owned(),
100+
},
101+
RTCPFeedback {
102+
typ: "nack".to_owned(),
103+
parameter: "pli".to_owned(),
104+
},
105+
];
106+
let video_codecs = vec![
107+
RTCRtpCodecParameters {
108+
capability: RTCRtpCodecCapability {
109+
mime_type: MIME_TYPE_VP8.to_owned(),
110+
clock_rate: 90000,
111+
channels: 0,
112+
sdp_fmtp_line: "".to_owned(),
113+
rtcp_feedback: video_rtcp_feedback.clone(),
114+
},
115+
payload_type: 96,
116+
..Default::default()
117+
},
118+
RTCRtpCodecParameters {
119+
capability: RTCRtpCodecCapability {
120+
mime_type: MIME_TYPE_H264.to_owned(),
121+
clock_rate: 90000,
122+
channels: 0,
123+
sdp_fmtp_line:
124+
"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f"
125+
.to_owned(),
126+
rtcp_feedback: video_rtcp_feedback.clone(),
127+
},
128+
payload_type: 102,
129+
..Default::default()
130+
},
131+
RTCRtpCodecParameters {
132+
capability: RTCRtpCodecCapability {
133+
mime_type: MIME_TYPE_H264.to_owned(),
134+
clock_rate: 90000,
135+
channels: 0,
136+
sdp_fmtp_line:
137+
"level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f"
138+
.to_owned(),
139+
rtcp_feedback: video_rtcp_feedback.clone(),
140+
},
141+
payload_type: 127,
142+
..Default::default()
143+
},
144+
RTCRtpCodecParameters {
145+
capability: RTCRtpCodecCapability {
146+
mime_type: MIME_TYPE_H264.to_owned(),
147+
clock_rate: 90000,
148+
channels: 0,
149+
sdp_fmtp_line:
150+
"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f"
151+
.to_owned(),
152+
rtcp_feedback: video_rtcp_feedback.clone(),
153+
},
154+
payload_type: 125,
155+
..Default::default()
156+
},
157+
RTCRtpCodecParameters {
158+
capability: RTCRtpCodecCapability {
159+
mime_type: MIME_TYPE_H264.to_owned(),
160+
clock_rate: 90000,
161+
channels: 0,
162+
sdp_fmtp_line:
163+
"level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f"
164+
.to_owned(),
165+
rtcp_feedback: video_rtcp_feedback.clone(),
166+
},
167+
payload_type: 108,
168+
..Default::default()
169+
},
170+
RTCRtpCodecParameters {
171+
capability: RTCRtpCodecCapability {
172+
mime_type: MIME_TYPE_H264.to_owned(),
173+
clock_rate: 90000,
174+
channels: 0,
175+
sdp_fmtp_line:
176+
"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032"
177+
.to_owned(),
178+
rtcp_feedback: video_rtcp_feedback.clone(),
179+
},
180+
payload_type: 123,
181+
..Default::default()
182+
},
183+
];
184+
for codec in video_codecs {
185+
media_engine.register_codec(codec, RTPCodecType::Video)?;
186+
}
187+
188+
Ok(())
189+
}

integration_tests/examples/vp8_rtp_input.rs renamed to integration_tests/examples/vp8_input.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use anyhow::Result;
22
use compositor_api::types::Resolution;
33
use serde_json::json;
4+
use tracing::info;
45
use std::{process::Command, thread::sleep, time::Duration};
56

67
use integration_tests::{
@@ -33,6 +34,24 @@ fn client_code() -> Result<()> {
3334
}),
3435
)?;
3536

37+
let token_input_1 = examples::post(
38+
"input/input_2/register",
39+
&json!({
40+
"type": "whip",
41+
"video": {
42+
"decoder": "ffmpeg_vp8"
43+
},
44+
"audio": {
45+
"decoder": "opus"
46+
},
47+
}),
48+
)?
49+
.json::<serde_json::Value>();
50+
51+
if let Ok(token) = token_input_1 {
52+
info!("Bearer token for input_2: {}", token["bearer_token"]);
53+
}
54+
3655
examples::post(
3756
"output/output_1/register",
3857
&json!({
@@ -54,13 +73,18 @@ fn client_code() -> Result<()> {
5473
"background_color": "#4d4d4dff",
5574
"children": [
5675
{
57-
"type": "rescaler",
58-
"width": VIDEO_RESOLUTION.width,
59-
"height": VIDEO_RESOLUTION.height,
60-
"child": {
61-
"type": "input_stream",
62-
"input_id": "input_1"
63-
}
76+
"type": "rescaler",
77+
"child": {
78+
"type": "input_stream",
79+
"input_id": "input_1"
80+
}
81+
},
82+
{
83+
"type": "rescaler",
84+
"child": {
85+
"type": "input_stream",
86+
"input_id": "input_2"
87+
}
6488
}
6589
]
6690
}

0 commit comments

Comments
 (0)