急用~怎样将摄像头捕捉的流回显?(100分)

  • 主题发起人 主题发起人 yxgszm
  • 开始时间 开始时间
Y

yxgszm

Unregistered / Unconfirmed
GUEST, unregistred user!
基于vfw开发包
现已通过帧回调函数捕获每帧图像流,如果将该流发送到客户端,怎么回显?
(我曾测试在本地保存为BMP,但无法显示,估计是编码格式不对,但是小弟没发现vfw软件包中提供有回显函数,有劳有这方面开发经验的朋友指点一二,谢谢!)
 
就没一个人能回答吗?
 
难道是我的问题太天真?或者是问题太复杂?整个大富翁就没一个能回答的???
 
这个问题比较深哦。。
一般人无法回答,你找找高手
 
看看这个或许有用的:
=============================
AVICap窗口类支持实时的视频流捕获和单帧捕获,并提供对视频源的控制。虽然MCI也提供数字视频服务(比如它为显示.AVI文件的视频提供了AVI VIDEO命令集),为视频叠加提供了Overlay命令集,但这些命令主要是基于文件的操作,它们不能满足实时地从视频缓存中取数据的要求, 对于使用没有视频叠加能力的捕获卡的PC机来说, 用MCI提供的命令集是无法捕获视频流的。而AVICap窗口类在捕获视频方面具有一定的优势,它能直接访问视频缓冲区,不需要生成中间文件,实时性很强,效率很高。而且,它还可将数字视频捕获到一个文件中。
1.创建“捕获窗”
在进行视频捕获之前必需要先创建一个“捕获窗”,并以它为基础进行所有的捕获及设置操作。“捕获窗”用AVICap窗口类的“CapCreateCaptureWindow”函数来创建,其窗口风格一般为WS_CHILD和WS_VISIBLE。
捕获窗类似于标准控件(如按钮、列表框等),并具有下列功能:
●将视频流和音频流捕获到一个AVI文件中;
●动态地同视频和音频输入器件连接或断开;
●以Overlay或Preview模式对输入的视频流进行实时显示;
●在捕获时,可指定所用的文件名并能将捕获文件的内容拷贝到另一个文件;
●设置捕获速率;
●显示控制视频源、视频格式、视频压缩的对话框;
●创建、保存或载入调色板;
●将图像和相关的调色板拷贝到剪贴板;
●将捕获的单帧图像保存为DIB格式的文件。
2.关联捕获窗和驱动程序
单独定义的一个捕获窗是不能工作的,它必需与一个设备相关联,这样才能取得视频信号。用函数CapDriverConnect可使一个捕获窗与一个设备驱动程序相关联。
3.设置视频设备的属性
通过设置TcaptureParms结构变量的各个成员变量,可以控制设备的采样频率、中断采样按键、状态行为等等。设置好TCaptureParms结构变量后,可以用函数CapCaptureSetSetup使设置生效。之后还可以用CapPreviewScale、CapPreviewRate来设置预览的比例与速度,也可以直接使用设备的默认值。
4.打开预览
利用函数CapOverlay选择是否采用叠加模式预览,这样占用系统资源小,并且视频显示速度快。然后用CapPreview启动预览功能,这时就可以在屏幕上看到来自摄像机的图像了。
通过以上4步就可以建立一个基本的视频捕获程序。但如果想自已处理从设备捕获到的视频数据,则要使用捕获窗回调函数来处理,比如一帧一帧地获得视频数据或以流的方式获得视频数据等等。
实例编程
下面以一个一帧一帧地从视频设备上捕获视频数据的Delphi程序为例,来说明每个函数的作用以及开发过程。
该程序的功能是可以在屏幕上显视捕获到的视频,并可以获得每一帧的图像数据。
新建一个工程,并将AVICAP32.PAS包含到USES中。
在Form1上放置一个TPanel控件,设Name为“gCapVideoArea”,该控件用于显示视频。再放置两个TButton控件,一个Name为“Openvideo”,另一个Name为“Closevideo”。
定义全局变量:
var
//定义捕获窗句柄
ghCapWnd: THandle;

//可以得到视频数据指针的结构变量,用于回调函数中
VideoStr: LPVIDEOHDR;

//用于设置设备属性的结构变量
CapParms: TCaptureParms;

在Name为“Openvideo”的TButton 的Click事件中写入以下代码:
procedure TForm1.OpenvideoClick(Sender: TObject);

begin

//使用Tpanel控件来创建捕获窗口
ghCapWnd := CapCreateCaptureWindow
( PChar(‘KruwoSoft'), //捕获窗口的名字
WS_CHILD or WS_VISIBLE,//窗口样式
0, //X坐标
0, //Y坐标
gCapVideoArea.Width, //窗口宽
gCapVideoArea.Height, //窗口高
gCapVideoArea.Handle, //窗口句柄
0);
//一般为0
{为了能够捕获视频帧,要启动一个捕获帧回调函数VideoStreamCallBack。捕获一个视频流或当前设备状态时分别使用以下函数:
//捕获一个视频流
CapSetCallbackOnVideoStream;

//得到一个设备错误
CapSetCallbackOnError;

//得到一个设备状态
CapSetCallbackOnStatus
}
//定义一个帧捕获回调函数
CapSetCallbackOnFrame (ghCapWnd,LongInt(@VideoStreamCallBack));

//将一个捕获窗口与一个设备驱程相关联,第二个参数是个序号,当系统中装有多个显视驱动程序时,其值分别依次为0到总个数
CapDriverConnect(ghCapWnd, 0);

//设置设备属性的结构变量
CapParms.dwRequestMicroSecPerFrame:=40000;

CapParms.fLimitEnabled := FALSE;

CapParms.fCaptureAudio := FALSE;
// NO Audio
CapParms.fMCIControl := FALSE;

CapParms.fYield := TRUE;

CapParms.vKeyAbort := VK_ESCAPE;

CapParms.fAbortLeftMouse := FALSE;

CapParms.fAbortRightMouse := FALSE;

//使设置生效
CapCaptureSetSetup(ghCapWnd,LongInt(@CapParms),sizeof(TCAPTUREPARMS));

//设置预览时的比例
CapPreviewScale(ghCapWnd, 1);

//设置预览时的帧频率
CapPreviewRate(ghCapWnd,66);

//如果要捕获视频流,则要使用函数指定不生成文件。否则将会自动生成AVI文件
CapCaptureSequenceNoFile(ghCapWnd);

//指定是否使用叠加模式,使用为1,否则为0
CapOverlay(ghCapWnd, 1);

//打开预览
CapPreview(ghCapWnd, 1);

end;


在Name为“Closevideo”的TButton 的Click事件中写入以下代码:
procedure TForm1.ClosevideoClick(Sender: TObject);

begin

//停止捕获
capCaptureAbort(ghCapWnd);

//将捕获窗同驱动器断开
capDriverDisconnect(ghCapWnd);

end;


定义捕获帧回调函数:
function FrameCallBack(hWnd:HWND;
lpVHdr:LongInt) :LongInt;
stdcall;

var
DataPoint:^byte;

DibLen,RectWidth,RectHeight:integer;

begin

//转换从回调函数中得到的指针
VideoStr:=LPVIDEOHDR(lpVHdr);

//得到返回的数据大小
DibLen:=VideoStr^.dwBufferLength;

GetMem(DataPoint,64000);

//将帧数据COPY到一个内存中,注意DATAPOINT要先分配空间
CopyMemory(DataPoint,VideoStr^.lpData,Diblen);

//一些其他处理
……
end;


灵活地使用AVICap窗口类的回调函数可以满足各种不同的需求,但要注意从视频卡中捕获的视频数据的格式和图像的长宽要参考视频卡的参数。而且有些视频卡通过设置可支持多种的格式和图像长宽,所以在还原图像时要注意参考所用的视频卡的参数。
 
谢谢!不过这资料很早就看过了,对于视频还原的问题,也是一笔带过,“所以在还原图像时要注意参考所用的视频卡的参数”,怎么实现呢?
 
DSPACK231中的ASF Capture例子啊
 
hehe,看到同路人了
你的问题我已经解决了
不过我还有很多的问题没有解决[:(]
>>现已通过帧回调函数捕获每帧图像流,如果将该流发送到客户端,怎么回显?
除了传回视频数据外还需要传回该捕获图像的头信息(TBitmapInfoHeader)。
如果回显图像的话,还要传回图像的数据(TBitmapInfo)。
 
等了好久才等到知音啊~~~
TO helloalber:
TBitmapInfoHeader、和TBitmapInfo我都了解过,但知道得很少,你的意思是说
我现在采集到的只是视频数据块的头信息(TBitmapInfoHeader)?那TBitmapInfo怎么得到呢?得到后怎样将其“组合”回显呢?望不吝赐教!我已经把你的mail记下来了,我的mail是jiao@ewai.net,QQ:19442096 大家多多探讨,我最近在做视频会议,这个问题困绕我很久了,昨天想到了一个不是办法的办法,用BitBlt截屏压缩传输,这只能治标不能治本,我很希望得到你的帮助,获得治本妙法!谢谢!
 
ALL TO yxgszm:
第一,你得到的TVIDEOHDR结构就是视频数据,但要显示视频只需要视频数据块的头信息(TBitmapInfoHeader),不需要获得了TBitmapInfo的数据。
第二,如果你要把视频数据的每一帧专成bitmap(Frame -> Bitmap),那么还要有每一帧的TBitmapInfo的数据。
以上是我这段时间研究所得到的结论,我也不知道是怎么回事,但根据我写的实验代码推测
应该是这样。

我用的是控件做的视频捕捉,所以没有遇到太多这样的问题。
这是我看那个控件的源码用的API函数(希望对你有用)。
capGetVideoFormat(fhcapWnd, @result,sizeof(TBitmapInfo));
capSetVideoFormat(fhcapWnd,p,size);//获得了TBitmapInfo的数据(fhcapWnd是捕捉窗口句柄)你在到msdn上查查这个函数。
用同样的函数还可以得到TBitmapInfoHeader数据。
DrawDibDraw(hdd,canvas.handle,0,0,fbiwidth,fbiheight,@fBitmapInfoHeader, frame,0,0,fBitmapInfoHeader.biWidth,fbitmapInfoHeader.biheight,flags);//这是那个用来显示视频的函数。
DrawDibDraw(hdd,canvas.handle,0,0,BitmapInfo.BmiHeader.biwidth,BitmapInfo.bmiheader.biheight,@BitmapInfo.bmiHeader, frameBuffer,0,0,bitmapInfo.bmiHeader.biWidth,bitmapInfo.bmiHeader.biheight,0);
//Frame -> bitmap的方法。

我有件事不明白,你在视频捕捉这块的问题都没有完全解决,是如何把后面的工作完成的?
如果你真的完成了,希望能够不吝赐教。
1。能否大致说一下你的视频会议系统的程序工作的流程?
2。你用的是什么压缩方法和传输方式的。
3。你是如何设置缓冲队列或者说缓冲区的。

呵呵,最后声明一下,我是刚刚开始做这块内容(有一个月了吧)而且是个菜鸟(我至今没写过任何的delphi程序,我用的是cb),但我每天都研究到深夜,估计能在这个月把局域网的调试完成。预祝你也尽快成功!

 
自己搞定了!
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部