网站导航免费论文 原创论文 论文搜索 原创论文 网学软件 学术大家 资料中心 会员中心 问题解答 原创论文 论文素材 设计下载 最新论文 下载排行 论文上传 在线投稿 联系我们
返回网学首页
网学联系
最新论文 推荐专题 热门论文 素材专题
当前位置: 网学 > 编程文档 > VC++ > 正文
利用VC++实现局域网实时视频传输(网络视频)
来源:Http://myeducs.cn 联系QQ:点击这里给我发消息 作者: 用户投稿 来源: 网络 发布时间: 12/10/15
下载{$ArticleTitle}原创论文样式
,客户端通过capSetCallbackOnFrame()注册回调函数,当采集卡采集到一幅图像后,系统就会自动调用回调函数,然后再回调函数中使用ICSeqCompressFrame()函数进行压缩。然后再通过Winsock将压缩后的数据发送到服务器端。服务器端接收完一帧以后,交给ICDecompress()解压,最后用SetDIBitsToDevice()将图像显示出来。

  1、视频帧的组建

  视频采集的数据是位图型式的视频帧,Divx编码器压缩以后形成以帧为格式的Mpeg4流。Divx解码器也是以帧的格式解压。所以提出以帧为单位发送视频数据流。为了在接收端能够方便地提取出一帧,提出如图2所示的格式组建帧。


帧开始标志

帧大小

帧编号

帧类型

帧数据
图2 视频帧格式

  完整的一帧由5个字段组成,各个字段的意义如下:帧开始标志,标志着一帧地开始,占用4个字节的空间。不妨设为0xffffffff。帧大小,表示整个帧的大小,包括5个字段的大小,占用4个字节的空间。帧编号,表示帧的顺序编号,占用4个字节的空间。帧类型,标志此帧是否是关键帧,占用1个字节的空间。帧数据,存放压缩后一帧的完整数据。

  2、视频帧的发送

  实时视频传输为了达到实时,要不断地将压缩好的数据发送到接受端。所以在发送端创建一个线程,专门用来发送数据。同时主线程仍然不停的采集数据并进行压缩。发送线程的工作流程如图3所示。

图3 发送线程工作流程

  不妨假设创建的线程名为sendThread,其核心代码实现如下:

while(1)
{
 isOK=true; //准备就绪
 SuspendThread(sendThread); //挂起线程
 isOK=false; //线程正在发送数据
 int length=frameLength; //待发数据长度
 if(length <50000) {//判断数据是否正常
  int n=0;
  int sendCount=0;
  while(length >0) {
   n=send(sock,(char*)imageBuf+sendCount,length,0); //发送数据,
   //imageBuf是指针,指向待发数据帧
   if(n==SOCKET_ERROR) //网络出现异常,则退出线程
    break;
   length-=n;
   sendCount+=n;
  }
 }
}

  线程中发送的数据帧是按照上一节中的方法组建好的数据帧。这种方法能够保证正在发送的当前帧能够完整地到达接收端。

  注意此线程中刚开始或者每当发送完一帧以后,线程就转到挂起状态,等待外界唤醒。这个任务由回调函数完成,在回调函数中,判定如果发送线程准备就绪(处于挂起状态),则进行图像压缩,然后唤醒线程发送压缩完的数据,否则直接跳出,等待下一次调用回调函数,这种策略称之为“停等”策略,在后面有详细介绍。

  3、视频帧的接收

  接收端最重要的是从接受的数据流中提取出完整的一帧。方法的思想是:首先从数据流中寻找帧开始标志,再从紧挨后面的数据中提取出帧的大小,然后再从接收缓冲区中读入该帧剩余的数据。再寻找下一帧的开始标志,如此往复。图4是接收端的工作流程。

  同样接收端创建一个线程专门用来执行数据接收。不妨假设线程名为recThread,核心代码实现如下:

while(temp!=SOCKET_ERROR)
{
 if(!isStart) {//帧数据是否开始,true表示开始
  if(endNum >3) //endNum纪录当前接收未处理的数据
   endNum=0;
  temp=recv(clisock,(char*)(recBuf+endNum),1000,0);//从缓冲区读取数据
  startPos=serchStr(temp+endNum); //查找帧开始标志
  if(startPos!=-1) {
   isStart=true;
   endNum=temp+endNum-startPos-4;
   memcpy(imageBuf,recBuf+startPos+4,endNum); //保存帧数据
  }
  else{
   memcpy(recBuf,recBuf+temp+endNum-3,3);//保存最后三个字节的数据
   endNum=3;
  }
 }
 else{
  if(endNum <4) {//判定紧跟开始标志的数据,如果小于4表示不能获得帧大小
   temp=recv(clisock,(char*)(recBuf),1000,0); //读入数据
   memcpy(imageBuf+endNum,recBuf,temp);//保存数据
   endNum+=temp;
   if(endNum <4)
    continue;
   frameSize= *((int*)imageBuf);//获得帧大小
   if(frameSize <500 || frameSize>50000) {//异常处理(帧大小非法)
    isStart = false; //丢弃数据重新查找帧开始标志
    endNum = 0;
    continue;
   }
   frameSize-=endNum+4;
  }
  else{
   while(frameSize >0&&temp!=SOCKET_ERROR) {//获得完整帧的剩余数据
    temp=recv(clisock,(char*)(imageBuf+endNum),frameSize,0);
    endNum+=temp;
    frameSize-=temp;
   }
   if(frameSize <=0) {//帧结束置位,解压
    isStart=false;
    endNum=0;
    deCompress();//判断数据的有效性,调用ICDecompress进行解压
   }
  }
 }
}

 

网学推荐

免费论文

原创论文

浏览:
设为首页 | 加入收藏 | 论文首页 | 论文专题 | 设计下载 | 网学软件 | 论文模板 | 论文资源 | 程序设计 | 关于网学 | 站内搜索 | 网学留言 | 友情链接 | 资料中心
版权所有 QQ:3710167 邮箱:3710167@qq.com 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
Copyright 2008-2015 myeducs.Cn www.myeducs.Cn All Rights Reserved
湘ICP备09003080号