V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
VideoCloudTech
V2EX  ›  视频技术

实战排查|为什么遮挡推流摄像头,会导致播放绿屏?

  •  
  •   VideoCloudTech · 275 天前 · 697 次点击
    这是一个创建于 275 天前的主题,其中的信息可能已经有所发展或是发生改变。

    做音视频的小伙伴们多少都遇到过奇怪的 BUG (如:卡顿、花屏、绿屏、变声等),表象上矛盾点颇多,推理得出的结论都是:“不应该啊!”,最终你抽丝剥茧,发现真相只有一个:“事出反常必有妖”!

    奇怪现象

    背景:RTC 互动中增加对 RTMP 的支持,实现 RTC 与 RTMP 相互订阅。

    遇到一个奇怪的 BUG,遮挡住 RTC 端的摄像头,有的 RTMP 播放端( iPad air 2,iPad mini 2/4 )会偶发绿屏。

    image.png

    要不先发版?

    初步分析问题后,我们认为这是:一个偶发的终端兼容性问题,有很大概率需要修改 RTC 端的编码来适配,耗时不好评估。

    “距离发版本的时间不到 2 周,要不就先发版本吧?” 这个请求被产品无情的拒绝了(这次真的感谢你们的坚持),测试也反馈了新的情况:iPhone 6 也出现了绿屏,关闭 RTC 端的摄像头也可能绿屏,Mac 摄像头对着白色墙面也可能绿屏(测试的同学们也太能折腾了),同时确认了 RTMP 编码 RTMP 播放时相同场景不绿屏。

    编码还是封装的坑?

    疑难杂症先会诊,同编解码的同学一起讨论完后确认两个可能的点:

    1. 编码的 264 码流不兼容。
    2. 封装发送的 RTMP 数据不兼容。

    我们制定了后续的排查方案:

    1. 录制 RTMP 编码和 RTC 编码的码流做对比。
    2. 使用 FFmpeg 发送 RTC 编码的码流确认是否绿屏。

    1. 码流对比

    我们录制了一个完整测试过程中的码流供编解码同学分析,通过粗略的对比发现一个重要的区别 vui 中色域相关信息不一致,色域会影响 yuv->rgb 的转换。下图是不绿屏码流的 vui

    image.png

    通过这个线索,我们做了两个验证测试:

    1. 我们的 vui 是否会造成黑色显示异常,通过摄像头采集一个黑色手机,在图像中形成大面积黑色。验证结果:正常显示。
    2. 按照正常码流修改 vui 。验证结果:偶发绿屏。

    算法的同学接着做更深入的分析。

    2. 封装对比

    FFmpeg 发布 RTMP 的示例:

    ffmpeg -re -i green.h264 -c copy -f flv rtmp://localhost/live/livestream
    

    测试结果:正常显示测试中绿屏的场景。

    封装对比结论:封装层问题,编解码的同学可以休息了(感谢你们一起填坑)。

    封装填坑记

    1. 怀疑一切

    对于这种黑盒问题,我们只能抱着怀疑一切的态度,开始各种猜测。

    Metadata 排查 背景描述:我们没有发 Metadata (不是我们懒,RTC 场景音视频不一定都存在,没有准确的 Metadata ), 是不是 Metadata 造成的(虽然我们有自己的答案,Metadata 就算影响也是全局的,怎么会是特定场景,还偶发)。

    验证方法:先用 FFmpeg 确认下,不发 Metadata 是否正常,如果正常再加 Metadata 。(为什么不先加 Metadata ?这次是真懒)

    ffmpeg -re -i green.h264 -c copy -flvflags no_metadata -f flv rtmp://localhost/live/livestream
    

    验证结果:没有绿屏,一切正常,Metadata 是无辜的。

    SPS 、PPS 排查 背景描述:RTC 场景 SPS 、PPS 是可能变化的(屏幕共享,横竖屏切换等),所以我们将 SPS 、PPS 通过 Sequence Header 和 IDR 帧进行了发送,FFmpeg 在这块可能是有区别的。

    验证方法:Wireshark 抓包,确认 FFmpeg 只发送了一次 Sequence Header, SPS 、PPS 也随 IDR 帧发送(录制码流中 IDR 前都有 SPS 、PPS )。按 FFmpeg 的修改进行测试。

    验证结果:还是绿屏,不过概率有所下降。

    验证外延:SPS 、PPS 全用 Sequence Header 发送,不再随 IDR 帧发送。

    验证结果:还是绿屏,概率比前一方案更低。

    警告:SPS 、PPS 全用 Sequence Header 发送,兼容性差,FFplay 有概率播放失败,vlc 无法成功播放。我们保留了 FFmpeg 相同的做法,继续排查。

    2. 蛛丝马迹

    各种猜测验证都失败了,只好跟测试同学不断沟通,希望可以寻找到些许线索,多次沟通和锁定一个比较有价值的线索:Mac 在关闭摄像头时,RTMP 端播放绿屏概率较高。

    定点排查 排查全部转移到 Mac 关闭摄像头这个场景,从埋点数据中确认:Mac 关闭摄像头后,RTMP 发送的视频数量不再增加。

    用 Wireshark 抓包确认关闭摄像头时 Mac 端是否有发送视频包,意外发现不仅有视频包,还有一些 seq 不变的视频 Padding 包(有效内容为 0 ),突然感觉黎明就在前方了,Review 完代码确认 Padding 包影响了组帧逻辑,受 Padding 包影响大部分视频帧被丢弃了,满怀信心的修改完代码。

    image.png

    所谓希望越大,失望越大。绿屏依旧存在,而且严重了很多,多次测试下来,它成了必现问题,虽然很失望,但是从偶发问题到必现问题也是一个很大的 “进步”。

    3. 黎明之前

    最黑暗的时刻,问题终于毕现了,却没了有效的排查手段。

    由于 TCP 粘包问题,Wireshark 并不能完全正确的解析出每一个 RTMP 包,没有一个高效的办法查看 RTC 转换的 RTMP 包。

    在忘篱同学的帮助下,通过 SRS 的 srs_rtmp_dump, 将 RTMP 数据保存为了 FLV 文件,具体用法: #编译

    git checkout 3.0release && ./configure --osx --with-librtmp --with-research && make -j8
    #保存 flv
    ./objs/research/librtmp/srs_rtmp_dump -r rtmp://127.0.0.1:1935/live/livestream -o output.flv > t.log
    

    通过 FFmpeg 发布 FLV 文件,绿屏问题重现了,莫名的兴奋。

    ffmpeg -re -i green.flv -c copy -flvflags no_metadata -f flv rtmp://localhost/live/livestream
    

    虽然知道了 FLV 有问题,可是接下来对于 FLV 的分析却犯难了,首先 FLV 格式分析的结果并没有任何问题,用 FFmpeg 抽取出 FLV 中的 264,再发布时也正常。这个 FLV 文件用 FFplay 播放也是有错误信息的。

    image.png

    4. 完美解决

    当你无计可施,看着代码发呆的时候,休息一下可能是个解决问题的好办法。上班的地铁上,终于有了头绪:mark bit 、stap,组帧逻辑判断条件,导致了两帧放到了一个 FLV 的 frame 中,造成部分终端不兼容。最终测试通过,版本正常发布,感谢这个过程中每一位同学的支持与配合。

    总结

    1. 即使 IDR 帧,也可以很小,小到都填不满一个 UDP 包。
    2. SPS 、PPS 和很小的 IDR 可以打到一个 STAP 的 RTP 包。
    3. 纯 Padding 包一定认真对待,没有实际数据的枷锁,它们可以做一些灵活的应用。
    4. 多帧封装到一起,有兼容性问题。
    5. “事出反常必有妖”,代码没有玄学。
    6. 认真考虑数据的准确性,优先排查两端的数据。
    7. 工具可以显著的提升效率。

    福利

    SRS 的 srs_flv_parser 中增加了 h264 video frame 中每个 nalu 的信息打印,希望对大家以后填坑有所帮助,提前发布预览效果,看看绿屏妖的原形。

    image.png

    3 条回复    2021-02-25 16:06:17 +08:00
    delectate
        1
    delectate   275 天前
    感谢经验分享。我看着的时候还以为是中间提到的,推流停了,所以解码错误导致呢。
    VideoCloudTech
        2
    VideoCloudTech   275 天前
    @delectate 每一次走进不科学都会发现科学的解释 😉
    wszgrcy
        3
    wszgrcy   275 天前 via Android
    翻到最后没有发现公众号,支持下
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2293 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 14:43 · PVG 22:43 · LAX 06:43 · JFK 09:43
    ♥ Do have faith in what you're doing.