[英]Android - BufferOverflowException while encoding aac audio using mediacodec
I am trying to encode some audio streams with aac
codec using Mediacodec
.我正在尝试使用
Mediacodec
使用aac
编解码器对一些音频流进行编码。 For this I'm using this implementation google cts ExtractDecodeEncodeMusTest .为此,我正在使用此实现google cts ExtractDecodeEncodeMusTest 。
For some aac files it throws BufferOverflowException
after encoding some frames.对于某些 aac 文件,它会在对某些帧进行编码后抛出
BufferOverflowException
。 To be more precise, it throws exception at line no 1030, encoderInputBuffer.put(decoderOutputBuffer);
更准确地说,它在第 1030 行抛出异常,
encoderInputBuffer.put(decoderOutputBuffer);
. .
I am configuring the outputAudioFormat
as following:我正在配置
outputAudioFormat
如下:
MediaFormat outputAudioFormat = MediaFormat.createAudioFormat(
inputAudioFormat.getString(MediaFormat.KEY_MIME),
inputAudioFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE),
inputAudioFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT)
);
outputAudioFormat.setInteger(MediaFormat.KEY_BIT_RATE, outputAudioBitRate);
I'm completely clueless about how to resolve this.我完全不知道如何解决这个问题。 Any kind of help would be really appreciated.
任何形式的帮助将非常感激。
Stacktrace with some log:带有一些日志的堆栈跟踪:
W/MPEG4Writer: Timed-out waiting for video track to reach final audio timestamp !
D/MPEG4Writer: Video track source stopping
Video track source stopped
Video track stopped. Stop source
Duration from tracks range is [0, 125135] us
Stopping writer thread
D/MPEG4Writer: 0 chunks are written in the last batch
D/MPEG4Writer: Writer thread stopped
W/System.err: java.nio.BufferOverflowException
at java.nio.ByteBuffer.put(ByteBuffer.java:611)
at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:256)
Sample file's info that causing the overflow:导致溢出的示例文件信息:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/storage/emulated/0/Sample/sample.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
creation_time : 2017-11-10T09:36:00.000000Z
encoder : Lavf57.71.100
Duration: 01:58:17.26, start: 0.000000, bitrate: 2726 kb/s
Stream #0:0(und): Video: h264, 1 reference frame (avc1 / 0x31637661), yuv420p(left), 1920x804 (1920x816) [SAR 1:1 DAR 160:67], 2497 kb/s, 23.98 fps, 23.98 tbr, 11988 tbn, 47.95 tbc (default)
Metadata:
creation_time : 2017-11-10T09:36:00.000000Z
handler_name : VideoHandler
Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 224 kb/s (default)
Metadata:
creation_time : 2017-11-10T09:36:00.000000Z
handler_name : SoundHandler
Update:更新:
Log says audioDecoderOutputBufferInfo.size= 12288 || encoderInputBuffer.limit()= 4096
日志说
audioDecoderOutputBufferInfo.size= 12288 || encoderInputBuffer.limit()= 4096
audioDecoderOutputBufferInfo.size= 12288 || encoderInputBuffer.limit()= 4096
before throwing the overflow exception.在抛出溢出异常之前,
audioDecoderOutputBufferInfo.size= 12288 || encoderInputBuffer.limit()= 4096
。
And log of decoderOutputAudioFormat
:和
decoderOutputAudioFormat
日志:
audio decoder: output format changed: {sample-rate=48000, pcm-encoding=2, mime=audio/raw, channel-count=6}
BufferOverflowException
happens when there is no agreement between the producer (eg decoder) and the consumer (eg encoder) about the size of the buffers. BufferOverflowException
当生产者(例如解码器)和消费者(例如编码器)之间就缓冲区的大小没有达成一致时,就会发生BufferOverflowException
。
When you configure the encoder, it allocates input buffers based on the information in the MediaFormat
that it receives.当您配置编码器时,它会根据它接收到的
MediaFormat
中的信息分配输入缓冲区。 The standard packet size for AAC is 1024 frames. AAC 的标准数据包大小为 1024 帧。 Frame size = sample size * channel count.
帧大小 = 样本大小 * 通道数。 PCM 16-bit (default encoding) uses 2 bytes per sample.
PCM 16 位(默认编码)每个样本使用 2 个字节。
So, based on the information you gave it, the encoder is supposed to allocate buffers of size 1024 * 2 * 6 = 12288 bytes.因此,根据您提供的信息,编码器应该分配大小为 1024 * 2 * 6 = 12288 字节的缓冲区。 However, in your case it actually allocates only 4096 bytes.
但是,在您的情况下,它实际上只分配了 4096 个字节。 So I assume that the encoder ignored the
channel-count
property and defaulted to 2 channels.所以我假设编码器忽略了
channel-count
属性并默认为 2 个通道。 Possibly, it printed some warning to the log.可能,它向日志打印了一些警告。
One thing that you can still do is to manually reduce the number of channels in every frame to at most 2. You will need to allocate a new buffer and copy the decoded data into it while skipping every Nth sample.您仍然可以做的一件事是手动将每帧中的通道数减少到最多 2 个。您需要分配一个新缓冲区并将解码数据复制到其中,同时跳过每个第 N 个样本。 And don't forget to
rewind
the resulting buffer before you pass it to the encoder.并且不要忘记在将结果缓冲区传递给编码器之前
rewind
它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.