使用 MediaCodec(AAC 解码)时 libstagefright_soft_aacdec.so 中的间歇性本机崩溃
Intermittent native crash in libstagefright_soft_aacdec.so when using MediaCodec (AAC decoding)
我在使用 Android 的 MediaCodec API 时出现间歇性低级别崩溃。我正在处理多个(最多 8 个)原始 AAC 音频流,因此我配置了 8 个 MediaCodec 实例,然后在它们到达时将样本缓冲区提供给它们(来自单个线程,因此没有并行解码)。
这大部分工作正常,但有时我会在会话开始时遇到低级别的崩溃。逻辑删除痕迹如下所示:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
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)
在尝试诊断此问题时,我什至从哪里开始?
最终找到了解决方案。我正在使用无效的 csd-0 流 header 配置我的解码器。当它只需要 3 个字节时,它的长度是 7 个字节。前 3 个字节是正确的,因此解码器配置正常,但接下来的 4 个字节必须被解释为流数据本身的一部分,导致第一个音频数据包损坏。令人惊讶的是,它在大部分时间仍然有效,但有时这种损坏显然足以使解码器崩溃。
无效的 CSD header 是:0xF8, 0xF0, 0x21, 0x2E, 0x00, 0xBA, 0x00
正确的 CSD header 是:0xF8, 0xF0, 0x20
我正在使用 16KHZ、单声道、AAC 低延迟,所以我的解码器配置如下所示:
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);
解释:
基于此供参考:http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio
CSD 由 Object 类型、频率索引、通道配置组成。
对我来说这是:
Object 类型 = 39:ER AAC ELD(增强型低延迟)
频率指数 = 8 (16000Hz)
声道配置 = 1(单声道)
前 5 位是 object 类型,如果 object 类型大于 31,则为 31,然后使用接下来的 6 位
所以:11111
接下来的 6 位 = 39
所以:000111
接下来的4位是频率索引,8 = 16KHz
所以:1000
接下来的4位是channel config = 1
所以0001
那是 20 位,但我们只能处理字节,因此必须四舍五入到最接近的 8 并用零填充
所以最终的csd数据为:
1111 1000 1111 0000 0010 0000
这是十六进制的 F8 F0 20
。
我在使用 Android 的 MediaCodec API 时出现间歇性低级别崩溃。我正在处理多个(最多 8 个)原始 AAC 音频流,因此我配置了 8 个 MediaCodec 实例,然后在它们到达时将样本缓冲区提供给它们(来自单个线程,因此没有并行解码)。
这大部分工作正常,但有时我会在会话开始时遇到低级别的崩溃。逻辑删除痕迹如下所示:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
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)
在尝试诊断此问题时,我什至从哪里开始?
最终找到了解决方案。我正在使用无效的 csd-0 流 header 配置我的解码器。当它只需要 3 个字节时,它的长度是 7 个字节。前 3 个字节是正确的,因此解码器配置正常,但接下来的 4 个字节必须被解释为流数据本身的一部分,导致第一个音频数据包损坏。令人惊讶的是,它在大部分时间仍然有效,但有时这种损坏显然足以使解码器崩溃。
无效的 CSD header 是:0xF8, 0xF0, 0x21, 0x2E, 0x00, 0xBA, 0x00
正确的 CSD header 是:0xF8, 0xF0, 0x20
我正在使用 16KHZ、单声道、AAC 低延迟,所以我的解码器配置如下所示:
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);
解释:
基于此供参考:http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio
CSD 由 Object 类型、频率索引、通道配置组成。
对我来说这是:
Object 类型 = 39:ER AAC ELD(增强型低延迟)
频率指数 = 8 (16000Hz)
声道配置 = 1(单声道)
前 5 位是 object 类型,如果 object 类型大于 31,则为 31,然后使用接下来的 6 位
所以:11111
接下来的 6 位 = 39
所以:000111
接下来的4位是频率索引,8 = 16KHz
所以:1000
接下来的4位是channel config = 1
所以0001
那是 20 位,但我们只能处理字节,因此必须四舍五入到最接近的 8 并用零填充
所以最终的csd数据为:
1111 1000 1111 0000 0010 0000
这是十六进制的 F8 F0 20
。