目标

视频的硬件解码近来发展非常快速,尤其是在低功耗的设备上。本教程会讲述一些硬件加速的背景知识并解释一下GStreamer是怎么做的。

悄悄告诉你,如果设置正确地话,我们什么也不用做,GStreamer自动做完这一切的。

介绍

视频解码是非常消耗CPU的一个任务,尤其是1080P这种高分辨率的高清节目。幸运的是,现在的显卡都带了可编程的GPU,如果我们用GPU用来做视频解码,那么CPU就可以解放出来做其他的任务了。低功耗的CPU是无法做解码这样的工作的,这时硬件的配合就是必须的了。

目前来说(2012.07),每个GPU的制造商都提供了访问它们的硬件的方法(API),不幸的是各家并不相同,并没有一个强制的标准。

VAAPI(Video Acceleration API):2007年Intel设计的,目的是在Unix操作系统的XWindow系统下运行,现在开源了。现在不仅仅局限于Intel的GPU了,其他制造商也可以使用了。GStreamer通过gstreamer-vaapi和fluvadec这个插件来使用。

VDPAU(Video Decode and Presentation API for Unix):2008年NVidia设计的,最早也是运行在Unix的XWindow系统下,现在同样开源了。虽然同样已经是开源库了,但除了NVidia自己外还没有其他制造商使用。GStreamer通过vdpau和fluvadec这个插件来使用。

DXVA(DirectX Video Acceleration):微软为了Windows系统和XBox360定制的。GStreamer通过fluvadec这个插件来使用。

XVBA(X-Video Bitstream Acceleration):AMD设计,在Linux操作系统的XWindow系统下下X
Video的扩展。目前在AMD的ATI显卡中有支持。GStreamer通过fluvadec这个插件来使用。

VDA(Video Decode Acceleration):应用于Mac OSX10.6.3之后,仅仅加速H.264的解码,GStreamer通过fluvadec这个插件来使用。

OpenMAX(Open Media Acceleration):由非盈利性联合Khronos Group设计的,是一组跨平台的C语言编程接口。GStreamer通过gstreamer-omx这个插件来使用。

OVD(Open Video Decode):AMD的又一个API,GStreamer目前不能使用这个接口。

DCE(Distributed Codec Engine):一个开源的软件库(libdce)和TI定制的API,提供给linux系统和ARM平台的。GStreamer通过gstreamer-ducati插件可以使用。

硬件加速视频解码插件内部的工作原理

通常这些API提供了一系列的功能,比如:视频解码,后处理,解码帧的描述,或者把帧下载到系统内存等等。相应的,不同的功能插件一般是给不同的element使用的,这样pipeline可以适应任何需求。

例如:gstreamer-vaapi这个插件提供了vaapidecode、vaapiupload、vaapidownload、vaapisink这些element,允许通过VAAPI来使用硬件加速功能,上传原始视频帧数据到GPU内存,下载GPU帧到系统内存并且描述GPU帧的内容。

这里区分传统的GStreamer帧(在系统内存中)和由硬件加速API生成的帧是很重要的。硬件加速生成的帧位于GPU的内存中,是GStreamer不能直接操作的。通常他们是下载到系统内存中,然后就可以被当成普通帧来处理了,但留在GPU中由GPU来显示效率是最高的。

GStreamer需要追踪这些“硬件缓冲区”,因为这样传统的缓冲区可以继续从一个element流向另一个element,但他们的内容尽皆是硬件缓冲区的ID或者Handler。比如:一个appsink获得了硬件缓冲区ID,硬件缓冲区什么都不会响应,因为它们只能由生成它们的插件来处理。

为了让这个更加明确,这些缓冲区都有特殊的Caps,就像video/x-vdpau-output或者video/x-fluendo-va这样。在这种方式下,GStreamer的自动插入机制不会试着把硬件缓冲区去传给传统的element——因为他们根本风马牛不相及。而且,使用了这些Caps之后,自动插入机制就可以使用硬件加速来搭建pipeline了,因为,在VAAIP解码器之后,只有VAAPI
sink这一种element是可以连接上去的。

这些都说明,如果一个硬件加速的API在系统中可用而且对应的GStreamer插件也有的话,playbin2等自动连接的element可用随意的使用它们来搭建pipeline,应用不需要做什么特殊的处理。

当playbin2必须在一些element中选择时,就像是选择传统的软件解码还是硬件加速的解码,它会使用rank来决定。这个rank属性是每个element都有的,它会指明优先级,playbin2会选用最高的rank的element来搭建pipeline。

所以,playbin2是否使用硬件加速的element取决于当时所有可用的element的rank值。而且,最简单地确保硬件加速的element被选中的方法是修改rank属性的值。代码如下:

[objc] view
plain
 copy

【GStreamer开发】GStreamer播放教程08——视频解码的硬件加速-LMLPHP【GStreamer开发】GStreamer播放教程08——视频解码的硬件加速-LMLPHP

  1. static void enable_factory (const gchar *name, gboolean enable) {
  2. GstRegistry *registry = NULL;
  3. GstElementFactory *factory = NULL;
  4. registry = gst_registry_get_default ();
  5. if (!registry) return;
  6. factory = gst_element_factory_find (name);
  7. if (!factory) return;
  8. if (enable) {
  9. );
  10. }
  11. else {
  12. gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), GST_RANK_NONE);
  13. }
  14. gst_registry_add_feature (registry, GST_PLUGIN_FEATURE (factory));
  15. return;
  16. }

传给方法的第一个参数是要修改的element的名字,比如:vaapidecode或者fluvadec。

这里主要的方法是gst_plugin_feature_set_rank(),它会设置element的rank。为了方便起见,rank分成NONE,MARGINAL,SECONDARY和PRIMARY,但任何数字都可以的。比如我们可用给某个element设置PRIMARY+1,那么它就比其他设置成PRIMARY的rank高,设置一个element的rank是NONE,会让自动连接机制屏蔽它(永远选不上)。

硬件加速视频解码和GStreamer的SDK

GStreamer的SDK在2012年七月前是没有硬件加速的视频解码的插件的。主要原因是有些还没有完全写完,还有一些问题。但请记住这个情况会在不久改变。

有些插件可用在它们公开源码的基础上自己编译出来,使用Cerbero编译系统。有些插件是供应商已经编译好了。

下面会简单介绍一下当前这些插件的情况。

vdpad在gst-plugin-bad

针对VDPAU的GStreamer element,在gst-plugin-bad里面

支持mpeg2,mpeg4和H264的编解码

gstreamer-vaapi

针对VAAPI的GStreamer element,项目的网址请猛戳这里

支持mpeg2,mpeg4,H264,VC1和WMV3的编解码

可用直接和Clutter配合使用,这样帧就可以一直在GPU里面

和playbin2兼容

gst-omx

针对OpenMax的GStreamer element,项目网址请猛戳这里

在不同的硬件下支持不同的编解码

fluvadec

针对VAAPI,VDPAU,DXVA2,XVBA和VDA的GStreamer element.

根据不同的API,支持不同的编解码


MPEG2MPEG4H.264VC1
VAAPI
VDPAU
XVBA

DXVA2


VDA


可用直接和Clutter配合使用,这样帧就可以一直在GPU里面

和playbin2兼容


05-15 15:15