如何在安卓设备上使用硬件加速视频解码?

35

为了测试一个自定义协议,我需要进行硬件加速的H.264解码。

在网上搜索后,我发现了一些 Android 上执行硬件加速视频解码的方法:

  1. 使用ffmpeg的libstagefright (关于libstagefright的概述) 或者直接在操作系统中使用 libstagefright,例如这里
  2. 在特定的硬件平台上使用OpenMax,例如这里是关于三星设备的讨论以及这里是关于高通Snapdragon系列的讨论
  3. 一些人提到了PVplayer

有些人声称只有libstagefright是可行的方法,而高通的工程师显然已经取得了成功。

目前我不确定哪种方法可行,我有些困惑。如果所有方法都可行,我当然更愿意选择一个硬件无关的方法。

我测试过几个使用硬件加速的视频播放器,包括 Galaxy Tab 7.7(3.2 & Enxyos)、VLC、Mobo、Rock、vplayer。其中,Rock 和 Mobo 的表现良好,VLC 不起作用,vplayer 存在一个渲染缺陷影响了其性能。

不管怎样,我对 Rockplayer 进行了一个“操作”,删除了 data\data\com.redirecting\rockplayer 目录下的所有 .so 库文件,软件解码崩溃,但硬件解码仍然正常工作!我不明白他们是如何做到这点的。它似乎让我认为硬件加速可以独立于硬件平台。

有谁能够解决这个问题吗?或者提供任何相关的参考资料以及更好的细节描述?


我有点困惑!你是想直接访问(不使用Android媒体API)硬件加速解码器来解码你的比特流吗?因为所有现代手机SOC都使用硬件加速解码H.264。 - Oak Bytes
@OakBytes,我想要实现硬件加速解码,无论是怎样的方式。目前我只知道如何使用FFmpeg软件解码来解码流。硬件加速指的是在1080P @ 30fps下的性能水平,而软件解码则要弱得多。我避免将软件解码称为使用CPU,因为硬件加速模块也是CPU的一部分。你所说的现代手机已经都在使用硬件加速是什么意思? - Glenn Yu
当使用画廊媒体播放器播放H.264剪辑时,所有最近的Android手机都使用H/W加速的H.264解码器。我猜你计划使用H.264解码器来解码原始的H.264比特流并获取解码输出,而不是播放包含H.264视频和一些音频的文件。 - Oak Bytes
@OakBytes 你说得对。那正是我想要的。只要裸比特流,没有mkv或mp4容器。抱歉我没有表述清楚。我想基于NAL或帧级别的裸比特流调用硬件解码,而不是为文件设置媒体播放器。 - Glenn Yu
@Holyglenn - 你的项目成功了吗?也许你找到了一些关于这个主题的新信息? - HitOdessit
libstagefright在ffmpeg中已经废弃。https://dev59.com/Bmkw5IYBdhLWcg3whK88 - Ciro Santilli OurBigBook.com
3个回答

22
为了回答上面的问题,让我介绍一些与Android相关的概念。 OpenMAX Android使用OpenMAX作为编解码器接口。因此,所有本地编解码器(无论是否采用硬件加速)都提供OpenMAX接口。这个接口由StageFright(播放器框架)用于使用编解码器解码媒体。 NDK Android允许Java应用程序使用NDK与底层C/C++本机库进行交互。这需要使用JNI(Java Native Interface)。
现在回到你的问题”如何利用本机解码器解码原始视频比特流?“
在Android 4.0版本及以下版本中,Android没有在Java层提供访问底层视频解码器的功能。您需要编写本机代码来直接与OMX解码器交互。虽然这是可能的,但并不容易,因为它需要了解OMX的工作原理以及如何使用NDK将此OMX映射到应用程序中。
在4.1版(Jelly Bean版本)中,Android似乎通过JAVA API为应用程序级别提供对硬件加速解码器的访问权限。有关新API的更多详细信息,请访问http://developer.android.com/about/versions/android-4.1.html#Multimedia

感谢您对概念和答案的澄清。我已经查阅了参考资料,发现必须深入操作系统框架,这是确实的。这肯定会奏效。 - Glenn Yu
然而,正如Rockplayer上的操作所示,在其中我删除了所有.so库文件,硬件解码仍然有效,而软件解码失败,这可能在Android 4.0版本及以下版本中有一些更简单的方法。至于我的原始比特流解码等等,我可能必须弄清楚整个OMX的事情。你能给出Jelly Bean中的Java API吗? - Glenn Yu
@Holygenn 我已经在Jelly Bean中添加了媒体播放器API的链接。对于RockPlayer,它是直接使用硬件加速解码器显示视频,还是提供输出缓冲区?使用硬件加速解码器进行前者比后者更容易。 - Oak Bytes
2
RockPlayer是封闭源代码的,只有ffmpeg的配置是开放的,因此我不确定它使用了哪个。我的猜测是,在解复用后,原始视频被送入一个开关中,在菜单中让用户选择第三方解码器或硬件系统解码器,然后进行处理和显示。我在Honeycomb 3.2下进行了Rockplayer实验。因此似乎有一种方法可以在没有NDK/JNI的情况下利用系统编解码器,这并不意味着NDK太麻烦,而是探索一种可能性。 - Glenn Yu
1
据我所知,Jelly Bean MediaCodec为原始比特流提供系统编解码器(SW/HW)。这似乎正是我所需要的——我需要使用硬件解码并显示原始视频流。然而,由于好奇心驱使,我更渴望知道如何在没有Jelly Bean的情况下实现硬件加速解码。非常感谢您迄今为止的帮助。 - Glenn Yu

1

1

使用ExoPlayergithub)。

这是一个由谷歌资助的开源项目,取代了平台的MediaPlayer。 管道中的每个组件都是可扩展的,包括示例源(从自定义协议中提取H.264帧的方式)到呈现(到Surface、SurfaceTexture等)。

它包括一个漂亮的演示应用程序展示用法


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接