尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

深入Mira Screenshare源码:Windows.Graphics.Capture截屏引擎与D3D11 GPU转NV12像素格式原理

深入Mira Screenshare源码:Windows.Graphics.Capture截屏引擎与D3D11 GPU转NV12像素格式原理 深入Mira Screenshare源码Windows.Graphics.Capture截屏引擎与D3D11 GPU转NV12像素格式原理【免费下载链接】sharerA screen-sharing / remote collaboration software written in Rust项目地址: https://gitcode.com/gh_mirrors/sha/sharerMira Screenshare 是一款基于 Rust 的开源屏幕共享 / 远程协作软件可实现 4K 60FPS、约 110ms 端到端低延迟的屏幕串流。本文带你深入它的源码剖析Windows.Graphics.Capture 截屏引擎如何高效抓帧以及D3D11 GPU 如何把 BGRA 屏幕帧转换为 NV12 像素格式——这正是它能在 CPU 上零拷贝喂给 x264 编码器的关键。整个数据流可以概括为一条 GPU 管线Windows.Graphics.Capture (截屏帧池) │ BGRA8 D3D11 纹理 ▼ D3D11 GPU 着色器转换 (Y pass UV pass) │ NV12 (亮度平面 色度平面) ▼ x264 硬件级编码 → WebRTC 串流出站截屏引擎Windows.Graphics.Capture 帧池是如何工作的在 Windows 上Mira 使用系统原生的Windows.Graphics.CaptureAPI要求 Win10 1803。其核心实现在 src/capture/wgc/wgc_capture.rs。关键设计点有四个 ️自由线程帧池通过Direct3D11CaptureFramePool::CreateFreeThreaded创建一个容量为 3 的帧池像素格式指定为BGRA8_UNORM。FreeThreaded意味着系统可以在任意线程投递帧避免截屏被绑定到 UI 线程 src/capture/wgc/wgc_capture.rs#L44-L50。事件驱动 无锁通道系统每次屏幕刷新画面变化都会触发FrameArrived事件回调里用TryGetNextFrame取出帧再通过容量为 1 的mpsc通道try_send给主循环——一旦处理不过来就自然丢帧保证永远抓最新画面 src/capture/wgc/wgc_capture.rs#L95-L107。帧率节流主循环用tokio::time::interval按config.max_fps打节拍配合select!同时监听帧到达与停止信号 src/capture/wgc/wgc_capture.rs#L112-L140。WinRT 与 D3D11 双世界桥接WGC 的帧池只认 WinRT 的IDirect3DDevice而着色器管线用的是ID3D11Device。Mira 在 src/capture/wgc/d3d.rs 中用CreateDirect3D11DeviceFromDXGIDevice把同一个底层 DXGIDevice 包装出两种接口一套设备通吃两条管线若硬件驱动不支持DXGI_ERROR_UNSUPPORTED还会自动回退到 WARP 软件光栅化器保证任何机器都能跑 src/capture/wgc/d3d.rs#L36-L54。D3D11 GPU 转 NV12一次拷贝 两趟着色器拿到帧后WGC 给的是 BGRA 纹理而 x264 最擅长吃的却是NV12Y 平面满分辨率 U/V 交错半分辨率。如果放 CPU 上做矩阵变换4K 帧动辄要十几毫秒Mira 的做法是全程在 GPU 上完成核心类YuvConverter位于 src/capture/yuv_convert/yuv_converter.rs。整个转换只有三步 ⚡️第一步CopyResource 拉入自己的纹理把系统截屏纹理通过CopyResource拷到一块 BGRA 后端纹理上。这一步是纯 GPU 显存拷贝CPU 完全不参与 src/capture/yuv_convert/yuv_converter.rs#L100-L107。第二步两趟全屏着色器分别渲染 Y 与 UV着色器源码见 PixelShaderY.hlsl 与 PixelShaderUV.hlsl采用BT.709 HDTV 色彩矩阵Y pass亮度着色器对每个像素做Y RGB · [0.182585, 0.614230, 0.062007] 0.0625输出到一块R8_UNORM满分辨率渲染目标 PixelShaderY.hlsl#L38-L43UV pass色度着色器做 3×2 矩阵乘法得到(U, V)输出到R8G8_UNORM的半分辨率W/2 × H/2渲染目标 PixelShaderUV.hlsl#L38-L43。注意 UV 平面分辨率减半——这正是 NV12 的 4:2:0 色度抽样要求。几何部分简单到令人发笑仅 6 个顶点拼成两个三角形铺满整个屏幕全屏四边形顶点着色器是恒等映射 dx_math.rs#L27-L76。更妙的是纹理格式的选择R81 字节/像素正好装 YR8G82 字节/像素正好装交错的 UV——渲染目标本身就是标准的 NV12 内存布局无需任何打包转换。第三步staging 纹理 Map 回读 CPUGPU 渲染结果无法直接给 CPU 读Mira 为 Y、UV 各建了一块D3D11_USAGE_STAGING可读纹理先CopyResource把渲染纹理拷进 staging 纹理再Map(D3D11_MAP_READ)把指针拿到用户态最终组装成YUVFrame含luminance_bytes/chrominance_bytes双平面与各自 stride交给编码器 src/capture/yuv_convert/yuv_converter.rs#L181-L243结构体定义见 src/capture/frame.rs。 一次回读 一帧 Y 平面W×H 字节 一帧 UV 平面W×H/2 字节。对 4K 而言约 11.25MB远小于 BGRA 的 24.5MB——色彩空间转换顺带把数据量砍了 54%。为什么是 NV12——为 x264 而生编码器侧通过encoder::encode(FrameData::NV12(...))直接把两平面指针交给 FFmpeg/x264 硬件编码通路 src/capture/wgc/wgc_capture.rs#L121-L128。NV12 是 x264、NVENC 等硬件编码器原生的输入格式选它意味着从截屏到编码之间没有任何 CPU 像素格式转换整条链路只剩 GPU 拷贝和 GPU 矩阵变换。编码质量、速度等参数可在configs/目录的预设配置中调整例如 configs/config.libx264.toml 与 configs/config.nvenc.toml。小结这套设计的三个精髓设计收益CreateFreeThreaded帧池 try_send丢帧截屏永不阻塞画面永远最新GPU 双 pass 着色器直出 NV12 布局色彩转换零 CPU 开销数据量减半硬件驱动失败自动回退 WARP任何机器含远程桌面都能降级运行配合max_fps节流与PerformanceProfiler逐阶段计时见 src/performance_profiler.rs这套截屏引擎 GPU 转格式的组合拳正是 Mira Screenshare 能做到 4K 60FPS 低延迟串流的核心。想动手读源码克隆仓库后即可按上文路径逐文件对照git clone https://gitcode.com/gh_mirrors/sha/sharer【免费下载链接】sharerA screen-sharing / remote collaboration software written in Rust项目地址: https://gitcode.com/gh_mirrors/sha/sharer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表