当我使用mediaCodec解码AMR文件时,它会输出一个字节缓冲区,但是当我尝试将字节缓冲区转换为双精度数组时,应用程序将崩溃。
我尝试从字节缓冲区中取出一个字节,并且应用程序也崩溃了。字节缓冲区上的任何操作都会导致我的应用崩溃。
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.
答案 0 :(得分:0)
您的代码中有两个错误/误解。
第一期:
// 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);
一些解码器隐式地执行此操作,但不一定全部执行该操作。