• [转]WPF 通过共享内存播放视频


     
          WPF中非继承FrameworkElement的控件,是无法在wpf的界面上展现的,必须用WindowsFormsHost来嵌套,比如一些第三方的ocx,而这其中我个人经常遇到的最郁闷的事情就是在wpf中播放特殊格式的视频,本人做视频监控方面的应用,面对各种乱七八糟的视频格式,有些必须厂商的库才能播放,可以想象把这些视频在wpf上播放多难受,一切因为wpf的控件是无句柄的,而用了WindowsFormsHost,控件又会置顶,视频菜单和视频叠加无法实现.

          最近看到一个调用VLC播放器的C#开源代码,其中有Wpf的控件,看完代码发现,他实际是把视频的每一帧读取出来,然后再建一个共享内存,把视频数据转为InteropBitmap,InteropBitmap使开发人员能够提高在互操作方案中由 WPF 承载的非 WPF UIs 的呈现性能,可以直接赋值给Image.Source,这样通过Image播放每帧画面,就让视频动起来,当然项目中是借了vlc的解码功能能,如果我们要解自己的视频格式,就需要自己来实现解码转换为InteropBitmap的构成了,要是够强可以直接改VLC的解码器,VLC也是开源的.

      借鉴开源代码中的思路和方法,打算实现自己的播放器,一般第三方解码库会提供:句柄播放视频,播放控制,截图等功能,我不打算完全实现一个wpf中的播放器,那样不实际,因为有太多厂商的接口要处理,只打算把句柄播放视频这里改成Image来展现,为了实现这个功能,先了解一些必备知识。

          内存映射API

    //创建内存映射
    [DllImport("kernel32", SetLastError = true)]
    public static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, PageAccess flProtect, int dwMaximumSizeLow, int dwMaximumSizeHigh, string lpName);
     
    //获取内存映射地址
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, FileMapAccess dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
     
    //释放内存映射
    [DllImport("kernel32", SetLastError = true)]
    public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);
     
    //释放句柄
    [DllImport("kernel32", SetLastError = true)]
    public static extern bool CloseHandle(IntPtr handle);

      Imaging如何从非托管内存获取位图,使用Imaging.CreateBitmapSourceFromMemorySection方法

    //
    // 摘要:
    //     基于所提供的非托管内存位置,返回托管的 System.Windows.Media.Imaging.BitmapSource。
    //
    // 参数:
    //   section:
    //     内存部分的指针。
    //
    //   pixelWidth:
    //     用于指定位图宽度(以像素为单位)的整数。
    //
    //   pixelHeight:
    //     用于指定位图高度(以像素为单位)的整数。
    //
    //   format:
    //     枚举的一个值。
    //
    //   stride:
    //     位图的跨距。
    //
    //   offset:
    //     图像从其开始的内存流字节偏移量。
    //
    // 返回结果:
    //     创建的 System.Windows.Media.Imaging.BitmapSource。
    [SecurityCritical]
    public static BitmapSource CreateBitmapSourceFromMemorySection(IntPtr section, int pixelWidth, int pixelHeight, PixelFormat format, int stride, int offset);
    CreateBitmapSourceFromMemorySection出来的类型显的转换为InteropBitmap,定义依赖属性绑定到image控件就可以了;<br><br>接下来就是怎么把视频数据一桢桢从内存中映射出来,这个需要和你的视频解码提供商有关系了,他解出来的每帧图片是什么格式,一般都那几种PixelFormats.Bgr32、PixelFormats.Pbgra32等,根据格式大小等图片信息,用CreateBitmapSourceFromMemorySection把它从内存中读取出来,内存隐射做的就是一帧帧的把内存隐射出来给CreateBitmapSourceFromMemorySection来处理,处理完释放掉,在继续下一帧,对方要是提供回调函数最好,没有回调就要自己去对这个视频内存做处理,视频组件都会带着些接口的。
  • 相关阅读:
    python3--函数(函数,全局变量和局部变量,递归函数)
    Acunetix Web Vulnarability Scanner V10.5 详细中文手册
    Splunk学习与实践
    Visual studio code离线安装插件
    calling c++ from golang with swig--windows dll(一)
    Golang版protobuf编译
    大型网站架构系列:负载均衡详解(3)
    大型网站架构系列:负载均衡详解(2)
    大型网站架构系列:负载均衡详解(1)
    大型网站架构系列:分布式消息队列(二)
  • 原文地址:https://www.cnblogs.com/psim/p/3747799.html
Copyright © 2020-2023  润新知