Я использую mediaCodec для преобразования изображений, снятых с помощью camera2 api, в видео. Проблема возникла, когда я обнаружил, что YV12 не поддерживается на некоторых устройствах.
Когда я использовал YV12 в качестве входного формата изображения и COLOR_FormatYUV420SemiPlanar в качестве выходного, размер входного буфера и захваченного изображения точно такой же. И это хорошо работает.
Но когда я использовал YUV_420_888 в качестве формата входного изображения, размер изображения увеличился, в то время как размер входного буфера такой же, как и раньше, что дало мне исключение переполнения буфера.
Более конкретно,
Размер входного буфера MediaCodec всегда: ширина * высота * 3/2
Но размер входного изображения в формате YUV_420_888 получается: ширина * высота * 2
Я не уверен, как передать это изображение в медиа-кодек, не вызывая переполнения буфера и не ставя под угрозу качество.
Любая помощь будет оценена!
Код для настройки 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();
}