我正在使用mediaCodec将使用camera2 api捕获的图像转换为视频。当我发现某些设备不支持YV12时,问题就来了。 当我使用YV12作为输入图像格式,并使用COLOR_FormatYUV420SemiPlanar作为输出时,输入缓冲区和图像的大小完全相同。而且效果很好。
但是当我使用YUV_420_888作为输入图像格式时,图像的大小增加了,而输入缓冲区的大小与以前相同,这给了我缓冲区溢出异常。 进一步来说, 输入缓冲区的大小始终为:宽度*高度* 3/2 但是使用YUV_420_888格式的输入图像的大小竟然是宽度*高度* 2
我不确定如何在不导致缓冲区溢出和不影响质量的情况下将该图像提供给mediacodec。
任何帮助将不胜感激!
用于配置MediaCode的代码
try {
MediaCodecInfo codecInfo = MediaCodecUtil.selectCodec(MIME_TYPE);
mediaCodec = MediaCodec.createByCodecName(codecInfo.getName());
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, size.getWidth(), size.getHeight());
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
colorFormat = MediaCodecUtil.selectColorFormat(codecInfo, MIME_TYPE);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 20);
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
} catch (IOException e) {
e.printStackTrace();
}
从相机拍摄图像的代码
try {
imageSize = CameraUtil.getImageSize(this, currentCameraId);
ImageReader imageReader = ImageReader.newInstance(imageSize.getWidth(), imageSize.getHeight(), ImageFormat.YUV_420_888, 1);
imageReaderListener = new ImageReaderListener(this);
imageReader.setOnImageAvailableListener(imageReaderListener, backgroundHandler);
List<Surface> outputSurfaces = new ArrayList<>(2);
outputSurfaces.add(imageReader.getSurface());
Surface preview = new Surface(textureView.getSurfaceTexture());
outputSurfaces.add(preview);
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
captureBuilder.addTarget(imageReader.getSurface());
captureBuilder.addTarget(preview);
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
cameraDevice.createCaptureSession(outputSurfaces,
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
if (cameraDevice == null) {
return;
}
try {
mSession = session;
session.setRepeatingRequest(captureBuilder.build(), null, backgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Util.printLogs(CameraActivity.this, TAG, "Capturing picture failed");
}
}, backgroundHandler);
} catch (Exception e) {
e.printStackTrace();
}