0

为了在预览模式下将实时帧提取到NDK端(openCv)中,我使用了android camera2。 我使用ImageReader表面来获取框架。但它被限制为最大帧值。android camera2获取帧时的预览滞后

ImageReader.newInstance(800,600,ImageFormat.YUV_420_888, MAX_FRAME); 

它的作品不错,但因为我们需要所有帧,必须从CaptureRequest.Builder删除ImageReader的目标表面,然后重新添加。所以我们现在有一个滞后。

我们如何在没有最大帧的情况下使用ImageReader,或者如何从camera2中的实时视频获取所有帧而不会在预览中产生任何延迟?

我的代码:

private void startPreview() { 
     if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) { 
      return; 
     } 
     try { 

      SurfaceTexture texture = mTextureView.getSurfaceTexture(); 
      assert texture != null; 
      texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
      Surface previewSurface = new Surface(texture); 
      surfaces = new ArrayList<>(); 
      mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); 
      surfaces.add(previewSurface); 
      mPreviewBuilder.addTarget(previewSurface); 
      mPreviewCaptureCallback = new CameraCaptureSession.StateCallback() { 

       @Override 
       public void onConfigured(@NonNull CameraCaptureSession session) { 
//     closePreviewSession(); 
        mPreviewSession = session; 
        try { 
         session.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler); 
        } catch (CameraAccessException e) { 
         e.printStackTrace(); 
        } 
       } 

       @Override 
       public void onConfigureFailed(@NonNull CameraCaptureSession session) { 
        Activity activity = getActivity(); 
        if (null != activity) { 
         Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show(); 
        } 
       } 
      }; 
      mCameraDevice.createCaptureSession(surfaces, mPreviewCaptureCallback, mBackgroundHandler); 
     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void addImageReaderSurface() { 
     try { 

      SurfaceTexture texture = mTextureView.getSurfaceTexture(); 
      assert texture != null; 
      texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
      Surface previewSurface = new Surface(texture); 
      surfaces = new ArrayList<>(); 
      mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); 
      surfaces.add(previewSurface); 
      mPreviewBuilder.addTarget(previewSurface); 
      newImageReader(10); 
      surfaces.add(mImageReader.getSurface()); 
      mPreviewBuilder.addTarget(mImageReader.getSurface()); 

      mPreviewCaptureCallback = new CameraCaptureSession.StateCallback() { 

       @Override 
       public void onConfigured(@NonNull CameraCaptureSession session) { 
        mPreviewSession = session; 
        try { 
         mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler); 
        } catch (CameraAccessException e) { 
         e.printStackTrace(); 
        } 
       } 

       @Override 
       public void onConfigureFailed(@NonNull CameraCaptureSession session) { 
        Activity activity = getActivity(); 
        if (null != activity) { 
         Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show(); 
        } 
       } 
      }; 
      mCameraDevice.createCaptureSession(surfaces, mPreviewCaptureCallback, mBackgroundHandler); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private void newImageReader(final int count) { 
     mImageReader = ImageReader.newInstance(800, 600, ImageFormat.YUV_420_888, count); 
     mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { 
      @Override 
      public void onImageAvailable(ImageReader reader) { 
       index++; 
       Log.e("xxx", "frame " + index + " received"); 
       if (index == count) { 
        index = 0; 
//     remove it before reached max value 
        addImageReaderSurface(); 
       } 
      } 
     }, mBackgroundHandler); 
    } 
+0

您不需要重新启动ImageReader。 MAX_FRAME是队列大小,如果回调足够快,将永远不会满,预览帧将继续流入。 –

回答

0

获取来自阅读器的图像与Image img = reader.acquireLatestImage()后,你必须调用img.close()

public void onImageAvailable(ImageReader reader) { 
    Image img = reader.acquireLatestImage(); 
    if (img == null) { return; } 
    // do work 
    img.close(); 
} 
相关问题