转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
在网络上进行摄像头视频通讯         ★★★★

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

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1551 更新时间:2009/4/23 18:28:20

    
    文章分类:网络、视频,聊天
    文章作者:廖长科
    (转贴请注明原创作者)

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

      本例子使用的是简的老技术(VFW),开发起来相对简单,以下是Delphi代码,你需要先加入VFW.PAS文件,没有这个文件你可以在网上找一下。作者从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;


         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.hic>0) 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);

  &nbs

[1] [2]  下一页


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台