对于YUV回放在WPFD3D的解决方案
在视频媒体播放、监控系统通常涉及的YUV数据显示建设问题。一般的播放控制和SDK都直接渲染到窗口的窗口句柄使用DirectDraw。然而,如果用户界面开发使用WPF,它通常仅由winformhost WPF界面嵌入WinForm完成。但这会遇到航天,这就是问题的所在,WinForm的控制总是浮在WPF的顶部,任何WPF元素将被覆盖,而缩放和拖动会导致用户体验不佳。原因是WPF和WinForm使用不同的渲染技术。完善在WPF的YUV数据显示,通常的解决方法是转换成YUV数据WPF支持RGB数据,然后使用writeablebitmap像控件显示在WPF。这样做的主要问题是,当你做RGB的转换,你需要消耗大量的CPU,而且效率低一个优化的是ffmpeg中使用swscale或英特尔IPP库,从而优化了有限的硬件加速。这是使用writablebitmap例。
writeablebitmap图像源=新writeablebitmap(videowidth,videoheight,
dpi_x,dpi_y,system.windows.media.pixelformats.bgr32,null);
…
国际rgbsize =宽×高×4; / / bgr32
IntPtr rgbptr = marshal.allochglobal(rgbsize);
yv12torgb(yv12ptr,rgbptr,宽度,高度);
更新/图像
图像源锁();
互操作。memcpy(this.imagesource.backbuffer,rgbptr,rgbsize);
ImageSource.AddDirtyRect(这个。imagesourcerect);
图像源解锁();
Marshal.FreeHGlobal(rgbptr);
另一个解决方案是使用d3dimage为WPF和显卡之间的桥梁。我们可以直接使用d3dimage D3D渲染直接到WPF的部分。一个参考是在wpf.vmr9 VMR9应用是使微软提供的DirectShow,VMR9相关代码在WpfMediaTookit仔细参考后,核心思想是初始化DirectShow构建VMR9渲染,输出一个d3d9surface。d3dimage将使用表面BackBuffer。当一个新的视频帧被表面绘制完成,VMR9将发送一个事件通知。在收到该通知时的d3dimage刷新缓冲。下面的代码显示了思想的核心部分。
私人videomixingrenderer9 createrenderer(){
VaR结果=新videomixingrenderer9();
VaR作为ivmrfilterconfig9 CFG =结果;
(1)cfg.setnumberofstreams;
Cfg.SetRenderingMode(vmr9mode。renderless);
VaR作为ivmrsurfaceallocatornotify9通知=结果;
无功分配=新vmr9allocator();
notify.advisesurfaceallocator(m_userid,分配器);
allocator.advisenotify(通知);
在VMR9 / /建筑渲染,渲染新的视频帧完成事件注册
allocator.newallocatorframe =新的行动(allocator_newallocatorframe);
新d3dsurface创建/注册以接收事件
allocator.newallocatorsurface =新newallocatorsurfacedelegate(allocator_newallocatorsurface);
返回结果;
}
无效allocator_newallocatorsurface(object sender,IntPtr pSurface)
{
/ /方便理解,只保留核心部分,其他部分省略改写
…
/ / P到d3dimage后备缓冲区
this.m_d3dimage.lock();
this.m_d3dimage.setbackbuffer(d3dresourcetype.idirect3dsurface9,P);
this.m_d3dimage.unlock();
…
}
allocator_newallocatorframe(无效)
{
…
/ /重绘
this.m_d3dimage.lock();
this.m_d3dimage.adddirtyrect(新int32rect(0,左 / * * /
0
this.m_d3dimage.pixelwidth,宽度 / * * /
this.m_d3dimage.pixelheight身高 / * * /));
this.m_d3dimage.unlock();
…
}
因此,只要使用DirectShow视频游戏能完美的呈现与VMR9帮助WPF。但很多时候,DirectShow不能解决所有的问题。例如,当视频互动优化或视频叠加完成,很难满足固定过滤器管道DirectShow的要求。有时它需要一个方便、直接的方式呈现。
从VMR9的例子,我们可以看到,生产d3d9surface和渲染它是关键。剩下的问题是如何使YUV数据d3d9surface。
D3D并不直接支持YUV图像格式的。所以我们要想让D3D渲染的YUV数据的方式。在C #重写的过程中,我突然发现,D3D已经帮助我们YUV到RGB颜色空间变换提供了一种简单的方法,它是直接由图形卡的硬件支持。效率是相当高的。主要原理是对d3ddevice的strentchrectangle的使用方法。
Public void StretchRectangle (
表面sourcesurface,
矩形sourcerectangle,
表面destsurface,
矩形destrectangle,
texturefilter滤波器
);
strentchrectangle方法的主要功能是复制一个地区的内容在一个表面上的指定区域,另一个表面,在复制的过程中,只要对视频卡的格式的直接支持,如YV12,YUY2等等,它会自动转换成D3D像素格式!因此,我们只需要创建一个D3D offscreenplainsurface指定好的像素格式,填写原始数据,并调用StrentchRectangle复制的靶面,并得到所需的表面。剩下的事交给d3dimage。这里的示例代码的核心部分
公共无效渲染(IntPtr imgBuffer)
{
锁(这个。renderlock)
{
图像数据填充到画外 / /表面
This.FillBuffer(imgbuffer);
/ /叫StrentchRectangle从复制的原始图像数据,texturesurface
This.StretchSurface();
渲染操作
This.CreateScene();
}
通知 / / d3dimage刷新图像
This.InvalidateImage();
}
以上是D3D的解决方案,介绍了WPF YUV的帮助下Xiaobi。我们希望能帮助你。如果你有任何问题,请给我留言,萧边会及时给您回复。谢谢您支持网站。