前言
peerconnection_client中也实现了视频渲染,是通过GDI的方式实现的,因此其性能相较于使用D3D来说要差很多。
源码分析
MainWnd::VideoRenderer::OnFrame
void MainWnd::VideoRenderer::OnFrame(const webrtc::VideoFrame& video_frame) {
{
AutoLock<VideoRenderer> lock(this);
// 视频帧转为i420格式,然后保存到buffer
rtc::scoped_refptr<webrtc::I420BufferInterface> buffer(
video_frame.video_frame_buffer()->ToI420());
// 如果视频有旋转,则偏转回去并保存到buffer
if (video_frame.rotation() != webrtc::kVideoRotation_0) {
buffer = webrtc::I420Buffer::Rotate(*buffer, video_frame.rotation());
}
SetSize(buffer->width(), buffer->height());
// 将yuv数据转换为RGB,转换好的数据保存到image_
RTC_DCHECK(image_.get() != NULL);
libyuv::I420ToARGB(buffer->DataY(), buffer->StrideY(), buffer->DataU(),
buffer->StrideU(), buffer->DataV(), buffer->StrideV(),
image_.get(),
bmi_.bmiHeader.biWidth * bmi_.bmiHeader.biBitCount / 8,
buffer->width(), buffer->height());
}
// 主动触发WM_PAINT消息
InvalidateRect(wnd_, NULL, TRUE);
}
当需要重绘窗口时,只要调一下InvalidateRect()函数,就会发送一个WM_PAINT消息。
rtc::VideoBroadcaster::OnFrame(const webrtc::VideoFrame & frame)
VideoBroadcaster获取的数据,分发到各个模块进行处理。
MainWnd::OnPaint
渲染显示本端和远端的数据。
总结
每次peerconnection_client从WebRTC库收到一帧视频数据时,就会调用一次InvalidateRect()函数,触发WM_PAINT消息的发送;该消息被WndProc()方法接收,调用OnPaint()方法对视频窗口进行重绘,从而实现视频的连续渲染与播放的。