视频会议应用开发指南

在局域网/内网(甚至可能在互联网上)进行视频会议是现代通信技术的一项重要应用。目前市面上存在多种视频会议应用程序,每种程序都有其独特的性能增强技术。视频会议中的主要问题在于视频帧的大小对于传输来说过大。因此,性能基于用于编码和解码帧的编解码器。使用的是Fast h263 Encoder库,它在高速下提供更好的压缩率。这个应用程序也可以稍作修改后在互联网上使用。

音频录制与播放

使用了之前在语音会议应用中使用的相同的RecordSound和PlaySound类。在这里,将简要概述如何使用这些类。

创建并启动录音器线程:

record = new RecordSound(this); record->CreateThread();

创建并启动播放器线程:

play = new PlaySound1(this); play->CreateThread();

开始录音:

record->PostThreadMessage(WM_RECORDSOUND_STARTRECORDING, 0, 0);

开始播放:

play->PostThreadMessage(WM_PLAYSOUND_STARTPLAYING, 0, 0);

音频录制期间,数据将在RecordSound类的OnSoundData回调函数中可用。在这里,可以放置代码以将数据发送到远程主机...

要播放从远程主机接收到的数据:

play->PostThreadMessage(WM_PLAYSOUND_PLAYBLOCK, size, (LPARAM)data);

停止录音:

record->PostThreadMessage(WM_RECORDSOUND_STOPRECORDING, 0, 0);

停止播放:

play->PostThreadMessage(WM_PLAYSOUND_STOPPLAYING, 0, 0);

最后,停止录音线程:

record->PostThreadMessage(WM_RECORDSOUND_ENDTHREAD, 0, 0);

要停止播放线程...

play->PostThreadMessage(WM_PLAYSOUND_ENDTHREAD, 0, 0);

视频捕获

视频捕获是通过VFW(Video For Windows)API完成的。它提供了从网络摄像头捕获视频的支持。VideoCapture.h和VideoCapture.cpp是包含完整视频捕获过程代码的文件。

创建类的实例:

vidcap = new VideoCapture();

这稍后用于在捕获帧时调用主对话框类的显示函数...

vidcap->SetDialog(this);

这包括很多工作,包括连接到驱动程序和设置所需的视频格式。如果成功连接到视频捕获设备,则返回TRUE。

vidcap->Initialize();

如果成功连接,那么可以获取与视频格式关联的BITMAPINFO结构。这稍后用于显示捕获的帧...

this->m_bmpinfo = &vidcap->m_bmpinfo;

现在可以开始捕获了...

vidcap->StartCapture();

一旦开始捕获,帧将在VideoCapture类的OnCaptureVideo回调函数中到达。在这里调用显示函数以显示帧。

要停止捕获:

vidcap->StopCapture();

如果工作结束了...就销毁它。

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

然后调用这个函数,使用合适的参数...

::DrawDibBegin(hdib,...);

现在如果准备好了帧数据,只需调用这个函数来显示帧

::DrawDibDraw(hdib,...);

最后终止...

::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);

如果需要从RGB24转换到YUV420,那么调用这个

InitLookupTable();

设置回调函数

OwnWriteFunction是全局函数,在编码过程中被调用以返回编码数据...

WriteByteFunction = OwnWriteFunction;

压缩数据必须是YUV420格式...

因此,在压缩之前调用这个方法

ConvertRGB2YUV(IMAGE_WIDTH, IMAGE_HEIGHT, data, yuv);

压缩帧。。。

cparams.format = CPARAM_QCIF; cparams.inter = CPARAM_INTRA; cparams.Q_intra = 8; cparams.data = yuv;

数据是YUV格式...

CompressFrame(&cparams, &bits);

可以从回调函数中获取压缩数据,已经在开始时注册了...

最后终止编码器

ExitH263Encoder();

解码器:

这是tmndecoder(H.263解码器)的修改版本。它原本是ANSI C。已将其转换为C++,以便它可以集成到任何Windows应用程序中。移除了一些具有显示和文件存储功能的文件。移除了一些不必要的代码,并添加了一些新文件。

原始库处理文件。它不适合用于实时解码。做了一些重大更改,使其可以轻松集成到应用程序中,用于实时解码过程。现在,可以使用这个库来解码H263帧。这个库相当快,并且提供更好的性能。

解码器的使用。。。

Initialize the decoder InitH263Decoder();

解压缩帧。。。

DecompressFrame(data, size, rgbdata, buffersize);

最后终止解码器

ExitH263Decoder();

如何运行应用程序

将可执行文件复制到两台不同的机器A和B上,它们位于局域网上。在两台机器上运行应用程序。从机器A(或B)中,选择连接菜单项,在弹出的对话框中输入另一台主机(B)的名称或IP地址,然后按连接按钮。在另一台机器(B)上,将出现接受/拒绝对话框。按接受按钮。在机器A上,将显示通知对话框。按OK开始会议。

就是这样...享受吧!

nsry2002@yahoo.co.in
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485