12

我正在尝试使用 Android 上的 MediaCodec API 来解码 AAC 流。(它是原始 AAC。)我尝试使用 MediaFormat.createAudioFormat() 创建要传递给 MediaCodec.configure() 的格式对象,但在使用 AAC (audio/mp4a-latm) 时我不断收到错误消息。(虽然它适用于 MP3(音频/mpeg)......)

最后,我为 AAC 文件创建了一个 MediaExtractor,并查看了它生成的格式对象。我看到它包含一个 ByteBuffer 的键“csd-0”,它由两个字节组成,两个字节的值都是 0x12。如果我在用于配置 AAC 编解码器的格式对象中包含该键和值,则一切正常。

有谁知道发生了什么?该文档指出我不应该配置该密钥。有没有人有指向 MediaCodec 示例的指针来解码 AAC 文件而不使用 MediaExtractor 生成格式对象?

4

3 回答 3

4

是的,编解码器配置 2 个字节是您收到的初始值。是的,它是原始的 aac 数据块。您可以看到我在编码时如何得出以下格式。我最初尝试遵循文档,该文档说它们是 latm 格式,并尝试对其进行解析。然后我在 android 文档上发现了一些“差异”,说输出确实是原始块。那时知道,这只是为我的需要选择一个容器的问题。特别是,我需要 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);
于 2013-06-28T03:55:10.910 回答
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);
于 2014-03-12T03:10:46.343 回答
0

在我测试的少数设备上解码/播放 AAC 内容没有问题。我的方法是首先使用 MediaExtractor 来设置数据源,然后初始化 MediaFormat,最后在循环中完成工作,其中缓冲区从 MediaCodec 传入/传出。对于我使用 null 的表面,因为这只是一个音频播放器,所以没有什么可以显示的。

于 2014-06-01T18:49:48.607 回答