用VC编写点对点视频会议程序

来源:互联网 发布:js 日期排序 编辑:程序博客网 时间:2024/05/06 05:37

该程序可以用于两个人在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->PostThreadMessageWM_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后开始会议。