[RN] Use native API for toggling cameras

Use the curstom _switchCamera API provided by react-native-webrtc to toggle the
camera instead of destroying the current track and creating a new one.

_switchCamera is implemented at a low level, so the track perceives no changes,
thus being a lot faster and less involved since the capturer doesn't need to be
destroyed and re-created.

In addition, don't mirror the video for the back camera.

Ref: https://github.com/oney/react-native-webrtc/pull/235
This commit is contained in:
Saúl Ibarra Corretgé 2017-04-03 10:57:01 +02:00 committed by Lyubo Marinov
parent f5973e0eee
commit 7c76f124bf
4 changed files with 73 additions and 14 deletions

View File

@ -30,3 +30,15 @@ export const SET_CAMERA_FACING_MODE = Symbol('SET_CAMERA_FACING_MODE');
* } * }
*/ */
export const SET_VIDEO_MUTED = Symbol('SET_VIDEO_MUTED'); export const SET_VIDEO_MUTED = Symbol('SET_VIDEO_MUTED');
/**
* The type of (redux) action to toggle the local video camera facing mode. In
* contrast to SET_CAMERA_FACING_MODE, allows the toggling to be optimally
* and/or natively implemented without the overhead of separate reads and writes
* of the current/effective camera facing mode.
*
* {
* type: TOGGLE_CAMERA_FACING_MODE
* }
*/
export const TOGGLE_CAMERA_FACING_MODE = Symbol('TOGGLE_CAMERA_FACING_MODE');

View File

@ -5,7 +5,8 @@ import type { Dispatch } from 'redux';
import { import {
SET_AUDIO_MUTED, SET_AUDIO_MUTED,
SET_CAMERA_FACING_MODE, SET_CAMERA_FACING_MODE,
SET_VIDEO_MUTED SET_VIDEO_MUTED,
TOGGLE_CAMERA_FACING_MODE
} from './actionTypes'; } from './actionTypes';
import { CAMERA_FACING_MODE } from './constants'; import { CAMERA_FACING_MODE } from './constants';
@ -73,21 +74,19 @@ export function toggleAudioMuted() {
} }
/** /**
* Toggles the camera between front and rear (user and environment). * Toggles the camera facing mode. Most commonly, for example, mobile devices
* such as phones have a front/user-facing and a back/environment-facing
* cameras. In contrast to setCameraFacingMode, allows the toggling to be
* optimally and/or natively implemented without the overhead of separate reads
* and writes of the current/effective camera facing mode.
* *
* @returns {Function} * @returns {{
* type: TOGGLE_CAMERA_FACING_MODE
* }}
*/ */
export function toggleCameraFacingMode() { export function toggleCameraFacingMode() {
return (dispatch: Dispatch<*>, getState: Function) => { return {
let cameraFacingMode type: TOGGLE_CAMERA_FACING_MODE
= getState()['features/base/media'].video.facingMode;
cameraFacingMode
= cameraFacingMode === CAMERA_FACING_MODE.USER
? CAMERA_FACING_MODE.ENVIRONMENT
: CAMERA_FACING_MODE.USER;
return dispatch(setCameraFacingMode(cameraFacingMode));
}; };
} }

View File

@ -5,7 +5,8 @@ import { ReducerRegistry } from '../redux';
import { import {
SET_AUDIO_MUTED, SET_AUDIO_MUTED,
SET_CAMERA_FACING_MODE, SET_CAMERA_FACING_MODE,
SET_VIDEO_MUTED SET_VIDEO_MUTED,
TOGGLE_CAMERA_FACING_MODE
} from './actionTypes'; } from './actionTypes';
import { CAMERA_FACING_MODE } from './constants'; import { CAMERA_FACING_MODE } from './constants';
@ -88,6 +89,20 @@ function _video(state = VIDEO_INITIAL_MEDIA_STATE, action) {
muted: action.muted muted: action.muted
}; };
case TOGGLE_CAMERA_FACING_MODE: {
let cameraFacingMode = state.facingMode;
cameraFacingMode
= cameraFacingMode === CAMERA_FACING_MODE.USER
? CAMERA_FACING_MODE.ENVIRONMENT
: CAMERA_FACING_MODE.USER;
return {
...state,
facingMode: cameraFacingMode
};
}
default: default:
return state; return state;
} }

View File

@ -6,6 +6,7 @@ import {
SET_AUDIO_MUTED, SET_AUDIO_MUTED,
SET_CAMERA_FACING_MODE, SET_CAMERA_FACING_MODE,
SET_VIDEO_MUTED, SET_VIDEO_MUTED,
TOGGLE_CAMERA_FACING_MODE,
setAudioMuted, setAudioMuted,
setVideoMuted setVideoMuted
} from '../media'; } from '../media';
@ -64,6 +65,38 @@ MiddlewareRegistry.register(store => next => action => {
_setMuted(store, action, MEDIA_TYPE.VIDEO); _setMuted(store, action, MEDIA_TYPE.VIDEO);
break; break;
case TOGGLE_CAMERA_FACING_MODE: {
const localTrack = _getLocalTrack(store, MEDIA_TYPE.VIDEO);
let jitsiTrack;
let mediaStreamTrack;
if (localTrack
&& (jitsiTrack = localTrack.jitsiTrack)
&& (mediaStreamTrack = jitsiTrack.track)) {
// XXX MediaStreamTrack._switchCamera a custom function implemented
// in react-native-webrtc for video which switches between the
// cameras via a native WebRTC library implementation without making
// any changes to the track.
// FIXME JitsiLocalTrack defines getCameraFacingMode. By calling
// _switchCamera on MediaStreamTrack without the knowledge of
// lib-jitsi-meet we are likely introducing an inconsistency in
// JitsiLocalTrack's state.
mediaStreamTrack._switchCamera();
// Don't mirror the video of the back/environment-facing camera.
// FIXME Relies on the fact that we always open the camera in
// user-facing mode first.
store.dispatch({
type: TRACK_UPDATED,
track: {
jitsiTrack,
mirror: !localTrack.mirror
}
});
}
break;
}
case TRACK_UPDATED: case TRACK_UPDATED:
return _trackUpdated(store, next, action); return _trackUpdated(store, next, action);
} }