woshidan's loose leaf

ぼんやり勉強しています

セマフォとロックとPauseからの復帰

  • セマフォは獲得してから解放するまでのコードを一つのスレッドしか通ってくれるなよ、的なもの
    • 1つ、というのはコンストラクタの引数1から
      • 同時に実行していい数が指定できるロック的な
    • と現状理解している
  • サンプル見てるとこのセマフォでCamera2 APIの利用のタイミングの同期を取っているっぽい
  • 獲得 ~ 解放までの流れ 1
    • CameraManager.openCameraCameraDevice インスタンスを経由して Camera2 APIにアクセスしようとする*1
    • CameraDevice.StateCallbackonOpened, onDisconnected, onError で解放
      • openCamera でCamera2 API へのアクセスを試すあたりの処理に他のスレッドが入ってくるのを制限している
  • 獲得 ~ 解放までの流れ 2
    • CameraCaptureSession, CameraDevice, 他のSurface をcloseする前に獲得
    • 上記close後 or closeに失敗した後に解放
  • ちなみに昨日の自分のコードはそもそも onPauseCameraDevice をcloseしていなかったのでした…

獲得 ~ 解放までの流れ 1

https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java#L268-L271

    /**
     * A {@link Semaphore} to prevent the app from exiting before closing the camera.
     */
    private Semaphore mCameraOpenCloseLock = new Semaphore(1);

https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java#L599-L621

    /**
     * Opens the camera specified by {@link Camera2BasicFragment#mCameraId}.
     */
    private void openCamera(int width, int height) {
        if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            requestCameraPermission();
            return;
        }
        setUpCameraOutputs(width, height);
        configureTransform(width, height);
        Activity activity = getActivity();
        CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
        try {
            if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
                throw new RuntimeException("Time out waiting to lock camera opening.");
            }
            manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
        }
    }

https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java#L187-L215

    private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {

        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {
            // This method is called when the camera is opened.  We start camera preview here.
            mCameraOpenCloseLock.release();
            mCameraDevice = cameraDevice;
            createCameraPreviewSession();
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
            mCameraOpenCloseLock.release();
            cameraDevice.close();
            mCameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int error) {
            mCameraOpenCloseLock.release();
            cameraDevice.close();
            mCameraDevice = null;
            Activity activity = getActivity();
            if (null != activity) {
                activity.finish();
            }
        }

    };

獲得 ~ 解放までの流れ 2

https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java#L624-L647

    /**
     * Closes the current {@link CameraDevice}.
     */
    private void closeCamera() {
        try {
            mCameraOpenCloseLock.acquire();
            if (null != mCaptureSession) {
                mCaptureSession.close();
                mCaptureSession = null;
            }
            if (null != mCameraDevice) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
            if (null != mImageReader) {
                mImageReader.close();
                mImageReader = null;
            }
        } catch (InterruptedException e) {
            throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
        } finally {
            mCameraOpenCloseLock.release();
        }
    }

回転とかでうまく表示されなくなるの、デバイスとかのせいでないことがわかったから回転再チャレンジしてもいいかも

  • [既存課題]縦向きの場合と横向きの場合でちょうどいいrotationのMatrixを見つける 関連: http://mslgt.hatenablog.com/entry/2015/05/12/013013#rotatescreen 横向き or 縦向きだけの対応で十分では、となり、横向き固定の場合の行列見つけて安堵中
  • [既存課題]縦向きの場合と横向きの場合でそれぞれちょうどよくCameraのPreviewが表示されるようにする
  • [新しい課題]作成した画像のファイルへの書き込み、あるいはImageWriter
  • [新しい課題]ImageReaderでできること他に
  • [新しい課題]TextureViewのカスタムクラス読みに行ってはどうか

*1:という言い方がエラーメッセージ見てるかぎり良さそうなんだが、書いてるノリとしてコールバックを経由してCameraDeviceのインスタンスを取得とか、カメラ起動とかそれくらいのノリ