2017年になり、ようやくCamera1からCamera2への切り替えを開始しました。 Camera1では、リアルタイムフレーム処理を実行するためにsetPreviewCallbackWithBuffer()
に大きく依存していましたが、Camera2では、これははるかに遅く、ほとんど使用できなくなります。
比較すると、Moto G3ではCamera1は30〜40 FPSを簡単に生成できますが、Camera2では10〜15FPSを超えることはできませんでした。
これが私がImageReader
を作成する方法です
imageReader = ImageReader
.newInstance(
previewSize.width, // size is around 1280x720
previewSize.height,
ImageFormat.YUV_420_888, // note, it is not JPEG
2 // max number of images, does not really affect performance
);
imageReader.setOnImageAvailableListener(
callback,
CameraThread.getInstance().createHandler()
);
コールバック自体は、可能な限り最小限の仕事をします。
Image image = reader.acquireNextImage();
image.close();
これ などの同様の回答をすでに確認しました。ただし、問題は、YUV_420_888
ではなくJPEG
画像形式を使用していることです。
Camera1と同様のパフォーマンスを実現するにはどうすればよいですか?
Camera1APIとCamera2APIの両方をサポートするアプリで同じパフォーマンスの問題が発生しました。 AndroidバージョンがLollipopを上回っていたとき、以前はCamera2 APIに切り替えていたため、パフォーマンスが非常に悪くなりました(ImageReaderとSurfaceの2つのターゲットがありました)。
電話でハードウェアが完全にサポートされている場合にのみ、Camera2APIを使用することになりました。 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVELを使用して確認できます。
それが役に立てば幸い
これは単なる観察ですが、とにかく投稿します。
OnImageAvailableListener を登録していると言います。このリスナーは画像を配信しませんが、サブスクライブした同じImageReader
への参照を配信します。次に、実際の画像を取得するには、acquireLatestImage
またはacquireNextImage
のいずれかを呼び出す必要があります。
docs には、何が起こっているのかを理解するのに役立つ可能性のある段落があります。
画像データは
Image
オブジェクトにカプセル化され、maxImages
コンストラクターパラメーターで指定された数まで、複数のそのようなオブジェクトに同時にアクセスできます。 Surfaceを介してImageReader
に送信された新しい画像は、acquireLatestImage()
またはacquireNextImage()
呼び出しを介してアクセスされるまでキューに入れられます。 メモリの制限により、ImageReader
が画像を取得および解放しない場合、画像ソースは最終的に画像を停止またはドロップしてサーフェスにレンダリングしようとします。生産率。
だから役立つかもしれないいくつかのこと:
maxImages
引数をImageReader
コンストラクターに渡します(とにかくキューを使い果たすと、IllegalStateException
を取得します)。acquireLatestImage
よりもacquireNextImage
を優先します。この方法では古い画像が自動的に解放されますが、他の方法では解放されないため、誤ってacquireNextImage
を使用すると、メモリが不足するまで画像の配信がますます遅くなります。