惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Fortinet All Blogs
博客园 - 叶小钗
T
Tailwind CSS Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
T
The Exploit Database - CXSecurity.com
Blog — PlanetScale
Blog — PlanetScale
T
Tenable Blog
人人都是产品经理
人人都是产品经理
D
DataBreaches.Net
A
Arctic Wolf
P
Proofpoint News Feed
S
SegmentFault 最新的问题
C
CERT Recently Published Vulnerability Notes
T
Threatpost
Y
Y Combinator Blog
WordPress大学
WordPress大学
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
V
Vulnerabilities – Threatpost
AWS News Blog
AWS News Blog
小众软件
小众软件
U
Unit 42
云风的 BLOG
云风的 BLOG
美团技术团队
S
Securelist
C
Cybersecurity and Infrastructure Security Agency CISA
L
LangChain Blog
G
GRAHAM CLULEY
P
Proofpoint News Feed
I
Intezer
Security Latest
Security Latest
L
Lohrmann on Cybersecurity
NISL@THU
NISL@THU
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The Hacker News
The Hacker News
Cisco Talos Blog
Cisco Talos Blog
T
The Blog of Author Tim Ferriss
H
Heimdal Security Blog
T
Tor Project blog
MongoDB | Blog
MongoDB | Blog
The Cloudflare Blog
T
Troy Hunt's Blog
Know Your Adversary
Know Your Adversary
博客园 - 司徒正美
Google Online Security Blog
Google Online Security Blog
V
V2EX
Application and Cybersecurity Blog
Application and Cybersecurity Blog

博客园 - 昨夜飘风

C# 模拟网页拖拽 .net4.0中wpf单例启动 wpf 自定义ContextMenu样式,可以调节ContextMenu的宽度 Oracle 开发经验 WPF跑马灯效果 android私有文件夹的访问 [转]C#内存操作 C#串口发送接受数据 C# 制作外挂常用的API silverlight 动画 性能优化 SilverLight 动画缓冲(Animation Easing) - 昨夜飘风 体面地处理程序的未捕获异常 C# 访问USB(HID)设备 收藏一个地址(居然说我标题已经存在) 收藏一个地址 (2009-06-24) SqlCommandBuilder使用的注意事项 助睡眠音乐 (2009-06-22) 班德瑞官方试听网站 (2009-06-18)今日收获 工厂方法 (2009-06-17)今日收获-只读列隐藏-win2003 dll文件下载
WPF 通过共享内存播放视频
昨夜飘风 · 2013-05-29 · via 博客园 - 昨夜飘风

      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控件就可以了;

接下来就是怎么把视频数据一桢桢从内存中映射出来,这个需要和你的视频解码提供商有关系了,他解出来的每帧图片是什么格式,一般都那几种PixelFormats.Bgr32、PixelFormats.Pbgra32等,根据格式大小等图片信息,用CreateBitmapSourceFromMemorySection把它从内存中读取出来,内存隐射做的就是一帧帧的把内存隐射出来给CreateBitmapSourceFromMemorySection来处理,处理完释放掉,在继续下一帧,对方要是提供回调函数最好,没有回调就要自己去对这个视频内存做处理,视频组件都会带着些接口的。