WPF视频渲染系列

第一章 使用HwndHost渲染视频
第二章 使用d3d渲染视频(本章)
第三章 使用d3d渲染dxva2数据
第四章 使用WriteableBitmap渲染视频



前言

《C# wpf 通过HwndHost渲染视频》中介绍了一种在wpf渲染视频的方法,但是有一个缺点,和wpf的控件不太契合,无法在播放框放控件,也无法改变形状,导致一些界面需求较难实现。为了解决这一问题,找到了一种可以和wpf绘制兼容的视频渲染方式,使用d3d渲染。


一、如何实现?

我们首先选择用Image控件来显示视频,Image控件有个Source属性,类型是ImageSource。

1.继承D3DImage

在System.Windows.Interop中有个D3DImage即是ImageSource的子类。
.net源码如下:

namespace System.Windows.Interop
{
    //
    // 摘要:
    //     An System.Windows.Media.ImageSource that displays a user-created Direct3D surface.
    public class D3DImage : ImageSource
}

我们需要继承这个类,自定义一个D3DImageSource继承D3DImage:

public class D3DImageSource : D3DImage
{
        /// <summary>
        /// 渲染
        /// </summary>
        /// <param name="data">数据,比如YU12放在data[0-2]、NV12放在data[0-1]、ARGB32放在data[0]</param>
        /// <param name="lineSize">linesize表示每行数据长度。d3d渲染是64位对齐的。由外部确保内存对齐,方法内部重新处理内存对齐效率是不高的,最好的方式是外部构造数据时已经内存对齐。</param>
        public void Present(IntPtr[] data, int[] lineSize);
         /// <summary>
        /// 清除画面
        /// </summary>
        public void Clear();      
}

2.关联D3D9

(1)安装SharpDx
D3DImage可以使用D3D对象写数据,在.net中有个Dx的封装叫SharpDx可以使用D3D,安装方可以在vs2019中可以通过类名直接自动安装。
在这里插入图片描述
(2)设置缓冲区
初始化D3D9对象后,设置D3DImage的缓冲区为D3D9的Surface:

D3DImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, textureSurface.NativePointer);

3.写入数据

往Surface写入数据

DataRectangle rect = surface.LockRectangle(LockFlags.None);
IntPtr surfaceBufferPtr = rect.DataPointer;
//内存拷贝写入YUV数据
surface.UnlockRectangle();

二、完整代码

https://download.csdn.net/download/u013113678/40831794


三、使用方法

将Image控件的Source设置为D3DImageSource对象,视频数据写入D3DImageSource对象即可。
(1)定义Image控件

<Image x:Name="Img_Diplay"  Height="360" Width="640" >

(2)关联D3DImageSource

D3DImageSource d3dImageSource = new D3DImageSource(width, height, FrameFormat.YV12);
Img_Diplay.Source = d3dImageSource;

(3)写入数据
其中data和linesize可以参考ffmpeg

 d3dImageSource.Present(data, linesize);

(4)释放资源
使用完成后需要释放资源

 d3dImageSource.Dispose();

四、效果预览

视频框内放置控件:
在这里插入图片描述
圆角视频框:
在这里插入图片描述
通过绑定实现多个视频框显示同一个画面:
在这里插入图片描述


总结

通过Image关联到D3DImage,再通过D3DImage关联到D3D9,实现了通过D3D9渲染画面到Image的功能,这种方法的渲染机制与wpf一致,所以可以兼容wpf控件,有了很好的兼容性就意味着可以使用wpf的各种强大界面功能,极大的降低了开发难度以及提升了界面的可造性。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐