Skip to content

Commit 475d423

Browse files
committed
Stabilize Android WebRTC readiness
1 parent 6055435 commit 475d423

2 files changed

Lines changed: 41 additions & 3 deletions

File tree

client/src/features/stream/streamWorkerClient.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,13 @@ interface WebCodecsVideoDecoderConstructor {
353353
}>;
354354
}
355355

356+
interface WebRtcAnswerPayload extends RTCSessionDescriptionInit {
357+
video?: {
358+
height?: number;
359+
width?: number;
360+
};
361+
}
362+
356363
interface PendingVideoFrame {
357364
frame: WebCodecsVideoFrame;
358365
sequence: number | null;
@@ -1532,7 +1539,7 @@ class WebRtcStreamClient implements StreamClientBackend {
15321539
target,
15331540
localDescription,
15341541
);
1535-
const answer = (await response.json()) as RTCSessionDescriptionInit;
1542+
const answer = (await response.json()) as WebRtcAnswerPayload;
15361543
if (generation !== this.connectGeneration) {
15371544
return;
15381545
}
@@ -1541,6 +1548,15 @@ class WebRtcStreamClient implements StreamClientBackend {
15411548
);
15421549
this.postDiagnostics(target, `${options.detailPrefix}-answer`);
15431550
await peerConnection.setRemoteDescription(answer);
1551+
if (
1552+
typeof answer.video?.width === "number" &&
1553+
typeof answer.video?.height === "number" &&
1554+
answer.video.width > 0 &&
1555+
answer.video.height > 0
1556+
) {
1557+
this.syncCanvasSize(answer.video.width, answer.video.height);
1558+
this.reportVideoConfig(answer.video.width, answer.video.height);
1559+
}
15441560
}
15451561

15461562
destroy() {
@@ -1687,10 +1703,14 @@ class WebRtcStreamClient implements StreamClientBackend {
16871703
return;
16881704
}
16891705
const now = performance.now();
1690-
const hasRenderedFrame = this.stats.renderedFrames > 0;
1706+
const hasMediaProgress =
1707+
this.hasRenderedFrame ||
1708+
this.stats.renderedFrames > 0 ||
1709+
this.stats.decodedFrames > 0 ||
1710+
this.stats.receivedPackets > 0;
16911711
const frameAgeMs =
16921712
this.lastVideoFrameAt > 0 ? now - this.lastVideoFrameAt : Infinity;
1693-
if (!hasRenderedFrame) {
1713+
if (!hasMediaProgress) {
16941714
this.handleConnectionError(
16951715
target,
16961716
generation,
@@ -1699,6 +1719,10 @@ class WebRtcStreamClient implements StreamClientBackend {
16991719
);
17001720
return;
17011721
}
1722+
if (!this.hasRenderedFrame) {
1723+
this.scheduleFrameWatchdog(target, generation);
1724+
return;
1725+
}
17021726
if (frameAgeMs > WEBRTC_STALLED_FRAME_TIMEOUT_MS) {
17031727
this.sendControl({ snapshot: true, type: "streamControl" });
17041728
this.scheduleFrameWatchdog(target, generation);

server/src/transport/webrtc.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ pub struct WebRtcAnswerPayload {
8989
pub sdp: String,
9090
#[serde(rename = "type")]
9191
pub kind: String,
92+
pub video: WebRtcVideoMetadata,
93+
}
94+
95+
#[derive(Debug, Serialize)]
96+
#[serde(rename_all = "camelCase")]
97+
pub struct WebRtcVideoMetadata {
98+
pub width: u32,
99+
pub height: u32,
92100
}
93101

94102
#[derive(Debug, Clone, Serialize)]
@@ -289,6 +297,8 @@ pub async fn create_answer(
289297
summarize_sdp_candidate_types(&local_description.sdp)
290298
);
291299

300+
let first_frame_width = first_frame.width;
301+
let first_frame_height = first_frame.height;
292302
let (cancellation_token, cancellation) =
293303
register_webrtc_media_stream(&udid, payload.client_id.as_deref(), true);
294304
tokio::spawn(
@@ -309,6 +319,10 @@ pub async fn create_answer(
309319
Ok(WebRtcAnswerPayload {
310320
sdp: local_description.sdp,
311321
kind: "answer".to_owned(),
322+
video: WebRtcVideoMetadata {
323+
width: first_frame_width,
324+
height: first_frame_height,
325+
},
312326
})
313327
}
314328

0 commit comments

Comments
 (0)