7

I am using mediaCodec to convert images captured using camera2 api to videos. The problem arrived when I found YV12 isn't supported in some devices. When I used YV12 as input image format, and COLOR_FormatYUV420SemiPlanar as output, the size of input buffer and captured image is exact same. And it works well.

But when I used YUV_420_888 as input image format, the size of image got increased while the size of input buffer is same as before which gave me buffer overflow exception. More specifically, size of input buffer of MediaCodec is always : width * height * 3/2 But size of input image using YUV_420_888 format turns out to be: width * height * 2

I am not sure how to feed this image to mediacodec without causing buffer overflow and without compromising quality.

Any help would be appreciated!

Code for configuring 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();
    }

Code for taking image from Camera

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();
    }
Shivam Pokhriyal
  • 479
  • 4
  • 14
  • Could you add the code you use to configure the camera and the MediaCodec? It is not always clear what you mean by "input" and "output". – greeble31 May 18 '19 at 21:24
  • @greeble31 Added the code snippet – Shivam Pokhriyal May 19 '19 at 12:02
  • You should include the code for MediaCodecUtil too. But it may not matter; for a general solution to this problem, you probably just want to use `COLOR_FormatSurface`, as in [this answer](https://stackoverflow.com/a/46405261/6759241). – greeble31 May 19 '19 at 13:33
  • https://www.bigflake.com/mediacodec/ This has some really good information about android mediacode. It seems that MediaCodec in android does not support YUV_420_888 format. – Froyo Jun 14 '19 at 13:30
  • @Froyo Ohh, that's really sad – Shivam Pokhriyal Jun 29 '19 at 10:58

0 Answers0