安全播放:在MediaCodec中观察到崩溃

时间:2015-01-16 10:27:30

标签: android android-5.0-lollipop 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

我是android上的新手。任何调试这个的指针都会有所帮助

1 个答案:

答案 0 :(得分:1)

总结一下,与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->allocateBuffermOMX属于IOMX类型,即涉及绑定器交互。请注意此变量&buffer_data,它将转换为ptr图层中的ACodec::allocateBufferOnPorts,因为这对以下部分至关重要。

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

当控件返回时,相同的指针将写入绑定器接口here,然后回读here。因此,当控件出现ptr时,header->pBuffer的值等同于OMX组件分配的ACodec,但两者都在2个不同的进程中。

因此,当ABuffer基于此ptr创建MediaCodec时,MediaCodec会在{{1}}中访问,因为地址是在不同的过程&#39;上下文与{{1}}的进程ID相比。