实战排查|为什么遮挡推流摄像头,会导致播放绿屏? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
VideoCloudTech
V2EX    视频技术

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

  •  
  •   VideoCloudTech 2021-02-25 14:27:12 +08:00 1652 次点击
    这是一个创建于 1689 天前的主题,其中的信息可能已经有所发展或是发生改变。

    做音视频的小伙伴们多少都遇到过奇怪的 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  
       2021-02-25 15:47:35 +08:00
    感谢经验分享。我看着的时候还以为是中间提到的,推流停了,所以解码错误导致呢。
    VideoCloudTech
        2
    VideoCloudTech  
    OP
       2021-02-25 15:56:40 +08:00
    @delectate 每一次走进不科学都会发现科学的解释
    wszgrcy
        3
    wszgrcy  
       2021-02-25 16:06:17 +08:00 via Android
    翻到最后没有发现公众号,支持下
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2583 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 14:53 PVG 22:53 LAX 07:53 JFK 10:53
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86