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

Unified Diff: webrtc/sdk/android/src/java/org/webrtc/CameraCapturer.java

Issue 2833773003: Support adding and removing MediaRecorder to camera 2 session. (Closed)
Patch Set: Add unit test Created 3 years, 8 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/sdk/android/src/java/org/webrtc/CameraCapturer.java
diff --git a/webrtc/sdk/android/src/java/org/webrtc/CameraCapturer.java b/webrtc/sdk/android/src/java/org/webrtc/CameraCapturer.java
index c3e8daab17cd857f8f5a968f0fdc86ab94c20e63..127df3b20f0f035fad51101954a487f6eefb9333 100644
--- a/webrtc/sdk/android/src/java/org/webrtc/CameraCapturer.java
+++ b/webrtc/sdk/android/src/java/org/webrtc/CameraCapturer.java
@@ -11,6 +11,7 @@
package org.webrtc;
import android.content.Context;
+import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Looper;
import java.util.Arrays;
@@ -23,6 +24,13 @@ abstract class CameraCapturer implements CameraVideoCapturer {
IN_PROGRESS, // Waiting for new switched capture session to start.
}
+ enum MediaRecorderState {
+ IDLE, // No media recording update (add or remove) requested.
+ IDLE_TO_ACTIVE, // Waiting for new capture session with added MediaRecorder surface to start.
+ ACTIVE_TO_IDLE, // Waiting for new capture session with removed MediaRecorder surface to start.
+ ACTIVE, // MediaRecorder was successfully added to camera pipeline.
+ }
+
private static final String TAG = "CameraCapturer";
private final static int MAX_OPEN_CAMERA_ATTEMPTS = 3;
private final static int OPEN_CAMERA_DELAY_MS = 500;
@@ -37,7 +45,9 @@ abstract class CameraCapturer implements CameraVideoCapturer {
@Override
public void onDone(CameraSession session) {
checkIsOnCameraThread();
- Logging.d(TAG, "Create session done");
+ Logging.d(TAG,
+ "Create session done. Switch state: " + switchState
+ + ". MediaRecorder state: " + mediaRecorderState);
uiThreadHandler.removeCallbacks(openCameraTimeoutRunnable);
synchronized (stateLock) {
capturerObserver.onCapturerStarted(true /* success */);
@@ -57,6 +67,20 @@ abstract class CameraCapturer implements CameraVideoCapturer {
switchState = SwitchState.IDLE;
switchCameraInternal(switchEventsHandler);
}
+
+ if (mediaRecorderState == MediaRecorderState.IDLE_TO_ACTIVE
+ || mediaRecorderState == MediaRecorderState.ACTIVE_TO_IDLE) {
+ if (mediaRecorderEventsHandler != null) {
+ mediaRecorderEventsHandler.onMediaRecorderSuccess();
+ mediaRecorderEventsHandler = null;
+ }
+ if (mediaRecorderState == MediaRecorderState.IDLE_TO_ACTIVE) {
+ mediaRecorderState = MediaRecorderState.ACTIVE;
+ } else {
+ mediaRecorderState = MediaRecorderState.IDLE;
+ }
+ mediaRecorder = null;
+ }
}
}
@@ -81,6 +105,15 @@ abstract class CameraCapturer implements CameraVideoCapturer {
switchState = SwitchState.IDLE;
}
+ if (mediaRecorderState != MediaRecorderState.IDLE) {
+ if (mediaRecorderEventsHandler != null) {
+ mediaRecorderEventsHandler.onMediaRecorderError(error);
+ mediaRecorderEventsHandler = null;
+ }
+ mediaRecorderState = MediaRecorderState.IDLE;
+ mediaRecorder = null;
+ }
+
if (failureType == CameraSession.FailureType.DISCONNECTED) {
eventsHandler.onCameraDisconnected();
} else {
@@ -213,6 +246,11 @@ abstract class CameraCapturer implements CameraVideoCapturer {
private CameraStatistics cameraStatistics; /* guarded by stateLock */
private boolean firstFrameObserved; /* guarded by stateLock */
+ // Variables used on camera thread - do not require stateLock synchronization.
+ private MediaRecorderState mediaRecorderState = MediaRecorderState.IDLE;
+ private MediaRecorderHandler mediaRecorderEventsHandler;
+ private MediaRecorder mediaRecorder;
+
public CameraCapturer(
String cameraName, CameraEventsHandler eventsHandler, CameraEnumerator cameraEnumerator) {
if (eventsHandler == null) {
@@ -287,7 +325,7 @@ abstract class CameraCapturer implements CameraVideoCapturer {
@Override
public void run() {
createCameraSession(createSessionCallback, cameraSessionEventsHandler, applicationContext,
- surfaceHelper, cameraName, width, height, framerate);
+ surfaceHelper, mediaRecorder, cameraName, width, height, framerate);
}
}, delayMs);
}
@@ -350,6 +388,29 @@ abstract class CameraCapturer implements CameraVideoCapturer {
}
@Override
+ public void addMediaRecorderToCamera(
+ final MediaRecorder mediaRecorder, final MediaRecorderHandler mediaRecoderEventsHandler) {
+ Logging.d(TAG, "addMediaRecorderToCamera");
+ cameraThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ updateMediaRecorderInternal(mediaRecorder, mediaRecoderEventsHandler);
+ }
+ });
+ }
+
+ @Override
+ public void removeMediaRecorderFromCamera(final MediaRecorderHandler mediaRecoderEventsHandler) {
+ Logging.d(TAG, "removeMediaRecorderFromCamera");
+ cameraThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ updateMediaRecorderInternal(null /* mediaRecorder */, mediaRecoderEventsHandler);
+ }
+ });
+ }
+
+ @Override
public boolean isScreencast() {
return false;
}
@@ -370,6 +431,13 @@ abstract class CameraCapturer implements CameraVideoCapturer {
}
}
+ private void reportCameraSwitchError(String error, CameraSwitchHandler switchEventsHandler) {
+ Logging.e(TAG, error);
+ if (switchEventsHandler != null) {
+ switchEventsHandler.onCameraSwitchError(error);
+ }
+ }
+
private void switchCameraInternal(final CameraSwitchHandler switchEventsHandler) {
Logging.d(TAG, "switchCamera internal");
@@ -384,18 +452,15 @@ abstract class CameraCapturer implements CameraVideoCapturer {
synchronized (stateLock) {
if (switchState != SwitchState.IDLE) {
- Logging.d(TAG, "switchCamera switchInProgress");
- if (switchEventsHandler != null) {
- switchEventsHandler.onCameraSwitchError("Camera switch already in progress.");
- }
+ reportCameraSwitchError("Camera switch already in progress.", switchEventsHandler);
+ return;
+ }
+ if (mediaRecorderState != MediaRecorderState.IDLE) {
+ reportCameraSwitchError("switchCamera: media recording is active", switchEventsHandler);
return;
}
-
if (!sessionOpening && currentSession == null) {
- Logging.d(TAG, "switchCamera: No session open");
- if (switchEventsHandler != null) {
- switchEventsHandler.onCameraSwitchError("Camera is not running.");
- }
+ reportCameraSwitchError("switchCamera: camera is not running.", switchEventsHandler);
return;
}
@@ -429,6 +494,73 @@ abstract class CameraCapturer implements CameraVideoCapturer {
Logging.d(TAG, "switchCamera done");
}
+ private void reportUpdateMediaRecorderError(
+ String error, MediaRecorderHandler mediaRecoderEventsHandler) {
+ checkIsOnCameraThread();
+ Logging.e(TAG, error);
+ if (mediaRecoderEventsHandler != null) {
+ mediaRecoderEventsHandler.onMediaRecorderError(error);
+ }
+ }
+
+ private void updateMediaRecorderInternal(
+ MediaRecorder mediaRecorder, MediaRecorderHandler mediaRecoderEventsHandler) {
+ checkIsOnCameraThread();
+ boolean addMediaRecorder = (mediaRecorder != null);
+ Logging.d(TAG,
+ "updateMediaRecoderInternal internal. State: " + mediaRecorderState
+ + ". Switch state: " + switchState + ". Add MediaRecorder: " + addMediaRecorder);
+
+ synchronized (stateLock) {
+ if ((addMediaRecorder && mediaRecorderState != MediaRecorderState.IDLE)
+ || (!addMediaRecorder && mediaRecorderState != MediaRecorderState.ACTIVE)) {
+ reportUpdateMediaRecorderError(
+ "Incorrect state for MediaRecorder update.", mediaRecoderEventsHandler);
+ return;
+ }
+ if (switchState != SwitchState.IDLE) {
+ reportUpdateMediaRecorderError(
+ "MediaRecorder update while camera is switching.", mediaRecoderEventsHandler);
+ return;
+ }
+ if (currentSession == null) {
+ reportUpdateMediaRecorderError(
+ "MediaRecorder update while camera is closed.", mediaRecoderEventsHandler);
+ return;
+ }
+ if (sessionOpening) {
+ reportUpdateMediaRecorderError(
+ "MediaRecorder update while camera is still opening.", mediaRecoderEventsHandler);
+ return;
+ }
+
+ this.mediaRecorderEventsHandler = mediaRecoderEventsHandler;
+ if (addMediaRecorder) {
sakal 2017/04/26 07:34:12 nit: can be replaced with a ternary operator
AlexG 2017/04/26 21:04:10 Done.
+ mediaRecorderState = MediaRecorderState.IDLE_TO_ACTIVE;
+ } else {
+ mediaRecorderState = MediaRecorderState.ACTIVE_TO_IDLE;
+ }
+ this.mediaRecorder = mediaRecorder;
+
+ Logging.d(TAG, "updateMediaRecoder: Stopping session");
+ cameraStatistics.release();
+ cameraStatistics = null;
+ final CameraSession oldSession = currentSession;
+ cameraThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ oldSession.stop();
+ }
+ });
+ currentSession = null;
+
+ sessionOpening = true;
+ openAttemptsRemaining = 1;
+ createSessionInternal(0);
+ }
+ Logging.d(TAG, "updateMediaRecoderInternal done");
+ }
+
private void checkIsOnCameraThread() {
if (Thread.currentThread() != cameraThreadHandler.getLooper().getThread()) {
Logging.e(TAG, "Check is on camera thread failed.");
@@ -444,6 +576,6 @@ abstract class CameraCapturer implements CameraVideoCapturer {
abstract protected void createCameraSession(
CameraSession.CreateSessionCallback createSessionCallback, CameraSession.Events events,
- Context applicationContext, SurfaceTextureHelper surfaceTextureHelper, String cameraName,
- int width, int height, int framerate);
+ Context applicationContext, SurfaceTextureHelper surfaceTextureHelper,
+ MediaRecorder mediaRecoder, String cameraName, int width, int height, int framerate);
}

Powered by Google App Engine
This is Rietveld 408576698