Ускорение захвата изображения с камеры2

Я работаю над приложением для Android, которое делает снимок с помощью camera2 api. Проблема, с которой я сталкиваюсь, заключается в огромной задержке между нажатием кнопки "Сфотографировать" и фактическим захватом изображения - где-то около 1800-2000 мс, что лично мне кажется неприемлемым.

Я был бы очень признателен, если бы кто-то мог указать способ улучшить это. Что бы это ни стоило, я позже обработаю выходное изображение JPEG в растровое изображение, если это имеет значение.

Класс "фотографирования" отображается ниже.

protected void takePicture() {
    if (null == cameraDevice) {
        Log.e(TAG, "cameraDevice is null");
        return;
    }
    debugTime(1,"");
    try {
        Log.e(TAG, "Taking a picture");
        int width, height;

        Size trySize = defineSize();
        width = trySize.getWidth();
        height = trySize.getHeight();

        debugTime(3,"Defining sizes took ");
        ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
        List<Surface> outputSurfaces = new ArrayList<>(2);

        outputSurfaces.add(reader.getSurface());
        outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));

        debugTime(3,"Defining output surfaces took ");

        final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureBuilder.addTarget(reader.getSurface());
        captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);

        debugTime(3,"Creating capture request took ");

        // Orientation
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));

        debugTime(3,"Defining rotation took ");

        final File file = new File(Environment.getExternalStorageDirectory() + "/pic.jpg");

        debugTime(3,"Creating new file took ");

        ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                Log.e(TAG, "Running method onImageAvailable");
                Image image = null;
                try {
                    debugTime(3,"Image becoming available took ");
                    image = reader.acquireLatestImage();
                    debugTime(2,"");
                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    bytes = new byte[buffer.capacity()];
                    buffer.get(bytes); //My final output

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (image != null) {
                        image.close();
                    }
                }
            }
        };

        reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);

        final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
                Log.e(TAG, "Invoking running method sendToScan");
                sendToScan();
            }
        };

        cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(CameraCaptureSession session) {
                Log.e(TAG, "Running method onConfigured");
                try {
                    session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
                debugTime(3,"Configuring capture session took ");
            }

            @Override
            public void onConfigureFailed(CameraCaptureSession session) {
            }
        }, mBackgroundHandler);
        //stopBackgroundThread();

    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

А вот и журнал

E/CameraActivity: Taking a picture
E/CameraActivity: Defining Size
E/CameraActivity: CHOOSING at size 720x1280
E/DEBUG_TIME: Defining sizes took 25 ms
E/DEBUG_TIME: Defining output surfaces took 20 ms
E/DEBUG_TIME: Creating capture request took 4 ms
E/DEBUG_TIME: Defining rotation took 1 ms
E/DEBUG_TIME: Creating new file took 5 ms
I/RequestQueue: Repeating capture request cancelled.
I/CameraDeviceState: Legacy camera service transitioning to state IDLE
I/CameraDeviceState: Legacy camera service transitioning to state CONFIGURING
I/RequestThread-0: Configure outputs: 2 surfaces configured.
D/Camera: app passed NULL surface
I/RequestThread-0: configureOutputs - set take picture size to 1280x720
I/CameraDeviceState: Legacy camera service transitioning to state IDLE
E/CameraActivity: Running method onConfigured
I/Choreographer: Skipped 38 frames!  The application may be doing too much work on its main thread.
W/art: Long monitor contention event with owner method=void java.lang.Object.wait!() from Object.java:4294967294 waiters=0 for 563ms
W/LegacyRequestMapper: convertRequestMetadata - control.awbRegions setting is not supported, ignoring value
W/LegacyRequestMapper: Only received metering rectangles with weight 0.
E/DEBUG_TIME: Configuring capture session took 586 ms
E/BufferQueueProducer: [SurfaceTexture-0-17825-3] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=13 undequeued=0)
E/BufferQueueProducer: [SurfaceTexture-0-17825-3] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=12 undequeued=1)
I/CameraDeviceState: Legacy camera service transitioning to state CAPTURING
I/RequestThread-0: Received jpeg.
I/RequestThread-0: Producing jpeg buffer...
E/CameraActivity: Running method onImageAvailable
E/DEBUG_TIME: Image becoming available took 1110 ms
D/ImageReader_JNI: ImageReader_lockedImageSetup: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.
W/ImageReader_JNI: Unable to acquire a lockedBuffer, very likely client tries to lock more than maxImages buffers
E/DEBUG_TIME: Taking picture took 1752 ms in TOTAL

В соответствии с этим, настройка сеанса захвата занимает ~500-600 мс (!), Но, что еще хуже, требуется около 1100-1200 мс, чтобы изображение стало доступным в imageReader!

Там явно что-то не так, и я не могу понять это. Буду рад любой помощи.

PS Для записи я сделал попытку сохранить результат в формате YUV_420_888, но это всего лишь ускорило меня до ~1000.

0 ответов

Другие вопросы по тегам