2017-04-06 4 views
0

ImageReaderを使用してフレームを処理しようとしていて、同時にSurfaceViewにビデオカメラのプレビューを表示しようとしています。追加する唯一のターゲットサーフェスがSurfaceViewである場合、プレビューはスムーズですが、2番目のターゲットとしてImageReaderを追加すると、プレビューが大きく遅れるようになります。なぜそれができますか?私はHandlerThreadとHandlerを作成してそれらを使用しようとしましたが、変更されませんでした。私が現在しているのは、次の画像を取得して閉じることだけです。ImageReaderをターゲットサーフェスとして追加するCamera2APIがカメラのプレビューを遅らせます

public void startBackgroundThread() { 
    handlerThread = new HandlerThread("Image Processing Thread"); 
    handlerThread.start(); 
    handler = new Handler(handlerThread.getLooper()); 
} 

ここでカメラの設定:

public void configureCamera() { 
    try { 
     CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId); 
     StreamConfigurationMap configs = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 

     Size[] sizes = configs.getOutputSizes(ImageFormat.YUV_420_888); 
     imageReader = ImageReader.newInstance(sizes[0].getWidth(), sizes[0].getHeight(), ImageFormat.YUV_420_888, 1); 

     Range<Integer>[] ranges = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); 
     fpsRange = ranges[ranges.length - 1]; 

     imageReader.setOnImageAvailableListener(this, handler); 

     cameraSurfaceView.getHolder().setFixedSize(sizes[0].getWidth(), sizes[0].getHeight()); 
    } catch (CameraAccessException | NullPointerException e) { 
     e.printStackTrace(); 
    } 
} 

は、カメラのプレビューの開始:

@Override 
public void onImageAvailable(ImageReader reader) { 
    reader.acquireNextImage().close(); 
} 
:ここ

private void startCamera() { 
    try { 
     cameraManager.openCamera("0", new CameraDevice.StateCallback() { 
      @Override 
      public void onOpened(@NonNull CameraDevice camera) { 
       cameraDevice = camera; 

       try { 
        cameraDevice.createCaptureSession(Arrays.asList(cameraSurfaceView.getHolder().getSurface(), imageReader.getSurface()), 
          new CameraCaptureSession.StateCallback() { 
           @Override 
           public void onConfigured(@NonNull CameraCaptureSession session) { 
            captureSession = session; 
            try { 
             requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 

             requestBuilder.addTarget(cameraSurfaceView.getHolder().getSurface()); 
             requestBuilder.addTarget(imageReader.getSurface()); 

             requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH); 
             requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange); 

             captureRequest = requestBuilder.build(); 
             cameraReady = true; 

             captureSession.setRepeatingRequest(captureRequest, null, handler); 

             onStartButtonClick(startButton); 
            } catch (CameraAccessException e) { 
             e.printStackTrace(); 
            } 
           } 

           @Override 
           public void onConfigureFailed(@NonNull CameraCaptureSession session) { 

           } 
          }, null); 
       } catch (CameraAccessException e) { 
        e.printStackTrace(); 
       } 
      } 

とは、(現在、私の主な活動である)のImageReaderのOnImageAvailableListener来ます

これらのコードスニペットはすべて現在私の主な活動に含まれています。私が使用している電話は、テストの目的でMotorola Moto X Playです。 cameraSurfaceViewは単純なSurfaceViewであり、カスタマイズはまったくありません。

+0

プレビューの解像度を下げることにより、より高いfpsカウントを得ることができますが、これは理想的な解決策ではありません。 – masm64

答えて

0

インデントを表示するのは少し難しいですが、コードスニペットから現在のスレッドでカメラハンドラを実行しているようです。

cameraManager.openCameraの最後のパラメータは、使用するスレッドを指示します。ヌルの場合、現在のスレッドのみを使用します。

パラメータ cameraId文字列::カメラが

ハンドラハンドラを開かれたときに呼び出されるコールバック:

コールバックCameraDevice.StateCallbackを開くには、カメラ装置の固有の識別子Androidのドキュメントから:コールバックが呼び出されるべきハンドラ、または現在のスレッドのルーパーを使用するためのヌル。

あなたはCamera2BasicためのGitHubの(上の例で見ると)あなたは、彼らが別のハンドラを指定する見ることができます:

manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler); 

これは別のスレッド上で開始されています。私は、管理

/** 
    * Starts a background thread and its {@link Handler}. 
    */ 
    private void startBackgroundThread() { 
     mBackgroundThread = new HandlerThread("CameraBackground"); 
     mBackgroundThread.start(); 
     mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); 
    } 
+0

ヒントはありがたいですが、私はすでに試してみました。 – masm64

+0

上記のコード抽出では、ハンドラを作成しますが、openCameraコールで使用されているようには見えません。最後にnullが表示されます。これにより、メインスレッドでコールバックが実行されます。 – Mick

+0

私は知っているが、私は現在、与えられた値を実行しているコードではnullではなく、ハンドラオブジェクト自体 – masm64

関連する問題