我正致力于在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上的新手。任何调试这个的指针都会有所帮助
答案 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->allocateBuffer
。 mOMX
属于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相比。