KunSpace
返回博客

大屏 No Signal 后小屏卡顿:patch 线程睡太久

2026年7月2日
尚无阅读

读完了?别空手走啊 😏

若有所获,赐一赞 — 作者会假装很忙实则刷新页面

写评论

赞同、吐槽、提问都行,评论区开放

这篇写什么?

双屏电视上一种「看起来像解码卡、其实是音频线程拖后腿」的现象:

  • 大屏 进入 No Signal(无信号)
  • 小屏 再播视频 → 画面/声画卡顿

根因不在小屏播放器本身,而在 TV audio patch 输入线程 在无信号分支里 睡得太久,环形缓冲处理节奏被打乱。

一句话:

无信号 / tv_mute
  → patch 输入线程清缓冲后 usleep
  → 20ms 太长:醒得少、积得多、醒来连吐
  → 小屏卡顿
  → 改成 5ms:更勤检查、更少堆积

No Signal 时 usleep 过长导致小屏卡顿

相关:TV HDMI-IN Patch 流程ALSA period 与缓冲


一、现象

条件 表现
大屏 无信号(No Signal)
小屏 播放视频出现卡顿
关联模块 audio_patch_input_threadloop(TV 音频 patch 输入循环)

大屏无节目时,patch 线程仍会跑「静音 / 无信号」分支;若这里节奏不对,会 indirectly 影响同进程里其它音频路径的调度与缓冲水位,小屏听感/观感就会发糊、发顿。


二、原因:无信号分支里 usleep(20ms) 太长

问题出在类似逻辑(示意):

if (aml_dev->tv_mute || !check_tv_stream_signal(&in->stream)) {
    memset(patch->in_buf, 0, bytes_avail);
    ring_buffer_clear(ringbuffer);
    usleep(20 * 1000);   // 原来:每次循环睡 20ms
}

含义拆开看:

步骤 作用
tv_mute!check_tv_stream_signal 电视静音,或检测不到有效 TV 音频信号(含 No Signal)
memset + ring_buffer_clear 丢掉无效/脏数据,避免乱响
usleep 空转时少占 CPU,隔一段时间再检查信号

20ms 的问题:

  1. 线程在无信号状态下 醒来频率偏低(大约 50 次/秒量级)
  2. 其它路径仍可能往环里写、或共享调度资源
  3. 线程长时间阻塞 → 缓冲侧更容易出现 滞留 / 水位异常
  4. 一旦信号或路径恢复、线程连续跑起来,容易 短时间连吐堆积数据
  5. 表现到小屏:播放发卡、声画不跟手

所以不是「清缓冲写错了」,而是 清完以后睡太久,处理节拍跟不上


三、修复:20ms5ms

if (aml_dev->tv_mute || !check_tv_stream_signal(&in->stream)) {
    memset(patch->in_buf, 0, bytes_avail);
    ring_buffer_clear(ringbuffer);
    usleep(5 * 1000);    // 改为 5ms
}
对比 20ms 5ms
醒来检查频率 约 50 Hz 约 200 Hz
无信号时空转 CPU 更省 略高一点,仍可接受
环缓冲滞留风险 更高 更低
小屏卡顿 易复现 验证可解除

usleep 单位是 微秒5 * 1000 = 5000µs = 5ms

改完后,无信号时仍会清缓冲、仍会休眠降载,但会 更勤地醒来看信号、维持环水位,避免「睡久了 → 积一堆 → 醒来连吐」。


四、为什么双屏更容易暴露?

单屏时,大屏无信号往往整机都闲着,卡顿不明显。
双屏时:

大屏 patch:No Signal → 长 usleep 空转
小屏:仍在播视频,需要正常音频/调度

两边共用 audio 服务与缓冲策略时,一侧睡太死,另一侧就更容易抖。把无信号空转从 20ms 收到 5ms,是很小的改动,但对「双屏各干各的」场景很关键。


五、调参时注意

注意点 说明
不是越短越好 usleep(0) 或极短会导致空转打满 CPU
5ms 是经验值 在「降载」和「及时处理」之间折中;现场可按 CPU 占用再微调
先确认进了这个分支 log / 断点确认 No Signal 时确实走 tv_mute / !check_tv_stream_signal
与 pop 修复区分 清缓冲防的是脏数据噪声;这里卡顿是 睡太久,别混成一个问题

六、小结

项目 内容
现象 大屏 No Signal → 小屏播视频卡顿
根因 audio_patch_input_threadloop 无信号分支 usleep(20ms) 过长
修复 改为 usleep(5 * 1000)
本质 空转要省电,但不能把 patch 线程睡到跟不上环缓冲

一句话:无信号时可以睡,但别睡到小屏都卡。


相关阅读

评论

还没有评论,来做第一个吧

赞同、吐槽、提问都行,评论区开放