Android 对于YUV_420_888图像格式,MediaCodec输入缓冲区大小较小

Android 对于YUV_420_888图像格式,MediaCodec输入缓冲区大小较小,android,android-mediacodec,Android,Android Mediacodec,我正在使用mediaCodec将使用camera2 api捕获的图像转换为视频。当我发现某些设备不支持YV12时,问题出现了。 当我使用YV12作为输入图像格式,使用彩色格式YUV420作为输出时,输入缓冲区和捕获图像的大小是完全相同的。而且效果很好 但是当我使用YUV_420_888作为输入图像格式时,图像的大小增加了,而输入缓冲区的大小与以前相同,这给了我缓冲区溢出的异常。 更具体地说, MediaCodec的输入缓冲区大小始终为:宽度*高度*3/2 但使用YUV_420_888格式的输入图

我正在使用mediaCodec将使用camera2 api捕获的图像转换为视频。当我发现某些设备不支持YV12时,问题出现了。 当我使用YV12作为输入图像格式,使用彩色格式YUV420作为输出时,输入缓冲区和捕获图像的大小是完全相同的。而且效果很好

但是当我使用YUV_420_888作为输入图像格式时,图像的大小增加了,而输入缓冲区的大小与以前相同,这给了我缓冲区溢出的异常。 更具体地说, MediaCodec的输入缓冲区大小始终为:宽度*高度*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();
    }
试试看{
imageSize=CameraUtil.getImageSize(此,currentCameraId);
ImageReader ImageReader=ImageReader.newInstance(imageSize.getWidth(),imageSize.getHeight(),ImageFormat.YUV_420_888,1);
imageReaderListener=新的imageReaderListener(此);
setOnImageAvailableListener(imageReaderListener,backgroundHandler);
List outputSurfaces=新的ArrayList(2);
add(imageReader.getSurface());
曲面预览=新曲面(textureView.getSurfaceTexture());
outputSurfaces.add(预览);
final CaptureRequest.Builder captureBuilder=cameraDevice.createCaptureRequest(cameraDevice.TEMPLATE\U记录);
addTarget(imageReader.getSurface());
captureBuilder.addTarget(预览);
captureBuilder.set(CaptureRequest.CONTROL\u AF\u MODE,CameraMetadata.CONTROL\u AF\u MODE\u CONTINUOUS\u PICTURE);
captureBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
cameraDevice.createCaptureSession(输出表面,
新建CameraCaptureSession.StateCallback(){
@凌驾
未配置公共void(@NonNull CameraCaptureSession会话){
如果(cameraDevice==null){
返回;
}
试一试{
mSession=会话;
setRepeatingRequest(captureBuilder.build(),null,backgroundHandler);
}捕获(CameraAccessE异常){
e、 printStackTrace();
}
}
@凌驾
已配置公用void onconfig(@NonNull CameraCaptureSession会话){
Util.printLogs(CameraActivity.this,标记“捕获图片失败”);
}
},背景处理程序);
}捕获(例外e){
e、 printStackTrace();
}

能否添加用于配置摄像头和MediaCodec的代码?并不总是清楚“输入”和“输出”是什么意思。@greeble31添加了代码段,您也应该包含MediaCodecuti的代码。但这可能无关紧要;对于此问题的一般解决方案,您可能只想使用
COLOR\u FormatSurface
,如中所示。这有一些关于android mediacode的非常好的信息。android中的MediaCodec似乎不支持YUV_420_888格式。@Froyo Ohh,这真是太遗憾了