You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将WebRTC接收的Argb32VideoFrame/I420AVideoFrame转为Texture2D

Win10 C#桌面端WebRTC视频帧Direct3D显示方案

Argb32VideoFrame 直接转 Texture2D 实现(性能最优)

你当前监听的Argb32回调是最适配Direct3D渲染的方案,无需像素格式转换,直接内存拷贝即可实现渲染,优化后的实现逻辑如下:

  1. 预先定义复用的动态纹理成员,避免每次回调创建纹理造成性能损耗:
// 类成员定义
private SharpDX.Direct3D11.Texture2D _dynamicVideoTexture;
private int _lastFrameWidth = 0;
private int _lastFrameHeight = 0;
  1. 帧回调逻辑优化:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 10:15:04