基于avd7181c解决视频输入效果差的问题<三>---CVBS无色彩疑难调试手记
笔者在前两篇文章中讲述了基于AVD7181C来解决平台视频输入效果差的问题大概解决方案以及遇到的IIC兼容性问题的解决方法,在本文中将继续解释笔者在调试AVD7181C CVBS输入信号的情况下遇到的没有色彩的问题。笔者经过逐步的验证、推敲终于解决了这个问题,现将过程大概介绍一下。
通过前面的努力,CSI的数据通道已经打通,通过camera APK可以看到YPBPR\CVBS的输入信号了,YPBPR相对更方便一些,因为AVD7181C输出的是YUV4:2:2的信号,跟普通camera是一样的,所以很容易就出来彩色了,显示正常。笔者在CVBS上,发现只有黑白图像,没有任何彩色,怎么回事?在没有cvbs信号的时候AVD7181C输出的设置为蓝色,显示可是红色,为什么?
/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/sundesheng125原创,转载请注明出处,谢谢!
/*****************************************************************************************************/
首先,AVD7181C在CVBS输入信号的情况下,输出的656的信号,这个跟ypbpr是不大一样的,在yuv信号过来的uv的顺序上也是不大一样,因此android 层的显示系统需要相应调整。笔者修改了android4.0\device\softwinner\common\hardware\camera\CameraHardware.cpp的status_t CameraHardware::doStartPreview()接口实现。具体代码如下:
} else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { // bPixFmtNV12 = true; if (bPixFmtNV12) { LOGD("============== DISP_SEQ_UVUV"); mPreviewWindow.setLayerFormat(DISP_SEQ_UVUV); org_fmt = V4L2_PIX_FMT_NV12; // for HW encoder } else { LOGD("============== DISP_SEQ_VUVU"); LOGD("==============force to DISP_SEQ_UVUV"); mPreviewWindow.setLayerFormat(DISP_SEQ_UVUV); org_fmt = V4L2_PIX_FMT_NV12; // for HW encoder //mPreviewWindow.setLayerFormat(DISP_SEQ_VUVU); // org_fmt = V4L2_PIX_FMT_NV21; // for some apps } } else { LOGE("%s: Unsupported pixel format %s", __FUNCTION__, pix_fmt); mPreviewWindow.stopPreview(); return EINVAL; }
笔者经过这样修改了后,在无cvbs输入信号的情况下,已经可以顺利显示蓝色了,UV反了还好说,至少还是有彩色的。可是在接入cvbs信号后,怎么只有黑白信号,无彩色呢,这样很难让人理解。跟在其他OS平台上使用过AVD7181C的同事沟通后,觉得要么是显示系统的问题,要么是前端有问题。哎!是啊!整条通路上都可以怀疑。
作为软件工程师,都比较老实,首先开展自我批评,从自己能做的入手吧!把自己能够验证的地方都先去验证一下。这样到最后问题还是没眉目,找硬件同事也好沟通,笔者就这样干了一回。首先从接收YUV数据的buffer入手,应该接收数据的buffer是必须连续的,所以得到的都是物理地址。笔者把设置接收fifo数据的buffer地址先记录下来,在frame IRQ来的时候,也就是一帧数据采集好后会有一个中断过来。在中断处理函数中,把这个buffer里的UV数据给认为写一些自己定义的值。笔者增加的测试代码如下:
#if 1 int i; i = (bufindex)%2; if(NULL == gbuforg[i]) i = 0;//just empty operate else { //memset((void *)__phys_to_virt(gbuforg[i]), 0x39, gwh);//0x39 89 memset((void *)__phys_to_virt(gbuforg[i]+gwh), 0x20, gwh/8);//0x60 10 //memset((void *)__phys_to_virt(gbuforg[i]+gwh+gwh*1/8), 0x70, gwh/8);//0x60 use src data memset((void *)__phys_to_virt(gbuforg[i]+gwh+gwh*1/4), 0xf0, gwh/8);//0x60 10 memset((void *)__phys_to_virt(gbuforg[i]+gwh+gwh*3/8), 0x80, gwh/8);//0x60 10 } // for(i=0; i < 1000; i++) // printk("%x ", ((unsigned char *)__phys_to_virt(gbuforg[bufindex%2]+gwh))[1000+i]); // printk("\n"); #endif
代码中gwh为图像的宽X高。gbuforg[]是一个buffer数组,存放YUV数据的buffer 地址,当然要从物理地址转化成虚拟地址。
加了上面代码后,显示结果在理论上是把整个图像分成了4份,其中一份不去破坏原始数据,采用采集到的的数据。图像显示如下:
从这个显示结果上看,彩色是能显示出来的,因此从理论上讲显示系统应该是能够显示出彩色,由此判断可能是数据采集的问题。在IRQ处理中,笔者打印了一些采集到的数据,发现得到的都是同一个值0x80,也就是没有彩色,很显然是前端的问题了。
跟硬件工程师沟通后,有理有据,应该从硬件方面再下点功夫了,软件上已经没什么招了。硬件同事仔细对比、分析,给晶振上加了两个电容。果然,色彩出来了。跟硬件同事沟通,从他的角度可能是软件方面的问题,因为ypbpr是有色彩的,cvbs也就是一根线,有亮度,应该说通路是可以的。这样说也是有道理的,在工作配合中,软件工程师跟硬件同事要和谐相处,不要相互埋怨。硬件搞不动了,软件再倒腾倒腾;软件上没法倒腾了,硬件工程师再搞搞,多验证,多怀疑,所以要跟硬件同事搞好关系,问题还没定位出来解决之前,都不能肯定是谁的问题。有问题,找问题,找解决办法,千万不能相互指责、埋怨,即使最后确定不是自己的问题,也不要去埋怨同事。智者千虑必有一失,更何况我们还不能算是智者呢!哈哈!融洽相处,快乐工作!
下面贴一张正常出彩色的图片作为本文结尾。