基于TCP协议的网络摄像头的设计与实现

一、摘要

  基于TCP协议的网络摄像头的设计大部分和博文“基于UDP协议的网络摄像头的设计与实现”相同,本篇博文采用的TCP协议栈为NicheStack协议栈(同理,可使用LWIP协议栈实现),协议分析及上位机设计可参考博文“基于NicheStack协议栈的网络例程分析及客户端程序设计”。

 

二、实验平台

硬件平台:DIY_DE2

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

 

三、硬件部分

  该部分可参考博文“基于UDP协议的网络摄像头的设计与实现”。

 

四、底层软件设计及上位机程序

  该篇博文介绍的重点是底层软件(NIOS II端)和上位机程序的设计,底层和上位机的通信流程图如下图所示。

基于TCP协议的网络摄像头的设计与实现_第1张图片

图 1 底层和PC之间的通信流程图

  以上是系统的整体流程图,下面对一些关键的调试过程做个阐述。

1、图像传输的基本功能实现

  根据“基于UDP协议的网络摄像头的设计与实现”里面的调试经验,对系统进行调试。

  首先,在C#端,重写buffer,验证C#显示控件的正常。调试图片如图2所示。

基于TCP协议的网络摄像头的设计与实现_第2张图片

图2 C#控件显示调试图

  底层的发送数据包长度为1500,TCP数据包的包头长度为54,所以一包数据可以显示(1500-54)/2=723个像素,在控件显示2行83个像素。在控件的顶端细节部分可以看到。

  其次,在NIOS II写待发送的数据,发送到C#端,验证显示正常。这里采用TCP的拉模式。即C#端手动发送一次命令,底层发送上来一包数据,这样手动发送107次命令之后,C#控件可以显示出底层发送上来的一帧既定色彩的图像,如图3所示。

基于TCP协议的网络摄像头的设计与实现_第3张图片

图3 底层发送的既定色彩图像

  再次,在验证上述2个步骤的基础上,添加读取SRAM数据,即将获取的图像传输上来,并在C#中添加自动发送命令功能,则可以在C#端连续收到图像数据,如图4所示。

 

基于TCP协议的网络摄像头的设计与实现_第4张图片

图4 图像效果图

2、图像传输的速度测试及改进

  按照1中的步骤可以将图像显示出来,只是速度很低,约30s显示出一帧图像,网络传输速度约为10KB/s。之前传输慢的原因是,网络传输采用的是拉模式,即C#发一次命令,底层传输一包数据,这样一帧图像要107次命令,可见效率极低。另外C#端的程序也有造成速度慢的原因。

  改进1:C#端删除掉不必要的内容,接收及绘图部分单独开了一个线程。代码如下:

        private void TelnetThread()
        {
            while (socket.Connected)
            {
                try
                {
                    Receive();

                    //去掉不必要的输出,提高接收效率
                    //string str = Receive();
                    ////string str = "";
                    //str = str.Replace("\0", "");
                    //string delim = "\b";
                    //str = str.Trim(delim.ToCharArray());
                    //if (str.Length > 0)
                    //{
                    //    Console.WriteLine(str);

                    //    if (str == OUTPUTMARK + BACK)
                    //    {
                    //        //BackupSpace键处理
                    //        this.rtbConsole.ReadOnly = false;
                    //        int curpos = rtbConsole.SelectionStart;
                    //        this.rtbConsole.Select(curpos - 1, 1);
                    //        this.rtbConsole.SelectedText = "";
                    //        this.rtbConsole.ReadOnly = true;
                    //    }
                    //    else
                    //    {
                    //        Log(LogMsgType.Incoming, str);
                    //    }
                    //}
                    Thread.Sleep(100);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
            this.sbpStatus.Text = "状态:已断开";
        }

  这个改进大大提高了C#端的数据接收速度,也解除了不能用for循环连续发送数据包的问题。另外,C#端每收到一帧图像数据后,自动发送一次命令,使底层继续传输下一帧图像。

  改进2:底层部分,每发送一包数据,将发送指针指向发送数组的首地址,代码如下:

    for(j = 0; j < 107; j++)
    {
        //每发送完一包数据,使指针指向数组的首地址
        tx_wr_pos = tx_buf;
        
        for(k = 0; k < 1446; k++)
        {
            if((k%2) == 0)          
                tx_buf[k] = a[k/2 + j*723];
            else
                tx_buf[k] = b[k/2 + j*723];
            tx_wr_pos++;
        }
        //写满发送数组之后,将其发送出去
        send(conn->fd, tx_buf, tx_wr_pos - tx_buf, 0);  
            
        printf("NIOS WORKING\n"); 
            
    }

  改进3:底层部分,PIO中断,每次进入PIO中断后,先将中断标志位清零,可是在没有中断源的情况下,系统还是频频进入中断服务函数,不知何解?无奈之举是,进入中断服务函数之后,直接关闭中断使能并将中断标志位清零,等uC/OS II端将图像数据完全传输出去之后,再开启中断使能。另外,uC/OS II系统启动之前,不能开启中断使能,所以在初始化的时候应将PIO中断使能禁止,当收到客户端的命令时,再开启中断使能。该部分的操作流程见图1。

  通过上述3个方面的改进,传输速度大大提高了,约100KB/s,这样,显示一帧图像不到3s,显示效果也比较清晰。

 

五、总结

  根据上述几篇博文的阐述,分别完成了基于UDP和TCP传输协议的网络摄像头的设计与实现,博文重点分析了调试过程,即发现问题、解决问题的过程。博文论证了设计原理的正确性,同时,网络传输的速度也得到了测试,不过仍有许多改进和提高的地方,比如在传输的同时,写下一帧图像。

  另外一个重点是,博文阐述的图像压缩使用的是有损压缩的方法,最终的分辨率为320*240,rgb555形式。因此,下一步将重点研究图像编解码算法,最大限度的降低码率。使视频更加流畅。

 

 

 

 

 

你可能感兴趣的:(基于TCP协议的网络摄像头的设计与实现)