1.引言
視訊的采集和壓縮是進行視訊傳輸、監控等視訊應用開發時必須采取的步驟。
關于視訊采集,本文探讨了一種基于Windows平台的簡單而實用的方法,利用微軟提供的VFW(Video For Windows)軟體包來實作,隻需要有一般的USB攝像頭,就可以友善地對視訊進行采集和儲存。
視訊壓縮方面,本文探讨了如何利用現階段壓縮率最大、傳輸可靠性最高的一種編碼标準—H.264标準的開源編碼器(T264)來實作對采集到的視訊檔案進行壓縮的方法,利用VFW 所采集到的視訊格式是沒有進行任何壓縮的AVI 格式,首先對AVI 格式進行轉換,再利用T264源碼對轉換後的視訊流檔案進行壓縮編碼,這樣就極大地壓縮了視訊檔案,友善視訊的傳輸。
2.視訊資訊的采集
由于利用VFW軟體包能夠友善地實作視訊、音頻資料流到AVI檔案的存儲,在Visual C++中将VFW軟體包的函數封裝成為AVICAP視窗類函數,利用AVICAP視窗類函數,程式員能夠通過發送消息或設定屬性來捕獲、播放和編輯視訊剪輯,能靈活地實作從模拟視訊源采集數字視訊信号,并将捕捉的視訊流存儲到磁盤或者直接對視訊緩存進行處理。
本文所述的方法是在Viusal C++ 6.0 軟體平台上實作的,而軟體實作的具體步驟如下:
1)在采集視訊前必須先建立一個視訊采集的視窗,以及添加一些具體的操作按鈕,視窗利用函數capCreateCaptureWindow 來建立,如果視窗建立成功,傳回視窗的句柄(程式中hwndV),如果建立不成功,則傳回NULL 值。具體的建立程式及注釋如下:
hwndV=capCreateCaptureWindow(
(LPSTR) "My Capture Window", //捕捉視窗名稱
WS_CHILD | WS_VISIBLE, //視窗風格樣式
150, 150, 300, 280, //視窗位置和大小
(HWND) hwndMain, //父視窗句柄
(int) 1); //視窗辨別
2)采集開始前,要将采集視窗與視訊裝置相關聯,VFW接口采用capDriverConnect (hWndCap,,nIndex)這個函數,式中:hWndCap所建立的視訊捕捉視窗的句柄;nIndex為查詢得到的視訊卡驅動程式的索引号。接下來,擷取視訊采集裝置的能力及狀态資訊,VFW中采用函數capDriverGetCaps(hwnd,psCaps,wsize)來得到采集裝置的能力,而采用capGetStatus (hwnd,s,size)函數來得到采集裝置的狀态資訊。
3)啟動顯示模式并設定其模式參數,AVICAP 視窗類采用兩個函數來實作,具體程式和注釋如下:
capPreviewRate( hwndVideo, 66); //設定預覽播放速率
capreview( hwndVideo, TRUE); //啟動預覽模式
4)采集視訊流并儲存,并終止視訊采集并斷開與采集裝置的連接配接,在程式的開頭定義一個結構體OPENFN,用于初始化一個對話框,而這個對話框是用來儲存視訊的對話框。
具體程式如下:
if (!isRecordFileOpen)
{
OPENFN ofname; //打開檔案結構體
ZeroMemory(&ofname, sizeof(OPENFN)); //初始化結構體
ofname.lStructSize = sizeof(OPENFN); //結構體的大小
ofname.hwndOwner = hwndMain; //主視窗句柄
ofname.lpstrFile = recordFile; //儲存的檔案指針
ofname.nMaxFile = sizeof(recordFile); //儲存檔案的大小
ofname.lpstrFilter = "Video\0*.avi"; //儲存檔案的字尾
ofname.nFilterIndex = 1; //檔案索引号
ofname.lpstrFileTitle = NULL; //檔案名指針
ofname.nMaxFileTitle = 0;
ofname.lpstrInitialDir = NULL;
ofname.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
if(GetSaveFileName(&ofn) == TRUE) //顯示儲存檔案的對話框
{
strcpy(recordFile, ofn.lpstrFile);
strcat(recordFile, ".avi");
isRecordFileOpen = true;
}
}
設定好儲存檔案以後,需用函數CreateThread來建立一個錄像的線程在其中采集視訊流,并利用函數capDriverDisconnect 來終止視訊采集并斷開與采集裝置的連接配接,錄像線程的具體代碼如下:
DWORD id; //建立一個錄像線程
SECURITY_ATTRIBUTES ma;
ma.nLength = sizeof(SECURITY_ATTRIBUTES);
ma.lpSecurityDescriptor = NULL;
ma.bInheritHandle = TRUE;
hVideoThread = (&ma, (ULONG)0,
videoThreadProc, (LPVOID)(ULONG)0, (ULONG)0, &id);
3.視訊格式的轉換
本文所采用的是基于H.264編碼标準的視訊壓縮方法,所利用的源碼是由中國視訊編碼自由組織聯合開發的t264編解碼器,在使用本源碼前,編碼器要求進行壓縮的檔案格式應為YUV 格式視訊檔案,而VFW采集到的視訊檔案是最原始的AVI 格式,因而要進行格式的轉換 。
從AVI格式到YUV 格式的轉換,并沒有直接的公式,而AVI視訊檔案流的每一幀對應一個BMP(RGB)檔案,則可以利用公式轉換成YUV 檔案,轉換的公式如下:
Y = 0.299R + 0.587G + 0.114B
Cb = 0.564(B - Y )
Cr = 0.713(R -Y )
其中,Cb 對應U,Cr 對應V,分别表示構成彩色的兩個分量,而在程式中,則通過以下的程式來實作(按4:2:0 采樣格式):
void RGB2YUV ( uint8 R, uint8 G, uint8 B, uint8 *y, uint8 *u, uint8 *v )
{
*y = Clip ( ( ( 66 * int(R) + 129 * int(G) + 25 * int(B) + 128) >> 8) + 16 );
*u = Clip ( ( ( -38 * int(R) - 74 * int(G) + 112 * int(B) + 128) >> 8) + 128 );
*v = Clip ( ( ( 112 * int(R) - 94 * int(G) - 18 * int(B) + 128) >> 8) + 128 );
}
4.利用編碼器進行壓縮編碼
由中國視訊編碼自由組織聯合開發的編碼器在基于VisualC++平台上建立了一個console程式,而前述的視訊采集程式因為有視窗、按鈕等視圖視窗,故是一個windows程式,在Visual C++平台中,要将console 程式和windows 程式很好地結合在一起使用,是個很複雜的過程,是以,可以在前面視訊采集程式裡面運用一個C++函數ShellExecute 來調用編碼器函數。
具體實作的步驟如下:
1)首先針對采集後經格式轉換生成的YUV檔案,得到它的幀數目,在配置檔案enconfig.txt修改編碼幀的數目,例如如果幀數目為100,将enconfig.txt 檔案中的第6、7、8 行:
300 # total frame number
300 # i intervals
300 # idr intervals
改為 :
100 # total frame number
100 # i intervals
100 # idr intervals
幀數目修改以後,檔案生成的路徑也應該改為最終exe 檔案生成的路徑,在enconfig.txt的最後三行進行修改。
1)編譯編碼器,是采用的CONSOLE 程式,一般是在指令行中來執行exe 程式,而本文中的方法是利用入口函數main(int argc, char* argv[])的特征,其中,argc 表示參數的個數,而argv[]數組用于儲存參數的指針,在程式中就對參數進行指派,省去了進入指令行進行執行的繁瑣過程,進而生成一個可以直接拿來運用的exe 程式。具體指派語句如下:
argv[0]="T264.exe";
argv[1]="-e";
argv[2]="enconfig.txt";
2)設定t264.exe 檔案路徑,上述的過程中已經生成一個可執行的t264.exe 檔案,如果将YUV檔案放在與之相同的目錄下,在調試運作這個程式的時候就可以生成264碼流檔案,達到編碼的目的。但本文是需要将采集、壓縮編碼在同一個程式中完成,因而把生成的t264.exe檔案複制到采集程式的調試目錄下面。
3)上述的工作都做好以後,可以在采集程式裡面調用編碼器程式了,這時用一個函數來實作,具體代碼是:
ShellExecute(NULL,"open","t264.exe",
"T264.exe –e enconfig.txt",NULL,SW_SHOWNORMAL);
其中,SW_SHOWNORMAL 指的是一種程式運作風格,此時代表正常運作,在調用時可以看到程式運作的全部過程(DOS指令視窗顯示),如果需要程式透明執行,不可見,則可以用SW_HIDE 來代替它。
至此,整個視訊采集、格式轉換與編碼壓縮的過程就全部完成了,本文中所采集的AVI檔案大小為4.075M,經格式轉換後的YUV 檔案大小為5.458M,而最終生成的264 碼流大小隻有27k,壓縮率達到了150.9倍。
5.總結
本文所探讨的從視訊采集、格式轉換到壓縮編碼的整個過程,可以簡單友善地完成,可以直接應用在視訊監控或者視訊的網絡傳輸等的前期開發。佰銳科技已為視訊監控音視訊即時通訊提供了解決方案。
本文轉自 fanxiaojun 51CTO部落格,原文連結:http://blog.51cto.com/2343338/493899,如需轉載請自行聯系原作者