What I am trying to do: 使用Android的MediaCodec将原始PCM音频样本编码为原始AAC文件 .
The problem I have: 当我使用FFMPEG将生成的原始AAC文件打包到M4A容器中时,FFMPEG抱怨文件中缺少编解码器参数 .
Details:
由于我找不到生成输出AAC文件的音频编码器的任何MediaCodec示例代码,我尝试将视频编码器修改为音频编码器 . 原始代码在这里:source_code
我配置了这样的音频编码器:
mEncoderFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", (int)mAudioSampleRate, 2);
// redundant?
mEncoderFormat.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
mEncoderFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,
MediaCodecInfo.CodecProfileLevel.AACObjectELD);
mEncoderFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, kSampleRates);
mEncoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates);
mEncoderFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
testEncoderWithFormat("audio/mp4a-latm", mEncoderFormat);
try {
codec.configure(
mEncoderFormat,
null /* surface */,
null /* crypto */,
MediaCodec.CONFIGURE_FLAG_ENCODE);
} catch (IllegalStateException e) {
Log.e(TAG, "codec '" + componentName + "' failed configuration.");
return;
}
Log.d(TAG, " testEncoder configured with format = " + format);
然后我给编码器每帧提供10ms的PCM采样 . 编码器获取每个帧,生成一个比特流帧,然后将比特流写入FileOutputStream . 循环一直持续到输入文件结束 .
代码运行完成 . 我'adb pull'将生成的AAC文件从设备传送到我的PC,并使用FFMPEG来读取它 . 下面是命令和错误FFMPEG吐出:
$ ffmpeg -f aac -i BlessedNoColor_nexus7_api18.aac
ffmpeg version N-45739-g04bf2e7 Copyright (c) 2000-2012 the FFmpeg developers
built on Oct 20 2012 00:20:36 with gcc 4.7.2 (GCC)
configuration: --enable-gpl --enable-version3 --disable-pthreads --enable-runt
ime-cpudetect --enable-avisynth --enable-bzlib --enable-frei0r --enable-libass -
-enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libfreetype --enab
le-libgsm --enable-libmp3lame --enable-libnut --enable-libopenjpeg --enable-libo
pus --enable-librtmp --enable-libschroedinger --enable-libspeex --enable-libtheo
ra --enable-libutvideo --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-li
bvorbis --enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid --ena
ble-zlib
libavutil 51. 76.100 / 51. 76.100
libavcodec 54. 67.100 / 54. 67.100
libavformat 54. 33.100 / 54. 33.100
libavdevice 54. 3.100 / 54. 3.100
libavfilter 3. 19.103 / 3. 19.103
libswscale 2. 1.101 / 2. 1.101
libswresample 0. 16.100 / 0. 16.100
libpostproc 52. 1.100 / 52. 1.100
[aac @ 00000000002efae0] channel element 2.0 is not allocated
[aac @ 00000000003cf520] decoding for stream 0 failed
[aac @ 00000000003cf520] Could not find codec parameters for stream 0 (Audio: aac, 0 channels, s16): unspecified sample rate
Consider increasing the value for the 'analyzeduration' and 'probesize' options
[aac @ 00000000003cf520] Estimating duration from bitrate, this may be inaccurate
BlessedNoColor_nexus7_api18.aac: could not find codec parameters
My questions:
-
我在调用codec.start()之前配置了编码器 . 为什么生成的AAC文件缺少编解码器参数?
-
在原始视频编解码器示例中,参数"csd-0"从编码器传递到解码器,但未明确写入比特流文件 . 我是否需要明确地将它们写入AAC文件?
-
我将输入PCM样本分成每帧10ms,这不一定产生完整的输出包 . 对于每个输入帧,我只需将编码器输出写入文件即可 . 这是一个值得关注的问题吗?
任何帮助将深表感谢 . 如果有一个示例项目可以完成我在这里尝试做的事情,那就太棒了 . 如果我的源代码可以帮助您,我会发布它 . 我需要做一些清理工作 . 谢谢!
Edit :将 Headers 从"Elementary AAC file generated by MediaCodec missing codec parameters"更改为"How to generate the AAC ADTS elementary stream with Android MediaCodec"
1 回答
我终于生成了可在Android设备和Windows主机上播放的AAC文件 . 我在这里发布我的解决方案,希望它可以帮助其他人 .
首先,我之前关于Android MediaCodec编码器生成基本AAC流的假设不准确 . MediaCodec编码器生成原始AAC流 . 这就是无法播放文件的原因 . 原始AAC流需要转换为可播放格式,例如ADTS流 . 我已经改变了这篇文章的 Headers ,以反映我的新理解 . 有一个another post提出了类似的问题,并得到了很好的答案 . 但是,新手可能不一定了解那里的简要描述 . 我第一次阅读那篇文章时并没有得到它 .
因此,为了生成可以由媒体播放器播放的AAC比特流,我从fadden在他的第一条评论中给出的EncoderTest示例开始,但是修改了原始代码以在每个输出帧(访问单元)中添加ADTS标头,并将结果流写入文件(使用以下代码片段替换原始代码的第248到267行):
在循环之外,我像这样定义了addADTStoPacket函数:
我还添加了代码来控制如何停止生成AAC ADTS流,但这是特定于应用程序的,所以我在此不再赘述 . 通过所有这些更改,生成的AAC文件可以在Android设备上,在我的Windows PC上播放,ffmpeg对它们感到满意 .