mirror of
https://github.com/oxen-io/session-android.git
synced 2025-06-09 05:58:34 +00:00
Skip monochrome cameras when switching cameras on video calls.
This commit is contained in:
parent
ffa01d491a
commit
284fe294ac
@ -117,7 +117,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation project(':libsignal-service')
|
implementation project(':libsignal-service')
|
||||||
|
|
||||||
implementation 'org.signal:ringrtc-android:0.3.0'
|
implementation 'org.signal:ringrtc-android:0.3.1'
|
||||||
|
|
||||||
implementation "me.leolin:ShortcutBadger:1.1.16"
|
implementation "me.leolin:ShortcutBadger:1.1.16"
|
||||||
implementation 'se.emilsjolander:stickylistheaders:2.7.0'
|
implementation 'se.emilsjolander:stickylistheaders:2.7.0'
|
||||||
|
@ -351,8 +351,8 @@ dependencyVerification {
|
|||||||
['org.signal:android-database-sqlcipher:3.5.9-S3',
|
['org.signal:android-database-sqlcipher:3.5.9-S3',
|
||||||
'33d4063336893af00b9d68b418e7b290cace74c20ce8aacffddc0911010d3d73'],
|
'33d4063336893af00b9d68b418e7b290cace74c20ce8aacffddc0911010d3d73'],
|
||||||
|
|
||||||
['org.signal:ringrtc-android:0.3.0',
|
['org.signal:ringrtc-android:0.3.1',
|
||||||
'c3c294915f86d6dbaf934d6542e3f99a003c50f5490bd2c0b80f5fe3a7a5fdfc'],
|
'785c422a2322f810141d85f63eab3874961b19face886daaf140ab011d39e166'],
|
||||||
|
|
||||||
['org.signal:signal-metadata-java:0.1.0',
|
['org.signal:signal-metadata-java:0.1.0',
|
||||||
'f3faa23b7d9b5096d12979c35679d1e3b5e007522d8bef167a28e456f2a7c7d9'],
|
'f3faa23b7d9b5096d12979c35679d1e3b5e007522d8bef167a28e456f2a7c7d9'],
|
||||||
|
@ -1,11 +1,20 @@
|
|||||||
package org.thoughtcrime.securesms.ringrtc;
|
package org.thoughtcrime.securesms.ringrtc;
|
||||||
|
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.hardware.camera2.CameraAccessException;
|
||||||
|
import android.hardware.camera2.CameraCharacteristics;
|
||||||
|
import android.hardware.camera2.CameraManager;
|
||||||
|
import android.hardware.camera2.CameraMetadata;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import org.signal.ringrtc.CallConnection;
|
import org.signal.ringrtc.CallConnection;
|
||||||
import org.signal.ringrtc.CallConnectionFactory;
|
import org.signal.ringrtc.CallConnectionFactory;
|
||||||
@ -17,6 +26,7 @@ import org.thoughtcrime.securesms.logging.Log;
|
|||||||
import org.webrtc.AudioSource;
|
import org.webrtc.AudioSource;
|
||||||
import org.webrtc.AudioTrack;
|
import org.webrtc.AudioTrack;
|
||||||
import org.webrtc.Camera1Enumerator;
|
import org.webrtc.Camera1Enumerator;
|
||||||
|
import org.webrtc.Camera2Capturer;
|
||||||
import org.webrtc.Camera2Enumerator;
|
import org.webrtc.Camera2Enumerator;
|
||||||
import org.webrtc.CameraEnumerator;
|
import org.webrtc.CameraEnumerator;
|
||||||
import org.webrtc.CameraVideoCapturer;
|
import org.webrtc.CameraVideoCapturer;
|
||||||
@ -265,7 +275,7 @@ public class CallConnectionWrapper {
|
|||||||
|
|
||||||
Log.i(TAG, "Camera2 enumerator supported: " + camera2EnumeratorIsSupported);
|
Log.i(TAG, "Camera2 enumerator supported: " + camera2EnumeratorIsSupported);
|
||||||
|
|
||||||
return camera2EnumeratorIsSupported ? new Camera2Enumerator(context)
|
return camera2EnumeratorIsSupported ? new FilteredCamera2Enumerator(context)
|
||||||
: new Camera1Enumerator(true);
|
: new Camera1Enumerator(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,4 +295,106 @@ public class CallConnectionWrapper {
|
|||||||
public interface CameraEventListener {
|
public interface CameraEventListener {
|
||||||
void onCameraSwitchCompleted(@NonNull CameraState newCameraState);
|
void onCameraSwitchCompleted(@NonNull CameraState newCameraState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(21)
|
||||||
|
private static class FilteredCamera2Enumerator extends Camera2Enumerator {
|
||||||
|
|
||||||
|
@NonNull private final Context context;
|
||||||
|
@Nullable private final CameraManager cameraManager;
|
||||||
|
@Nullable private String[] deviceNames;
|
||||||
|
|
||||||
|
FilteredCamera2Enumerator(@NonNull Context context) {
|
||||||
|
super(context);
|
||||||
|
|
||||||
|
this.context = context;
|
||||||
|
this.cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
|
||||||
|
this.deviceNames = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMonochrome(String deviceName, CameraManager cameraManager) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(deviceName);
|
||||||
|
int[] capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
|
||||||
|
|
||||||
|
if (capabilities != null) {
|
||||||
|
for (int cap : capabilities) {
|
||||||
|
if (cap == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLensFacing(String deviceName, CameraManager cameraManager, Integer facing) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(deviceName);
|
||||||
|
Integer lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING);
|
||||||
|
|
||||||
|
return facing.equals(lensFacing);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull String[] getDeviceNames() {
|
||||||
|
|
||||||
|
if (deviceNames != null) {
|
||||||
|
return deviceNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<String> cameraList = new LinkedList<>();
|
||||||
|
|
||||||
|
if (cameraManager != null) {
|
||||||
|
// While skipping cameras that are monochrome, gather cameras
|
||||||
|
// until we have at most 1 front facing camera and 1 back
|
||||||
|
// facing camera.
|
||||||
|
|
||||||
|
List<String> devices = Stream.of(cameraManager.getCameraIdList())
|
||||||
|
.filterNot(id -> isMonochrome(id, cameraManager))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
String frontCamera = Stream.of(devices)
|
||||||
|
.filter(id -> isLensFacing(id, cameraManager, CameraMetadata.LENS_FACING_FRONT))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (frontCamera != null) {
|
||||||
|
cameraList.add(frontCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
String backCamera = Stream.of(devices)
|
||||||
|
.filter(id -> isLensFacing(id, cameraManager, CameraMetadata.LENS_FACING_BACK))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (backCamera != null) {
|
||||||
|
cameraList.add(backCamera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.deviceNames = cameraList.toArray(new String[0]);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
Log.e(TAG, "Camera access exception: " + e);
|
||||||
|
this.deviceNames = new String[] {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return deviceNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull CameraVideoCapturer createCapturer(@Nullable String deviceName,
|
||||||
|
@Nullable CameraVideoCapturer.CameraEventsHandler eventsHandler) {
|
||||||
|
return new Camera2Capturer(context, deviceName, eventsHandler, new FilteredCamera2Enumerator(context));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user