7

我想将音频文件解码为原始 PCM 数据,以将其流式传输到本地网络中的播放设备。为此,我使用 API 级别 16 引入的新MediaExtractorMediaCodec类。该设备要求 PCM 数据为 44,100 kHz,具有 2 个通道和 16 位样本大小。只要输入文件大致符合这些要求,它就可以正常工作。但是,每当我解码一个 MP3 文件时,它使用 - 例如 - 32,000 kHz 的采样率并且可能只有一个通道,然后我没有从 MediaCodec 类获得所需的输出。

看来我无法指定 MediaCodec 类的输出格式。所以我决定实例化另一个 MediaCodec 对象,将原始数据重新编码成我想要的格式。根据支持的媒体格式列表, 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 实例,并且可以为我提供一个工作示例?

4

1 回答 1

6

根据我们在评论中的对话,这个答案与使用 OpenSL 将音频数据解码为 PCM 有关。不幸的是,我无法使用该MediaCodec课程提供类似的答案。

首先,设置一个 Android NDK 项目(使用 Eclipse:右键单击项目,Android 工具 -> 添加本机支持...)。然后,在创建的 Android.mk 文件中,至少您需要链接到 OpenSL 库:

LOCAL_LDLIBS += -lOpenSLES

如果您对 NDK 项目还不满意,旧互联网上有大量教程,例如,这里这里

一旦你有一个 NDK 项目工作,一般目标将是设置一个音频播放器,作为 PCM 的解码器。实际上,NDK 示例中有一个示例正是这样做的。它比你要制作一个功能最少的工具要复杂一些,但它应该能让你继续前进。在这个链接上有一个非常容易理解的描述(搜索“Decode audio to PCM”)。我在评论中为您提供了相关OpenSL 规范的链接,但它又出现了。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,或者(更好地)从本机代码流式传输数据。

于 2013-12-25T14:28:06.137 回答