バースト画像をキャプチャするようにAndroid-Camera2Basicコードを変更しようとしています。ただし、L 5.0.1を実行しているNexus5では、画像間の遅延を200〜300ミリ秒より速く取得できません。
私はたくさんのことを試しましたが、これが最も基本的なことです。これは、私が変更したCamera2Basicコードの唯一の部分です。私のプレビューTextureViewは50x50dpだけですが、それは問題ではありませんよね?
価値があるのは、このコードの遅延は、L5.1を搭載したNexus6では約50〜100ミリ秒だけです。
private void captureStillPicture() {
try {
List<CaptureRequest> captureList = new ArrayList<CaptureRequest>();
mPreviewRequestBuilder.addTarget(mImageReader.getSurface());
for (int i=0;i<10;i++) {
captureList.add(mPreviewRequestBuilder.build());
}
mCaptureSession.stopRepeating();
mCaptureSession.captureBurst(captureList, cameraCaptureCallback, null);
mPreviewRequestBuilder.removeTarget(mImageReader.getSurface());
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
CameraCaptureSession.CaptureCallback cameraCaptureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
TotalCaptureResult result) {
Log.d("camera","saved");
mPictureCounter++;
if (mPictureCounter >= 10)
unlockFocus();
}
};
発生している問題は、要求した画像出力形式のアーティファクトです。 JPEGエンコードプロセスでは、カメラパイプラインに大きなストール時間がかかるため、このエンコードが行われている間、1つの露出が終了してから次の露出が開始するまでに多くのダウンタイムが発生します。
引用されている30fpsのレートは、ImageReader
の出力画像形式をYUVとして設定することで実現できます。これは、カメラにとってより「ネイティブな」出力であるためです。これは、キャプチャされた画像を保存する方法であり、その後、カメラのインライン処理とは別に、JPEGエンコーディングを実行する必要があります。
たとえば、Nexus 5では、JPEG
エンコーディングの出力ストール時間は243ミリ秒であり、これは観察されています。 _YUV_420_888
_出力の場合、0msです。同様に、サイズが大きいため、_RAW_SENSOR
_エンコーディングでは200msのストール時間が発生します。
また、「高速」フォーマットを選択してストール時間の障害を取り除いたとしても、出力画像のサイズに応じて、最小フレーム時間が存在することにも注意してください。しかし、Nexus 5のフル解像度出力の場合、これは33ミリ秒であり、これは予想どおりです。
関連情報は、カメラメタデータのStreamConfigurationMap
オブジェクト、 ここ にあります。確認のためにgetOutputStallDuration(int format, Size size)
メソッドとgetOutputMinFrameDuration(int format, Size size)
メソッドを確認してください。
次のキャプチャリクエストパラメータを設定してみてください
requestBuilder = camDevice
.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
requestBuilder.set(CaptureRequest.Edge_MODE,
CaptureRequest.Edge_MODE_OFF);
requestBuilder.set(
CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE,
CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON);
requestBuilder.set(
CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_OFF);
requestBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE,
CaptureRequest.NOISE_REDUCTION_MODE_OFF);
requestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
requestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, true);
requestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, true);
CameraCaptureSession.CaptureCallbackに情報がどのくらいの速さで届くかわかりません。画像データがなく、ImageReader.OnImageAvailableListenerの前または後に呼び出すことができます。 ImageReader.OnImageAvailableListener呼び出し間の時間を測定してみてください。また、バッファがいっぱいで画像が解放されていない場合、新しい画像は利用できないため、画像を読んで解放することを忘れないでください。例えば:
private class imageAvailableListener implements
ImageReader.OnImageAvailableListener {
@Override
public void onImageAvailable(ImageReader ir) {
Log.i(TAG, "Time = " + System.currentTimeMillis());
Image im = ir.acquireNextImage();
im.close();
}
}
ImageReader mImageReader = ImageReader.newInstance(imageReaderWidth,
imageReaderHeight, ImageFormat.YUV_420_888, 2);
mImageReader.setOnImageAvailableListener(
new imageAvailableListener(), null);