perf(video): 改善视频卡顿问题并优化编码性能

改善内容:
1. NAL单元duration累积bug修复
   - 修改video_track.rs和unified_video_track.rs
   - 只有帧内最后一个NAL获得frame_duration,其他为ZERO
   - 确保同一帧的所有NAL共享相同的RTP时间戳

2. 修复VP8/VP9固定1秒duration错误
   - 将Duration::from_secs(1)改为正确的frame_duration计算

3. PTS计算优化(shared_video_pipeline.rs)
   - 将pipeline_start_time从Mutex<Option<Instant>>改为AtomicI64
   - 消除每帧一次的async mutex lock
   - 使用compare_exchange实现无锁的首帧时间设置

4. 避免重复读取config
   - 在encode_frame中缓存fps,避免末尾再次获取config锁

5. 编码器零拷贝优化
   - H264/H265/VP8/VP9编码器使用drain()替代clone()
   - 减少内存分配和拷贝开销

6. MJPEG处理器优化
   - 无客户端时跳过JPEG编码(WebRTC-only模式优化)

7. RKMPP YUYV直接输入支持
   - hwcodec C++层添加YUYV422格式支持
   - H264编码器添加Yuyv422输入格式选项
This commit is contained in:
mofeng-git
2026-01-02 11:58:55 +08:00
parent 0fc5be21c6
commit 04e62d1e3f
9 changed files with 168 additions and 40 deletions

View File

@@ -362,10 +362,11 @@ impl VP8Encoder {
match self.inner.encode(data, pts_ms) {
Ok(frames) => {
// Zero-copy: drain frames from hwcodec buffer instead of cloning
let owned_frames: Vec<HwEncodeFrame> = frames
.iter()
.drain(..)
.map(|f| HwEncodeFrame {
data: f.data.clone(),
data: f.data, // Move, not clone
pts: f.pts,
key: f.key,
})
@@ -416,7 +417,7 @@ impl Encoder for VP8Encoder {
fn encode(&mut self, data: &[u8], sequence: u64) -> Result<EncodedFrame> {
let pts_ms = (sequence * 1000 / self.config.fps as u64) as i64;
let frames = self.encode_raw(data, pts_ms)?;
let mut frames = self.encode_raw(data, pts_ms)?;
if frames.is_empty() {
warn!("VP8 encoder returned no frames");
@@ -425,11 +426,12 @@ impl Encoder for VP8Encoder {
));
}
let frame = &frames[0];
// Take ownership of the first frame (zero-copy)
let frame = frames.remove(0);
let key_frame = frame.key == 1;
Ok(EncodedFrame {
data: Bytes::from(frame.data.clone()),
data: Bytes::from(frame.data), // Move Vec into Bytes (zero-copy)
format: EncodedFormat::Vp8,
resolution: self.config.base.resolution,
key_frame,