使用 MediaCodec 编码数据获取 BufferOverflowException
Getting BufferOverflowException with MediaCodec encode data
我正在使用 Camera2
API 从相机获取数据,然后使用图像 reader、OnImageAvailableListener
实现,我将相机数据插入队列,然后使用新的 MediaCodec.Callback
实现我想编码数据
这是我初始化编解码器的方式:
MediaCodecInfo codecInfo = selectCodec(MIMETYPE_VIDEO_AVC);
MediaFormat format = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_AVC, cameraRawData.getSize().getWidth(), cameraRawData.getSize().getHeight());
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
format.setLong(MediaFormat.KEY_MAX_INPUT_SIZE, Long.MAX_VALUE);
try {
encoder = MediaCodec.createByCodecName(codecInfo.getName());
} catch (IOException e) {
Log.e(TAG, "error creating encoder", e);
throw new RuntimeException(e);
}
onInputBufferAvailable
实现:
ByteBuffer inputBuffer = codec.getInputBuffer(index);
ImageData imageData = imageDataQueue.poll();
if (imageData != null) {
if (inputBuffer != null) {
Log.i(TAG, "onInputBufferAvailable: " + imageData.getBuffer().length);
inputBuffer.clear();
byte[] bytes = imageData.getBuffer();
try {
Log.w(TAG, "before failure, the limit is: " + inputBuffer.limit());
Log.w(TAG, "before failure, the byte array size is: " + bytes.length);
inputBuffer.put(bytes);
} catch (Exception e) {
Log.e(TAG, "error", e);
}
codec.queueInputBuffer(index,
0,
imageData.getBuffer().length,
imageData.getPresentationTimeUs(),
0);
}
} else {
codec.queueInputBuffer(index,
0,
0,
0,
0);
}
最终,我收到异常:
java.nio.BufferOverflowException
at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:298)
at java.nio.ByteBuffer.put(ByteBuffer.java:732)
一些附加信息,ByteBuffer 限制设置为 12。
经过几个小时的调试,问题出在错误的颜色格式上。
而不是:
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatSurface);
应该是:
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatYUV420Flexible);
我正在使用 Camera2
API 从相机获取数据,然后使用图像 reader、OnImageAvailableListener
实现,我将相机数据插入队列,然后使用新的 MediaCodec.Callback
实现我想编码数据
这是我初始化编解码器的方式:
MediaCodecInfo codecInfo = selectCodec(MIMETYPE_VIDEO_AVC);
MediaFormat format = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_AVC, cameraRawData.getSize().getWidth(), cameraRawData.getSize().getHeight());
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
format.setLong(MediaFormat.KEY_MAX_INPUT_SIZE, Long.MAX_VALUE);
try {
encoder = MediaCodec.createByCodecName(codecInfo.getName());
} catch (IOException e) {
Log.e(TAG, "error creating encoder", e);
throw new RuntimeException(e);
}
onInputBufferAvailable
实现:
ByteBuffer inputBuffer = codec.getInputBuffer(index);
ImageData imageData = imageDataQueue.poll();
if (imageData != null) {
if (inputBuffer != null) {
Log.i(TAG, "onInputBufferAvailable: " + imageData.getBuffer().length);
inputBuffer.clear();
byte[] bytes = imageData.getBuffer();
try {
Log.w(TAG, "before failure, the limit is: " + inputBuffer.limit());
Log.w(TAG, "before failure, the byte array size is: " + bytes.length);
inputBuffer.put(bytes);
} catch (Exception e) {
Log.e(TAG, "error", e);
}
codec.queueInputBuffer(index,
0,
imageData.getBuffer().length,
imageData.getPresentationTimeUs(),
0);
}
} else {
codec.queueInputBuffer(index,
0,
0,
0,
0);
}
最终,我收到异常:
java.nio.BufferOverflowException
at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:298)
at java.nio.ByteBuffer.put(ByteBuffer.java:732)
一些附加信息,ByteBuffer 限制设置为 12。
经过几个小时的调试,问题出在错误的颜色格式上。 而不是:
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatSurface);
应该是:
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatYUV420Flexible);