Commit 0b367d23 authored by Margaux Clerc's avatar Margaux Clerc

Add Camera2 interface for detecting camera without using android permission

parent d1f37780
......@@ -33,6 +33,8 @@ public class MediastreamerAndroidContext {
private native void setDeviceFavoriteSampleRate(int samplerate);
private native void setDeviceFavoriteBufferSize(int bufferSize);
private native void addSoundDeviceDescription(String manufacturer, String model, String platform, int flags, int delay, int recommended_rate);
private static Context mContext;
private MediastreamerAndroidContext() {
......@@ -45,6 +47,10 @@ public class MediastreamerAndroidContext {
instance = new MediastreamerAndroidContext();
return instance;
}
public static Context getContext(){
return mContext;
}
public static void addSoundDeviceDesc(String manufacturer, String model, String platform, int flags, int delay, int recommended_rate) {
getInstance().addSoundDeviceDescription(manufacturer, model, platform, flags, delay, recommended_rate);
......@@ -54,15 +60,15 @@ public class MediastreamerAndroidContext {
public static void setContext(Object c) {
if (c == null)
return;
Context context = (Context)c;
mContext = (Context)c;
int bufferSize = 64;
int sampleRate = 44100;
MediastreamerAndroidContext mac = getInstance();
// When using the OpenSLES sound card, the system is capable of giving us the best values to use for the buffer size and the sample rate
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
AudioManager audiomanager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
AudioManager audiomanager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
String bufferProperty = audiomanager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
bufferSize = parseInt(bufferProperty, bufferSize);
String sampleRateProperty = audiomanager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
......
......@@ -27,7 +27,6 @@ import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration.
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.view.SurfaceView;
/**
......@@ -138,7 +137,7 @@ public class AndroidVideoApi5JniWrapper {
}
AndroidCamera[] cameras = AndroidCameraConfiguration.retrieveCameras();
List<Size> supportedSizes = null;
List<AndroidCamera.Size> supportedSizes = null;
for(AndroidCamera c: cameras) {
if (c.id == id)
supportedSizes = c.resolutions;
......@@ -148,7 +147,7 @@ public class AndroidVideoApi5JniWrapper {
return null;
}
Log.d("mediastreamer", supportedSizes.size() + " supported resolutions :");
for(Size s : supportedSizes) {
for(AndroidCamera.Size s : supportedSizes) {
Log.d("mediastreamer", "\t" + s.width + "x" + s.height);
}
int r[] = null;
......@@ -158,11 +157,11 @@ public class AndroidVideoApi5JniWrapper {
try {
// look for nearest size
Size result = supportedSizes.get(0); /*by default return first value*/
AndroidCamera.Size result = supportedSizes.get(0); /*by default return first value*/
int req = rW * rH;
int minDist = Integer.MAX_VALUE;
int useDownscale = 0;
for(Size s: supportedSizes) {
for(AndroidCamera.Size s: supportedSizes) {
int dist = /*Math.abs*/-1*(req - s.width * s.height);
if ( ((s.width >= rW && s.height >= rH) || (s.width >= rH && s.height >= rW)) && dist < minDist) {
minDist = dist;
......
......@@ -18,14 +18,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.mediastream.video.capture.hwconf;
import java.util.ArrayList;
import java.util.List;
import org.linphone.mediastream.Log;
import org.linphone.mediastream.Version;
import android.hardware.Camera.Size;
/**
* Entry point for accessing hardware cameras configuration.
......@@ -60,10 +58,15 @@ public class AndroidCameraConfiguration {
return;
try {
if (Version.sdk() < 9)
if (Version.sdk() < 9) {
camerasCache = AndroidCameraConfiguration.probeCamerasSDK5();
else
camerasCache = AndroidCameraConfiguration.probeCamerasSDK9();
} else {
if (Version.sdk() >= 21) {
camerasCache = AndroidCameraConfiguration.probeCamerasSDK21();
} else {
camerasCache = AndroidCameraConfiguration.probeCamerasSDK9();
}
}
} catch (Exception exc) {
Log.e("Error: cannot retrieve cameras information (busy ?)", exc);
exc.printStackTrace();
......@@ -79,21 +82,45 @@ public class AndroidCameraConfiguration {
return AndroidCameraConfigurationReader9.probeCameras();
}
static AndroidCamera[] probeCamerasSDK21() {
return AndroidCameraConfigurationReader21.probeCameras();
}
/**
* Default: no front; rear=0; default=rear
* @author Guillaume Beraudo
*
*/
static public class AndroidCamera {
public AndroidCamera(int i, boolean f, int o, List<Size> r) {
static public class Size{
public final int width;
public final int height;
public Size(int w, int h){
this.width = w;
this.height = h;
}
}
public AndroidCamera(int i, boolean f, List<Size> r, int o) {
this.id = i;
this.frontFacing = f;
this.orientation = o;
this.resolutions = r;
}
public AndroidCamera(int i, boolean f, int o, List<android.hardware.Camera.Size> origin) {
this.resolutions = new ArrayList<Size>(origin.size());
for (android.hardware.Camera.Size s : origin) {
this.resolutions.add(new AndroidCamera.Size(s.width,s.height));
}
this.id = i;
this.frontFacing = f;
this.orientation = o;
}
public int id;
public boolean frontFacing; // false => rear facing
public int orientation;
public List<Size> resolutions;
}
}
\ No newline at end of file
package org.linphone.mediastream.video.capture.hwconf;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Build;
import org.linphone.mediastream.MediastreamerAndroidContext;
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration.AndroidCamera;
import org.linphone.mediastream.Log;
import java.util.ArrayList;
import java.util.List;
/**
* Android cameras detection, using SDK >= 21.
*/
public class AndroidCameraConfigurationReader21 {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
static public AndroidCameraConfiguration.AndroidCamera[] probeCameras() {
Context context = MediastreamerAndroidContext.getContext();
if (context != null) {
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
int numOfAvailableCameras = 0;
String[] cameraList;
try {
cameraList = manager.getCameraIdList();
final List<AndroidCamera> cam = new ArrayList<AndroidCamera>(cameraList.length);
for (int i = 0; i < cameraList.length; i++) {
String cameraId = cameraList[i];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
int camFacing = characteristics.get(CameraCharacteristics.LENS_FACING);
boolean frontFacing = false;
if (camFacing == CameraCharacteristics.LENS_FACING_FRONT) {
frontFacing = true;
}
int camOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
StreamConfigurationMap configs = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
android.util.Size[] supportedSizes = configs.getOutputSizes(ImageFormat.JPEG);
List<AndroidCamera.Size> supportedPreviewSizes = new ArrayList<AndroidCamera.Size>(supportedSizes.length);
for (int j = 0; j < supportedSizes.length; j++) {
android.util.Size size = supportedSizes[j];
supportedPreviewSizes.add(new AndroidCamera.Size(size.getWidth(), size.getHeight()));
}
cam.add(new AndroidCamera(i, frontFacing, supportedPreviewSizes, camOrientation));
numOfAvailableCameras++;
}
AndroidCamera[] result = new AndroidCamera[numOfAvailableCameras];
result = cam.toArray(result);
return result;
} catch (CameraAccessException exp) {
Log.e(exp);
}
}
return new AndroidCamera[0]; //empty array
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment