gpt4 book ai didi

java - Bytebuffor 操作在从小 amr 文件中提取原始数据时导致 Android 应用程序崩溃

转载 作者:行者123 更新时间:2023-12-02 05:45:23 24 4
gpt4 key购买 nike

当我使用 mediaCodec 解码 AMR 文件时,它会输出一个字节缓冲区,但是当我尝试将字节缓冲区转换为 double 组时,应用程序崩溃了。

我尝试从字节缓冲区中取出一个字节,应用程序也崩溃了。对字节缓冲区的任何操作都会导致我的应用程序崩溃。

decoder.start();
inputBuffers = decoder.getInputBuffers();
outputBuffers = decoder.getOutputBuffers();
end_of_input_file = false;

MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
ByteBuffer data = readData(info);

int samplesRead = info.size;

byte[] bytesArray = new byte[data.remaining()];
bytesArray = getByteArrayFromByteBuffer(data);

here the app crashes.

这是 readData 方法:

 private ByteBuffer readData(MediaCodec.BufferInfo info) {
if (decoder == null)
return null;

for (;;) {
// Read data from the file into the codec.
if (!end_of_input_file) {
int inputBufferIndex = decoder.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
int size = mExtractor.readSampleData(inputBuffers[inputBufferIndex], 0);
if (size < 0) {
// End Of File
decoder.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
end_of_input_file = true;
} else {
decoder.queueInputBuffer(inputBufferIndex, 0, size, mExtractor.getSampleTime(), 0);
mExtractor.advance();
}
}
}

// Read the output from the codec.
if (outputBufferIndex >= 0)
// Ensure that the data is placed at the start of the buffer
outputBuffers[outputBufferIndex].position(0);

outputBufferIndex = decoder.dequeueOutputBuffer(info, 10000);
if (outputBufferIndex >= 0) {
// Handle EOF
if (info.flags != 0) {
decoder.stop();
decoder.release();
decoder = null;
return null;
}

// Release the buffer so MediaCodec can use it again.
// The data should stay there until the next time we are called.
decoder.releaseOutputBuffer(outputBufferIndex, false);

return outputBuffers[outputBufferIndex];

} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
// This usually happens once at the start of the file.
outputBuffers = decoder.getOutputBuffers();
}
}
}

这是 getByteArrayFromByteBuffer 方法:

private static byte[] getByteArrayFromByteBuffer(ByteBuffer byteBuffer) {
byte[] bytesArray = new byte[byteBuffer.remaining()];
byteBuffer.get(bytesArray, 0, bytesArray.length);
return bytesArray;
}
````


I would like to get the output of the decoder into a double array.

最佳答案

您的代码中有两个错误/误解。

第一期:

        // Read the output from the codec.
if (outputBufferIndex >= 0)
// Ensure that the data is placed at the start of the buffer
outputBuffers[outputBufferIndex].position(0);

outputBufferIndex = decoder.dequeueOutputBuffer(info, 10000);

在调用dequeueOutputBuffer之前,你无法知道它将返回什么输出缓冲区。即使这样,您也无法控制编解码器将其输出放置在缓冲区中的位置。解码器将从可用缓冲区中选择一个缓冲区,并将输出数据放置在该缓冲区中所需的任何位置。 (实际上它几乎总是在开始处。)

如果您想在输出缓冲区内以任何特定方式设置位置/限制,请在 dequeueOutputBuffer 将其返回给您之后执行此操作。

只需删除整个 if 语句和position() 调用即可。

第二个错误,这是真正的主要问题:

            // Release the buffer so MediaCodec can use it again.
// The data should stay there until the next time we are called.
decoder.releaseOutputBuffer(outputBufferIndex, false);

return outputBuffers[outputBufferIndex];

只有在 dequeueOutputBuffer 返回缓冲区后,您才可以接触和使用 outputBuffers 中的缓冲区,直到通过 releaseOutputBuffer 将其返回给解码器为止。正如您的评论所说,在 releaseOutputBuffers 之后,MediaCodec 可以再次使用它。您的 ByteBuffer 变量只是对编解码器可以写入新输出的相同数据的引用 - 它还不是这里的副本。因此,在使用完 ByteBuffer 对象之前,您无法调用releaseOutputBuffer。

奖励积分:在使用 ByteBuffer 之前,最好为其设置位置/限制,如下所示:

outputBuffers[outputBufferIndex].position(info.offset);
outputBuffers[outputBufferIndex].limit(info.offset + info.size);

一些解码器隐式地执行此操作,但不一定是全部。

关于java - Bytebuffor 操作在从小 amr 文件中提取原始数据时导致 Android 应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56100282/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com