如何将WebRTC接收的Argb32VideoFrame/I420AVideoFrame转为Texture2D
Win10 C#桌面端WebRTC视频帧Direct3D显示方案
Argb32VideoFrame 直接转 Texture2D 实现(性能最优)
你当前监听的Argb32回调是最适配Direct3D渲染的方案,无需像素格式转换,直接内存拷贝即可实现渲染,优化后的实现逻辑如下:
- 预先定义复用的动态纹理成员,避免每次回调创建纹理造成性能损耗:
// 类成员定义 private SharpDX.Direct3D11.Texture2D _dynamicVideoTexture; private int _lastFrameWidth = 0; private int _lastFrameHeight = 0;
- 帧回调逻辑优化:
private void _remoteVideoTrack_Argb32VideoFrameReady(Argb32VideoFrame frame) { // 处理分辨率变更 if (frame.width != _lastFrameWidth || frame.height != _lastFrameHeight) { _lastFrameWidth = (int)frame.width; _lastFrameHeight = (int)frame.height; // 释放旧纹理 _dynamicVideoTexture?.Dispose(); // 创建CPU可写的动态纹理,格式和WebRTC返回的Argb32、SwapChain格式完全匹配 var textureDesc = new SharpDX.Direct3D11.Texture2DDescription() { Width = _lastFrameWidth, Height = _lastFrameHeight, ArraySize = 1, BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource, Usage = SharpDX.Direct3D11.ResourceUsage.Dynamic, CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Write, Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, MipLevels = 1, OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None, SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0) }; _dynamicVideoTexture = new SharpDX.Direct3D11.Texture2D(d3dDevice, textureDesc); // 同步重设SwapChain缓冲区 swapChain.ResizeBuffers(2, _lastFrameWidth, _lastFrameHeight, SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.DXGI.SwapChainFlags.None); } // 拷贝WebRTC帧数据到动态纹理 var dataBox = d3dDevice.ImmediateContext.MapSubresource( _dynamicVideoTexture, 0, SharpDX.Direct3D11.MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None ); SharpDX.Utilities.CopyMemory(dataBox.DataPointer, frame.data, (int)(frame.stride * frame.height)); d3dDevice.ImmediateContext.UnmapSubresource(_dynamicVideoTexture, 0); // 拷贝纹理到后台缓冲并呈现 using (var backBuffer = swapChain.GetBackBuffer<SharpDX.Direct3D11.Texture2D>(0)) { d3dDevice.ImmediateContext.CopyResource(_dynamicVideoTexture, backBuffer); } swapChain.Present(1, SharpDX.DXGI.PresentFlags.None); }
- 注意:WebRTC返回的Argb32VideoFrame像素顺序是B8G8R8A8,和DXGI的B8G8R8A8_UNorm格式完全对齐,无需做任何像素转换,性能损耗最低。
I420AVideoFrame 转 Texture2D 实现
如果选择监听I420A帧回调,可选两种实现方案:
- CPU侧转换:通过YUV转RGB算法将I420帧数据转换为Argb32格式,再复用上述Argb32的渲染逻辑,适合低分辨率低帧率场景,开发成本低。
- GPU侧转换:分别创建Y、U、V三个单通道纹理,将三个平面的帧数据分别拷贝到对应纹理,通过像素着色器完成YUV到RGB的格式转换后直接渲染,适合高分辨率高帧率场景,性能更好但需要编写简单的着色器代码。
低开发成本直接显示方案
如果不需要自己封装Direct3D渲染逻辑,可以用桌面端UI框架自带控件实现快速渲染:
- WPF项目:将Argb32帧数据拷贝到WriteableBitmap,直接赋值给Image控件的Source属性即可,无需手动管理SwapChain。
- WinForm项目:将Argb32帧数据拷贝到Bitmap对象,赋值给PictureBox控件的Image属性即可,开发效率更高。
内容的提问来源于stack exchange,提问作者seacoolth
相关产品推荐
相关产品推荐

