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

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: Address comments - 3 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
« no previous file with comments | « webrtc/sdk/android/src/java/org/webrtc/Camera2Session.java ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..859b7f745331841016ff78ba52b34a27b1d4af09 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,19 @@ 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;
+ }
+ }
}
}
@@ -81,6 +104,14 @@ abstract class CameraCapturer implements CameraVideoCapturer {
switchState = SwitchState.IDLE;
}
+ if (mediaRecorderState != MediaRecorderState.IDLE) {
+ if (mediaRecorderEventsHandler != null) {
+ mediaRecorderEventsHandler.onMediaRecorderError(error);
+ mediaRecorderEventsHandler = null;
+ }
+ mediaRecorderState = MediaRecorderState.IDLE;
+ }
+
if (failureType == CameraSession.FailureType.DISCONNECTED) {
eventsHandler.onCameraDisconnected();
} else {
@@ -88,8 +119,7 @@ abstract class CameraCapturer implements CameraVideoCapturer {
}
} else {
Logging.w(TAG, "Opening camera failed, retry: " + error);
-
- createSessionInternal(OPEN_CAMERA_DELAY_MS);
+ createSessionInternal(OPEN_CAMERA_DELAY_MS, null /* mediaRecorder */);
}
}
}
@@ -213,6 +243,10 @@ 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;
+
public CameraCapturer(
String cameraName, CameraEventsHandler eventsHandler, CameraEnumerator cameraEnumerator) {
if (eventsHandler == null) {
@@ -277,17 +311,17 @@ abstract class CameraCapturer implements CameraVideoCapturer {
sessionOpening = true;
openAttemptsRemaining = MAX_OPEN_CAMERA_ATTEMPTS;
- createSessionInternal(0);
+ createSessionInternal(0, null /* mediaRecorder */);
}
}
- private void createSessionInternal(int delayMs) {
+ private void createSessionInternal(int delayMs, final MediaRecorder mediaRecorder) {
uiThreadHandler.postDelayed(openCameraTimeoutRunnable, delayMs + OPEN_CAMERA_TIMEOUT);
cameraThreadHandler.postDelayed(new Runnable() {
@Override
public void run() {
createCameraSession(createSessionCallback, cameraSessionEventsHandler, applicationContext,
- surfaceHelper, cameraName, width, height, framerate);
+ surfaceHelper, mediaRecorder, cameraName, width, height, framerate);
}
}, delayMs);
}
@@ -350,6 +384,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 +427,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 +448,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;
}
@@ -424,11 +485,74 @@ abstract class CameraCapturer implements CameraVideoCapturer {
sessionOpening = true;
openAttemptsRemaining = 1;
- createSessionInternal(0);
+ createSessionInternal(0, null /* mediaRecorder */);
}
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;
+ mediaRecorderState =
+ addMediaRecorder ? MediaRecorderState.IDLE_TO_ACTIVE : MediaRecorderState.ACTIVE_TO_IDLE;
+
+ 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, mediaRecorder);
+ }
+ 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 +568,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);
}
« no previous file with comments | « webrtc/sdk/android/src/java/org/webrtc/Camera2Session.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698