Fix NPE when accessing Android camera focus modes
Looks like getSupportedFocusModes() may return null, despite the documentation stating otherwise.
Bug: webrtc:13032
Change-Id: I0119b8a97be9ef4340c3e93f16e2dcaa899f2f3c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/227288
Reviewed-by: Xavier Lepaul <xalep@webrtc.org>
Commit-Queue: Xavier Lepaul <xalep@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#34873}
diff --git a/sdk/android/src/java/org/webrtc/Camera1Session.java b/sdk/android/src/java/org/webrtc/Camera1Session.java
index 7b4f6ca..a54f720 100644
--- a/sdk/android/src/java/org/webrtc/Camera1Session.java
+++ b/sdk/android/src/java/org/webrtc/Camera1Session.java
@@ -11,6 +11,7 @@
package org.webrtc;
import android.content.Context;
+import android.hardware.Camera;
import android.os.Handler;
import android.os.SystemClock;
import java.io.IOException;
@@ -39,8 +40,8 @@
private final Context applicationContext;
private final SurfaceTextureHelper surfaceTextureHelper;
private final int cameraId;
- private final android.hardware.Camera camera;
- private final android.hardware.Camera.CameraInfo info;
+ private final Camera camera;
+ private final Camera.CameraInfo info;
private final CaptureFormat captureFormat;
// Used only for stats. Only used on the camera thread.
private final long constructionTimeNs; // Construction time of this class.
@@ -66,17 +67,17 @@
return;
}
- final android.hardware.Camera camera;
+ final Camera camera;
try {
- camera = android.hardware.Camera.open(cameraId);
+ camera = Camera.open(cameraId);
} catch (RuntimeException e) {
callback.onFailure(FailureType.ERROR, e.getMessage());
return;
}
if (camera == null) {
- callback.onFailure(FailureType.ERROR,
- "android.hardware.Camera.open returned null for camera id = " + cameraId);
+ callback.onFailure(
+ FailureType.ERROR, "Camera.open returned null for camera id = " + cameraId);
return;
}
@@ -88,12 +89,12 @@
return;
}
- final android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
- android.hardware.Camera.getCameraInfo(cameraId, info);
+ final Camera.CameraInfo info = new Camera.CameraInfo();
+ Camera.getCameraInfo(cameraId, info);
final CaptureFormat captureFormat;
try {
- final android.hardware.Camera.Parameters parameters = camera.getParameters();
+ final Camera.Parameters parameters = camera.getParameters();
captureFormat = findClosestCaptureFormat(parameters, width, height, framerate);
final Size pictureSize = findClosestPictureSize(parameters, width, height);
updateCameraParameters(camera, parameters, captureFormat, pictureSize, captureToTexture);
@@ -111,7 +112,7 @@
}
}
- // Calculate orientation manually and send it as CVO insted.
+ // Calculate orientation manually and send it as CVO instead.
try {
camera.setDisplayOrientation(0 /* degrees */);
} catch (RuntimeException e) {
@@ -124,9 +125,8 @@
surfaceTextureHelper, cameraId, camera, info, captureFormat, constructionTimeNs));
}
- private static void updateCameraParameters(android.hardware.Camera camera,
- android.hardware.Camera.Parameters parameters, CaptureFormat captureFormat, Size pictureSize,
- boolean captureToTexture) {
+ private static void updateCameraParameters(Camera camera, Camera.Parameters parameters,
+ CaptureFormat captureFormat, Size pictureSize, boolean captureToTexture) {
final List<String> focusModes = parameters.getSupportedFocusModes();
parameters.setPreviewFpsRange(captureFormat.framerate.min, captureFormat.framerate.max);
@@ -139,14 +139,14 @@
if (parameters.isVideoStabilizationSupported()) {
parameters.setVideoStabilization(true);
}
- if (focusModes.contains(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
- parameters.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
+ if (focusModes != null && focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
+ parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
camera.setParameters(parameters);
}
private static CaptureFormat findClosestCaptureFormat(
- android.hardware.Camera.Parameters parameters, int width, int height, int framerate) {
+ Camera.Parameters parameters, int width, int height, int framerate) {
// Find closest supported format for `width` x `height` @ `framerate`.
final List<CaptureFormat.FramerateRange> supportedFramerates =
Camera1Enumerator.convertFramerates(parameters.getSupportedPreviewFpsRange());
@@ -162,16 +162,14 @@
return new CaptureFormat(previewSize.width, previewSize.height, fpsRange);
}
- private static Size findClosestPictureSize(
- android.hardware.Camera.Parameters parameters, int width, int height) {
+ private static Size findClosestPictureSize(Camera.Parameters parameters, int width, int height) {
return CameraEnumerationAndroid.getClosestSupportedSize(
Camera1Enumerator.convertSizes(parameters.getSupportedPictureSizes()), width, height);
}
private Camera1Session(Events events, boolean captureToTexture, Context applicationContext,
- SurfaceTextureHelper surfaceTextureHelper, int cameraId, android.hardware.Camera camera,
- android.hardware.Camera.CameraInfo info, CaptureFormat captureFormat,
- long constructionTimeNs) {
+ SurfaceTextureHelper surfaceTextureHelper, int cameraId, Camera camera,
+ Camera.CameraInfo info, CaptureFormat captureFormat, long constructionTimeNs) {
Logging.d(TAG, "Create new camera1 session on camera " + cameraId);
this.cameraThreadHandler = new Handler();
@@ -208,18 +206,18 @@
state = SessionState.RUNNING;
- camera.setErrorCallback(new android.hardware.Camera.ErrorCallback() {
+ camera.setErrorCallback(new Camera.ErrorCallback() {
@Override
- public void onError(int error, android.hardware.Camera camera) {
+ public void onError(int error, Camera camera) {
String errorMessage;
- if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
+ if (error == Camera.CAMERA_ERROR_SERVER_DIED) {
errorMessage = "Camera server died!";
} else {
errorMessage = "Camera error: " + error;
}
Logging.e(TAG, errorMessage);
stopInternal();
- if (error == android.hardware.Camera.CAMERA_ERROR_EVICTED) {
+ if (error == Camera.CAMERA_ERROR_EVICTED) {
events.onCameraDisconnected(Camera1Session.this);
} else {
events.onCameraError(Camera1Session.this, errorMessage);
@@ -251,7 +249,7 @@
state = SessionState.STOPPED;
surfaceTextureHelper.stopListening();
// Note: stopPreview or other driver code might deadlock. Deadlock in
- // android.hardware.Camera._stopPreview(Native Method) has been observed on
+ // Camera._stopPreview(Native Method) has been observed on
// Nexus 5 (hammerhead), OS version LMY48I.
camera.stopPreview();
camera.release();
@@ -277,21 +275,21 @@
// Undo the mirror that the OS "helps" us with.
// http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)
- final VideoFrame modifiedFrame = new VideoFrame(
- CameraSession.createTextureBufferWithModifiedTransformMatrix(
- (TextureBufferImpl) frame.getBuffer(),
- /* mirror= */ info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT,
- /* rotation= */ 0),
- /* rotation= */ getFrameOrientation(), frame.getTimestampNs());
+ final VideoFrame modifiedFrame =
+ new VideoFrame(CameraSession.createTextureBufferWithModifiedTransformMatrix(
+ (TextureBufferImpl) frame.getBuffer(),
+ /* mirror= */ info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT,
+ /* rotation= */ 0),
+ /* rotation= */ getFrameOrientation(), frame.getTimestampNs());
events.onFrameCaptured(Camera1Session.this, modifiedFrame);
modifiedFrame.release();
});
}
private void listenForBytebufferFrames() {
- camera.setPreviewCallbackWithBuffer(new android.hardware.Camera.PreviewCallback() {
+ camera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
@Override
- public void onPreviewFrame(final byte[] data, android.hardware.Camera callbackCamera) {
+ public void onPreviewFrame(final byte[] data, Camera callbackCamera) {
checkIsOnCameraThread();
if (callbackCamera != camera) {
@@ -328,7 +326,7 @@
private int getFrameOrientation() {
int rotation = CameraSession.getDeviceOrientation(applicationContext);
- if (info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK) {
+ if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
rotation = 360 - rotation;
}
return (info.orientation + rotation) % 360;