我想将音频文件解码为原始PCM数据,以将其流式传输到本地网络中的播放设备。我使用API级别16引入的新MediaExtractor和MediaCodec类。设备要求PCM数据为44,100 kHz,有2个通道和16位样本大小。只要输入文件大致符合这些要求,这就可以正常工作。但是,无论何时我正在解码使用的文件 - 例如 - 32,000 kHz的采样率并且可能只有一个通道,那么我无法从MediaCodec类获得所需的输出。
因为它似乎我无法指定MediaCodec类的输出格式。所以我决定实例化另一个MediaCodec对象,将原始数据重新编码为我想要的格式。根据{{3}} Android列表自Android 4.1支持编码到PCM / Wave的列表。但是我无法创建编码为PCM / Wave 的MediaCodec对象。我尝试将各种MIME类型传递给MediaCodec.createEncoderByType(type);但我总是以IOException失败:
java.io.IOException: Failed to allocate component instance
at android.media.MediaCodec.native_setup(Native Method)
at android.media.MediaCodec.<init>(MediaCodec.java:210)
at android.media.MediaCodec.createEncoderByType(MediaCodec.java:194)
[..]
您是否有人能够成功创建编码为PCM / Wave 的MediaCodec实例,并可以为我提供一个有效的示例?
答案 0 :(得分:6)
根据我们在评论中的对话,这个答案涉及使用OpenSL将音频数据解码为PCM。不幸的是,我无法使用MediaCodec
类提供类似的答案。
首先,设置一个Android NDK项目(使用Eclipse:右键单击项目,Android工具 - &gt;添加原生支持...)。然后,在创建的Android.mk文件中,至少需要链接到OpenSL库:
LOCAL_LDLIBS += -lOpenSLES
如果您对NDK项目不熟悉,旧的互联网上会有很多教程,例如here和here。
一旦你有一个NDK项目工作,总的目标是设置一个音频播放器作为PCM的解码器。实际上有一个example in the NDK samples就是这样做的。它比你制作一个最小功能的工具要复杂一点,但它应该让你前进。有一个非常容易理解的描述发生了什么at this link(搜索“解码音频到PCM”)。我在评论中为您提供了相关OpenSL spec的链接,但又有了。指定数据接收器时需要使用的SLDataFormat_PCM
结构类似于:
SLDataFormat_PCM pcm = {
SL_DATAFORMAT_PCM,
2, // numChannels
SL_SAMPLINGRATE_44_1, // samplesPerSec
SL_PCMSAMPLEFORMAT_FIXED_16, // bitsPerSample
SL_PCMSAMPLEFORMAT_FIXED_16, // containerSize
SL_SPEAKER_FRONT_LEFT |
SL_SPEAKER_FRONT_RIGHT, // channelMask
SL_BYTEORDER_LITTLEENDIAN // endianness
};
按照示例和描述性指南,您将使用Android简单缓冲区队列数据定位器和上述数据格式定义SLDataSink。然后,播放器应为您提供一系列包含正确格式数据的缓冲区。然后,您可以将该数据传递回Java,或者(更好地)从本机代码中传输数据。