Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Unified Diff: webrtc/api/java/android/org/webrtc/VideoCapturerAndroid.java

Issue 1840193007: Android: Handle SurfaceTextureHelper ctor failure for decoder and capturer (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/api/java/android/org/webrtc/VideoCapturerAndroid.java
diff --git a/webrtc/api/java/android/org/webrtc/VideoCapturerAndroid.java b/webrtc/api/java/android/org/webrtc/VideoCapturerAndroid.java
index b8ab1a8c5ea6223ce46aebf7dae8a43e8fd21241..c41aa0991874487ab62e3e9f4960e23057b02368 100644
--- a/webrtc/api/java/android/org/webrtc/VideoCapturerAndroid.java
+++ b/webrtc/api/java/android/org/webrtc/VideoCapturerAndroid.java
@@ -11,7 +11,11 @@
package org.webrtc;
import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.opengl.GLES11Ext;
+import android.opengl.GLES20;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.SystemClock;
import android.view.Surface;
import android.view.WindowManager;
@@ -77,8 +81,11 @@ public class VideoCapturerAndroid implements
// potentially stalling the capturer if it runs out of buffers to write to).
private static final int NUMBER_OF_CAPTURE_BUFFERS = 3;
private final Set<byte[]> queuedBuffers = new HashSet<byte[]>();
- private final boolean isCapturingToTexture;
+ private boolean isCapturingToTexture;
private SurfaceTextureHelper surfaceHelper;
+ // These dummy variables are used in case |surfaceHelper| is null.
+ private int dummyTextureId;
+ private SurfaceTexture dummySurfaceTexture;
// The camera API can output one old frame after the camera has been switched or the resolution
// has been changed. This flag is used for dropping the first frame after camera restart.
private boolean dropNextFrame = false;
@@ -119,7 +126,7 @@ public class VideoCapturerAndroid implements
if (CAMERA_OBSERVER_PERIOD_MS * freezePeriodCount >= CAMERA_FREEZE_REPORT_TIMOUT_MS
&& eventsHandler != null) {
Logging.e(TAG, "Camera freezed.");
- if (surfaceHelper.isTextureInUse()) {
+ if (surfaceHelper != null && surfaceHelper.isTextureInUse()) {
// This can only happen if we are capturing to textures.
eventsHandler.onCameraFreezed("Camera failure. Client must return video buffers.");
} else {
@@ -374,9 +381,6 @@ public class VideoCapturerAndroid implements
final SurfaceTextureHelper surfaceTextureHelper, final Context applicationContext,
final CapturerObserver frameObserver) {
Logging.d(TAG, "startCapture requested: " + width + "x" + height + "@" + framerate);
- if (surfaceTextureHelper == null) {
- throw new IllegalArgumentException("surfaceTextureHelper not set.");
- }
if (applicationContext == null) {
throw new IllegalArgumentException("applicationContext not set.");
}
@@ -387,8 +391,20 @@ public class VideoCapturerAndroid implements
if (this.cameraThreadHandler != null) {
throw new RuntimeException("Camera has already been started.");
}
- this.cameraThreadHandler = surfaceTextureHelper.getHandler();
- this.surfaceHelper = surfaceTextureHelper;
+ if (surfaceTextureHelper != null) {
+ this.cameraThreadHandler = surfaceTextureHelper.getHandler();
+ this.surfaceHelper = surfaceTextureHelper;
+ } else {
+ // No SurfaceTextureHelper - create own handler.
+ if (isCapturingToTexture) {
+ Logging.e(TAG, "No SurfaceTextureHelper - falling back to byte buffer capture");
+ isCapturingToTexture = false;
+ }
+ this.surfaceHelper = null;
+ final HandlerThread thread = new HandlerThread(TAG);
+ thread.start();
+ this.cameraThreadHandler = new Handler(thread.getLooper());
+ }
final boolean didPost = maybePostOnCameraThread(new Runnable() {
@Override
public void run() {
@@ -445,7 +461,14 @@ public class VideoCapturerAndroid implements
}
try {
- camera.setPreviewTexture(surfaceHelper.getSurfaceTexture());
+ if (surfaceHelper != null) {
+ camera.setPreviewTexture(surfaceHelper.getSurfaceTexture());
+ } else {
+ // No SurfaceTextureHelper - create own dummy SurfaceTexture.
+ this.dummyTextureId = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
+ this.dummySurfaceTexture = new SurfaceTexture(dummyTextureId);
+ camera.setPreviewTexture(dummySurfaceTexture);
+ }
} catch (IOException e) {
Logging.e(TAG, "setPreviewTexture failed", error);
throw new RuntimeException(e);
@@ -456,7 +479,7 @@ public class VideoCapturerAndroid implements
camera.setErrorCallback(cameraErrorCallback);
startPreviewOnCameraThread(width, height, framerate);
frameObserver.onCapturerStarted(true);
- if (isCapturingToTexture) {
+ if (isCapturingToTexture && surfaceHelper != null) {
surfaceHelper.startListening(this);
}
@@ -474,6 +497,7 @@ public class VideoCapturerAndroid implements
synchronized (handlerLock) {
// Remove all pending Runnables posted from |this|.
cameraThreadHandler.removeCallbacksAndMessages(this /* token */);
+ releaseOwnHandlerAndDummySurfaceTexture();
cameraThreadHandler = null;
}
frameObserver.onCapturerStarted(false);
@@ -483,6 +507,22 @@ public class VideoCapturerAndroid implements
return;
}
+ private void releaseOwnHandlerAndDummySurfaceTexture() {
+ if (surfaceHelper == null) {
+ // We are using our own thread - quit it.
+ cameraThreadHandler.getLooper().quit();
+ cameraThreadHandler = null;
+ }
+ if (dummyTextureId != 0) {
+ GLES20.glDeleteTextures(1, new int[] {dummyTextureId}, 0);
+ dummyTextureId = 0;
+ }
+ if (dummySurfaceTexture != null) {
+ dummySurfaceTexture.release();
+ dummySurfaceTexture = null;
+ }
+ }
+
// (Re)start preview with the closest supported format to |width| x |height| @ |framerate|.
private void startPreviewOnCameraThread(int width, int height, int framerate) {
checkIsOnCameraThread();
@@ -584,6 +624,7 @@ public class VideoCapturerAndroid implements
synchronized (handlerLock) {
// Remove all pending Runnables posted from |this|.
cameraThreadHandler.removeCallbacksAndMessages(this /* token */);
+ releaseOwnHandlerAndDummySurfaceTexture();
cameraThreadHandler = null;
surfaceHelper = null;
}
@@ -609,7 +650,9 @@ public class VideoCapturerAndroid implements
Logging.d(TAG, "stopCaptureOnCameraThread");
// Make sure onTextureFrameAvailable() is not called anymore.
- surfaceHelper.stopListening();
+ if (surfaceHelper != null) {
+ surfaceHelper.stopListening();
+ }
cameraThreadHandler.removeCallbacks(cameraObserver);
cameraStatistics.getAndResetFrameCount();
Logging.d(TAG, "Stop preview.");

Powered by Google App Engine
This is Rietveld 408576698