基于UDP协议的网络摄像头的关键问题解决及调试过程

一、摘要

  该篇博文主要对“基于UDP协议的网络摄像头的设计与实现”调试过程遇到的问题进行说明,并阐述其解决过程。

 

二、实验平台

硬件平台:DIY_DE2

软件平台:Quartus II 9.0 + Nios II 9.0 + Visual Studio 2008

 

三、实验内容

  以VGA显示作为参照,综合调试,使C#端的视频显示正常。C#端的控件显示分辨率为320*240。

1、初始图像

基于UDP协议的网络摄像头的关键问题解决及调试过程_第1张图片

图1 初始图片

       上图是初步搭建完成的网络摄像头显示效果,观察视频图像,其具有以下特点:

(1)有一半的色彩未完全显示;

(2)显示的部分呈斜体状,有锯齿;

(3)显示的部分分辨率降低为160*120,同(1);

(4)显示的图像的起始位置并非一帧图像的开始,即图像错位。

2、解决图像错位的问题

  解决过程大致如下:

(1)首先,保证Quartus II端不变的情况下,在NIOS II端不读取缓存在SRAM中的视频数据,而是直接对待传输的数组赋一个定值,则C#端应显示一个单色图像。NIOS II的代码如下,C#端的显示效果如图2所示。

NIOS II端测试代码:

 

    for(j = 0;j < 76800;j++)

    {

        //a[j] = IORD(SRAM_16BIT_512K_0_BASE,j);

        //b[j] = IORD(SRAM_16BIT_512K_0_BASE,j) >> 8;

        a[j] = 0xff;

        b[j] = 0x03;

     }

 

 

基于UDP协议的网络摄像头的关键问题解决及调试过程_第2张图片

图2 C#端显示单色图像1

       上述图像能够验证UDP传输正确和C#端的显示程序正确。

(2)其次,保证NIOS II正常传输的基础上,即不做刚才的改动,在Quartus II端压缩子程序press_moudle模块中,直接设定特定数据,观察C#端显示效果,效果如图3所示。

 

基于UDP协议的网络摄像头的关键问题解决及调试过程_第3张图片

图3 C#端显示单色图像2

       这张图像与图1很相似,即有一半的色彩未正确显示(因为是单色图片,其他的特征不容易看出来)。根据图2和图3的对比,可以得知:图像数据在读写SRAM时出了问题。到底是读SRAM还是写SRAM的问题?

       (3)再次,在NIOS II端,往SRAM里面写特定数据,之后再读取出来,最后通过网络传输给PC,PC端用C#显示,通过这个测试,可以发现NIOS II端读SRAM没有问题,因此,问题便可以确定为写SRAM。

       (4)图像错位的问题可以定位为:开始往SRAM写图像数据时,当前数据并非一帧图像的开始,即写图像数据的条件不正确。为了能够正确的锁存住帧开始信号,采用状态机功能,关键代码如下:

 

always@(posedge iclk or negedge rst_n)
begin
    if(!rst_n)
        test_out <= 0;
    else
    begin
        if((niosii_cmd) && (oVAL_VS == 2'b01))
        begin
            test_out <= ~test_out;
//            if(test_out)
//                rgb_zuhe <= rgb_zuhe + 1;
        end
//        else
//            test_out <= 0;
    end
end
always@(posedge iclk or negedge rst_n)
begin
    if(!rst_n)
    begin
//        oaddress <= 0;
        rd_en <= 0;
        rgb_zuhe <= 0;
    end
    else
    begin
        case(test_out)
        0:
        begin
            oaddress <= 0;
            rd_en <= 0;
            rgb_zuhe <= 0;
        end
        1:
        begin
            if(VGA_X_count[0] && VGA_Y_count[0] && oVAL_HS)
            begin
//                rgb_zuhe <= (rgb_zuhe + 1)%32;
                rgb_zuhe <= {1'b0,iR[9:5],iG[9:5],iB[9:5]};
                oaddress <= oaddress + 2;
                if(oaddress == 18'h257fe)
                begin
                    rd_en <= 1;
                    oaddress <= 0;
                end
            end
            else
                rd_en <= 0;
        end
        endcase
    end
end

  

  因为test_out的反转,这里其实是隔一帧采一帧的结果。

  采用状态机之后,图像错位的现象便得到解决,显示效果如图4所示。

 

基于UDP协议的网络摄像头的关键问题解决及调试过程_第4张图片

图4 解决图像错位的显示效果

3、解决显示部分分辨率降低的问题

  在Quartus II端的压缩子程序press_moudle中,设定图像数据为+1递增的数据,在网络抓包工具wireshark,收到的数据可以看出,数据是呈+2的形式递增的,因此可以断定,存储的时候出现了问题。

       刚开始,以为SRAM存储的时候是隔一个地址存储一个数据,后分析一下,实则不然。因为在NIOS II读取缓存在SRAM中的数据的时候,是挨个地址读取的,而读出来的数据确实呈+2的关系,说明:实际写入SRAM的时候还是挨个地址写的,只是写控制器端问题。

       后查阅相关资料,16位数据的存储器对应CPU时,地址线应左移一位,在系统的顶层文件中,并没有将地址线左移,因此,造成了分辨率又一次的降低了1/4,解决办法为,往SRAM存储数据时,地址线每次+2即可(在第2步代码中已有所体现)。显示效果如图5所示。

 

基于UDP协议的网络摄像头的关键问题解决及调试过程_第5张图片

图5 调试完成分辨率降低问题的效果

4、解决图像偏斜的问题

(1)开始一直以为C#端绘图部分的问题,经C#端写buffer数据显示,并认真分析显示效果后,确定绘图没有问题。下面是分析过程。采用单色递增进行分析。

C#端写buffer测试代码:

 

            for (int m = 0; m < num; m++)

            {

               if (m % 2 == 0)

                    buffer[m] = 0;

                else

                    buffer[m] = (byte)(((m - 1) * 2) % 128);

            }

 

  通过C#端调试,可以得知num=1468,即734个像素,按照320*240分辨率来算,一包数据可以绘制2行94个像素点,截取细节图(图5的左上部分),如图6所示。

 

 

图6 C#端测试细节图

       由图形可以看出,第一包数据刚好绘制了2行94个像素点,且3行的起始部分均正确对应,即均从纯黑色开始,说明造成图像倾斜的不是C#的问题。

(2)NIOS II测试,同样采用单色递增的方式进行验证,同样分析前2行94个像素点及以后的像素点,发现第95和96个像素点为非纯黑色,而第97个像素点才开始为纯黑色。这说明95和96像素点为其他的值,并非预期的像素值。

(3)仔细分析,发现最后2个像素点,即4个字节为一包数据的校验位。NIOS II端发送一包数据的最大值为1510-42-4=1464,前42个字节为包头,后4个字节为校验位。而C#端在绘制图像的时候是按照1468个字节来绘制的,因此,绘制的效果是,每次错位2个像素点。在C#端绘制图像的时候需要将num-4。改正后的显示效果如图7所示。

 

基于UDP协议的网络摄像头的关键问题解决及调试过程_第6张图片

图7 显示效果

5、最后一个问题

  C#端控制底层发送视频数据,即实现C#接收视频数据时是从一帧图像的开头,而不是中间的某一包数据,否则,仍会造成图像的错位。但实现的过程出现一些问题。C#端发送命令,NIOS II通过中断方式获取命令时,则会出现以下两种可能的问题:

(1)首先,NIOS II一直往PC发送数据,PC向NIOS II发送命令,NIOS II能够正确收到命令数据,但是在PC不发送命令的时候,NIOS II端仍会进入中断服务函数,接收到空命令或者是未知的多余命令,疑为PC会自动发送命令?这里的PC并非C#。

(2)NIOS II等待PC命令,PC发送命令,但是PC端的命令最多只能进入一次NIOS II的中断服务函数。

  这个问题的本质其实就是PC和DM9000A互相发送数据,其中,DM9000A是通过中断的方式接收PC发送下来的数据,但是DM9000A却不能正常的接收到PC发送到数据。测试好久,仍没有好的效果,难道是DM9000A中断处理机制的问题?

  鉴于上述两种均不理想的情况,系统采用另外一种解决办法:

  NIOS II向PC发送视频数据之前,先发送一包全是0的数据,一旦C#先解析出该包数据,便使能一个标志位,当该标志位使能后,开始绘制图像。这能够解决PC端图像错位的问题,但是不是最优的办法。因为第一包数据为0的缘故,则显示图片的顶部有些许其他的色彩。如图8所示。

 

基于UDP协议的网络摄像头的关键问题解决及调试过程_第7张图片

图8 最终的显示效果

 

四、实验总结

  最后通过wireshark测的传输速度为1Mbps,也就是说基于UDP协议的网络摄像头的帧率为1帧左右,分辨率为320*240。初步验证了系统的可行性。由于视频的帧率和分辨率均太小,下步将研究一下压缩算法及在TCP传输协议上的实现。

 

 

你可能感兴趣的:(基于UDP协议的网络摄像头的关键问题解决及调试过程)