简体   繁体   English

Android - 使用 mediacodec 编码 aac 音频时出现 BufferOverflowException

[英]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)
  • Device: Xiaomi POCO x3设备:小米 POCO x3
  • OS: Android 10操作系统:安卓 10

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM