小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Delphi中控制、使用攝像頭

 昵稱(chēng)22130903 2015-03-01
筆 者序:也許在寫(xiě)這編文章時(shí),有很多朋友正被老板要求做類(lèi)似QQ一樣的***軟件,在這里,我把自己的一些經(jīng)驗(yàn)和代碼寫(xiě)出來(lái)與大家一起分享,高手不要笑我 哈!看了這編文章后,你也可以自己做一個(gè)簡(jiǎn)單的網(wǎng)絡(luò)視頻通訊軟件,如果自己家里上了網(wǎng),就可以在公司和家人進(jìn)行可視通訊了,多爽,不用給電話(huà)費(fèi)了。 

本 例子使用的是簡(jiǎn)的老技術(shù)(VFW),開(kāi)發(fā)起來(lái)相對(duì)簡(jiǎn)單,以下是Delphi代碼,你需要先加入VFW.PAS文件,沒(méi)有這個(gè)文件你可以在網(wǎng)上找一下。作者 從Delphi4就開(kāi)始編程,其實(shí)Delphi可以做很多事情,只是太多Delphi程序員沒(méi)有深專(zhuān)技術(shù)和思想,沒(méi)有超越自己,Delphi只是一個(gè)開(kāi)發(fā) 工具,代碼思想是的設(shè)計(jì)的精髓。 
下面讓我們一起來(lái)講解一下: 

在程序的開(kāi)始,你需要用capCreateCaptureWindow來(lái)創(chuàng)建一個(gè)攝像頭句柄, 
CapWnd := capCreateCaptureWindow('預(yù)覽窗口',WS_VISIBLE or WS_CHILD,0,0,320,240,PrevWnd,1); 
在后面的參數(shù):PrevWnd代表預(yù)覽窗口的句柄,你可以指定一個(gè)Panel的句柄;320和240代表了窗口的長(zhǎng)寬。 

if CapWnd = 0 then exit; 
capDriverConnect(CapWnd,0); //連接攝像頭設(shè)備 

capDlgVideoFormat(CapWnd); //顯示視頻設(shè)置對(duì)話(huà)框,進(jìn)行配置視頻的大小、顏色位數(shù)等。 
capGetVideoFormat(CapWnd,@BmpInInfo,sizeof(BITMAPINFO)); //取得視頻圖像數(shù)據(jù)頭,后面壓縮時(shí)需要用到 

capPreviewRate(CapWnd, 33); //設(shè)置預(yù)覽視頻的頻率,33代表第秒30幀。 
capPreview(CapWnd, TRUE); 

capSetCallbackOnFrame(CapWnd,FrameCallBack); 

InitCaptureParams; 

最后一句是設(shè)置視頻壓縮參數(shù), 后面會(huì)進(jìn)行說(shuō)明。其中的capSetCallbackOnFrame(CapWnd,FrameCallBack)是設(shè)置每幀視頻數(shù)據(jù)的回調(diào)函數(shù),我們就可以將回調(diào)時(shí)的視頻數(shù)據(jù)通過(guò)網(wǎng)絡(luò)進(jìn)行傳輸,這樣的就實(shí)現(xiàn)了***的核心了。 

回調(diào)函數(shù)如下的格式: 

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代表壓縮后的視頻數(shù)據(jù)大小 
// form1.Label3.Caption := 'Compressed size:'+inttostr(OutActSize); 


//我用的是UDP方式, 因?yàn)閁DP數(shù)據(jù)包大小限制, 所以我控制了數(shù)據(jù)大小, 超出的數(shù)據(jù)會(huì)發(fā)生丟幀 
if (OutActSize <= sizeof(videodata.Buf) ) then 
begin 
zeromemory(@VideoData ,sizeof(TVIDEO_DATA)); 

//記錄是否為關(guān)鍵幀 
VideoData.bKeyFrame:=bKeyFrame; 


copymemory(@VideoData.Buf, Buf, OutActSize); 

VideoData.SampleNum:=SampleNum; //我們可以記錄下幀數(shù), 可以做擴(kuò)展用 
VideoData.BufSize:=OutActSize; //記錄數(shù)據(jù)大小, 傳輸時(shí)用 

//在這里, 你可以用你喜歡的網(wǎng)絡(luò)方式傳輸視頻數(shù)據(jù), 

//cc1.SendBuffer(VideoData,sizeof(TVIDEO_DATA)-SendBufferSize+Outactsize); 

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

其中,PVIDEOHDR類(lèi)型可以從VFW中看到其定義: 
TVIDEOHDR = record 
lpData : PBYTE; // 視頻數(shù)據(jù)buffer 
dwBufferLength : DWORD; // 數(shù)據(jù)buffer長(zhǎng)度 
dwBytesUsed : DWORD; 
dwTimeCaptured : DWORD; // 時(shí)間長(zhǎng)度(毫秒) 
dwUser : DWORD; 
dwFlags : DWORD; 
dwReserved : array[0..3] of DWORD; 
end; 

在回調(diào)函數(shù)中, 只用到了視頻函數(shù): ICSeqCompressFrame,可以看到此函數(shù)傳入了CapVar參數(shù),這個(gè)參數(shù)是由我們先前看到的InitCaptureParams函數(shù)產(chǎn)生,下面代碼來(lái)實(shí)現(xiàn): 
function InitCaptureParams : boolean; 
begin 
result := False; 

//初始化CapVar 
zeromemory(@CapVar,sizeof(TCOMPVARS)); 

CapVar.cbSize:=sizeof(CapVar); //必須指定cbSize為T(mén)COMPVARS結(jié)構(gòu)大小 
CapVar.dwFlags:=ICMF_COMPVARS_VALID; 

CapVar.cbState:=0; 

//fccHandler代表壓縮編碼類(lèi)型,我們使用的是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); 

//我們可以通過(guò)初始化時(shí)得到的BmpInInfo來(lái)獲取壓縮傳出圖像頭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('請(qǐng)先安裝視頻壓縮編碼器'); 
Exit; 
end 
end; 

使用之后,如果要斷開(kāi)編碼器連接,是這樣調(diào)用的: 
if (CapVar.hic > 0) then 
begin 
ICSeqCompressFrameEnd(@CapVar); 
ICCompressorFree(@CapVar); 
ICClose(CapVar.hic); 
end; 

于是,服務(wù)端的攝像頭數(shù)據(jù)捕捉連接就完成了,那么對(duì)于客戶(hù)端是乍樣進(jìn)行視頻數(shù)據(jù)解壓呢?這個(gè)問(wèn)題當(dāng)然還是通過(guò)IC函數(shù)解決,但你必須先把服務(wù)端上的BmpOutinfo和CapVar傳輸?shù)娇蛻?hù)端才行。 

接著,一起來(lái)看看客戶(hù)端的圖像顯示過(guò)程: 
//先用取得的CapVar來(lái)連接視頻編碼器 
CapVar.hic := ICOpen(CapVar.fccType,CapVar.fccHandler,ICMODE_DECOMPRESS); 

//成功后,用服務(wù)器傳來(lái)的BmpOutInfo當(dāng)作客戶(hù)端的BmpInInfo來(lái)取得解壓輸出的圖像頭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); 


最后,當(dāng)然是視頻數(shù)據(jù)的解壓過(guò)程 

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; 

這樣,傳送過(guò)來(lái)的視頻數(shù)據(jù)變直接畫(huà)到了Canvas.Handle上了。 
還忘記了服務(wù)端關(guān)閉攝像頭的方法,調(diào)用capDriverDisconnect(CapWnd) 就OK了。 

全 文就Over了,jasonke還要說(shuō)的就是,這個(gè)方法是用的微軟的老函數(shù),不過(guò)實(shí)現(xiàn)起來(lái)很簡(jiǎn)單,相信會(huì)點(diǎn)API的都能開(kāi)發(fā)出來(lái),還有一種方法當(dāng)然是用 DirectShow了喲,這需要你開(kāi)發(fā)Filter,要搞明白微軟的幾個(gè)接口,你可以看看DShowNetwork例子。 
網(wǎng)中戲 發(fā)表于 2006-7-27 12:25:42
廖長(zhǎng)科 在關(guān)鍵的回調(diào)函數(shù)一筆帶過(guò)、不過(guò)可以參考

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代表壓縮后的視頻數(shù)據(jù)大小 
// form1.Label3.Caption := 'Compressed size:'+inttostr(OutActSize); 


//我用的是UDP方式, 因?yàn)閁DP數(shù)據(jù)包大小限制, 所以我控制了數(shù)據(jù)大小, 超出的數(shù)據(jù)會(huì)發(fā)生丟幀 
if (OutActSize <= sizeof(videodata.Buf) ) then 
begin 
zeromemory(@VideoData ,sizeof(TVIDEO_DATA)); 

//記錄是否為關(guān)鍵幀 
VideoData.bKeyFrame:=bKeyFrame; 


copymemory(@VideoData.Buf, Buf, OutActSize); 

VideoData.SampleNum:=SampleNum; //我們可以記錄下幀數(shù), 可以做擴(kuò)展用 
VideoData.BufSize:=OutActSize; //記錄數(shù)據(jù)大小, 傳輸時(shí)用 

//在這里, 你可以用你喜歡的網(wǎng)絡(luò)方式傳輸視頻數(shù)據(jù), 

//cc1.SendBuffer(VideoData,sizeof(TVIDEO_DATA)-SendBufferSize+Outactsize); 

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

原文來(lái)自: http://www.cnblogs.com/python001/ 【100腳本網(wǎng)


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多