I've been following the camera2 documentation trying to implement a non-previewed camera with an ImageReader, but when I get to cameraDevice.createCaptureSession(outputs, mccsStateCallback, cameraHandler);
, the cameraDevice
object is null, even though I'm sure it should have been assigned in the CameraCaptureSession.StateCallback
event listener (which isn't being triggered either because the CameraCaptureSession itself is null). Either I have this all completely wrong or I've missed something big. Here's my code:
private CameraDevice cameraDevice;
private String cameraId;
private Handler cameraHandler = new Handler();
private CameraCharacteristics cameraCharacteristics;
private ImageReader jpgReader;
Bitmap bitmap;
private Handler imgHandler = new Handler();
private CameraCaptureSession mSession;
private CameraManager cameraManager;
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
cameraDevice = camera;
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
cameraDevice.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};
OnImageAvailableListener imageAvailableListener = new OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
Image.Plane[] planes = image.getPlanes();
Buffer buffer = planes[0].getBuffer().rewind();
bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
mFaceOverlayView.setBitmap(bitmap);
}
};
private CameraCaptureSession.StateCallback mccsStateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
try {
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(getBaseContext(), android.Manifest.permission.CAMERA)) {
mSession = session;
CaptureRequest.Builder request = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
request.addTarget(jpgReader.getSurface());
mSession.setRepeatingRequest(request.build(), new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
}
}, null);
cameraManager.openCamera(cameraId, mStateCallback, cameraHandler);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
}
};
private void initialiseCamera() {
cameraManager = (CameraManager) FilesPlayer.this.getSystemService(Context.CAMERA_SERVICE);
try {
cameraId = getFrontFacingCameraId(cameraManager);
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)) {
cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
android.util.Size[] jpegSizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);
Size biggestSize = new Size(0, 0);
for (Size size : jpegSizes) {
if (size.getHeight() >= biggestSize.getHeight() && size.getWidth() >= biggestSize.getWidth()) {
biggestSize = size;
}
}
jpgReader = ImageReader.newInstance(biggestSize.getWidth(), biggestSize.getHeight(), ImageFormat.JPEG, 1);
jpgReader.setOnImageAvailableListener(imageAvailableListener, imgHandler);
List<Surface> outputs = Arrays.asList(jpgReader.getSurface());
cameraDevice.createCaptureSession(outputs, mccsStateCallback, cameraHandler);
}
else{
Log.d("NOOO","NOOOO");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private String getFrontFacingCameraId(CameraManager cameraManager) {
try {
for (String id : cameraManager.getCameraIdList()) {
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(id);
Integer cameraOrientation = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
if (cameraOrientation != null && cameraOrientation == CameraMetadata.LENS_FACING_FRONT) {
return id;
}
}
} catch (CameraAccessException ex) {
ex.printStackTrace();
}
return null;
}
EDIT: I've managed to make the CameraDevice assign itself by placing cameraManager.openCamera(cameraId,mStateCallback,cameraHandler);
before cameraDevice.createCaptureSession(outputs, mccsStateCallback, cameraHandler);
in initialiseCamera()
.
Now I'm having an issue where the camera output isn't being directed to the ImageReader's surface, and I'm getting an error in the console saying E/Surface: getSlotFromBufferLocked: unknown buffer: 0xa1ae7000
.