From a6b8efd358778f7df01ab711d106da05aa93a1d6 Mon Sep 17 00:00:00 2001 From: Paul Kompfner Date: Thu, 22 Oct 2020 19:45:52 -0400 Subject: [PATCH 1/2] =?UTF-8?q?On=20iOS,=20return=20the=20new=20camera=20f?= =?UTF-8?q?acing=20mode=20("user"=20or=20"environment")=20from=20=5Fswitch?= =?UTF-8?q?Camera(),=20and=20introduce=20a=20new=20method=E2=80=94=5FgetCa?= =?UTF-8?q?meraFacingMode()=E2=80=94for=20retrieving=20the=20current=20cam?= =?UTF-8?q?era=20facing=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MediaStreamTrack.js | 16 ++++++++++++++- ios/RCTWebRTC/VideoCaptureController.h | 3 ++- ios/RCTWebRTC/VideoCaptureController.m | 7 ++++++- ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m | 22 +++++++++++++++++++-- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/MediaStreamTrack.js b/MediaStreamTrack.js index fc9125475..a81770edb 100644 --- a/MediaStreamTrack.js +++ b/MediaStreamTrack.js @@ -89,7 +89,21 @@ class MediaStreamTrack extends EventTarget(MEDIA_STREAM_TRACK_EVENTS) { if (this.kind !== 'video') { throw new Error('Only implemented for video tracks'); } - WebRTCModule.mediaStreamTrackSwitchCamera(this.id); + return WebRTCModule.mediaStreamTrackSwitchCamera(this.id); + } + + /** + * Private / custom API for retrieving the current camera facing mode. + * Returns "user" or "environment". + */ + _getCameraFacingMode() { + if (this.remote) { + throw new Error('Not implemented for remote tracks'); + } + if (this.kind !== 'video') { + throw new Error('Only implemented for video tracks'); + } + return WebRTCModule.mediaStreamTrackGetCameraFacingMode(this.id); } applyConstraints() { diff --git a/ios/RCTWebRTC/VideoCaptureController.h b/ios/RCTWebRTC/VideoCaptureController.h index fc337fbbf..6f4aa33cf 100644 --- a/ios/RCTWebRTC/VideoCaptureController.h +++ b/ios/RCTWebRTC/VideoCaptureController.h @@ -8,6 +8,7 @@ andConstraints:(NSDictionary *)constraints; -(void)startCapture; -(void)stopCapture; --(void)switchCamera; +-(NSString *)switchCamera; +-(NSString *)facingMode; @end diff --git a/ios/RCTWebRTC/VideoCaptureController.m b/ios/RCTWebRTC/VideoCaptureController.m index 12c901cff..cfd1635e4 100644 --- a/ios/RCTWebRTC/VideoCaptureController.m +++ b/ios/RCTWebRTC/VideoCaptureController.m @@ -114,10 +114,15 @@ -(void)stopCapture { dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); } --(void)switchCamera { +-(NSString *)switchCamera { _usingFrontCamera = !_usingFrontCamera; [self startCapture]; + return [self facingMode]; +} + +-(NSString *)facingMode { + return _usingFrontCamera ? @"user" : @"environment"; } #pragma mark Private diff --git a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m index 06063dd2a..b3826904e 100644 --- a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m +++ b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m @@ -228,13 +228,31 @@ - (RTCVideoTrack *)createVideoTrack:(NSDictionary *)constraints { } } -RCT_EXPORT_METHOD(mediaStreamTrackSwitchCamera:(nonnull NSString *)trackID) +RCT_EXPORT_METHOD(mediaStreamTrackSwitchCamera:(nonnull NSString *)trackID + withResolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { RTCMediaStreamTrack *track = self.localTracks[trackID]; if (track) { RTCVideoTrack *videoTrack = (RTCVideoTrack *)track; - [videoTrack.videoCaptureController switchCamera]; + NSString *newFacingMode = [videoTrack.videoCaptureController switchCamera]; + resolve(newFacingMode); + return; + } + reject(@"invalid_track_id", @"No track found with given ID", nil); +} + +RCT_EXPORT_METHOD(mediaStreamTrackGetCameraFacingMode:(nonnull NSString *)trackID + withResolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + RTCMediaStreamTrack *track = self.localTracks[trackID]; + if (track) { + RTCVideoTrack *videoTrack = (RTCVideoTrack *)track; + resolve([videoTrack.videoCaptureController facingMode]); + return; } + reject(@"invalid_track_id", @"No track found with given ID", nil); } #pragma mark - Helpers From 2760ba70217a030f6e8cde9dcfba8bb413391172 Mon Sep 17 00:00:00 2001 From: Paul Kompfner Date: Fri, 23 Oct 2020 09:59:55 -0400 Subject: [PATCH 2/2] =?UTF-8?q?On=20Android,=20return=20the=20new=20camera?= =?UTF-8?q?=20facing=20mode=20("user"=20or=20"environment")=20from=20=5Fsw?= =?UTF-8?q?itchCamera(),=20and=20introduce=20a=20new=20method=E2=80=94=5Fg?= =?UTF-8?q?etCameraFacingMode()=E2=80=94for=20retrieving=20the=20current?= =?UTF-8?q?=20camera=20facing=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oney/WebRTCModule/GetUserMediaImpl.java | 17 ++++++++- .../WebRTCModule/VideoCaptureController.java | 24 +++++++++--- .../com/oney/WebRTCModule/WebRTCModule.java | 38 ++++++++++++++++++- ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m | 8 +++- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java b/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java index 338d1fe1f..ccc5e4ef5 100644 --- a/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java +++ b/android/src/main/java/com/oney/WebRTCModule/GetUserMediaImpl.java @@ -233,10 +233,23 @@ void disposeTrack(String id) { } } - void switchCamera(String trackId) { + void switchCamera(String trackId, VideoCaptureController.SwitchCameraHandler handler) throws Exception { TrackPrivate track = tracks.get(trackId); if (track != null && track.videoCaptureController != null) { - track.videoCaptureController.switchCamera(); + track.videoCaptureController.switchCamera(handler); + } + else { + throw new Exception("Track not found when attempting to switch camera"); + } + } + + String getCameraFacingMode(String trackId) throws Exception { + TrackPrivate track = tracks.get(trackId); + if (track != null && track.videoCaptureController != null) { + return track.videoCaptureController.facingMode(); + } + else { + throw new Exception("Track not found when attempting to get camera facing mode"); } } diff --git a/android/src/main/java/com/oney/WebRTCModule/VideoCaptureController.java b/android/src/main/java/com/oney/WebRTCModule/VideoCaptureController.java index 2f77065ef..6f6cac47c 100644 --- a/android/src/main/java/com/oney/WebRTCModule/VideoCaptureController.java +++ b/android/src/main/java/com/oney/WebRTCModule/VideoCaptureController.java @@ -87,7 +87,12 @@ public boolean stopCapture() { } } - public void switchCamera() { + public interface SwitchCameraHandler { + // Called whether or not it succeeded + public void onSwitchCameraDone(String facingMode); + } + + public void switchCamera(SwitchCameraHandler handler) { if (videoCapturer instanceof CameraVideoCapturer) { CameraVideoCapturer capturer = (CameraVideoCapturer) videoCapturer; String[] deviceNames = cameraEnumerator.getDeviceNames(); @@ -95,7 +100,7 @@ public void switchCamera() { // Nothing to switch to. if (deviceCount < 2) { - return; + handler.onSwitchCameraDone(facingMode()); } // The usual case. @@ -104,29 +109,34 @@ public void switchCamera() { @Override public void onCameraSwitchDone(boolean b) { isFrontFacing = b; + handler.onSwitchCameraDone(facingMode()); } @Override public void onCameraSwitchError(String s) { Log.e(TAG, "Error switching camera: " + s); + handler.onSwitchCameraDone(facingMode()); } }); - return; } // If we are here the device has more than 2 cameras. Cycle through them // and switch to the first one of the desired facing mode. - switchCamera(!isFrontFacing, deviceCount); + switchCamera(!isFrontFacing, deviceCount, handler); } } + public String facingMode() { + return isFrontFacing ? "user" : "environment"; + } + /** * Helper function which tries to switch cameras until the desired facing mode is found. * * @param desiredFrontFacing - The desired front facing value. * @param tries - How many times to try switching. */ - private void switchCamera(boolean desiredFrontFacing, int tries) { + private void switchCamera(boolean desiredFrontFacing, int tries, SwitchCameraHandler handler) { CameraVideoCapturer capturer = (CameraVideoCapturer) videoCapturer; capturer.switchCamera(new CameraVideoCapturer.CameraSwitchHandler() { @@ -135,16 +145,18 @@ public void onCameraSwitchDone(boolean b) { if (b != desiredFrontFacing) { int newTries = tries-1; if (newTries > 0) { - switchCamera(desiredFrontFacing, newTries); + switchCamera(desiredFrontFacing, newTries, handler); } } else { isFrontFacing = desiredFrontFacing; + handler.onSwitchCameraDone(facingMode()); } } @Override public void onCameraSwitchError(String s) { Log.e(TAG, "Error switching camera: " + s); + handler.onSwitchCameraDone(facingMode()); } }); } diff --git a/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java b/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java index 5a2481921..c9a639a1e 100644 --- a/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java +++ b/android/src/main/java/com/oney/WebRTCModule/WebRTCModule.java @@ -9,6 +9,7 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; @@ -634,11 +635,44 @@ private void mediaStreamTrackSetEnabledAsync(String id, boolean enabled) { getUserMediaImpl.mediaStreamTrackSetEnabled(id, enabled); } + private static final String SWITCH_CAMERA_ERROR = "SWITCH_CAMERA_ERROR"; + + @ReactMethod + public void mediaStreamTrackSwitchCamera(String id, Promise promise) { + MediaStreamTrack track = getLocalTrack(id); + if (track != null) { + try { + getUserMediaImpl.switchCamera(id, new VideoCaptureController.SwitchCameraHandler() { + @Override + public void onSwitchCameraDone(String facingMode) { + promise.resolve(facingMode); + } + }); + } + catch (Exception e) { + promise.reject(SWITCH_CAMERA_ERROR, e); + } + } + else { + promise.reject(SWITCH_CAMERA_ERROR, "Local track not found when attempting to switch camera"); + } + } + + private static final String GET_CAMERA_FACING_MODE_ERROR = "GET_CAMERA_FACING_MODE_ERROR"; + @ReactMethod - public void mediaStreamTrackSwitchCamera(String id) { + public void mediaStreamTrackGetCameraFacingMode(String id, Promise promise) { MediaStreamTrack track = getLocalTrack(id); if (track != null) { - getUserMediaImpl.switchCamera(id); + try { + promise.resolve(getUserMediaImpl.getCameraFacingMode(id)); + } + catch (Exception e) { + promise.reject(GET_CAMERA_FACING_MODE_ERROR, e); + } + } + else { + promise.reject(GET_CAMERA_FACING_MODE_ERROR, "Local track not found when attempting to get camera facing mode"); } } diff --git a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m index b3826904e..aed4e7223 100644 --- a/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m +++ b/ios/RCTWebRTC/WebRTCModule+RTCMediaStream.m @@ -239,7 +239,9 @@ - (RTCVideoTrack *)createVideoTrack:(NSDictionary *)constraints { resolve(newFacingMode); return; } - reject(@"invalid_track_id", @"No track found with given ID", nil); + reject(@"switch_camera_error", + @"Local track not found when attempting to switch camera", + nil); } RCT_EXPORT_METHOD(mediaStreamTrackGetCameraFacingMode:(nonnull NSString *)trackID @@ -252,7 +254,9 @@ - (RTCVideoTrack *)createVideoTrack:(NSDictionary *)constraints { resolve([videoTrack.videoCaptureController facingMode]); return; } - reject(@"invalid_track_id", @"No track found with given ID", nil); + reject(@"get_camera_facing_mode_error", + @"Local track not found when attempting to get camera facing mode", + nil); } #pragma mark - Helpers