2017-02-13 60 views
1

Camera2 APIで連続して撮影する必要があります。ハイエンド端末(Nexus 5Xなど)では正常に動作しますが、低速の端末(Samsung Galaxy A3など)ではプレビューがフリーズします。Android Camera2、連続して画像を撮る

コードは少し長いですので、私は唯一の最も関連部品投稿:

private void takePicture() { 

    try { 

     CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
     captureBuilder.addTarget(mImageReader.getSurface()); 
     mCaptureSession.capture(captureBuilder.build(), null, mCaptureBackgroundHandler); 
    } 
    catch (CameraAccessException e) { e.printStackTrace(); } 
} 
:写真を撮るために呼び出さ

private void startPreview() { 

    SurfaceTexture texture = mTextureView.getSurfaceTexture(); 

    if(texture != null) { 

     try { 

      // We configure the size of default buffer to be the size of camera preview we want. 
      texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 

      // This is the output Surface we need to start preview. 
      Surface surface = new Surface(texture); 

      // We set up a CaptureRequest.Builder with the output Surface. 
      mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
      mPreviewRequestBuilder.addTarget(surface); 

      // Here, we create a CameraCaptureSession for camera preview. 
      mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() { 

        @Override 
        public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { 

         // If the camera is already closed, return: 
         if (mCameraDevice == null) { return; } 

         // When the session is ready, we start displaying the preview. 
         mCaptureSession = cameraCaptureSession; 

         // Auto focus should be continuous for camera preview. 
         mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 
         mPreviewRequest = mPreviewRequestBuilder.build(); 

         // Start the preview 
         try { mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mPreviewBackgroundHandler); } 
         catch (CameraAccessException e) { e.printStackTrace(); } 
        } 

        @Override 
        public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { 
         Log.e(TAG, "Configure failed"); 
        } 
       }, null 
      ); 
     } 
     catch (CameraAccessException e) { e.printStackTrace(); } 
    } 
} 

方法:私のプレビューを開始するために呼び出さ

方法を

ここに私のImageReaderはあります:

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() { 

    @Override 
    public void onImageAvailable(final ImageReader reader) { 

     mSaveBackgroundHandler.post(new Runnable() { 

      @Override 
      public void run() { 

       // Set the destination file: 
       File destination = new File(getExternalFilesDir(null), "image_" + mNumberOfImages + ".jpg"); 
       mNumberOfImages++; 

       // Acquire the latest image: 
       Image image = reader.acquireLatestImage(); 

       // Save the image: 
       ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 
       byte[] bytes = new byte[buffer.remaining()]; 
       buffer.get(bytes); 

       FileOutputStream output = null; 
       try { 
        output = new FileOutputStream(destination); 
        output.write(bytes); 
       } 
       catch (IOException e) { e.printStackTrace(); } 
       finally { 

        image.close(); 

        if (null != output) { 

         try { output.close(); } 
         catch (IOException e) { e.printStackTrace(); } 
        } 
       } 

       // Take a new picture if needed: 
       if(mIsTakingPictures) { 
        takePicture(); 
       } 
      } 
     }); 
    } 
}; 

私はmIsTakingPicturesブール値をトグルして、最初のtakePicture呼び出しを行うボタンを持っています。要約すると

、私は3つのスレッド使用しています:原因となることができますどのよう

画像保存用

  • プレビュー用の1
  • キャプチャの1
  • 1をこの凍結の?

答えて

0

弱いデバイスで常時画像を撮っているときに、プレビューでフレームが失われるのを避けることは不可能です。これを回避する唯一の方法は、TEMPLATE_ZERO_SHUTTER_LAGをサポートし、reprocessableCaptureSessionを使用するデバイスで行われます。これについてのドキュメントはかなり恐ろしいものであり、それを実装する方法がオデッセイであることがわかります。あなたはまた、一部のGoogle CTSテストのもReprocessableCaptureSessionを実装する見つけ、いくつかのバーストがZSLテンプレートを取り込み、撮影することができますその答えは

How to use a reprocessCaptureRequest with camera2 API

:私は数ヶ月前にこの問題を持っているし、最終的に私はそれを実装する方法を発見しました。

最後に、プレビューサーフェスとイメージリーダーサーフェスが添付された状態でCaptureBuilderを使用することもできます。この場合、プレビューは常に動作し、各フレームを新しい画像として保存します。しかし、あなたはまだ凍結問題を抱えています。

また、新しいcaptureを呼び出すハンドラを使用してバーストキャプチャを実装しようとしましたが、この2番目のオプションはパフォーマンスがかなり良く、フレームレートの損失を避けていましたが、 2つのImageReaderオプション。

私の答えがちょっとした助けになることを願っています.API 2はまだまだ複雑で、そこにはあまり多くの例や情報はありません。

1

ローエンドのデバイスで気付いたことの1つ:カメラ1 apiを使用していてもキャプチャ後にプレビューが停止するため、手動で再起動する必要があるため、高解像度の画像をキャプチャするときに小さなプレビューフリーズが発生します。

しかし、カメラ2のAPIを使用すると、カメラ1(Huawei P7、Sony Xperia E5、wiko UFeel)を使用しているデバイスでは不可能だった静止画像を撮影することができます。この機能を使用すると、JPEGをキャプチャするよりもはるかに高速です(JPEG圧縮による可能性があります)ので、プレビューを早めに再開することができ、プレビューフリーズが短くなります。もちろん、このソリューションを使用すると、バックグラウンドタスクでYUVからJPEGに画像を変換する必要があります。

関連する問題