Размер входного буфера MediaCodec мал для формата изображения YUV_420_888 - PullRequest
4 голосов
/ 18 мая 2019

Я использую 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();
    }
...