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?
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.