android - 安全回放 : Crash observed in MediaCodec

标签 android android-5.0-lollipop android-mediacodec stagefright

我正致力于在 Lollipop 上实现安全播放。我正在使用 ExoPlayer验证用例。我能够创建安全的 OMX 视频解码器组件 (H264.secure)。

但是,在创建之后,我在 MediaCodec 中遇到崩溃,如下所示

signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0xf0300000
eax f0300000  ebx ec1da038  ecx 00000005  edx 00000002
esi ec3ca200  edi f325b148
xcs 00000023  xds 0000002b  xes 0000002b  xfs 000000bf  xss 0000002b
eip ec0e1655  ebp e05ffb28  esp e05ffa90  flags 00210202  

#00 pc 000b5655  /system/lib/libstagefright.so (android::MediaCodec::onQueueInputBuffer(android::sp<android::AMessage> const&)+1061)
#01 pc 000b7b16  /system/lib/libstagefright.so (android::MediaCodec::onMessageReceived(android::sp<android::AMessage> const&)+1894)
#02 pc 0000e039  /system/lib/libstagefright_foundation.so (android::ALooperRoster::deliverMessage(android::sp<android::AMessage> const&)+345)
#03 pc 0000d3d0  /system/lib/libstagefright_foundation.so (android::ALooper::loop()+256)
#04 pc 0000d4ed  /system/lib/libstagefright_foundation.so (android::ALooper::LooperThread::threadLoop()+29)
#05 pc 000169de  /system/lib/libutils.so (android::Thread::_threadLoop(void*)+398)
#06 pc 0006fe92  /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+98)
#07 pc 000160fa  /system/lib/libutils.so (thread_data_t::trampoline(thread_data_t const*)+122)

经过一些分析,我发现崩溃发生在函数 ACodec::allocateBuffersOnPort

我是安卓新手。任何调试它的指针都会有所帮助

最佳答案

总而言之,该问题特定于 kFlagIsSecure 设置的情况 以及在不同进程中创建 OMX 缓冲区的比较到 MediaCodec,这会在 MediaCodec 中访问时导致段错误。有关此问题的详细背景,请参阅下文。

为了克服这个问题,我建议在 ACodec

中进行以下更改
size_t totalSize = def.nBufferCountActual * def.nBufferSize;
mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");

/* Check if the component resides in same pid as ACodec */
bool isLocalComponent = mOMX->livesLocally(mNode, getpid()); // New Code

for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
   sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
   ...
   ...

并如下修改分配检查

-- if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
--      || mUseMetadataOnEncoderOutput) {

// Modified check
++if (isLocalComponent && ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
++      || mUseMetadataOnEncoderOutput)) {

P.S:我建议您向 Google 咨询此解决方案。

背景:

ExoPlayer 创建视频解码器作为 MediaCodec 组件。创建新的 MediaCodec 组件时,corresponding object in JNI is created .请note that there is no interaction with MediaPlayerService在这个过程中。

MediaCodec 在内部创建一个 ACodec,它与 OMX 核心和随后的 OMX 组件交互。

ACodec 是在与 MediaCodec 相同的上下文中创建的。当OMXClient::connect被调用时,OMX 句柄在 MediaPlayer 服务的上下文中创建。因此,OMX 组件和 ACodec 的进程 ID 将不同。

对于安全输入缓冲区,there is a special handling in ACodec::allocateBuffersOnPorts .在这里,从 allocateBuffer 返回的缓冲区指针被包装为 ABuffer 并排队等待使用。在我看来,当前的实现存在如下潜在问题。

ACodec::allocateBufferOnPort 调用 mOMX->allocateBuffermOMXIOMX 类型,即涉及绑定(bind)器交互。请注意这个变量 &buffer_data,它将在 ACodec::allocateBufferOnPorts 层中转换为 ptr,因为这对以下部分至关重要。

在实际运行在MediaPlayerService上下文中的OMXNodeInstance中,调用了一个传统的OMX_AllocateBuffer。在 OMXNodeInstance::allocateBuffer 中,分配后 *buffer_data 被初始化为 header->pBuffer ,它基本上是由 分配的本地指针>OMX 组件可能通过简单的 malloc 调用。

当控制返回时,相同的指针被写入 Binder 接口(interface)here然后回读here .所以,当控制出来mOMX->allocateBuffer时,ptr的值就相当于OMX分配的header->pBuffer 组件,但它们都在 2 个不同的进程中。

因此,当 ACodec 基于此 ptr 创建 ABuffer 并在 MediaCodec 中访问时,将是访问冲突,因为与 MediaCodec 的进程 ID 相比,地址是在不同进程的上下文中创建的。

关于android - 安全回放 : Crash observed in MediaCodec,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27981897/

相关文章:

c# - Unity制作的Android游戏中的声音问题

android - 地理围栏和 Lollipop

android - Nexus 5 Android 5.0.1 上未显示某些 ProgressBar 样式

android - 上下文切换太昂贵

java - Android相机通过OpenGL编码

android - 我应该把我的 retrofit 电话和 Android 服务类放在里面吗?

安卓L : Data turn off error

android - 当用户长按电源按钮时禁用关机对话框

android - 如何更改过度滚动边缘和过度滚动发光的颜色

android - 使用没有 mediaextractor 的 mediacodec 的 MP3 解码失败