[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:
parent
f5973e0eee
commit
7c76f124bf
|
@ -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');
|
||||||
|
|
|
@ -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));
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue