求助:能否通过MediaCodec将AAC解码为PCM Float?输出始终为16位
如何用MediaCodec将AAC解码为PCM Float格式?
我之前做音频解码时也碰到过一模一样的问题——明明在MediaFormat里设置了KEY_PCM_ENCODING为ENCODING_PCM_FLOAT,但解码器输出还是16位PCM。这里给你几个关键的排查点和解决方案:
先确认解码器是否真的支持PCM Float输出
很多时候,即使你手动设置了KEY_PCM_ENCODING参数,硬件解码器可能并不支持这个输出格式,会自动 fallback 到默认的16位PCM。你可以在configure之后,通过解码器的实际输出格式来验证:mediaDecode.configure(format, null, null, 0); // 获取解码器实际使用的输出格式 MediaFormat actualOutputFormat = mediaDecode.getOutputFormat(); int actualEncoding = actualOutputFormat.getInteger(MediaFormat.KEY_PCM_ENCODING); // 打印或者判断实际编码格式 if (actualEncoding == AudioFormat.ENCODING_PCM_FLOAT) { // 解码器支持Float输出 } else { // 解码器不支持,只能拿到16位PCM }正确读取Float格式的输出Buffer
如果解码器确实支持PCM Float,你需要用FloatBuffer来读取输出数据,而不是习惯用的ShortBuffer。处理输出的代码大概是这样:int outputBufferId = mediaDecode.dequeueOutputBuffer(bufferInfo, 10000); if (outputBufferId >= 0) { ByteBuffer outputBuffer = mediaDecode.getOutputBuffer(outputBufferId); MediaFormat outputFormat = mediaDecode.getOutputFormat(outputBufferId); int encoding = outputFormat.getInteger(MediaFormat.KEY_PCM_ENCODING); if (encoding == AudioFormat.ENCODING_PCM_FLOAT) { // 转换为FloatBuffer读取数据 FloatBuffer floatBuffer = outputBuffer.asFloatBuffer(); float[] pcmFloatData = new float[floatBuffer.remaining()]; floatBuffer.get(pcmFloatData); // 在这里处理你的Float格式PCM数据 } else { // 处理16位PCM的情况 ShortBuffer shortBuffer = outputBuffer.asShortBuffer(); short[] pcm16BitData = new short[shortBuffer.remaining()]; shortBuffer.get(pcm16BitData); } mediaDecode.releaseOutputBuffer(outputBufferId, false); }兼容性方案:手动将16位PCM转为Float
如果你的目标设备解码器不支持PCM Float输出,也可以自己做格式转换。16位PCM的取值范围是-32768到32767,转换成Float格式只需要将每个short值除以32768.0f,得到-1.0f到1.0f之间的浮点值:short[] pcm16Bit = ...; // 从解码器获取的16位数据 float[] pcmFloat = new float[pcm16Bit.length]; for (int i = 0; i < pcm16Bit.length; i++) { pcmFloat[i] = pcm16Bit[i] / 32768.0f; }
另外补充一点:有些设备的软件解码器(比如OMX.google.aac.decoder)对PCM Float的支持会更好,如果硬件解码器不行,可以尝试指定使用软件解码器。
内容的提问来源于stack exchange,提问作者Nick Tseng
相关产品推荐
相关产品推荐

