您的位置:首页 > 理论基础 > 计算机网络

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

2014-03-18 21:36 489 查看


一、摘要

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

二、实验平台

硬件平台:DIY_DE2

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


三、硬件部分

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


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

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



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

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


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

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

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



图2 C#控件显示调试图

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

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



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

  再次,在验证上述2个步骤的基础上,添加读取SRAM数据,即将获取的图像传输上来,并在C#中添加自动发送命令功能,则可以在C#端连续收到图像数据,如图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形式。因此,下一步将重点研究图像编解码算法,最大限度的降低码率。使视频更加流畅。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: