Search code examples
androidandroid-mediacodecstagefright

Intermittent native crash in libstagefright_soft_aacdec.so when using MediaCodec (AAC decoding)


I'm getting an intermittent low level crash when using Android's MediaCodec API. I'm dealing with multiple (up to 8) raw AAC audio streams so I configure 8 MediaCodec instances and then feed them sample buffers as they arrive (from a single thread so no parallel decoding).

This mostly works fine but every so often I get a low level crash at the start of the session. The tombstone trace looks like this:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/hammerhead/hammerhead:6.0/MRA58K/2256973:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 32229, tid: 5451, name: gle.aac.decoder  >>> com.wizix.gridme <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4c
    r0 00007fff  r1 000002fc  r2 0000004c  r3 0000000d
    r4 00000010  r5 0000004c  r6 97adfc54  r7 0000000d
    r8 97ae0014  r9 00000001  sl 94a8c020  fp 97adf5b8
    ip 99c0ef08  sp 9422acd4  lr 000000f0  pc 99bf8cc0  cpsr 800f0030
    d0  0000000000000000  d1  0000000000000000
    d2  0000000000000000  d3  0000000000000000
    d4  fff9fff8fff70001  d5  fffdfffbfffafff7
    d6  fffdfffa00010003  d7  fff0fffb00040003
    d8  0000000000000000  d9  0000000000000000
    d10 0000000000000000  d11 0000000000000000
    d12 0000000000000000  d13 0000000000000000
    d14 0000000000000000  d15 0000000000000000
    d16 0000000000000000  d17 0000000000000000
    d18 0000000000000000  d19 0000000000000000
    d20 3f80000000000000  d21 0000000000000000
    d22 000000003f800000  d23 0000000000000000
    d24 bf56c16c16c15177  d25 3e21ee9ebdb4b1c4
    d26 392f1976b7ed8fc0  d27 b94377ce858a5d48
    d28 35e127004971adb1  d29 b94377ce858a5d48
    d30 3ff0000000000000  d31 3ba3198a2e000000
    scr 60000013

backtrace:
    #00 pc 00028cc0  /system/lib/libstagefright_soft_aacdec.so (maxSubbandSample(long**, long**, int, int, int, int)+85)
    #01 pc 0002a205  /system/lib/libstagefright_soft_aacdec.so (calculateSbrEnvelope(QMF_SCALE_FACTOR*, SBR_CALCULATE_ENVELOPE*, SBR_HEADER_DATA*, SBR_FRAME_DATA*, long**, long**, int, long*, unsigned int, int)+2644)
    #02 pc 000243a5  /system/lib/libstagefright_soft_aacdec.so (sbr_dec(SBR_DEC*, short*, short*, SBR_DEC*, short*, int, int, SBR_HEADER_DATA*, SBR_FRAME_DATA*, SBR_PREV_FRAME_DATA*, int, PS_DEC*, unsigned int)+632)
    #03 pc 00015a4d  /system/lib/libstagefright_soft_aacdec.so (sbrDecoder_Apply+740)
    #04 pc 0000ff8b  /system/lib/libstagefright_soft_aacdec.so (aacDecoder_DecodeFrame+610)
    #05 pc 0000ef15  /system/lib/libstagefright_soft_aacdec.so (android::SoftAAC2::onQueueFilled(unsigned int)+860)
    #06 pc 000224df  /system/lib/libstagefright_omx.so (android::SimpleSoftOMXComponent::onMessageReceived(android::sp<android::AMessage> const&)+242)
    #07 pc 000233d3  /system/lib/libstagefright_omx.so
    #08 pc 0000b2c9  /system/lib/libstagefright_foundation.so (android::AHandler::deliverMessage(android::sp<android::AMessage> const&)+16)
    #09 pc 0000d253  /system/lib/libstagefright_foundation.so (android::AMessage::deliver()+54)
    #10 pc 0000bcb7  /system/lib/libstagefright_foundation.so (android::ALooper::loop()+222)
    #11 pc 0001006d  /system/lib/libutils.so (android::Thread::_threadLoop(void*)+112)
    #12 pc 0003f3e7  /system/lib/libc.so (__pthread_start(void*)+30)
    #13 pc 00019b43  /system/lib/libc.so (__start_thread+6)

Where do I even start when trying to diagnose this issue?


Solution

  • Found the solution in the end. I was configuring my decoder with an invalid csd-0 stream header. It was 7 bytes in length when it only needed to be 3 bytes. The first 3 bytes were correct and thus the decoder was being configured OK but those next 4 bytes must have been interpreted as part of the stream data itself causing a corruption in the first audio packet. Amazingly it still works most of the time but sometimes that corruption was clearly enough to crash the decoder.

    The invalid CSD header was: 0xF8, 0xF0, 0x21, 0x2E, 0x00, 0xBA, 0x00

    The correct CSD header was: 0xF8, 0xF0, 0x20

    I'm working with 16KHZ, mono, AAC Low Delay so my decoder config looks like this:

    byte[] asc = new byte[]{(byte) 0xF8, (byte) 0xF0, 0x20}; // here is the valid csd data
    ByteBuffer ascBuf = ByteBuffer.wrap(asc);
    mediaFormat.setByteBuffer("csd-0", ascBuf);             
    m_decoder = MediaCodec.createByCodecName("OMX.google.aac.decoder");            
    m_decoder.configure(mediaFormat, null, null, 0);
    

    Explanation:

    Based on this for reference : http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio

    The CSD is made up of Object Type, Frquency Index, Channel config.

    For me this is:

    • Object type = 39: ER AAC ELD (Enhanced Low Delay)

    • Frequency index = 8 (16000Hz)

    • Channel configuration = 1 (mono)

    First 5 bits is the object type OR 31 if object type is greater than 31, which it is and then the next 6 bits are used instead So: 11111

    Next 6 bits = 39 So: 000111

    Next 4 bits is the frequency index, 8 = 16KHz So: 1000

    Next 4 bits is channel config = 1 So 0001

    That is 20 bits but we can only work with bytes so must round to nearest 8 and pad with zeros

    So the final csd data is:

    1111 1000 1111 0000 0010 0000
    

    Which is F8 F0 20 in hex.