服务器之家:专注于服务器技术及软件下载分享
分类导航

Linux|Centos|Ubuntu|系统进程|Fedora|注册表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服务器之家 - 服务器系统 - Linux - 基于嵌入式linux 3G下的无压缩视频传输

基于嵌入式linux 3G下的无压缩视频传输

2019-12-15 17:04Linux教程网 Linux

本课题研究嵌入式系统在数据采集,3G无线通信方面的应用,由于知识水平的缺乏和实验条件的限制,本人并没有采取视频压缩算法

这是我本科的毕业设计。时隔5个月,再次回顾一下。 
本课题研究嵌入式系统在数据采集,3G无线通信方面的应用,开发集视频采集、地理信息采集、无线传输、客户机/服务器模式于一体的车载终端,实现终端采集视频与GPS信息的传输,支持服务器端显示视频与GPS信息的功能。 
这里我着重介绍本项目中的视频传输。由于知识水平的缺乏和实验条件的限制,本人并没有采取视频压缩算法。但针对数据量大而且3G网络相对有线网络带宽限制的情况采取了措施。 
硬件环境:友善之臂mini2440实验板(ARM9)。 
操作系统:linux(终端)、windows7(服务器)。 
网络环境:WCDMA(联通3G上网卡)。 
Mini2440实验板上有CMOS摄像头接口。同时厂家提供的linux源代码中有摄像头驱动,编译进内核即可使用摄像头。摄像头采用的是OV9650,30万像素,在linux下作为字符串设备驱动,可通过读取设备文件,获得图像信息。 
读取摄像头数据的代码如下: 

复制代码

代码如下:


int camdata_count; 
int cam_fd=open("/dev/camera",O_RDONLY); 
printf("Camera init!\n"); 
while(1){ 
camdata_count=read(cam_fd,cam_data,640*512*2); 
if(camdata_count==640*512*2){ 
/*视频数据处理与传输的代码*/ 

else{ 
printf("CAMERA Error!\n"); 


close(cam_fd); 


从摄像头中读取的数据格式是RGB565的,如图所示。即红色分量占6位,绿色分量占6位,蓝色分量占5位,总共是16位。 

 

 
为了作为bmp文件显示,需要将RGB565转换为RGB888(即24位真彩色)。再在文件开头加上bmp文件头,就成为一个完整的bmp文件了。用UDP协议传输这些图像数据。在服务器端,用.NET的库可以将接收到的BMP数据在图形界面的指定组件上显示。 
.NET显示图像的代码如下: 

复制代码

代码如下:


// st是一个已经建立的MemoryStream对象,bmp_data是bmp数据(byte数组),bmpSize是BMP图像大小(单位是B)。 
st.Write(bmp_data, 0, bmpSize); 
try 

picBox.Image = Image.FromStream(st);//picBox是已经建立的PictureBox对象,呈现在图形界面上 

catch (Exception e) 

richTextBox2.Text += "error\n";//如果BMP数据错误,则输出如下错误 

//st对象清空 
st.SetLength(0); 
st.Position = 0; 
st.Flush(); 


流程图如下: 
基于嵌入式linux 3G下的无压缩视频传输 
以上方案在有线网络传输的情况下能顺利运行,但是在3G网络下图像几乎不能显示。这是因为3G网络的带宽限制和UDP协议不可靠的缺点,数据在传输过程中会产生丢包现象,影响图片质量。对此需要改善程序代码,增加一些措施来避免丢包: 
(1) 将数据转化的工作交给服务器。 
BMP文件基本不经过任何压缩,每个像素点占用3个字节(R、G、B分量分别占用一个字节),而从CMOS摄像头读取的数据是RGB565的,即一个像素点只占用2个字节。如果说从CMOS读取的图像信息不经真彩化处理,直接传输给服务器,这样,需要传输的数据量减少了大约1/3。 
(2) 减少图像的尺寸。 
从CMOS摄像头读取的图像尺寸是640*512的。如果打包成BMP数据的话,总共大小是640*512*3+54(B),大约960KB。如果说不经真彩化处理,一帧数据总共大小是640*512*2(B),大约640KB。正常情况下,一秒可以采集6-7帧图像。联通WCDMA理论的上行速率是5.76Mbps,约为720KB/s,实际情况一定低于此值。在此情况下,一秒基本上只能传输一帧图像。所以减小图片尺寸很必要。可以考虑将图片的长宽都减小为原来的1/6,再在服务器端进行真彩化处理和打包,放大为320*256的尺寸显示。这样,一帧RGB565的图像的大小约为107*86*2(B),约为18KB。这样就足够传输相应的数据了。 
(3) 分包传输。 
UDP协议仅负责传输,不保证对方可靠接收,没有拥塞控制。因此,在WCDMA这种相对来说较差的网络环境下,会造成大量数据包的丢失。实验证明,当一次传输数据量达到18KB(一帧的数据大小)时,丢包率在95%以上,这会严重影响图片质量。当一次传输数据量在1-2KB时,丢包率可以降低到一定值,并保证一定的传输效率。 
(4) 每次数据传输之间给与一定延时。 
如果将一帧图片分为每个1-2KB数据包来传输,大约要传输15-18次。在每次传输之间,如果不引入一定量的延时,同样会造成很大量的数据包丢失。而延时的时间也是需要把握好的,一般延时500-1000ns比较合适。在传输每帧图片之间,也需要给与一定的延时,此时延时时间过大的话,会造成每秒传输帧数过少,图片流畅率下降,一般传输每帧图片之间给予50ms的延时。 
修改后的程序代码: 

复制代码

代码如下:


count=read(fd,cam_data,WIDTH*HEIGHT*2);//缩小图片大小,data_buf为原图像数据,cam_data为缩小后的图像数据,两者都为字符数组类型 
if(count==WIDTH*HEIGHT*2){ 
shrink(data_buf,cam_data,WIDTH,HEIGHT); 
for(i=0;i<30;i++){ 
//用UDP分包传输图像数据 
sendto(sockfd,data_buf+(i*32768),32768,0,(struct sockaddr *)&addr,len); 
usleep(2000);//给与一定的延时 

printf("One picture sended!\n");//一帧传输完毕 
usleep(100000); 

else{ 
printf("Error\n"); 


以上措施可以减少UDP传输视频数据的丢包率,但是,不管怎样,UDP传输数据的丢包现象普遍存在,或多或少会有一些。在3G网速较差的地区,丢包率甚至还是会达到50%。视频数据从摄像头读取后存放在一个无符号字符串数组里,本来是按顺序分割数据进行传输,由于读取的图像数据对应的像素点分布是从左到右、从上到下排布的,如果丢包,会造成接收到的图像的部分图像条无法及时更新,影响肉眼观察图像的质量。下面两张图对比了网络状况较好和较差情况下的显示效果。 
基于嵌入式linux 3G下的无压缩视频传输 
基于嵌入式linux 3G下的无压缩视频传输
上图是网络状况良好情况下的显示效果,可以看出,显示比较流畅,图像质量较好。下图是网络状况较差情况下的显示效果,可以看出,动态图像的某些图像条未及时更新,这是由于决定该图像条的显示的数据包在传输过程中丢包。 
为了降低丢包带来的这种损失,可以考虑将每帧图像分成多个位平面并按一定顺序传输,每个位平面代表所有像素的同一位组成的二值图像。如下图所示,是每个位平面传输的顺序(从0开始计数)。 
基于嵌入式linux 3G下的无压缩视频传输 
实验证明,每一帧分包传输后,靠前面的数据包丢包率比较小,而每个颜色分量的最高位对图片色彩质量的影响最大,位数越低,对图像色彩质量的影响越小。所以即便后面的位平面数据没有接收到,对图片色彩质量的影响也不会很大。将RGB每种颜色分量的位数按照从最高到最低的顺序进行传输,每种颜色分量对应的位平面穿插进行传输,于是就采用了上图所示的顺序。由于RGB565格式的数据每个像素共16位,一帧图片总共需要分16个位平面数据包传输。为了服务器能够正确进行图片数据的组装,在传输之前,将每个位平面数据包的最前面加上该包传输顺序的值,如下图所示。 
基于嵌入式linux 3G下的无压缩视频传输 
终端部分代码如下: 

复制代码

代码如下:


shrink(data_buf,cam_data,WIDTH,HEIGHT);//缩小图片大小,data_buf为原图像数据,cam_data为缩小后的图像数据,两者都为字符数组类型 
for(i=0;i<16;i++) 

bzero(cut_buf,1152); 
cut_buf[0]=(uchar)i;//将要传输的数据首个字节设为顺序号 
for(j=0;j<9202;j++) 

//每个像素按位分位平面数据包 
cut_buf[j/8+1]|=(uchar)(((uchar)(data_buf[j]>>bit_index(i))&0x01)<<(j%8)); 

sendto(sockfd,cut_buf,1152,0,(struct sockaddr *)&cam_addr,sockaddr_len);//发送数据 
usleep(1000);//传输每个数据包之间的延时 

printf("One picture sended!\n");//传输每帧图像之间的延时 
usleep(100000); 


在服务器端,用如下函数进行数据的重组,同时进行真彩化处理(C#.NET语言): 

复制代码

代码如下:


private void picDataCopy(byte[] bBuf,byte[] bData) //bBuf为接收到的数据,bData是重组后的数据存放的数组 

int index=bBuf[0]; 
for (int i = 0; i < 9202;i++ )//循环9202次,逐位进行数据的重组 

if(index<15){ 
bData[3*i + 2 - (index%3)] |= 
(byte)(((bBuf[i/8 + 1] >> (i%8)) & 0x01) << (7 - index/3)); 

else if(index==15){ 
bData[3*i+1]|= 
(byte)(((bBuf[i/8 + 1] >> (i%8)) & 0x01) << 2); 



基于嵌入式linux 3G下的无压缩视频传输
如上图所示,是在改变传输方案后,即采用按位平面传输的方法传输后的显示效果图,在网络良好的情况下,可以正常显示。在网络状况较差的情况下,图像颜色质量会下降,而且会不稳定地变化。但是部分图像条不显示的情况就不再出现。 
总结:此方案重在联系,实际工程中肯定不会采取此方案,还是有必要学习视频压缩算法及其在linux上的移植。 

延伸 · 阅读

精彩推荐
  • LinuxLinux系统下无法卸载挂载的目录怎么办?

    Linux系统下无法卸载挂载的目录怎么办?

    我们在日常运维中经常性会遇到需要进行磁盘的扩容、卸载、挂载等操作,但是有时候这个系统上跑的应用并没有停止或者有其他的运维同事在操作这个目...

    今日头条10302020-12-30
  • Linuxlinux top命令详解

    linux top命令详解

    这篇文章主要介绍了linux top命令详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    sparkdev5622022-03-01
  • Linux理解 Linux/Unix 登录脚本的技巧

    理解 Linux/Unix 登录脚本的技巧

    有一些常见的情况,例如从Debian的包管理程序到Iaas的管理中,很多任务需要设置环境变量才能正常运行。 有时,程序通常只需要在 登陆时运行一次,例如...

    未知1042023-05-12
  • Linux将 Linux 终端与 Nautilus 文件管理器结合起来

    将 Linux 终端与 Nautilus 文件管理器结合起来

    Nautilus 是 GNOME 桌面环境中的图形化文件浏览器。你可以使用它来访问和管理系统中的文件和文件夹。 尽管并非所有人都喜欢使用终端来管理文件和目录,...

    未知812023-08-08
  • Linuxlinux设置tomcat自启动的方法

    linux设置tomcat自启动的方法

    这篇文章主要介绍了linux设置tomcat自启动的方法,需要的朋友可以参考下...

    Linux教程网8512021-10-10
  • Linuxlinux驱动程序开发详细介绍

    linux驱动程序开发详细介绍

    前提,一般来说内核代码的错误可能会引起一个用户进程的死亡,或者整个系统的瘫痪,更严重的后果,可能导致磁盘损伤~因此建议最好有一台实验机进行...

    Linux教程网5392019-12-17
  • Linux在Linux系统中创建新的亚马逊AWS访问密钥的方法

    在Linux系统中创建新的亚马逊AWS访问密钥的方法

    如何在Linux系统中创建新的亚马逊AWS访问密钥?我在配置一个需要访问我的亚马逊AWS帐号的应用时被要求提供AWS访问密钥ID和秘密访问密钥,我怎样创建一个...

    Linux教程网6182019-10-30
  • Linuxssh 登录很慢该如何解决

    ssh 登录很慢该如何解决

    这篇文章主要介绍了ssh 登录很慢该如何解决的相关资料,这里提供了两种方法,DNS反向解析及关闭ssh的gssapi认证的解决办法,需要的朋友可以参考下...

    linuxeye9922021-12-16