我正在尝试在Android上使用MediaCodec API来解码AAC流。 (它是原始的AAC。)我尝试使用MediaFormat.createAudioFormat()创建格式对象以传递给MediaCodec.configure(),但是在使用AAC(audio / mp4a-latm)时我一直遇到错误。 (它适用于MP3(audio / mpeg)虽然......)
最后,我为AAC文件创建了一个MediaExtractor,并查看了它正在生成的格式对象。我看到它包含了一个ByteBuffer的密钥“csd-0”,它由两个字节组成,值均为0x12。如果我在用于配置AAC编解码器的格式对象中包含该键和值,则一切正常。
有没有人知道发生了什么?文档说明我不应该配置该密钥。有没有人有一个指向MediaCodec示例的指针来解码AAC文件而不使用MediaExtractor来生成格式对象?
答案 0 :(得分:4)
是的,编解码器配置2个字节是您收到的初始值。是的,这是原始的aac数据块。你可以看到我在编码时如何得到下面的格式。我最初试图按照文档说,他们说它们是latm格式,并试图解析它。然后我在android文档上发现了一些'diff',表示输出确实是原始块。知道那时,只需要根据我的需要选择容器。特别是,我需要adts容器而不是flv或mp4。
将有效负载数据复制到一个足够容纳您容器的数组中,只需添加您的位。因此,在搜索我的解决方案后,我制作了以下代码:
profile = (configParams[0]>>3)&0x1f;
frequency_index = (this.configParams[0]&0x7) <<1 | (this.configParams[1]>>7) &0x1;
channel_config = (this.configParams[1]>>3) &0xf;
int finallength = encoded_length + 7;
ENCodedByteArray[0] = (byte) 0xff;
ENCodedByteArray[1] = (byte) 0xf1;
ENCodedByteArray[2] = (byte) ( ((profile - 1) << 6) + (frequency_index << 2) +(channel_config >> 2));
ENCodedByteArray[3] = (byte) (((channel_config & 0x3) << 6) + (finallength >> 11));
ENCodedByteArray[4] = (byte)( (finallength & 0x7ff) >> 3);
ENCodedByteArray[5] = (byte) (((finallength & 7) << 5) + 0x1f) ;
ENCodedByteArray[6] = (byte) 0xfc;
使用类似的东西:
byte chunkADTS[]=new byte[info.size + 7];
fillInADTSHeader(chunkADTS,info.size);
outputBuffers[bR].get(chunkADTS,7,info.size);
buffer.pushData(chunkADTS);
答案 1 :(得分:2)
我使用了以下代码并添加了删除ADTS标头的ES,它可以正常工作,但我真的不知道为什么要设置“csd-0”,否则编解码器会出错
decoder = MediaCodec.createDecoderByType("audio/mp4a-latm");
mMediaFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 44100,2);
byte[] bytes = new byte[]{(byte) 0x12, (byte)0x12};
ByteBuffer bb = ByteBuffer.wrap(bytes);
mMediaFormat.setByteBuffer("csd-0", bb);
答案 2 :(得分:0)
我在我测试的少数设备上解码/播放AAC内容没有问题。我的方法是首先使用MediaExtractor来设置数据源,然后初始化MediaFormat,最后在一个循环中进行工作,其中缓冲区是从/传出到/来自MediaCodec的。对于表面我使用null,因为这只是一个音频播放器所以没有什么可以显示。
我还将示例代码整理为Android库,可以在我的博客上找到:http://www.pocketmagic.net/2014/06/android-audio-player-using-mediacodec-mediaextractor/