OpenCV4.10.0 createCaptureSessionが非推奨 対策

2024.1.19 2021.3.3Coskx Lab  

1 概要

OpenCVのandroidソースの一部がAndroid11(API 30)以降で非推奨と警告が出るようになってきたので,対応します。

hardware cameraAPIを使わずにcamera2APIを使うプログラミングを対象にしています。(JavaCameraView.javaを使わずにJavaCamera2View.javaを使っている)

問題になるのは,JavaCamera2View.javaなので,OpenCV4.10.0のJavaCamera2View.javaを書き換えた対策済の差し替え版JavaCamera2View.javaを公開しています。

修正したJavaCamera2View.javaのダウンロード

2 使用環境

3 CameraDevice.createCaptureSessionが非推奨

Android11(API 30)以降を開発ターゲットにすると,OpenCVのJavaCamera2View(Camera2ライブラリ使用クラス)のCameraDevice.createCaptureSessionが非推奨となっており,警告が出ています。
そのままにしていても,当面は大丈夫と思いますが,「Developers」にて置き換えが指示されている別の形のコンストラクタに変更しました。

このJavaCamera2View classは重要なのでいずれOpenCV本家の記述が修正されると思いますが,それまでの間を過ごすための作業です。

4 対策前

非推奨警告が出るのはJavaCamera2View.javaのメソッドprivate void createCameraPreviewSession()内のCameraDevice.createCaptureSessionを作っているところです。

             OPenCV 4.10.0同梱のJavaCamera2View.java createCameraPreviewSession()

    private void createCameraPreviewSession() {
        final int w = mPreviewSize.getWidth(), h = mPreviewSize.getHeight();
        Log.i(LOGTAG, "createCameraPreviewSession(" + w + "x" + h + ")");
        if (w < 0 || h < 0)
            return;
        try {
            if (null == mCameraDevice) {
                Log.e(LOGTAG, "createCameraPreviewSession: camera isn't opened");
                return;
            }
            if (null != mCaptureSession) {
                Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started");
                return;
            }

            mImageReader = ImageReader.newInstance(w, h, mPreviewFormat, 2);
            mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
                @Override
                public void onImageAvailable(ImageReader reader) {
                    Image image = reader.acquireLatestImage();
                    if (image == null)
                        return;

                    // sanity checks - 3 planes
                    Image.Plane[] planes = image.getPlanes();
                    assert (planes.length == 3);
                    assert (image.getFormat() == mPreviewFormat);

                    JavaCamera2Frame tempFrame = new JavaCamera2Frame(image);
                    deliverAndDrawFrame(tempFrame);
                    tempFrame.release();
                    image.close();
                }
            }, mBackgroundHandler);
            Surface surface = mImageReader.getSurface();

            mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(mRequestTemplate);
            mPreviewRequestBuilder.addTarget(surface);

            mCameraDevice.createCaptureSession(Arrays.asList(surface),
                                               allocateSessionStateCallback(), null);
        } catch (CameraAccessException e) {
            Log.e(LOGTAG, "createCameraPreviewSession", e);
        }
    }

5 対策

https://developer.android.com/reference/android/hardware/camera2/CameraDevice
では
createCaptureSession(List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)
This method was deprecated in API level 30. Please use createCaptureSession(android.hardware.camera2.params.SessionConfiguration) for the full set of configuration options available.
となっています。
そこでSessionConfigurationを使うようにして,次のように置き換えます。

             修正後のJavaCamera2View.java createCameraPreviewSession()

    private void createCameraPreviewSession() {
        final int w = mPreviewSize.getWidth(), h = mPreviewSize.getHeight();
        Log.i(LOGTAG, "createCameraPreviewSession(" + w + "x" + h + ")");
        if (w < 0 || h < 0)
            return;
        try {
            if (null == mCameraDevice) {
                Log.e(LOGTAG, "createCameraPreviewSession: camera isn't opened");
                return;
            }
            if (null != mCaptureSession) {
                Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started");
                return;
            }

            mImageReader = ImageReader.newInstance(w, h, mPreviewFormat, 2);
            mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
                @Override
                public void onImageAvailable(ImageReader reader) {
                    Image image = reader.acquireLatestImage();
                    if (image == null)
                        return;

                    // sanity checks - 3 planes
                    Image.Plane[] planes = image.getPlanes();
                    assert (planes.length == 3);
                    assert (image.getFormat() == mPreviewFormat);

                    JavaCamera2Frame tempFrame = new JavaCamera2Frame(image);
                    deliverAndDrawFrame(tempFrame);
                    tempFrame.release();
                    image.close();
                }
            }, mBackgroundHandler);
            Surface surface = mImageReader.getSurface();

            mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(mRequestTemplate);
            mPreviewRequestBuilder.addTarget(surface);

            try {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    mCameraDevice.createCaptureSession(
                            new SessionConfiguration(
                                    SessionConfiguration.SESSION_REGULAR,
                                    Collections.singletonList(new OutputConfiguration(surface)),
                                    Executors.newCachedThreadPool(),
                                    allocateSessionStateCallback()
                            ));
                } else {
                    mCameraDevice.createCaptureSession(Collections.singletonList(surface),
                            allocateSessionStateCallback(), null);
                }
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }

        } catch (CameraAccessException e) {
            Log.e(LOGTAG, "createCameraPreviewSession", e);
        }
    }

修正したJavaCamera2View.javaのダウンロード

6 まとめ

OpenCV4.10.0のソースのJavaCamera2View.javaがAndroid11(API 30)以降で非推奨メソッドが使用されているため,対応しました。
ただし,JavaCamera2View.java内には互換対応用記述が残るので,コンパイル時の警告は出ます。

なお次の6つのファイルは使われていないので,無効にすると,コンパイル時のdeprecated警告表示は,かなりなくなります。 無効にしても問題なしです。
 Camera2Renderer.java
 CameraGLRendererBase.java
 CameraGLSurfaceView.java
 CameraRenderer.java
 JavaCameraView.java
 NativeCameraView.java