如何写Directshow Render Filter并实现视频渲染、叠加字幕和位图功能

    在播放器上叠加字幕或位图(Logo)是一个很常见的需求,现在很多播放器都支持该功能。播放器开发目前可基于框架的有很多,比如MPlayer,gstreamer,Directshow,而这篇教程就是讲解怎么在Directshow播放器上叠加字幕和Logo的,如果你不是从事Directshow开发的程序员或根本不熟悉Directshow,那可以绕路了。

叠加字幕或图标一般分两种应用:一种是在显示视频的界面上显示字幕或图标;另外一种是在采集设备采集出来的图像或从视频文件解码出来的图像中进行字幕叠加,叠加后对视频再编码保存。两者应用场景区别是:前者是在视频显示的时候(即渲染阶段)叠加,没有修改原来的视频图像数据,字幕可以动态添加或移除,而后者的应用场景中,原视频图像和OSD图像经过叠加处理,进行保存,OSD已经被写到视频画面上了。对于字幕叠加(和LOGO的处理流程基本一样),我们有多种实现方法,现在介绍两种最常见的方法。假设现在输入一张图片,我们要在上面叠加文字,我们可以分两步操作,第一:渲染这张图片,让它填充整个窗口;第二,在窗口某个位置上画字幕(DrawText)。这样,字幕就在原图像图层之上显示,这种方式我们叫渲染时叠加。而另外一种方法,我们可以在渲染前修改原图像素,在字幕要打上去的位置将字符点阵“拷贝”到目标区域,OSD区域分文字前景和背景,我们需要将OSD前景的像素保留,而背景的像素用原图像的像素代替,通过这种规则将两种像素(OSD像素和原图像像素)混合,最终生成另外一张图片。第一种方法(渲染时叠加)没有修改原图片,这种方法一般是在视频渲染到显卡到后备缓存时,将文字或位图作为一个图层或Texture表面与原图像进行图层混合,也就是使用显卡的硬件加速来进行图层混合 ,一般效率比较高,并且可以实现更加丰富的效果,比如图像旋转、变形、改变Alpha等。但是这种方法缺点是不适合作后期处理和保存,如果混合后还需要把叠加后图像保存到磁盘,则用第一种方法比较合适。

前面讲了两种不同字幕叠加方式的原理,这里只给大家讲一下第一种方法即渲染时叠加的方法的技术实现,而第二种方法(修改图像像素)就不作详细介绍了,我的另外一篇博文怎么在视频上叠加字幕和Logo--技术实现2有详细介绍。另外有必要说明一下,这篇博文采用的方法跟怎么在视频上叠加字幕和Logo--技术实现1所用方法是一样的,只是加多了Directshow Filter层的封装。

Directshow框架为我们提供了几个功能强大的渲染视频的插件:VMR7,VMR9。这两个插件(统称为VMR)提供了统一的接口对视频显示进行一些高级的控制,其中就包括叠加位图(叠加文字也可以用叠加位图的方法,因为叠加文字其实是通过创建一个位图,将文字BitBlt到位图上,熟悉GDI的朋友应该对这种方法不会陌生)。VMR提供的叠加位图的接口是:IVMRMixerBitmap,这个接口有一个方法:SetAlphaBitmap,这个方法传入一个位图结构对象,将叠加的位图信息告诉显卡,这样显卡就能将图层正确的显示到视频上。具体大家可以参考Directshow文档,标题:Displaying an Application-Supplied Bitmap on the Composited Image。用VMR7和VMR9在使用这个接口上有一点点区别:因为叠加字幕VMR需要启用Mixer模式,VMR7默认不工作在Mixer模式下,除非你显示调用Renderer的 IVMRFilterConfig::SetNumberOfStreams方法,而VMR9默认工作在Mixer模式下,不需要调用 IVMRFilterConfig::SetNumberOfStreams方法。虽然通过SDK的接口能够简易地实现叠加位图功能,但是,但是这个接口有个明显的弊端:它只能设置叠加一个位图到视频上,如果有两个Logo或有两段在不同位置显示的文字需要叠加,那这种方法就无能为力了(不要想着将多个OSD合并到一个位图上和原视频叠加,这种方法的效率太低,因为图层混合是有开销的,位图越大,资源消耗越大)。

既然框架提供的接口没有实现我们想要的功能,我们有什么其他办法呢?其实,在渲染阶段叠加方式,最终用到的都是GDI,DirectDraw,Direct3D等API,所以,我们也可以用这些API将OSD画到视频上。其中,用GDI绘制的方法效率比较低,一般不建议用,更常见的方法是用DirectDraw或D3D技术。因为DirectDraw的API更简单,更易于使用,所以我提供的这个例子也用到DirectDraw技术来画字幕和位图。这个例子实现了一个自定义的渲染器,Filter类名是CFilterNetSender,继承于CBaseRenderer,具有Directshow渲染器的基本属性和功能。这个类封装了渲染器的常见接口,并且提供回调将输入的Media Sample数据(可理解为视频图像)回调给应用层处理。

假设现在我们要播放一个文件,首先,用Directshow我们要创建一个FilterGraph,将一些需要用到的Filter加进去并连接起来,这些Filter包括SourceFilterÿ

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值