android: fix various API levels problems and cache camera resolutions

parent 8899360b
/*
Version.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.mediastream;
import org.linphone.mediastream.video.capture.hwconf.Hacks;
import android.os.Build;
/**
* Centralize version access and allow simulation of lower versions.
* @author Guillaume Beraudo
*/
public class Version {
public static final int API03_CUPCAKE_15 = 3;
public static final int API04_DONUT_16 = 4;
public static final int API06_ECLAIR_20 = 6;
public static final int API07_ECLAIR_21 = 7;
public static final int API08_FROYO_22 = 8;
public static final int API09_GINGERBREAD_23 = 9;
public static final int API11_HONEYCOMB_30 = 11;
private static native boolean nativeHasZrtp();
private static native boolean nativeHasNeon();
private static Boolean hasNeon;
private static final int buildVersion =
Integer.parseInt(Build.VERSION.SDK);
// 8; // 2.2
// 7; // 2.1
public static final boolean sdkAboveOrEqual(int value) {
return buildVersion >= value;
}
public static final boolean sdkStrictlyBelow(int value) {
return buildVersion < value;
}
public static int sdk() {
return buildVersion;
}
public static boolean isArmv7() {
try {
return sdkAboveOrEqual(4)
&& Build.class.getField("CPU_ABI").get(null).toString().startsWith("armeabi-v7");
} catch (Throwable e) {}
return false;
}
public static boolean hasNeon(){
if (hasNeon == null) hasNeon = nativeHasNeon();
return hasNeon;
}
public static boolean isVideoCapable() {
return !Version.sdkStrictlyBelow(5) && Version.hasNeon() && Hacks.hasCamera();
}
public static boolean hasZrtp(){
return nativeHasZrtp();
}
public static void dumpCapabilities(){
StringBuilder sb = new StringBuilder(" ==== Capabilities dump ====\n");
sb.append("Has neon: ").append(Boolean.toString(hasNeon())).append("\n");
sb.append("Has ZRTP: ").append(Boolean.toString(hasZrtp())).append("\n");
android.util.Log.i("mediastreamer", sb.toString());
}
}
......@@ -72,7 +72,7 @@ public class AndroidVideoApi5JniWrapper {
static public int[] selectNearestResolutionAvailable(int cameraId, int requestedW, int requestedH) {
Log.d("mediastreamer", "selectNearestResolutionAvailable: " + cameraId + ", " + requestedW + "x" + requestedH);
return selectNearestResolutionAvailableForCamera(Camera.open(), requestedW, requestedH);
return selectNearestResolutionAvailableForCamera(cameraId, requestedW, requestedH);
}
public static Object startRecording(int cameraId, int width, int height, int fps, int rotation, final long nativePtr) {
......@@ -117,15 +117,24 @@ public class AndroidVideoApi5JniWrapper {
}
}
protected static int[] selectNearestResolutionAvailableForCamera(Camera cam, int requestedW, int requestedH) {
protected static int[] selectNearestResolutionAvailableForCamera(int id, int requestedW, int requestedH) {
// inversing resolution since webcams only support landscape ones
if (requestedH > requestedW) {
int t = requestedH;
requestedH = requestedW;
requestedW = t;
}
Camera.Parameters p = cam.getParameters();
List<Size> supportedSizes = p.getSupportedPreviewSizes();
AndroidCamera[] cameras = AndroidCameraConfiguration.retrieveCameras();
List<Size> supportedSizes = null;
for(AndroidCamera c: cameras) {
if (c.id == id)
supportedSizes = c.resolutions;
}
if (supportedSizes == null) {
Log.e("mediastreamer", "Failed to retrieve supported resolutions.");
return null;
}
Log.d("mediastreamer", supportedSizes.size() + " supported resolutions :");
for(Size s : supportedSizes) {
Log.d("mediastreamer", "\t" + s.width + "x" + s.height);
......@@ -153,7 +162,6 @@ public class AndroidVideoApi5JniWrapper {
return null;
} finally {
Log.d("mediastreamer", "resolution selection done");
cam.release();
}
}
......
......@@ -43,11 +43,12 @@ public class AndroidVideoApi9JniWrapper {
*/
static public int[] selectNearestResolutionAvailable(int cameraId, int requestedW, int requestedH) {
Log.d("mediastreamer", "selectNearestResolutionAvailable: " + cameraId + ", " + requestedW + "x" + requestedH);
return AndroidVideoApi5JniWrapper.selectNearestResolutionAvailableForCamera(Camera.open(cameraId), requestedW, requestedH);
return AndroidVideoApi5JniWrapper.selectNearestResolutionAvailableForCamera(cameraId, requestedW, requestedH);
}
public static Object startRecording(int cameraId, int width, int height, int fps, int rotation, final long nativePtr) {
Log.d("mediastreamer", "startRecording(" + cameraId + ", " + width + ", " + height + ", " + fps + ", " + rotation + ", " + nativePtr + ")");
try {
Camera camera = Camera.open(cameraId);
Parameters params = camera.getParameters();
......@@ -77,6 +78,10 @@ public class AndroidVideoApi9JniWrapper {
camera.startPreview();
Log.d("mediastreamer", "Returning camera object: " + camera);
return camera;
} catch (Exception exc) {
exc.printStackTrace();
return null;
}
}
public static void stopRecording(Object cam) {
......
......@@ -18,7 +18,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.mediastream.video.capture.hwconf;
import android.os.Build;
import java.util.List;
import org.linphone.mediastream.Version;
import android.hardware.Camera.Size;
......@@ -54,7 +58,7 @@ public class AndroidCameraConfiguration {
if (camerasCache != null)
return;
if (Build.VERSION.SDK_INT < 9)
if (Version.sdk() < 9)
camerasCache = AndroidCameraConfiguration.probeCamerasSDK5();
else
camerasCache = AndroidCameraConfiguration.probeCamerasSDK9();
......@@ -74,13 +78,15 @@ public class AndroidCameraConfiguration {
*
*/
static public class AndroidCamera {
public AndroidCamera(int i, boolean f, int o) {
public AndroidCamera(int i, boolean f, int o, List<Size> r) {
this.id = i;
this.frontFacing = f;
this.orientation = o;
this.resolutions = r;
}
public int id;
public boolean frontFacing; // false => rear facing
public int orientation;
public List<Size> resolutions;
}
}
\ No newline at end of file
......@@ -23,6 +23,8 @@ import java.util.List;
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration.AndroidCamera;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.Log;
/**
......@@ -33,23 +35,27 @@ class AndroidCameraConfigurationReader5 {
static public AndroidCamera[] probeCameras() {
List<AndroidCamera> cam = new ArrayList<AndroidCamera>(1);
Camera camera = Camera.open();
List<Size> r = camera.getParameters().getSupportedPreviewSizes();
camera.release();
// Defaults
if (Hacks.isGalaxySOrTab()) {
Log.d("mediastreamer", "Hack Galaxy S : has one or more cameras");
if (Hacks.isGalaxySOrTabWithFrontCamera()) {
Log.d("mediastreamer", "Hack Galaxy S : HAS a front camera with id=2");
cam.add(new AndroidCamera(2, true, 90));
cam.add(new AndroidCamera(2, true, 90, r));
} else {
Log.d("mediastreamer", "Hack Galaxy S : NO front camera");
}
Log.d("mediastreamer", "Hack Galaxy S : HAS a rear camera with id=1");
cam.add(new AndroidCamera(1, false, 90));
cam.add(new AndroidCamera(1, false, 90, r));
} else {
cam.add(new AndroidCamera(0, false, 90));
cam.add(new AndroidCamera(0, false, 90, r));
if (Hacks.hasTwoCamerasRear0Front1()) {
Log.d("mediastreamer", "Hack SPHD700 has 2 cameras a rear with id=0 and a front with id=1");
cam.add(new AndroidCamera(1, true, 90));
cam.add(new AndroidCamera(1, true, 90, r));
}
}
......
......@@ -37,7 +37,9 @@ class AndroidCameraConfigurationReader9 {
for(int i=0; i<Camera.getNumberOfCameras(); i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
cam.add(new AndroidCamera(i, info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT, info.orientation));
Camera c = Camera.open(i);
cam.add(new AndroidCamera(i, info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT, info.orientation, c.getParameters().getSupportedPreviewSizes()));
c.release();
}
AndroidCamera[] result = new AndroidCamera[cam.size()];
......
......@@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.mediastream.video.capture.hwconf;
import org.linphone.mediastream.Version;
import android.hardware.Camera;
import android.media.AudioManager;
import android.os.Build;
......@@ -112,7 +114,7 @@ public final class Hacks {
}
public static boolean needRoutingAPI() {
return Build.VERSION.SDK_INT < 5;
return Version.sdkStrictlyBelow(5);
}
public static boolean needGalaxySAudioHack() {
......@@ -129,7 +131,7 @@ public final class Hacks {
}
public static boolean hasCamera() {
if (Build.VERSION.SDK_INT >= 9) {
if (Version.sdkAboveOrEqual(9)) {
int nb = 0;
try {
nb = (Integer) Camera.class.getMethod("getNumberOfCameras", (Class[])null).invoke(null);
......
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