Android MediaCodec AAC 编码器
Posted
技术标签:
【中文标题】Android MediaCodec AAC 编码器【英文标题】:Android MediaCodec AAC encoder 【发布时间】:2013-02-22 22:03:15 【问题描述】:我使用自 API 级别 16 起由 android SDK 提供的 MediaCodec
类和 OMX.SEC.aac.enc
编码器将音频编码为文件。我得到了音频
来自AudioRecord
类的输入。我的AudioRecord
类实例配置如下:
bufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
recorder = new AudioRecord(MediaRecorder.Audiosource.MIC, 44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_DEFAULT, bufferSize);
我能够播放来自AudioRecord
实例的原始数据,因此问题不存在。
我将AudioRecord
实例的输出写入ByteBuffer
实例,并将其从编码器传递到可用的输入缓冲区。编码器的输出被写入 SD 卡上的文件。
这些是我的MediaCodec
实例的配置参数:
codec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
VLC 告诉我我的 aac 文件中没有流。命令FFMPEG -i @filename@
给我以下错误:处理输入时发现无效数据。我测试的所有媒体播放器都无法播放我的文件。
为什么我无法播放我的文件?我在LogCat
中没有收到OpenMAX
错误,并且应用程序在编码时不会崩溃。我写了一个工作原理相同的视频编码器,它工作正常。
这是将数据从AudioRecord
实例读取到缓冲区的代码:
new Thread()
public void run()
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bufferSize);
int read = 0;
while (isRecording)
read = recorder.read(byteBuffer, bufferSize);
if(AudioRecord.ERROR_INVALID_OPERATION != read)
encoder.add(byteBuffer);
recorder.stop();
.start();
我的编码器的 add 函数将一个缓冲区的内容复制到另一个缓冲区:
public void add(ByteBuffer input)
if (!isRunning)
return;
if (tmpInputBuffer == null)
tmpInputBuffer = ByteBuffer.allocate(input.capacity());
if (!tmpBufferClear)
Log.e("audio encoder", "deadline missed"); //TODO lower bit rate
synchronized (tmpInputBuffer)
tmpInputBuffer.clear();
tmpInputBuffer.put(input);
tmpInputBuffer.notifyAll();
Log.d("audio encoder", "pushed data into tmpInputBuffer");
以下代码用于占用编码器的输入缓冲区:
new Thread()
public void run()
while (isRunning)
if (tmpInputBuffer == null)
continue;
synchronized (tmpInputBuffer)
if (tmpBufferClear)
try
Log.d("audio encoder", "falling asleep");
tmpInputBuffer.wait(); //wait when no input is available
catch (InterruptedException e)
e.printStackTrace();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
int inputBufferIndex;
do
inputBufferIndex = codec.dequeueInputBuffer(-1);
while (inputBufferIndex < 0);
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
Log.d("input buffer size", String.valueOf(inputBuffer.capacity()));
Log.d("tmp input buffer size", String.valueOf(tmpInputBuffer.capacity()));
inputBuffer.put(tmpInputBuffer.array());
tmpInputBuffer.clear();
codec.queueInputBuffer(inputBufferIndex, 0, tmpInputBuffer.capacity(), 0, 0);
tmpBufferClear = true;
Log.d("audio encoder", "added to input buffer");
.start();
我将编码器的输出写入本地文件,如下所示:
new Thread()
public void run()
while (isRunning)
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, -1);
while (outputBufferIndex >= 0)
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
try
fileWriter.write(outData, 0, outData.length);
catch (IOException e)
e.printStackTrace();
codec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 0);
Log.d("audio encoder", "removed from output buffer");
codec.stop();
try
fileWriter.close();
catch (IOException e)
e.printStackTrace();
.start();
tmpBufferClear = true;
Log.d("audio encoder", "added to input buffer");
.start();
【问题讨论】:
张贴完整的方法。用 start() stop().. 谢谢。 另外,看看这个线程 - code.google.com/p/spydroid-ipcamera/issues/detail?id=43 他们似乎有一段用于在那里录制 AAC 的工作代码。 @Sergey Benner,他们不使用 MediaCodec 类。 MediaRecorder 类用于 Spydroid。如果 MediaCodec 类不起作用,该类将是我的第二选择。 你能解决这个问题吗?我在编码现有的 wav 文件时遇到了类似的问题。编码过程没有错误完成,创建的文件具有合理的文件大小,但没有播放器能够播放。 我也遇到过这个问题,aac文件KEY_BIT_RATE不是64kps,而是128kps。可能这就是aac文件无法播放的原因。我还不能做对。 【参考方案1】:我猜你错过了MediaMuxer 课程。例如,如果您想将从 MediaCodec 获取的内容写入文件,则需要它。
【讨论】:
OP 要求 API 16,MediaMuxer 是通过 API 18 引入的以上是关于Android MediaCodec AAC 编码器的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Android MediaCodec 生成 AAC ADTS 基本流
研究Android音视频-3-在Android设备上采集音视频并使用MediaCodec编码为H.264
研究Android音视频-3-在Android设备上采集音视频并使用MediaCodec编码为H.264