【问题标题】:Secure Playback: Crash observed in MediaCodec安全播放:在 MediaCodec 中观察到崩溃
【发布时间】:2015-03-14 22:28:03
【问题描述】:

我正在努力在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 android-5.0-lollipop android-mediacodec stagefright


    【解决方案1】:

    总而言之,该问题特定于 设置kFlagIsSecure 的情况,并且与MediaCodec 相比,在不同的进程中创建OMX 缓冲区会导致分段在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-&gt;allocateBuffermOMX 属于 IOMX 类型,即涉及绑定器交互。请注意这个变量&amp;buffer_data,它将转换为ACodec::allocateBufferOnPorts 层中的ptr,因为这对于以下部分至关重要。

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

    当控件返回时,相同的指针被写入绑定接口here,随后读回here。所以,当控件出来mOMX-&gt;allocateBuffer时,ptr的值相当于OMX组件分配的header-&gt;pBuffer,但两者都在2个不同的进程中。

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

    【讨论】:

    • 感谢 ganesh 的回复。使用您建议的播放工作就可以了
    猜你喜欢
    • 2021-08-12
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    相关资源
    最近更新 更多