該程序可以用于兩個(gè)人在LAN/Intranet(或者Internet)上進(jìn)行視頻會(huì)議,F(xiàn)在有許多視頻會(huì)議程序,每個(gè)都有各自的性能提升技術(shù)。主要的問題是視頻會(huì)議視頻幀的尺寸對于傳輸來說太大。因此,性能依賴于對幀的編解碼。我使用快速h263編碼庫來達(dá)到更好的壓縮率提高速度。該程序做些小改動(dòng)也可以在Internet上使用。
音頻的錄制與播放
我在以前的語音會(huì)議程序中使用了RecordSound和PlaySound類,這里我將提供摘要說明RecordSound和PlaySound類的使用。
// Create and Start Recorder Thread
record=new RecordSound(this);
record->CreateThread();
// Create and Start Player Thread
play=new PlaySound1(this);
play->CreateThread();
// Start Recording
record->PostThreadMessage(WM_RECORDSOUND_STARTRECORDING,0,0);
// Start Playing
play->PostThreadMessage(WM_PLAYSOUND_STARTPLAYING,0,0);
// During audio recording, data will be available in the OnSoundData
// callback function of the RecordSound class. Here, you can place
// your code to send the data to remote host...
// To play the data received from the remote host
play->PostThreadMessage(WM_PLAYSOUND_PLAYBLOCK,size,(LPARAM)data);
// Stop Recording
record->PostThreadMessage(WM_RECORDSOUND_STOPRECORDING,0,0);
// Stop Playing
play->PostThreadMessage(WM_PLAYSOUND_STOPPLAYING,0,0);
// At last, to Stop the Recording Thread
record->PostThreadMessage(WM_RECORDSOUND_ENDTHREAD,0,0);
// To stop playing thread...
play->PostThreadMessage(WM_PLAYSOUND_ENDTHREAD,0,0);
視頻捕獲
使用VFW(Video For Windows)API進(jìn)行視頻捕獲,它提供了通過webcam進(jìn)行視頻捕獲。VideoCapture.h 和VideoCapture.cpp包含了處理視頻捕獲的代碼。
如下代碼說明了如何使用該類:
// Create instance of Class vidcap=new VideoCapture();
// This is later used to call display function of the main// dialog class when the frame is captured... vidcap->SetDialog(this);
// This does lot of work, including connecting to the driver// and setting the desired video format. Returns TRUE if// successfully connected to videocapture device. vidcap->Initialize();
// If successfully connected, you can get the BITMAPINFO// structure associated with the video format. This is later// used to display the captured frame... this->m_bmpinfo=&vidcap->m_bmpinfo;
// Now you can start the capture.... vidcap->StartCapture();
// Once capture is started, frames will arrive in the "OnCaptureVideo"http:// callback function of the VideoCapture class. Here you call the// display function to display the frame.
// To stop the capture vidcap->StopCapture();
// If your job is over....just destroy it.. vidcap->Destroy();
要使以上代碼通過編譯,你應(yīng)該鏈接適當(dāng)?shù)膸欤?/P>
#pragma comment(lib,"vfw32")
#pragma comment(lib,"winmm")
顯示捕獲的視頻幀
有許多方法和API可以顯示捕獲的視頻。你可以使用SetDIBitsToDevice()方法直接顯示,但給予GDI的函數(shù)非常的慢。更好的方法是使用DrawDib API 顯示。DrawDib函數(shù)為設(shè)備無關(guān)位圖(DIBs)提供了高性能的圖形繪制能力。DrawDib函數(shù)直接寫入視頻內(nèi)存,因此性能更好。
以下代碼摘要演示了使用DrawDib API顯示視頻幀。
// Initialize DIB for drawing... HDRAWDIB hdib=::DrawDibOpen();
// Then call this function with suitable parameters.... ::DrawDibBegin(hdib,...);
// Now, if you are ready with the frame data, just invoke this// function to display the frame ::DrawDibDraw(hdib,...);
// Finally, termination... ::DrawDibEnd(hdib); ::DrawDibClose(hdib);
編解碼庫
編碼器:
使用快速h.263編碼庫進(jìn)行編碼。該庫是使其實(shí)時(shí)編碼更快的 Tmndecoder 修改版。我已經(jīng)將該庫從C轉(zhuǎn)換到C++,這樣可以很容易用于任何Windows應(yīng)用程序。我移除了快速h263編碼庫中一些不必要的代碼與文件,并在.h和.cpp文件中移除了一些定義與申明。
以下是H263編碼庫的使用方法:
// Initialize the compressor CParam cparams; cparams.format = CPARAM_QCIF; InitH263Encoder(&cparams);
//If you need conversion from RGB24 to YUV420, call this InitLookupTable();
// Set up the callback function// OwnWriteFunction is the global function called during// encoding to return the encoded data... WriteByteFunction = OwnWriteFunction;
// For compression, data must be in the YUV420 format...// Hence, before compression, invoke this method ConvertRGB2YUV(IMAGE_WIDTH,IMAGE_HEIGHT,data,yuv);
// Compress the frame..... cparams.format = CPARAM_QCIF; cparams.inter = CPARAM_INTRA; cparams.Q_intra = 8; cparams.data=yuv; // Data in YUV format... CompressFrame(&cparams, &bits);
// You can get the compressed data from the callback function// that you have registerd at the begining...
// Finally, terminate the encoder// ExitH263Encoder();
解碼器:
這是tmndecoder(H.263解碼器)的修改版。使用ANSI C編寫,我們將它轉(zhuǎn)換到C++使其方便在Windows應(yīng)用程序中使用。移除了一些用于顯示和文件處理的文件,移除了不必要的代碼并增加了一些新文件。
原始的庫中一些文件不適合于實(shí)時(shí)的解碼。已經(jīng)做了修改使其適合實(shí)時(shí)的解碼處理,F(xiàn)在,可以使用該庫來解碼H263幀,該庫非?欤阅懿诲e(cuò)。
解碼的使用方法:
//Initialize the decoder InitH263Decoder();
// Decompress the frame....// > rgbdata must be large enough to hold the output data...// > decoder produces the image data in YUV420 format. After// decoding, it is converted into RGB24 format... DecompressFrame(data,size,rgbdata,buffersize);
// Finaly, terminate the decoder ExitH263Decoder();
如何運(yùn)行程序
拷貝可執(zhí)行文件到局域網(wǎng)上兩臺(tái)不同的機(jī)器中:A和B,運(yùn)行他們。在機(jī)器A(或B)中選擇connect菜單條,在彈出的對話框中輸入機(jī)器B的名字或IP地址然后按connect按鈕,在另外一臺(tái)機(jī)器(B)顯示出accept/reject對話框,按accept按鈕。在機(jī)器A將顯示一個(gè)通知對話框,按OK后開始會(huì)議。
That's it....Enjoy......!!!
致謝:
我感謝 Paul Cheffers 提供了他的音頻錄制播放類。因?yàn)橛辛碎_源人士奉獻(xiàn)的開源庫才有你所看到的videonet程序,我感激Tmndecoder的開發(fā)者Karl Lillevold和h.263快速編碼庫的開發(fā)者Roalt Aalmoes 免費(fèi)提供這些開發(fā)庫。
如果你有任何問題或建議,可以發(fā)郵件 nsry2002@yahoo.co.in