因为公司项目需要,研究了下腾讯的实时音视频的C# Winform
版本的Demo。
当然其他平台也有,不是我主要负责。
经过2天的摸索,对其代码和原理进行了一个简单的梳理。因为才接触腾讯的音视频直播,同时C# Winform
相关的知识已经5年没碰了。
所以下面的内容,应该会出现一些偏差,仅供大家参考。
腾讯的Demo 下载地址:
其实整个项目的最为核心的文件
是:TXLiteAVVideoViews
。翻译过来的意思应该是腾讯轻量级的音视频视图
。
在这个文件
中,包含了3个非常重要的类,我认为音视频在C#`层面上的核心。
TXLiteAVVideoView
,继承自Pannel
,将视频帧渲染到空间上。TXLiteAVVideoViewManager
,继承自ITRTCVideoRenderCallBack
,承上启下,将底层传递的帧数据再传递给TXLiteAVVideoView
FrameBufferInfo
帧数据的封装实体。以下为我把非核心代码删除后的简单模型。
public class TXLiteAVVideoView: Panel {
// 帧缓存,可以理解为视频暂停时候的一个画面
private volatile FrameBufferInfo _mArgbFrame = new FrameBufferInfo();
public bool AppendVideoFrame(byte[] data, int width, int height, TRTCVideoPixelFormat videoFormat, TRTCVideoRotation rotation) {
//...
}
protected override void OnPaint(PaintEventArgs pe) {
//....
}
}
该类继承了Pannl
,又重写了OnPaint
,所以可以猜测目的是为了根据Frame
数据来绘图。
_mArgbFrame
的作用是保存的某一时刻的一帧数据
,保存起来的目的是为了方便OnPaint
来绘图,它由什么地方传递过来的了,我们看下面这段话?
AppendVideoFrame
由TXLiteAVVideoViewManager
来调用,其中就传入了byte[] data
这个还没有处理的帧
的数据。
所以由此我们可以简单分析总结下:该类通过方法AppendVideoFrame
接收TXLiteAVVideoViewManager
传递过来的帧数据,在将帧数据保存到局部变量_mArgbFrame
后调用refresh
方法,该方法会调用重写后的OnPaint
来画图。
同样简化下代码:
class TXLiteAVVideoViewManager: ITRTCVideoRenderCallback {
private volatile Dictionary<string,TXLiteAVVideoView> _mMapViews;
public void onRenderVideoFrame(string userId, TRTCVideoStreamType streamType, TRTCVideoFrame frame) {
//...
}
}
ITRTCVideoRenderCallback
的方法onRenderVideoFrame
。通过签名,我大胆的猜测了从服务器拉数据的时候,数据中应该有远程用户的id,以及对应的数据帧和类型。TXLiteAVVideoView
进行视图渲染。_mMapViews
这个局部变量,通过userId-streamType
来作为key,其TXLiteAVVideView
作为value来保存的数据。我们可以简单看看onRenderVideoFrame
的实现
public void onRenderVideoFrame(string userId, TRTCVideoStreamType streamType, TRTCVideoFrame frame) {
//....
TXLiteAVVideoView view = null;
lock(_mMapViews) {
view = _mMapViews[GetKey(userId, streamType)];
}
//调用 AppendVideoFrame 进行帧的渲染
view?.AppendVideoFrame(frame.data, (int) frame.width, (int) frame.height, frame.videoFormat, frame.rotation);
}
其本质也是从Dictionary
中通过GetKey(userId, streamType)
来构成key
,获取到对应的view
,然后进行AppendVideoFrame
.
这个类的实现如下:
class FrameBufferInfo
{
public byte[] data { get; set; }
public int width { get; set; }
public int height { get; set; }
public bool newFrame { get; set; }
/**
* Rotation 是是否旋转
*/
public TRTCVideoRotation rotation { get; set; }
}
表示的应该是这个帧如何处理。
这是腾讯音视频实时通信的第一篇分析,后面会根据情况,看看有没有更多有意义的可以写文。
希望对大家有帮助。