前言
万里长征永远不可能一帆风顺,记录下一个看似寻常却对后续开发举足轻重的一次踩坑记录,这次之后,全新的问答搜索乱撞式的debug就要翻篇,开始正向的定位开发啦!
背景
经过一番对YUV420的折腾,相对而言差不太多的422格式本没放在心上,再加上有前同事用过这样的格式,似乎只是修改属性参数PIXEL_FORMAT_E的事情呗?
过程记录
最开始肯定是想当然的改了vpss的参数,自然不生效,因为对vi的理解并不深刻,之前由于都是传感器加载的问题,感觉自己配了也没用反正会调api从传感器里取参数,就没改,这样肯定是不对滴。而后尝试将vi也改成PIXEL_FORMAT_YVU_SEMIPLANAR_422之后,却还是在目前构建的通路上没有后续输出。所幸,角度旋转的坑让我注意到venc的设置肯定有哪里是不完善的。
可是基本参数的配置里,也就是venc通道的属性结构体又是没有这个成员的啊!这个绝对是肯定的!按理来讲海思这样严谨统一的代码风格,应该和vivpss一脉相承下来啊!为什么死活找不到呢?
面对越来越刁钻越不好搜索的问题,单单搜索看帖就花费了大量时间精力却回报甚微,突然在某次按下回车后感觉到每次都这样依靠问答来解决问题肯定不是个办法,除了要解决问题,我还要找到解决问题的办法!正所谓授人以鱼不如授人以渔。
回想起接触海思有段时间了,正向的排查更正思路老是建立不起来,不可能所有人都像大佬一样经验丰富触类旁通啊,在论坛和相关资源都不完善的时候,之前的开发者都是怎么做的呢?!他们是怎么排查解决问题的呢?只靠一本薄薄的开发手册吗?手册虽然详尽却很难及时快速的找到坑的注意事项啊!
思路一
最基本的学习办法肯定是搭配手册啃sample,既然给了这么丰富的sdk自然要利用起来。
首先搜索的就是422格式在sample里是怎么用的。所幸venc的最后一个case就用到了,反复对比从mpp初始化到vi再到vpss venc的所有通道属性,再在手册venc部分反复查找,
肯定是没看仔细,容我再看一遍
大佬,真没有啊
真的吗我不信,你上次就说真没有了
我。。我真的详细对比了,除了要实现的功能外,真的都一样啊
是吗,那为什么sample就可以呢?
是啊,为什么就可以呢?!
思路二
还是老办法,论坛搜索随缘靠同样的踩坑者找答案。提高搜商还是在解决问题性价比较高的方案了,毕竟最快解决问题才是王道。当然更高级一层的是直接避免问题,那就需要长年累月的积累靠基本功体系了,没法速成,但一定一定不能摒弃。
思路三
海思的log机制.搜着搜着,发现即便是解答了无数海思平台疑难杂症的大神也不可能面面俱到什么坑都踩过啊,他又是怎么定位的呢?答案是看log。海思平台有着非常完善的log机制。手册里详细的介绍了/proc/umap下的各个模块,之前倒是也简单看过一点,但是没有把他当成正经的分析工具,而且最为重要的排查logmpp,实际是放在/dev目录下的,并不在/proc下(这章的目录叫proc调试信息说明,看目录清单也是),其实深入仔细看13.4的LOG章节,也提到了/dev目录下的log(手册是真的基本都有,但是真的不好找啊)
既然想到日志了,那就用日志先结合思路一,看看sample到底有什么妖
修改vivpss的通道属性后,远程登录
cat /proc/venc观察,发现编码通道的图像格式仍然是YUV420,类似之前旋转的分辨率问题,也定位到了venc部分,是在编码设置的问题
VENC CHN ATTR 2-- ID VeStr SrcFr TarFr Timeref PixFmt PicAddr VakeUpFrmCnt YVU420 0x6fdfe800 0 2 1 N -1 1 YVU420 0x7258b800 Hx--1024 ----VENC TPEGE ATTR
主进程超时
ogin[1562]: root login on 'pts/0' SAMPLECOMMVENCGetVencStreamRtsp]-1943: get venc stream time out, exit thread SAMPLECOMMVENCGetVencStreamRtsp]-1943: get venc stream time out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream time out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream time out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream time i out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream time out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream time out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream time out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream ai time out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc:stream itime out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream time out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream time out, exit thread SAMPLE COMM VENC GetVencStreamRtsp]-1943: get venc stream time out, exit thread
再跑sample里422格式的进程
---VENC CHN ATTR 2-- ID VeStr SrcFr TarFr Timeref PixFmt PicAddr WakeUpFrmCnt Y 984 YVU422 ( 0x7258b800 1 0 1 486 YVU422 0x7258b800 H1-1024
同样查看venc通道属性,这不,说明编码通道肯定是支持YUV422SP的
可就是完全找不到修改编码通道属性中关于图片格式的设置入口啊
反复对比两个sample差异,做了两个实验:
实验条件:
sample1 h264编码 默认设置YUV420SP sample5 mjpe编码 默认设置YUV422SP
实验1:
将sample1的vi vpss属性设置为yuv422sp,此时cat到的venc通道属性仍未YUV420sp
实验2:
将sample5中的vi vpss属性设置为yuv420sp,此时cat到的venc通道属性自己变成了YUV420sp!
这就再一次确定了这个属性确实可以更改且都支持两个格式
思路二开始立大功了。在论坛刷见这样一个说法
会不会3559也是这样呢?
于是就又做了实验,将sample5的编码类型改为了h264,其余还是默认设置YUV422SP,果然发现venc通道属性自动变成了YUV420SP!
结论
也就是说手册上并没有明确的表述。但是venc的通道属性确实没有单独配置的入口,是通过venc_sendframe中VIDEO_FRAME_INFO_S结构体里的属性都保持一致的,但是由于编码类型不一样,h264不允许YUV422SP格式,就会强行转为YUV420SP
思路三的作用要是仅止于此肯定就不会单开一篇记录了,第二天一觉清醒后又刷到了logmpp的提醒,终于真相大白(格式25在枚举类型里就是YUV422SP。26是YUV420SP)
vencj runc enC c18c5 Se10 110 e111e 00800 venc [Func :avccheckpixelformat [Line]:1691 [Info]:H.264 don't support format 25. venc. [Func! :venccheck video info [Line]:1907 [Info]:venc 0:sendinfo pic info err. venc [Func] :venc_check_send_info [Line]:2028 [Info]:venc 0: video info err. venc [Func :avc_check_pixel_format_[Line]:1691 [Info]:H.264 don't support format 25. venc. [Func :venccheck videoinfo [Line]:1907 [Info]:venc 0 :sendinfo pic info err. venc. [Func] :venc_check_send_info [Line]:2028 [Info]:venc 0: video info err. venc [Func] avc check pixel format [Line]:1691 [Info]:H.264 don't support format 25. venc. [Func] :venccheckvideoinfo [Line]:1907 [Info]:venc 0 :sendinfo pic info err. venc [Func] :vencchecksend info [Line]:2028 [Info]:venc 0: video info err. venc] [Func avc check pixel format [Line]:1691 [Info]:H.264 don't support format 25. venc] [Func] :venccheckvideoinfo Line]:1907 [Info]:venc 0:sendinfo pic info err. venc. [Func] :vencchecksend info(Line]:2028 [Info]:venc 0: video info err. venc [Func avccheck pixel format [Line]:1691 [Info]:H.264 don't support format 25. vencl [Func] :venccheckvideo_info [Line]:1907 [Info]:venc 0 : sendinfo pic info err. venc. [Func] :venccheck_send_info [Line]:2028 [Info]:venc 0: video info err. venc. [Func :avc_check_pixel_format [Line]:1691 [Info]:H.264 don't support format 25. venc. [Func] :venccheckvideo_info [Line]:1907 [Info]:venc 0 : sendinfo pic info err. venc] [Func. :venccheck send info [Line]:2028 [Info]:venc 0: video info err. venc [Func. :avc_check_pixel_format_[Line]:1691_[Info]:H.264 don't support format 25. venc] [Func] :venccheck video info [Line]:1907 [Info]:venc 0:sendinfo pic info err. venc [Func] :vencchecksend info [Line]:2028 [Info]:venc 0: video info err. venc [Func] :avc_check_pixel_format [Line]:1691 [Info]:H.264 don't support format 25. venc [Func] :venccheck video info [Line]:1907 [Infol:venc 0:sendinfo pic info err. venc] [Func] :venccheck_sendinfo [Line]:2028 [Info]:venc 0: video info err. venc] [Func :avccheckpixel format [Line]:1691 [Info]:H.264 don't support format 25. venc[Func]:venccheckvideoinfo [Line]:1907 [Info]:venc 0: sendinfo pic info err.[Info]:venc 0:video info err.Hx--1024 venc] [Func]:venc_check_send_info [Line]:2028
这时思路一再次跳出来争宠了:我这最基本的指南不认真看,出了问题怪谁!(真不好找啊对于完全不熟悉框架的小白而言)
HI_MPI_VENC_SendFrame函数的注意事项中提及完完全全盖章定论,sample最底层实际上肯定调用到了这一函数,vpss的图像开始编码都经过了他,(虽然表象上只是vpss和venc做了绑定就再也没管了),所以说sample的编码格式更改h264后编码通道也强行变成了420.而且我们自己搭建的通路不是还特意调用了吗!代码框架设计就不符合人家的规范了呀!
补充
对了,下一篇提到的ive工具里也有海思自带的420和422互相转换的办法
想到一个理论上最简单的方式,可能底层也跟这个差不多吧?
YUV4:2:2 —> YUV4:2:0 : Y不变,将U和V信号值在行(垂直方向)在进行一次隔行抽样。
YUV4:2:0 —> YUV4:2:2 :Y不变,将U和V信号值的每一行分别拷贝一份形成连续两行数据。
教训。
解决问题的思路肯定是不能每次都瞎蒙或者单纯靠搜的,最最离不开的就是自身基础知识的积累,经验的丰富,眼界的提升,这是看待问题解决问题的基础,搜索的即时性补强只能起到添砖加瓦的作用,毕竟是工作,要第一时间解决问题,但一定一定不能忘了减少问题避免问题需要系统体系的学习积累;
其次就是要尽量用正向的思维去解决问题,每个平台会有自己独有的醒悟方式,但也会有共同的debug办法,比如遇见段错误后拿gdb调试啊,看dump文件啊,像海思类似的日志功能更是提供不少方便,同理在以后的工程框架里是不是也需要加入日志呢(之前的glog也是个很棒的开源项目),最最最不济,老苯办法printf定位大法总会有所帮助吧
不要慌不要紧,即便是全新的工作环境也要重拾信心,技术固然各领域有所不同,但也总会有殊途同归的部分,加油!