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..e19671f125d2b9550216d1b9bf5e18ecd76c2a79 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,11 @@ 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. |
+ IN_PROGRESS, // Waiting for new capture session with updated MediaRecorder surface to start. |
+ } |
+ |
private static final String TAG = "CameraCapturer"; |
private final static int MAX_OPEN_CAMERA_ATTEMPTS = 3; |
private final static int OPEN_CAMERA_DELAY_MS = 500; |
@@ -56,6 +62,13 @@ abstract class CameraCapturer implements CameraVideoCapturer { |
} else if (switchState == SwitchState.PENDING) { |
switchState = SwitchState.IDLE; |
switchCameraInternal(switchEventsHandler); |
+ } else if (mediaRecorderState == MediaRecorderState.IN_PROGRESS) { |
sakal
2017/04/21 08:06:15
One more thing, this shouldn't be else if. switchS
AlexG
2017/04/21 19:38:11
Done.
|
+ if (mediaRecorderEventsHandler != null) { |
+ mediaRecorderEventsHandler.onMediaRecorderSuccess(); |
+ mediaRecorderEventsHandler = null; |
+ } |
+ mediaRecorder = null; |
sakal
2017/04/21 08:06:15
Why is mediaRecorder set to null here? This means
AlexG
2017/04/21 19:38:11
Yes, camera switch is not allowed while MediaRecor
|
+ mediaRecorderState = MediaRecorderState.IDLE; |
} |
} |
} |
@@ -80,6 +93,14 @@ abstract class CameraCapturer implements CameraVideoCapturer { |
} |
switchState = SwitchState.IDLE; |
} |
+ if (mediaRecorderState == MediaRecorderState.IN_PROGRESS) { |
+ if (mediaRecorderEventsHandler != null) { |
+ mediaRecorderEventsHandler.onMediaRecorderError(error); |
+ mediaRecorderEventsHandler = null; |
+ } |
+ mediaRecorder = null; |
+ mediaRecorderState = MediaRecorderState.IDLE; |
+ } |
if (failureType == CameraSession.FailureType.DISCONNECTED) { |
eventsHandler.onCameraDisconnected(); |
@@ -198,6 +219,7 @@ abstract class CameraCapturer implements CameraVideoCapturer { |
private Context applicationContext; |
private CapturerObserver capturerObserver; |
private SurfaceTextureHelper surfaceHelper; |
+ private MediaRecorder mediaRecorder; |
private final Object stateLock = new Object(); |
private boolean sessionOpening; /* guarded by stateLock */ |
@@ -208,7 +230,10 @@ abstract class CameraCapturer implements CameraVideoCapturer { |
private int framerate; /* guarded by stateLock */ |
private int openAttemptsRemaining; /* guarded by stateLock */ |
private SwitchState switchState = SwitchState.IDLE; /* guarded by stateLock */ |
+ /* guarded by stateLock */ |
+ private MediaRecorderState mediaRecorderState = MediaRecorderState.IDLE; |
sakal
2017/04/21 07:56:49
Since these are only manipulated on the camera thr
AlexG
2017/04/21 19:38:11
Done.
|
private CameraSwitchHandler switchEventsHandler; /* guarded by stateLock */ |
+ private MediaRecorderHandler mediaRecorderEventsHandler; /* guarded by stateLock */ |
// Valid from onDone call until stopCapture, otherwise null. |
private CameraStatistics cameraStatistics; /* guarded by stateLock */ |
private boolean firstFrameObserved; /* guarded by stateLock */ |
@@ -287,7 +312,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 +375,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; |
} |
@@ -429,6 +477,60 @@ abstract class CameraCapturer implements CameraVideoCapturer { |
Logging.d(TAG, "switchCamera done"); |
} |
+ private void reportUpdateMediaRecorderError( |
+ String error, MediaRecorderHandler mediaRecoderEventsHandler) { |
+ Logging.e(TAG, error); |
sakal
2017/04/21 07:56:49
Please add checkIsOnCameraThread()
AlexG
2017/04/21 19:38:11
Done.
|
+ if (mediaRecoderEventsHandler != null) { |
+ mediaRecoderEventsHandler.onMediaRecorderError(error); |
+ } |
+ } |
+ |
+ private void updateMediaRecorderInternal( |
+ final MediaRecorder mediaRecorder, final MediaRecorderHandler mediaRecoderEventsHandler) { |
+ Logging.d(TAG, |
sakal
2017/04/21 07:56:49
Please add checkIsOnCameraThread()
AlexG
2017/04/21 19:38:11
Done.
|
+ "updateMediaRecoderInternal internal. State: " + mediaRecorderState |
+ + ". Session opening: " + sessionOpening); |
+ |
+ synchronized (stateLock) { |
+ if (mediaRecorderState != MediaRecorderState.IDLE) { |
+ reportUpdateMediaRecorderError( |
+ "MediaRecorder update already in progress.", mediaRecoderEventsHandler); |
+ return; |
+ } |
+ if (switchState != SwitchState.IDLE) { |
+ reportUpdateMediaRecorderError( |
+ "MediaRecorder update while camera is switching.", mediaRecoderEventsHandler); |
+ return; |
+ } |
+ if (sessionOpening) { |
+ reportUpdateMediaRecorderError( |
+ "MediaRecorder update while camera is still opening.", mediaRecoderEventsHandler); |
+ return; |
+ } |
+ |
+ this.mediaRecorder = mediaRecorder; |
+ this.mediaRecorderEventsHandler = mediaRecoderEventsHandler; |
+ mediaRecorderState = MediaRecorderState.IN_PROGRESS; |
+ |
+ 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 +546,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); |
} |