我正致力于在 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->allocateBuffer
。 mOMX
是 IOMX
类型,即涉及绑定(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分配的
组件,但它们都在 2 个不同的进程中。header->pBuffer
因此,当 ACodec
基于此 ptr
创建 ABuffer
并在 MediaCodec
中访问时,将是访问冲突,因为与 MediaCodec
的进程 ID 相比,地址是在不同进程的上下文中创建的。
关于android - 安全回放 : Crash observed in MediaCodec,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27981897/