Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1993382
  • 博文数量: 950
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 13070
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-04 09:23
文章分类

全部博文(950)

文章存档

2011年(1)

2008年(949)

我的朋友

分类: C/C++

2008-08-04 09:33:23

下载本文示例代码
下载源代码

该程序可以用于两个人在LAN/Intranet(或者Internet)上进行视频会议。现在有许多视频会议程序,每个都有各自的性能提升技术。主要的问题是视频会议视频帧的尺寸对于传输来说太大。因此,性能依赖于对帧的编解码。我使用快速h263编码库来达到更好的压缩率提高速度。该程序做些小改动也可以在Internet上使用。

音频的录制与播放

我在以前的语音会议程序中使用了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进行视频捕获,它提供了通过webcam进行视频捕获。 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"

// 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();



要使以上代码通过编译,你应该链接适当的库:
#pragma comment(lib,"vfw32")

#pragma comment(lib,"winmm")

显示捕获的视频帧

有许多方法和API可以显示捕获的视频。你可以使用SetDIBitsToDevice()方法直接显示,但给予GDI的函数非常的慢。更好的方法是使用DrawDib API 显示。DrawDib函数为设备无关位图(DIBs)提供了高性能的图形绘制能力。DrawDib函数直接写入视频内存,因此性能更好。

以下代码摘要演示了使用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编码库进行编码。该库是使其实时编码更快的 Tmndecoder 修改版。我已经将该库从C转换到C ,这样可以很容易用于任何Windows应用程序。我移除了快速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编写,我将它转换到C 使其方便在Windows应用程序中使用。我移除了一些用于显示和文件处理的文件,移除了不必要的代码并增加了一些新文件。

原始的库中一些文件不适合于实时的解码。我已经做了修改使其适合实时的解码处理。现在,可以使用该库来解码H263帧,该库非常快,性能不错。

解码的使用方法:
//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();



如何运行程序
拷贝可执行文件到局域网上两台不同的机器中:A和B,运行他们。在机器A(或B)中选择connect菜单条,在弹出的对话框中输入机器B的名字或IP地址然后按connect按钮,在另外一台机器(B)显示出accept/reject对话框,按accept按钮。在机器A将显示一个通知对话框,按OK后开始会议。

That''''s it....Enjoy......!!!

致谢:

我感谢 Paul Cheffers 提供了他的音频录制播放类。因为有了开源人士奉献的开源库才有你所看到的videonet程序,我感激Tmndecoder的开发者Karl Lillevold和h.263快速编码库的开发者Roalt Aalmoes 免费提供这些开发库。

如果你有任何问题或建议,可以发邮件给我 nsry2002@yahoo.co.in 下载本文示例代码
阅读(261) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~