diff --git a/default.properties b/default.properties
index 51e933a98..247186a6a 100644
--- a/default.properties
+++ b/default.properties
@@ -10,4 +10,4 @@
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
-target=android-8
+target=android-9
diff --git a/res/menu/videocall_activity_menu.xml b/res/menu/videocall_activity_menu.xml
index 4a3b5e099..88dca9776 100644
--- a/res/menu/videocall_activity_menu.xml
+++ b/res/menu/videocall_activity_menu.xml
@@ -8,5 +8,5 @@
-
+
diff --git a/src/org/linphone/BandwidthManager.java b/src/org/linphone/BandwidthManager.java
index 6af77423c..2ebf5d112 100644
--- a/src/org/linphone/BandwidthManager.java
+++ b/src/org/linphone/BandwidthManager.java
@@ -28,7 +28,6 @@ public class BandwidthManager {
public static final int HIGH_RESOLUTION = 0;
public static final int LOW_RESOLUTION = 1;
public static final int LOW_BANDWIDTH = 2;
- private static final boolean portraitMode = true; // FIXME: preference?
private static final int[][] bandwidthes = {{256,256}, {128,128}, {80,80}};
private static BandwidthManager instance;
@@ -71,7 +70,7 @@ public class BandwidthManager {
lc.setDownloadBandwidth(bandwidthes[newProfile][1]);
if (lc.isIncall()) {
- InviteManager.getInstance().reinvite();
+ CallManager.getInstance().reinvite();
} else {
updateWithProfileSettings(lc, null);
}
@@ -80,11 +79,9 @@ public class BandwidthManager {
public void updateWithProfileSettings(LinphoneCore lc, LinphoneCallParams callParams) {
// Setting Linphone Core Preferred Video Size
- AndroidCameraRecordManager cameraManager = AndroidCameraRecordManager.getInstance();
-
boolean bandwidthOKForVideo = isVideoPossible();
if (bandwidthOKForVideo) {
- VideoSize targetVideoSize = cameraManager.doYouSupportThisVideoSize(getMaximumVideoSize());
+ VideoSize targetVideoSize = getMaximumVideoSize();
lc.setPreferredVideoSize(targetVideoSize);
VideoSize actualVideoSize = lc.getPreferredVideoSize();
@@ -106,12 +103,12 @@ public class BandwidthManager {
}
- private VideoSize maximumVideoSize(int profile) {
+ private VideoSize maximumVideoSize(int profile, boolean cameraIsPortrait) {
switch (profile) {
case LOW_RESOLUTION:
- return VideoSize.createStandard(VideoSize.QCIF, portraitMode);
+ return VideoSize.createStandard(VideoSize.QCIF, cameraIsPortrait);
case HIGH_RESOLUTION:
- return VideoSize.createStandard(VideoSize.QVGA, portraitMode);
+ return VideoSize.createStandard(VideoSize.QVGA, cameraIsPortrait);
default:
throw new RuntimeException("profile not managed : " + profile);
}
@@ -123,6 +120,6 @@ public class BandwidthManager {
}
public VideoSize getMaximumVideoSize() {
- return maximumVideoSize(currentProfile);
+ return maximumVideoSize(currentProfile, AndroidCameraRecordManager.getInstance().outputIsPortrait());
}
}
diff --git a/src/org/linphone/InviteManager.java b/src/org/linphone/CallManager.java
similarity index 83%
rename from src/org/linphone/InviteManager.java
rename to src/org/linphone/CallManager.java
index 9ba2770f2..4d0eff734 100644
--- a/src/org/linphone/InviteManager.java
+++ b/src/org/linphone/CallManager.java
@@ -1,5 +1,5 @@
/*
-InviteManager.java
+CallManager.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
@@ -25,13 +25,19 @@ import org.linphone.core.LinphoneCallParams;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreException;
-public class InviteManager {
+/**
+ * Handle call updating, reinvites.
+ *
+ * @author Guillaume Beraudo
+ *
+ */
+public class CallManager {
- private static InviteManager instance;
+ private static CallManager instance;
- private InviteManager() {}
- public static final synchronized InviteManager getInstance() {
- if (instance == null) instance = new InviteManager();
+ private CallManager() {}
+ public static final synchronized CallManager getInstance() {
+ if (instance == null) instance = new CallManager();
return instance;
}
@@ -107,4 +113,14 @@ public class InviteManager {
lc.updateCall(lCall, params);
}
+ /**
+ * Update current call, without reinvite.
+ */
+ public void updateCall() {
+ LinphoneCore lc = lc();
+ LinphoneCall lCall = lc.getCurrentCall();
+ LinphoneCallParams params = lCall.getCurrentParamsCopy();
+ bm().updateWithProfileSettings(lc, params);
+ }
+
}
diff --git a/src/org/linphone/DialerActivity.java b/src/org/linphone/DialerActivity.java
index cb2ae8022..5fe8626c9 100644
--- a/src/org/linphone/DialerActivity.java
+++ b/src/org/linphone/DialerActivity.java
@@ -168,7 +168,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
mAddVideo.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// If no in video call; try to reinvite with video
- boolean alreadyInVideoCall = !InviteManager.getInstance().reinviteWithVideo();
+ boolean alreadyInVideoCall = !CallManager.getInstance().reinviteWithVideo();
if (alreadyInVideoCall) {
// In video call; going back to video call activity
startVideoView(VIDEO_VIEW_ACTIVITY);
@@ -364,6 +364,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
if (mWakeLock.isHeld()) mWakeLock.release();
theDialer=null;
}
+
@Override
protected void onResume() {
super.onResume();
@@ -522,6 +523,8 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
private void resetCameraFromPreferences() {
boolean useFrontCam = mPref.getBoolean(getString(R.string.pref_video_use_front_camera_key), false);
AndroidCameraRecordManager.getInstance().setUseFrontCamera(useFrontCam);
+ final int phoneOrientation = 90 * getWindowManager().getDefaultDisplay().getOrientation();
+ AndroidCameraRecordManager.getInstance().setPhoneOrientation(phoneOrientation);
}
private void exitCallMode() {
@@ -605,7 +608,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
boolean prefVideoEnable = mPref.getBoolean(getString(R.string.pref_video_enable_key), false);
boolean prefInitiateWithVideo = mPref.getBoolean(getString(R.string.pref_video_initiate_call_with_video_key), false);
resetCameraFromPreferences();
- InviteManager.getInstance().inviteAddress(lAddress, prefVideoEnable && prefInitiateWithVideo);
+ CallManager.getInstance().inviteAddress(lAddress, prefVideoEnable && prefInitiateWithVideo);
} catch (LinphoneCoreException e) {
Toast toast = Toast.makeText(DialerActivity.this
diff --git a/src/org/linphone/LinphoneService.java b/src/org/linphone/LinphoneService.java
index 73075df4e..dc938c184 100644
--- a/src/org/linphone/LinphoneService.java
+++ b/src/org/linphone/LinphoneService.java
@@ -54,7 +54,6 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.IBinder;
-import android.os.PowerManager;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
diff --git a/src/org/linphone/VideoCallActivity.java b/src/org/linphone/VideoCallActivity.java
index 4c913ee81..cc720699e 100644
--- a/src/org/linphone/VideoCallActivity.java
+++ b/src/org/linphone/VideoCallActivity.java
@@ -22,12 +22,12 @@ package org.linphone;
import org.linphone.core.AndroidCameraRecordManager;
import org.linphone.core.LinphoneCore;
+import org.linphone.core.Version;
import org.linphone.core.VideoSize;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
-import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
@@ -47,7 +47,8 @@ public class VideoCallActivity extends Activity {
private WakeLock mWakeLock;
private static final int capturePreviewLargestDimension = 150;
// private static final float similarRatio = 0.1f;
- private static final int version = Integer.parseInt(Build.VERSION.SDK);
+ private int previousPhoneOrientation;
+ private int phoneOrientation;
public void onCreate(Bundle savedInstanceState) {
launched = true;
@@ -61,9 +62,10 @@ public class VideoCallActivity extends Activity {
mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface);
- final int rotation = getWindowManager().getDefaultDisplay().getOrientation();
+ previousPhoneOrientation = AndroidCameraRecordManager.getInstance().getPhoneOrientation();
+ phoneOrientation = 90 * getWindowManager().getDefaultDisplay().getOrientation();
recordManager = AndroidCameraRecordManager.getInstance();
- recordManager.setSurfaceView(mVideoCaptureView, rotation);
+ recordManager.setSurfaceView(mVideoCaptureView, phoneOrientation);
mVideoCaptureView.setZOrderOnTop(true);
if (!recordManager.isMuted()) sendStaticImage(false);
@@ -71,15 +73,32 @@ public class VideoCallActivity extends Activity {
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE,"Linphone");
mWakeLock.acquire();
- if (version < 8) {
+ if (Version.sdkBelow(8)) {
// Force to display in portrait orientation for old devices
// as they do not support surfaceView rotation
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ setRequestedOrientation(recordManager.isCameraOrientationPortrait() ?
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT :
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
- // Handle the fact that the preferred size may have a ratio /an orientation different from the one
- // in the videocall.xml as the front camera on Samsung captures in landscape.
- resizeCapturePreviewForOldPhones(mVideoCaptureView, lc.getPreferredVideoSize());
+ // Base capture frame on streamed dimensions and orientation.
+ resizeCapturePreview(mVideoCaptureView, lc.getPreferredVideoSize());
+ }
+
+ private void updateCallIfOrientationChanged() {
+ if (Version.sdkAbove(8) && previousPhoneOrientation != phoneOrientation) {
+ CallManager.getInstance().updateCall();
+ // camera will be restarted when mediastreamer chain is recreated and setParameters is called
+
+ // Base capture frame on streamed dimensions and orientation.
+ resizeCapturePreview(mVideoCaptureView, LinphoneService.getLc().getPreferredVideoSize());
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ updateCallIfOrientationChanged();
+ super.onResume();
}
@@ -109,6 +128,9 @@ public class VideoCallActivity extends Activity {
rewriteToggleCameraItem(menu.findItem(R.id.videocall_menu_toggle_camera));
rewriteChangeResolutionItem(menu.findItem(R.id.videocall_menu_change_resolution));
+ if (!recordManager.hasSeveralCameras()) {
+ menu.findItem(R.id.videocall_menu_switch_camera).setVisible(false);
+ }
return true;
}
@@ -123,9 +145,7 @@ public class VideoCallActivity extends Activity {
* @param sv capture surface view to resize the layout
* @param vs video size from which to calculate the dimensions
*/
- private void resizeCapturePreviewForOldPhones(SurfaceView sv, VideoSize vs) {
- if (version >= 8) return;
-
+ private void resizeCapturePreview(SurfaceView sv, VideoSize vs) {
LayoutParams lp = sv.getLayoutParams();
float newRatio = ratioWidthHeight(vs);
@@ -158,7 +178,7 @@ public class VideoCallActivity extends Activity {
// Resize preview frame
VideoSize newVideoSize = LinphoneService.getLc().getPreferredVideoSize();
- resizeCapturePreviewForOldPhones(mVideoCaptureView, newVideoSize);
+ resizeCapturePreview(mVideoCaptureView, newVideoSize);
break;
case R.id.videocall_menu_terminate_call:
LinphoneCore lc = LinphoneService.getLc();
@@ -171,13 +191,17 @@ public class VideoCallActivity extends Activity {
sendStaticImage(recordManager.toggleMute());
rewriteToggleCameraItem(item);
break;
-/* case R.id.videocall_menu_switch_camera:
+ case R.id.videocall_menu_switch_camera:
recordManager.stopVideoRecording();
+ sendStaticImage(true);
recordManager.toggleUseFrontCamera();
- InviteManager.getInstance().reinvite();
+ CallManager.getInstance().updateCall();
// camera will be restarted when mediastreamer chain is recreated and setParameters is called
+
+ // Base capture frame on streamed dimensions and orientation.
+ resizeCapturePreview(mVideoCaptureView, LinphoneService.getLc().getPreferredVideoSize());
break;
-*/ default:
+ default:
Log.e(LinphoneService.TAG, "Unknown menu item ["+item+"]");
break;
}
diff --git a/src/org/linphone/core/AndroidCameraRecord.java b/src/org/linphone/core/AndroidCameraRecord.java
index 1696efbc7..6feafc322 100644
--- a/src/org/linphone/core/AndroidCameraRecord.java
+++ b/src/org/linphone/core/AndroidCameraRecord.java
@@ -39,14 +39,12 @@ public abstract class AndroidCameraRecord {
private PreviewCallback storedPreviewCallback;
private boolean previewStarted;
- protected int displayOrientation;
protected static final String tag="Linphone";
private List supportedVideoSizes;
private Size currentPreviewSize;
public AndroidCameraRecord(RecorderParams parameters) {
this.params = parameters;
- setDisplayOrientation(parameters.rotation);
}
protected List getSupportedPreviewSizes(Camera.Parameters parameters) {
@@ -67,7 +65,7 @@ public abstract class AndroidCameraRecord {
}
- camera=Camera.open();
+ camera = openCamera(params.cameraId);
camera.setErrorCallback(new ErrorCallback() {
public void onError(int error, Camera camera) {
Log.e(tag, "Camera error : " + error);
@@ -84,9 +82,10 @@ public abstract class AndroidCameraRecord {
}
- if (!params.videoDimensionsInverted) {
+ if (params.width >= params.height) {
parameters.setPreviewSize(params.width, params.height);
} else {
+ // invert height and width
parameters.setPreviewSize(params.height, params.width);
}
parameters.setPreviewFrameRate(Math.round(params.fps));
@@ -126,6 +125,10 @@ public abstract class AndroidCameraRecord {
+ protected Camera openCamera(int cameraId) {
+ return Camera.open();
+ }
+
protected void onSettingCameraParameters(Parameters parameters) {}
/**
@@ -164,24 +167,8 @@ public abstract class AndroidCameraRecord {
protected abstract void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb);
- public void setDisplayOrientation(int rotation) {
- displayOrientation = rotation;
- }
- protected int getDisplayOrientation() {return displayOrientation;}
-
- protected int rotateCapturedFrame() {
- if (params.videoDimensionsInverted) {
- return 1; // always rotate 90°
- } else if (params.cameraId == 2) {
- return 0;
- } else {
- return (4 + 1 - displayOrientation) % 4;
- }
- }
-
-
public static class RecorderParams {
public float fps;
public int height;
@@ -191,7 +178,6 @@ public abstract class AndroidCameraRecord {
public int cameraId;
public int rotation;
public SurfaceView surfaceView;
- public boolean videoDimensionsInverted;
public RecorderParams(long ptr) {
filterDataNativePtr = ptr;
@@ -200,7 +186,6 @@ public abstract class AndroidCameraRecord {
-
public boolean isStarted() {
return previewStarted;
}
@@ -215,4 +200,5 @@ public abstract class AndroidCameraRecord {
return currentPreviewSize.width * currentPreviewSize.height * 3 /2;
}
+
}
diff --git a/src/org/linphone/core/AndroidCameraRecordImplAPI5.java b/src/org/linphone/core/AndroidCameraRecord5Impl.java
similarity index 93%
rename from src/org/linphone/core/AndroidCameraRecordImplAPI5.java
rename to src/org/linphone/core/AndroidCameraRecord5Impl.java
index 7ff307d03..18e487d12 100644
--- a/src/org/linphone/core/AndroidCameraRecordImplAPI5.java
+++ b/src/org/linphone/core/AndroidCameraRecord5Impl.java
@@ -26,9 +26,9 @@ import android.hardware.Camera.Size;
import android.util.Log;
-public class AndroidCameraRecordImplAPI5 extends AndroidCameraRecordImpl {
+public class AndroidCameraRecord5Impl extends AndroidCameraRecordImpl {
- public AndroidCameraRecordImplAPI5(RecorderParams parameters) {
+ public AndroidCameraRecord5Impl(RecorderParams parameters) {
super(parameters);
}
diff --git a/src/org/linphone/core/AndroidCameraRecordAPI8Impl.java b/src/org/linphone/core/AndroidCameraRecord8Impl.java
similarity index 86%
rename from src/org/linphone/core/AndroidCameraRecordAPI8Impl.java
rename to src/org/linphone/core/AndroidCameraRecord8Impl.java
index 9655428db..490d9ad97 100644
--- a/src/org/linphone/core/AndroidCameraRecordAPI8Impl.java
+++ b/src/org/linphone/core/AndroidCameraRecord8Impl.java
@@ -30,10 +30,10 @@ import android.util.Log;
* @author Guillaume Beraudo
*
*/
-public class AndroidCameraRecordAPI8Impl extends AndroidCameraRecordImplAPI5 {
+public class AndroidCameraRecord8Impl extends AndroidCameraRecord5Impl {
- public AndroidCameraRecordAPI8Impl(RecorderParams parameters) {
+ public AndroidCameraRecord8Impl(RecorderParams parameters) {
super(parameters);
}
@@ -66,10 +66,6 @@ public class AndroidCameraRecordAPI8Impl extends AndroidCameraRecordImplAPI5 {
protected void onSettingCameraParameters(Parameters parameters) {
super.onSettingCameraParameters(parameters);
// Only on v8 hardware
- camera.setDisplayOrientation(90 * getPreviewCaptureRotation());
- }
-
- private int getPreviewCaptureRotation() {
- return (4 + 1 - displayOrientation) % 4;
+ camera.setDisplayOrientation(rotation);
}
}
diff --git a/src/org/linphone/core/AndroidCameraRecord9Impl.java b/src/org/linphone/core/AndroidCameraRecord9Impl.java
new file mode 100644
index 000000000..0ddb283d2
--- /dev/null
+++ b/src/org/linphone/core/AndroidCameraRecord9Impl.java
@@ -0,0 +1,40 @@
+/*
+AndroidCameraRecord9Impl.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.core;
+
+import android.hardware.Camera;
+
+/**
+ *
+ * Android >= 9 (2.3) version.
+ * @author Guillaume Beraudo
+ *
+ */
+public class AndroidCameraRecord9Impl extends AndroidCameraRecord8Impl {
+
+
+ public AndroidCameraRecord9Impl(RecorderParams parameters) {
+ super(parameters);
+ }
+
+ @Override
+ protected Camera openCamera(int cameraId) {
+ return Camera.open(cameraId);
+ }
+}
diff --git a/src/org/linphone/core/AndroidCameraRecordImpl.java b/src/org/linphone/core/AndroidCameraRecordImpl.java
index daf26ea4e..f1a4f4844 100644
--- a/src/org/linphone/core/AndroidCameraRecordImpl.java
+++ b/src/org/linphone/core/AndroidCameraRecordImpl.java
@@ -34,19 +34,19 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
private double timeElapsedBetweenFrames = 0;
private long lastFrameTime = 0;
private final double expectedTimeBetweenFrames;
- private boolean sizesInverted;
+ protected final int rotation;
public AndroidCameraRecordImpl(RecorderParams parameters) {
super(parameters);
expectedTimeBetweenFrames = 1d / Math.round(parameters.fps);
filterCtxPtr = parameters.filterDataNativePtr;
- sizesInverted = parameters.videoDimensionsInverted;
+ rotation = parameters.rotation;
storePreviewCallBack(this);
}
- private native void putImage(long filterCtxPtr, byte[] buffer, int rotate, boolean sizesInverted);
+ private native void putImage(long filterCtxPtr, byte[] buffer, int rotate);
public void onPreviewFrame(byte[] data, Camera camera) {
@@ -69,7 +69,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
long curTime = System.currentTimeMillis();
if (lastFrameTime == 0) {
lastFrameTime = curTime;
- putImage(filterCtxPtr, data, rotateCapturedFrame(), sizesInverted);
+ putImage(filterCtxPtr, data, rotation);
return;
}
@@ -82,7 +82,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
timeElapsedBetweenFrames = currentTimeElapsed;
// Log.d("onPreviewFrame: ", Integer.toString(data.length));
- putImage(filterCtxPtr, data, rotateCapturedFrame(), sizesInverted);
+ putImage(filterCtxPtr, data, rotation);
}
@@ -92,6 +92,4 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
camera.setPreviewCallback(cb);
}
-
-
}
diff --git a/src/org/linphone/core/AndroidCameraRecordManager.java b/src/org/linphone/core/AndroidCameraRecordManager.java
index a6c38d76d..5c9f4d7c8 100644
--- a/src/org/linphone/core/AndroidCameraRecordManager.java
+++ b/src/org/linphone/core/AndroidCameraRecordManager.java
@@ -22,6 +22,7 @@ import java.util.List;
import org.linphone.core.AndroidCameraRecord.RecorderParams;
+import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Build;
import android.util.Log;
@@ -38,14 +39,9 @@ import android.view.SurfaceHolder.Callback;
*
*/
public class AndroidCameraRecordManager {
- private static final int version = Integer.parseInt(Build.VERSION.SDK);
private static final String tag = "Linphone";
private static AndroidCameraRecordManager instance;
- // singleton
- private AndroidCameraRecordManager() {}
-
-
/**
* @return instance
*/
@@ -59,31 +55,76 @@ public class AndroidCameraRecordManager {
private AndroidCameraRecord.RecorderParams parameters;
private SurfaceView surfaceView;
private boolean muted;
-
+ private int cameraId;
private AndroidCameraRecord recorder;
-
-
private List supportedVideoSizes;
- private int rotation;
+ private int phoneOrientation;
+ public int getPhoneOrientation() {return phoneOrientation;}
+ public void setPhoneOrientation(int degrees) {this.phoneOrientation = degrees;}
- private boolean useFrontCamera;
+ private int frontCameraId;
+ private int rearCameraId;
+
+ // singleton
+ private AndroidCameraRecordManager() {
+ findFrontAndRearCameraIds();
+ }
+
+
+ private void findFrontAndRearCameraIds() {
+ if (Version.sdkAbove(9)) {
+ findFrontAndRearCameraIds9();
+ return;
+ }
+
+ if (Build.DEVICE.startsWith("GT-I9000")) {
+ // Galaxy S has 2 cameras
+ frontCameraId = 2;
+ rearCameraId = 1;
+ cameraId = rearCameraId;
+ return;
+ }
+
+ // default to 0/0
+ }
+
+ private void findFrontAndRearCameraIds9() {
+ for (int id=0; id < getNumberOfCameras9(); id++) {
+ if (isFrontCamera9(id)) {
+ frontCameraId = id;
+ } else {
+ rearCameraId = id;
+ }
+ }
+ }
+
+ public boolean hasSeveralCameras() {
+ return frontCameraId != rearCameraId;
+ }
+
+
public void setUseFrontCamera(boolean value) {
- if (useFrontCamera == value) return;
- this.useFrontCamera = value;
-
+ if (isFrontCamera() == value) return; // already OK
+
+ toggleUseFrontCamera();
+ }
+
+ public boolean isUseFrontCamera() {return isFrontCamera();}
+ public boolean toggleUseFrontCamera() {
+ boolean previousUseFront = isFrontCamera();
+
+ cameraId = previousUseFront ? rearCameraId : frontCameraId;
+
if (parameters != null) {
- parameters.cameraId = cameraId();
+ parameters.cameraId = cameraId;
if (isRecording()) {
stopVideoRecording();
tryToStartVideoRecording();
}
}
- }
- public boolean isUseFrontCamera() {return useFrontCamera;}
- public boolean toggleUseFrontCamera() {
- setUseFrontCamera(!useFrontCamera);
- return useFrontCamera;
+
+ return !previousUseFront;
}
@@ -94,16 +135,14 @@ public class AndroidCameraRecordManager {
p.fps = fps;
p.width = width;
p.height = height;
- p.cameraId = cameraId();
- p.videoDimensionsInverted = width < height;
- // width and height will be inverted in Recorder on startPreview
+ p.cameraId = cameraId;
parameters = p;
tryToStartVideoRecording();
}
- public final void setSurfaceView(final SurfaceView sv, final int rotation) {
- this.rotation = useFrontCamera ? 1 : rotation;
+ public final void setSurfaceView(final SurfaceView sv, final int phoneOrientation) {
+ this.phoneOrientation = phoneOrientation;
SurfaceHolder holder = sv.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
@@ -152,12 +191,15 @@ public class AndroidCameraRecordManager {
private void tryToStartVideoRecording() {
if (muted || surfaceView == null || parameters == null) return;
- parameters.rotation = rotation;
+ parameters.rotation = bufferRotationForCorrectImageOrientation();
+
parameters.surfaceView = surfaceView;
- if (version >= 8) {
- recorder = new AndroidCameraRecordAPI8Impl(parameters);
- } else if (version >= 5) {
- recorder = new AndroidCameraRecordImplAPI5(parameters);
+ if (Version.sdkAbove(9)) {
+ recorder = new AndroidCameraRecord9Impl(parameters);
+ } else if (Version.sdkAbove(8)) {
+ recorder = new AndroidCameraRecord8Impl(parameters);
+ } else if (Version.sdkAbove(5)) {
+ recorder = new AndroidCameraRecord5Impl(parameters);
} else {
recorder = new AndroidCameraRecordImpl(parameters);
}
@@ -188,8 +230,8 @@ public class AndroidCameraRecordManager {
if (supportedVideoSizes != null) return supportedVideoSizes;
}
- if (version >= 5) {
- supportedVideoSizes = AndroidCameraRecordImplAPI5.oneShotSupportedVideoSizes();
+ if (Version.sdkAbove(5)) {
+ supportedVideoSizes = AndroidCameraRecord5Impl.oneShotSupportedVideoSizes();
}
// eventually null
@@ -212,34 +254,86 @@ public class AndroidCameraRecordManager {
parameters = null;
}
- /**
- * Naive simple version.
- * @param askedSize
- * @return
- */
- public VideoSize doYouSupportThisVideoSize(VideoSize askedSize) {
- Log.d(tag, "Asking camera if it supports size "+askedSize);
- if (useFrontCamera && askedSize.isPortrait()) {
- return askedSize.createInverted(); // only landscape supported
- } else {
- return askedSize;
- }
+ public boolean outputIsPortrait() {
+ final int rotation = bufferRotationForCorrectImageOrientation();
+ final boolean isPortrait = (rotation % 180) == 90;
+
+ Log.d(tag, "Camera sensor in portrait orientation ?" + isPortrait);
+ return isPortrait;
}
- private VideoSize closestVideoSize(VideoSize vSize, int defaultSizeCode, boolean defaultIsPortrait) {
- VideoSize testSize = vSize.isPortrait() ? vSize.createInverted() : vSize;
-
- for (Size s : AndroidCameraRecordManager.getInstance().supportedVideoSizes()) {
- if (s.height == testSize.height && s.width == testSize.width) {
- return vSize;
- }
- }
-
- return VideoSize.createStandard(defaultSizeCode, defaultIsPortrait);
+
+
+ public static int getNumberOfCameras() {
+ if (Version.sdkAbove(9)) return getNumberOfCameras9();
+
+ // Use hacks to guess the number of cameras
+ if (Build.DEVICE.startsWith("GT-I9000")) {
+ // Galaxy S has 2 cameras
+ return 2;
+ } else
+ return 1;
}
- private static final int rearCamId() {return 1;}
- private static final int frontCamId() {return 2;}
- private final int cameraId() {return useFrontCamera? frontCamId() : rearCamId(); }
+ private static int getNumberOfCameras9() {
+ return Camera.getNumberOfCameras();
+ }
+
+ public boolean isCameraOrientationPortrait() {
+ return (getCameraOrientation() % 180) == 90;
+ }
+
+ public int getCameraOrientation() {
+ if (Version.sdkAbove(9)) return getCameraOrientation9();
+
+ // Use hacks to guess orientation of the camera
+ if (cameraId == 2 && Build.DEVICE.startsWith("GT-I9000")) {
+ // Galaxy S rear camera
+ // mounted in landscape for a portrait phone orientation
+ return 90;
+ }
+ return 0;
+ }
+
+
+ private int getCameraOrientation9() {
+ android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
+ Camera.getCameraInfo(cameraId, info);
+ return info.orientation;
+ }
+
+ public boolean isFrontCamera() {
+ if (Version.sdkAbove(9)) return isFrontCamera9();
+
+ // Use hacks to guess facing of the camera
+
+ if (cameraId == 2 && Build.DEVICE.startsWith("GT-I9000")) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isFrontCamera9() {
+ return isFrontCamera9(cameraId);
+ }
+
+
+ private boolean isFrontCamera9(int cameraId) {
+ android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
+ Camera.getCameraInfo(cameraId, info);
+ return info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT ? true : false;
+ }
+
+ private int bufferRotationForCorrectImageOrientation() {
+ final int cameraOrientation = getCameraOrientation();
+ final int rotation = Version.sdkAbove(8) ?
+ (360 - cameraOrientation + 90 - phoneOrientation) % 360
+ : 0;
+ Log.d(tag, "Capture video buffer will need a rotation of " + rotation
+ + " degrees : camera " + cameraOrientation
+ + ", phone " + phoneOrientation);
+ return rotation;
+ }
}
diff --git a/src/org/linphone/core/Version.java b/src/org/linphone/core/Version.java
new file mode 100644
index 000000000..0ec07fc25
--- /dev/null
+++ b/src/org/linphone/core/Version.java
@@ -0,0 +1,41 @@
+/*
+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.core;
+
+import android.os.Build;
+
+/**
+ * Centralize version access and allow simulation of lower versions.
+ * @author Guillaume Beraudo
+ */
+public class Version {
+
+ private static final int buildVersion =
+// Integer.parseInt(Build.VERSION.SDK);
+ 7; // 2.1
+
+ public static final boolean sdkAbove(int value) {
+ return buildVersion >= value;
+ }
+
+ public static final boolean sdkBelow(int value) {
+ return buildVersion < value;
+ }
+
+}