Skip to content

Commit

Permalink
Add Camera2 interface for detecting camera without using android perm…
Browse files Browse the repository at this point in the history
…ission
  • Loading branch information
Margaux Clerc committed Feb 23, 2016
1 parent d1f3778 commit 0b367d2
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 15 deletions.
Expand Up @@ -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() {

Expand All @@ -45,6 +47,10 @@ private static MediastreamerAndroidContext getInstance() {
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);
Expand All @@ -54,15 +60,15 @@ public static void addSoundDeviceDesc(String manufacturer, String model, String
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);
Expand Down
Expand Up @@ -27,7 +27,6 @@ of the License, or (at your option) any later version.

import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.view.SurfaceView;

/**
Expand Down Expand Up @@ -138,7 +137,7 @@ protected static int[] selectNearestResolutionAvailableForCamera(int id, int req
}

AndroidCamera[] cameras = AndroidCameraConfiguration.retrieveCameras();
List<Size> supportedSizes = null;
List<AndroidCamera.Size> supportedSizes = null;
for(AndroidCamera c: cameras) {
if (c.id == id)
supportedSizes = c.resolutions;
Expand All @@ -148,7 +147,7 @@ protected static int[] selectNearestResolutionAvailableForCamera(int id, int req
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;
Expand All @@ -158,11 +157,11 @@ protected static int[] selectNearestResolutionAvailableForCamera(int id, int req

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;
Expand Down
Expand Up @@ -18,14 +18,12 @@ of the License, or (at your option) any later version.
*/
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.
Expand Down Expand Up @@ -60,10 +58,15 @@ private static void initCamerasCache() {
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();
Expand All @@ -79,21 +82,45 @@ static AndroidCamera[] probeCamerasSDK9() {
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;

}
}
@@ -0,0 +1,67 @@
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
}
}

0 comments on commit 0b367d2

Please sign in to comment.