在网络上进行摄像头视频通讯

gangzi169

gangzi169

2016-02-19 16:22

下面图老师小编要跟大家分享在网络上进行摄像头视频通讯,简单的过程中其实暗藏玄机,还是要细心学习,喜欢还请记得收藏哦!

     
     
    (转贴请注明原创作者)

      笔者序:也许在写这编文章时,有很多朋友正被老板要求做类似QQ一样的视频聊天软件,在这里,我把自己的一些经验和代码写出来与大家一起分享,高手不要笑我哈!看了这编文章后,你也可以自己做一个简单的网络视频通讯软件,如果自己家里上了网,就可以在公司和家人进行可视通讯了,多爽,不用给电话费了。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

        本例子使用的是简的老技术(VFW),开发起来相对简单,以下是Delphi代码,你需要先加入文件,没有这个文件你可以在网上找一下。作者从Delphi4就开始编程,其实Delphi可以做很多事情,只是太多Delphi程序员没有深专技术和思想,没有超越自己,Delphi只是一个开发工具,代码思想是的设计的精髓。
        下面让我们一起来讲解一下:

        在程序的开始,你需要用capCreateCaptureWindow来创建一个摄像头句柄,
        CapWnd := capCreateCaptureWindow('预览窗口',WS_VISIBLE or WS_CHILD,0,0,320,240,PrevWnd,1);
        在后面的参数:PrevWnd代表预览窗口的句柄,你可以指定一个Panel的句柄;320和240代表了窗口的长宽。
      
        if CapWnd = 0 then exit;
        capDriverConnect(CapWnd,0);   //连接摄像头设备

        capDlgVideoFormat(CapWnd);  //显示视频设置对话框,进行配置视频的大小、颜色位数等。
        capGetVideoFormat(CapWnd,@BmpInInfo,sizeof(BITMAPINFO));  //取得视频图像数据头,后面压缩时需要用到

        capPreviewRate(CapWnd, 33);  //设置预览视频的频率,33代表第秒30帧。
        capPreview(CapWnd, TRUE);

        capSetCallbackOnFrame(CapWnd,FrameCallBack); 
       
        InitCaptureParams;
       
        最后一句是设置视频压缩参数, 后面会进行说明。其中的capSetCallbackOnFrame(CapWnd,FrameCallBack)是设置每帧视频数据的回调函数,我们就可以将回调时的视频数据通过网络进行传输,这样的就实现了视频聊天的核心了。

      回调函数如下的格式:

      function  FrameCallBack(hWnd: HWND; lpVHdr: PVIDEOHDR): DWORD; stdcall;
      var
         bKeyFrame : BOOL ;
         Buf : PBYTE;
         VideoData : TVIDEO_DATA;
         OutActSize : dword;
         i : integer;
      begin
         OutActSize := BmpInInfo.bmiHeader.biSizeImage;
         Buf := ICSeqCompressFrame(@CapVar,0,lpVHdr.lpData,@bKeyFrame,@OutActSize);
        
         //在这里, OutActSize代表压缩后的视频数据大小
         //  form1.Label3.Caption := 'Compressed size:'+inttostr(OutActSize);

  
         //我用的是UDP方式, 因为UDP数据包大小限制, 所以我控制了数据大小, 超出的数据会发生丢帧
         if (OutActSize = sizeof(videodata.Buf) ) then
         begin
           zeromemory(@VideoData ,sizeof(TVIDEO_DATA));
          
           //记录是否为关键帧
           VideoData.bKeyFrame:=bKeyFrame;

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  
           copymemory(@VideoData.Buf, Buf, OutActSize);
          
           VideoData.SampleNum:=SampleNum; //我们可以记录下帧数, 可以做扩展用
           VideoData.BufSize:=OutActSize;  //记录数据大小, 传输时用
          
           //在这里, 你可以用你喜欢的网络方式传输视频数据,
          
           //cc1.SendBuffer(VideoData,sizeof(TVIDEO_DATA)-SendBufferSize+Outactsize);

           inc(SampleNum);
         end;     
         result := 0;
      end;

      其中,PVIDEOHDR类型可以从VFW中看到其定义:
      TVIDEOHDR               = record
          lpData              : PBYTE;  // 视频数据buffer
          dwBufferLength      : DWORD;  // 数据buffer长度
          dwBytesUsed         : DWORD;               
          dwTimeCaptured      : DWORD;  // 时间长度(毫秒)
          dwUser              : DWORD;               
          dwFlags             : DWORD;               
          dwReserved          : array[0..3] of DWORD;
      end;
      
      在回调函数中, 只用到了视频函数: ICSeqCompressFrame,可以看到此函数传入了CapVar参数,这个参数是由我们先前看到的InitCaptureParams函数产生,下面代码来实现:
      function InitCaptureParams : boolean;
      begin
        result := False;
   
        //初始化CapVar
        zeromemory(@CapVar,sizeof(TCOMPVARS));

        CapVar.cbSize:=sizeof(CapVar); //必须指定cbSize为TCOMPVARS结构大小
        CapVar.dwFlags:=ICMF_COMPVARS_VALID;

        CapVar.cbState:=0;
   
        //fccHandler代表压缩编码类型,我们使用的是DIVX的编码器
        CapVar.fccHandler:=mmioFOURCC('d','i','v','x');
        CapVar.fccType:=ICTYPE_VIDEO;

       
        //正式连接编码器
        CapVar.hic:=ICOpen(ICTYPE_VIDEO, CapVar.fccHandler, ICMODE_COMPRESS);
      
        if (CapVar.hic0) then
        begin

          OutFormatSize:=ICCompressGetFormatSize(CapVar.hic,@BmpInInfo.bmiHeader);
          getmem(BmpOutInfo,OutFormatSize);
          
          //我们可以通过初始化时得到的BmpInInfo来获取压缩传出图像头BmpOutInfo
          ICCompressGetFormat(CapVar.hic,@BmpInInfo.bmiHeader,@BmpOutInfo^.bmiHeader);
          OutBufferSize:=ICCompressGetSize(CapVar.hic,@BmpInInfo.bmiHeader,@BmpOutInfo^.bmiHeader);
          ICSeqCompressFrameStart(@CapVar, @BmpInInfo);
          result := True;
        end
        else
        begin
          ShowMsg('请先安装视频压缩编码器');
          Exit;
        end
      end;

      使用之后,如果要断开编码器连接,是这样调用的:
      if (CapVar.hic 0) then
      begin
         ICSeqCompressFrameEnd(@CapVar);
         ICCompressorFree(@CapVar);
         ICClose(CapVar.hic);
      end;

      于是,服务端的摄像头数据捕捉连接就完成了,那么对于客户端是乍样进行视频数据解压呢?这个问题当然还是通过IC函数解决,但你必须先把服务端上的BmpOutinfo和CapVar传输到客户端才行。
     
      接着,一起来看看客户端的图像显示过程:
      //先用取得的CapVar来连接视频编码器
      CapVar.hic := ICOpen(CapVar.fccType,CapVar.fccHandler,ICMODE_DECOMPRESS);
     
      //成功后,用服务器传来的BmpOutInfo当作客户端的BmpInInfo来取得解压输出的图像头BmpOutInfo

      OutFormatSize:=ICDecompressGetFormatSize(CapVar.hic,@BmpInInfo.bmiHeader);
      GetMem(BmpOutInfo,OutFormatSize);
      zeromemory(BmpOutInfo,OutFormatSize);

      ICDecompressGetFormat(CapVar.hic, @BmpInInfo.bmiHeader, @BmpOutInfo^.bmiHeader);

      OutBufferSize:=BmpOutInfo^.bmiHeader.biSizeImage;
      getmem(OutBuffer,OutBufferSize);

      zeromemory(OutBuffer,OutBufferSize);
      ICDecompressBegin(CapVar.hic,@BmpInInfo.bmiHeader, @BmpOutInfo^.bmiHeader);

  
      最后,当然是视频数据的解压过程

      if VIDEO_DATA.bKeyFrame then
         Result:=ICDecompress(CapVar.hic,0,@BmpInInfo,@VIDEO_DATA.Buf,
                     @BmpOutInfo.bmiHeader,OutBuffer)
      else
         Result:=ICDecompress(CapVar.hic,ICDECOMPRESS_NOTKEYFRAME,@BmpInInfo,@VIDEO_DATA.Buf,
                     @BmpOutInfo.bmiHeader,OutBuffer);
      if (Result=ICERR_OK) then
      begin
         SetDIBitsToDevice(Canvas.Handle,0,0,bmptmp.Width,bmptmp.Height,0,0,0,BmpOutInfo^.bmiHeader.biHeight ,
                    OutBuffer,BmpOutInfo^,DIB_RGB_COLORS);
      end;

      这样,传送过来的视频数据变直接画到了Canvas.Handle上了。
      还忘记了服务端关闭摄像头的方法,调用capDriverDisconnect(CapWnd) 就OK了。

      全文就Over了,jasonke还要说的就是,这个方法是用的微软的老函数,不过实现起来很简单,相信会点API的都能开发出来,还有一种方法当然是用DirectShow了哟,这需要你开发Filter,要搞明白微软的几个接口,你可以看看DShowNetwork例子。这个方法也有很多C++的兄弟在痛苦的实现,想一想DirectShow的功能真是强大哟,哈哈。

  欢迎大家光临《黑雨共享软件》,谢谢大家对中国共享软件的支持
  
  http://brsoft.0033.cn 
  http://brsoft.008.net

展开更多 50%)
分享

猜你喜欢

在网络上进行摄像头视频通讯

编程语言 网络编程
在网络上进行摄像头视频通讯

摄像头驱动在哪 摄像头驱动修复方法

摄像头 软件教程
摄像头驱动在哪 摄像头驱动修复方法

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

如何开启win8.1摄像头以及添加摄像头

windows系统 摄像头
如何开启win8.1摄像头以及添加摄像头

Koozoo应用将旧手机变成网络摄像头

手机软件 应用软件
Koozoo应用将旧手机变成网络摄像头

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

iPhone摄像头使用技巧

iphone iPhone 5s iPhone 6 iphone刷机
iPhone摄像头使用技巧

如何安装摄像头驱动

电脑入门
如何安装摄像头驱动

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

在windows系统 Regsvr32使用技巧

在windows系统 Regsvr32使用技巧

ASP入门基础教程-VBScript概述

ASP入门基础教程-VBScript概述
下拉加载更多内容 ↓