Mit Kamera2-API mit ImageReader

Ich versuche zu erfassen, Bilddaten mit der Kamera 2 API auf einem Galaxy S4. ImageReader ist als die Oberfläche provider. Das Bild-format verwendet wurde, versuchte mit beiden ImageFormat.YV12-und ImageFormat.YUV_420_888 und liefert die gleichen Ergebnisse.

Setup scheint gut, und ich bekomme ein Bild aus dem ImageReader mit ImageReader. Das Bild hat 3 Ebenen. Die Puffer sind die erwarteten Größen, Breite*Höhe für Y-Ebene und (Breite*Höhe)/4 für die beiden anderen Ebenen.

Das Problem ist, dass ich nicht immer die Daten richtig in zweierlei Hinsicht. Das erste Problem ist, dass die Y-Ebene Daten in Spiegel-Bild. Dies kann behandelt werden, obwohl es seltsam ist, so bin ich neugierig, ob dies zu erwarten ist.

Das schlimmere Problem ist, dass die beiden anderen Ebenen scheinen nicht zu liefern Daten nicht korrekt auf allen. Zum Beispiel mit einem Bild mit der Größe 640x480, die Ergebnisse in U-und V-puffergrößen von 76800 bytes, werden nur die ersten 320 bytes, die Puffer sind nicht-null-Werte. Diese Zahl schwankt und scheint nicht zu gehen, das Verhältnis zwischen verschiedenen Bildgrößen, aber scheint konsequent zu sein, zwischen den Bildern für jede Größe.

Frage ich mich, ob es gibt etwas, dass ich vermisst werde in der Verwendung dieser API. Code ist unten.

public class OnboardCamera {
  private final String TAG = "OnboardCamera";

  int mWidth = 1280;
  int mHeight = 720;
  int mYSize = mWidth*mHeight;
  int mUVSize = mYSize/4;
  int mFrameSize = mYSize+(mUVSize*2); 

  //handler for the camera
  private HandlerThread mCameraHandlerThread;
  private Handler mCameraHandler;

  //the size of the ImageReader determines the output from the camera.
  private ImageReader mImageReader = ImageReader.newInstance(mWidth, mHeight, ImageFormat.YV12, 30);

  private Surface mCameraRecieverSurface = mImageReader.getSurface();
  {
      mImageReader.setOnImageAvailableListener(mImageAvailListener, mCameraHandler);
  }

  private byte[] tempYbuffer = new byte[mYSize];
  private byte[] tempUbuffer = new byte[mUVSize];
  private byte[] tempVbuffer = new byte[mUVSize];

  ImageReader.OnImageAvailableListener mImageAvailListener = new ImageReader.OnImageAvailableListener() {
      @Override
      public void onImageAvailable(ImageReader reader) {
          //when a buffer is available from the camera
          //get the image
          Image image = reader.acquireNextImage();
          Image.Plane[] planes = image.getPlanes();

          //copy it into a byte[]
          byte[] outFrame = new byte[mFrameSize];
          int outFrameNextIndex = 0;


          ByteBuffer sourceBuffer = planes[0].getBuffer();
          sourceBuffer.get(tempYbuffer, 0, tempYbuffer.length);

          ByteBuffer vByteBuf = planes[1].getBuffer();
          vByteBuf.get(tempVbuffer);

          ByteBuffer yByteBuf = planes[2].getBuffer();
          yByteBuf.get(tempUbuffer);

          //free the Image
          image.close();
      }
  };


  OnboardCamera() {
      mCameraHandlerThread = new HandlerThread("mCameraHandlerThread");
      mCameraHandlerThread.start();
      mCameraHandler = new Handler(mCameraHandlerThread.getLooper());

  }




  @Override
  public boolean startProducing() {
      CameraManager cm = (CameraManager) Ten8Application.getAppContext().getSystemService(Context.CAMERA_SERVICE);
      try {
          String[] cameraList = cm.getCameraIdList();
          for (String cd: cameraList) {
              //get camera characteristics
              CameraCharacteristics mCameraCharacteristics = cm.getCameraCharacteristics(cd);

              //check if the camera is in the back - if not, continue to next
              if (mCameraCharacteristics.get(CameraCharacteristics.LENS_FACING) != CameraCharacteristics.LENS_FACING_BACK) {
                  continue;
              }

              //get StreamConfigurationMap - supported image formats
              StreamConfigurationMap scm = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

              android.util.Size[] sizes =  scm.getOutputSizes(ImageFormat.YV12);

              cm.openCamera(cd, mDeviceStateCallback, mCameraHandler);
          }

      } catch (CameraAccessException e) {
          e.printStackTrace();
          Log.e(TAG, "CameraAccessException detected", e);
      }
      return false;
  }

  private final CameraDevice.StateCallback mDeviceStateCallback = new CameraDevice.StateCallback() {
      @Override
      public void onOpened(CameraDevice camera) {
          //make list of surfaces to give to camera
          List<Surface> surfaceList = new ArrayList<>();
          surfaceList.add(mCameraRecieverSurface);

          try {
              camera.createCaptureSession(surfaceList, mCaptureSessionStateCallback, mCameraHandler); 
          } catch (CameraAccessException e) {
              Log.e(TAG, "createCaptureSession threw CameraAccessException.", e);
          }
      }

      @Override
      public void onDisconnected(CameraDevice camera) {

      }

      @Override
      public void onError(CameraDevice camera, int error) {

      }
  };

  private final CameraCaptureSession.StateCallback mCaptureSessionStateCallback = new CameraCaptureSession.StateCallback() {
      @Override
      public void onConfigured(CameraCaptureSession session) {
          try {
              CaptureRequest.Builder requestBuilder = session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
              requestBuilder.addTarget(mCameraRecieverSurface);
              //set to null - image data will be produced but will not receive metadata
              session.setRepeatingRequest(requestBuilder.build(), null, mCameraHandler); 

          } catch (CameraAccessException e) {
              Log.e(TAG, "createCaptureSession threw CameraAccessException.", e);
          }


      }

      @Override
      public void onConfigureFailed(CameraCaptureSession session) {

      }
  };
}

InformationsquelleAutor Nicholas Spencer | 2015-07-10

Schreibe einen Kommentar