Bug: --port 模式下 wlr-screencopy 后端 negotiate_format panic #1

Closed
opened 2026-06-04 20:58:04 +08:00 by dailz · 1 comment
Owner

位置

src/state.rs:616

严重性

🔴

问题描述

main.rs:64 仅要求 --output--port 二选一,但 state.rsnegotiate_format 中没有任何 WebRTC 分支判断。当用户以 --port(WebRTC 模式)在 wlroots 合成器上运行且未指定 --output 时,self.args.outputNone.expect() 会直接 panic。

对比 state_portal.rs:150-174,Portal 后端在创建编码器前会检查 self.webrtc_tx,WebRTC 模式下走 new_webrtc 分支而完全避开 MP4 路径。

建议修复

main.rs 中增加校验:wlr-screencopy 后端暂不支持 WebRTC,应提前报错并给出清晰提示。或在 state.rsnegotiate_format 中增加 self.args.port > 0 的判断。

// state.rs:616 - 当前代码
Path::new(self.args.output.as_deref().expect("output required for MP4 mode")),
// TODO: Add WebRTC support or early reject when port > 0
## 位置 `src/state.rs:616` ## 严重性 🔴 高 ## 问题描述 `main.rs:64` 仅要求 `--output` 或 `--port` 二选一,但 `state.rs` 的 `negotiate_format` 中没有任何 WebRTC 分支判断。当用户以 `--port`(WebRTC 模式)在 wlroots 合成器上运行且未指定 `--output` 时,`self.args.output` 为 `None`,`.expect()` 会直接 panic。 对比 `state_portal.rs:150-174`,Portal 后端在创建编码器前会检查 `self.webrtc_tx`,WebRTC 模式下走 `new_webrtc` 分支而完全避开 MP4 路径。 ## 建议修复 在 `main.rs` 中增加校验:wlr-screencopy 后端暂不支持 WebRTC,应提前报错并给出清晰提示。或在 `state.rs` 的 `negotiate_format` 中增加 `self.args.port > 0` 的判断。 ```rust // state.rs:616 - 当前代码 Path::new(self.args.output.as_deref().expect("output required for MP4 mode")), // TODO: Add WebRTC support or early reject when port > 0 ```
Author
Owner

修复方案

已通过 commit 46367ef 修复。

问题根因

wlr-screencopy 后端的 negotiate_format() 无条件调用 .expect("output required for MP4 mode"),没有 WebRTC 分支判断。当 --port 模式下 output 为 None 时直接 panic。

修复内容

采用方案 B(完整 WebRTC 支持),而非提前拒绝:

  1. 引入 StreamingEncoder 枚举 — 包装 EncState(MP4 硬编)和 SwEncState(WebRTC 软编),统一 frames_rgb/encode_frame/flush 接口,EncConstructionStage::Streaming 持有枚举而非裸 EncState

  2. State 增加 WebRTC 字段 — webrtc/webrtc_tx/webrtc_rx/webrtc_frames_sent,与 Portal 后端模式一致

  3. State::new() 返回 Result — WebRtcState::new() 可干净地失败而非 panic

  4. negotiate_format() 增加分支 — webrtc_tx 存在时走 SwEncState::new_webrtc(),否则走原有 create_encoder()(VAAPI 硬编,无性能退化)

  5. 新增 poll_webrtc() 方法 — 驱动 signaling + channel drain,在事件循环每轮迭代调用

  6. 修复预存的测试编译错误 — Args 构造 output 类型不匹配 + 缺少 no_persist 字段

验证

  • cargo check --bin wl-webrtc 编译通过
  • cargo test 40 单元测试 + 3 集成测试全部通过
  • wlr-screencopy 后端 MP4 路径无改动,零性能影响
  • 代码审核通过(Oracle 设计 + 子 agent 审核)
# 修复方案 已通过 commit 46367ef 修复。 ## 问题根因 wlr-screencopy 后端的 negotiate_format() 无条件调用 .expect("output required for MP4 mode"),没有 WebRTC 分支判断。当 --port 模式下 output 为 None 时直接 panic。 ## 修复内容 采用方案 B(完整 WebRTC 支持),而非提前拒绝: 1. 引入 StreamingEncoder 枚举 — 包装 EncState(MP4 硬编)和 SwEncState(WebRTC 软编),统一 frames_rgb/encode_frame/flush 接口,EncConstructionStage::Streaming 持有枚举而非裸 EncState 2. State<S> 增加 WebRTC 字段 — webrtc/webrtc_tx/webrtc_rx/webrtc_frames_sent,与 Portal 后端模式一致 3. State::new() 返回 Result<Self> — WebRtcState::new() 可干净地失败而非 panic 4. negotiate_format() 增加分支 — webrtc_tx 存在时走 SwEncState::new_webrtc(),否则走原有 create_encoder()(VAAPI 硬编,无性能退化) 5. 新增 poll_webrtc() 方法 — 驱动 signaling + channel drain,在事件循环每轮迭代调用 6. 修复预存的测试编译错误 — Args 构造 output 类型不匹配 + 缺少 no_persist 字段 ## 验证 - cargo check --bin wl-webrtc 编译通过 - cargo test 40 单元测试 + 3 集成测试全部通过 - wlr-screencopy 后端 MP4 路径无改动,零性能影响 - 代码审核通过(Oracle 设计 + 子 agent 审核)
dailz closed this issue 2026-06-04 22:11:28 +08:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dailz/wl-webrtc#1