diff --git a/res/menu/videocall_activity_menu.xml b/res/menu/videocall_activity_menu.xml
index eaae6cf7a..88dca9776 100644
--- a/res/menu/videocall_activity_menu.xml
+++ b/res/menu/videocall_activity_menu.xml
@@ -8,4 +8,5 @@
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a146d3107..72415d678 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,5 +1,7 @@
+ Use front camera (if any)
+ pref_video_use_front_camera_key
Video
Preferences
H263
@@ -11,6 +13,7 @@
Video codecs
pref_video_codecs_key
Display dialer
+ Front/Rear Camera
Try High resolution
Low resolution
Change resolution
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index 3c76a9c33..007515444 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -83,6 +83,7 @@
android:defaultValue="false" android:selectable="false">
+
@@ -98,7 +99,8 @@
android:summary="@string/pref_video_automatically_share_my_video"
android:dependency="@string/pref_video_enable_key">
-
+
+
diff --git a/src/org/linphone/BandwidthManager.java b/src/org/linphone/BandwidthManager.java
index 36ef41bc8..9638fbbe0 100644
--- a/src/org/linphone/BandwidthManager.java
+++ b/src/org/linphone/BandwidthManager.java
@@ -91,10 +91,12 @@ public class BandwidthManager {
LinphoneCallParams params = lCall.getCurrentParamsCopy();
// Update video parm if
- if (newProfile == LOW_BANDWIDTH) {
+ if (newProfile == LOW_BANDWIDTH) { // NO VIDEO
params.setVideoEnabled(false);
+ params.setAudioBandwidth(40);
} else {
params.setVideoEnabled(true);
+ params.setAudioBandwidth(0); // disable limitation
}
diff --git a/src/org/linphone/DialerActivity.java b/src/org/linphone/DialerActivity.java
index 79a8362b9..43c8b3275 100644
--- a/src/org/linphone/DialerActivity.java
+++ b/src/org/linphone/DialerActivity.java
@@ -485,7 +485,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
}
private void enterIncalMode(LinphoneCore lc) {
-
+ resetCameraFromPreferences();
mCallControlRow.setVisibility(View.GONE);
mInCallControlRow.setVisibility(View.VISIBLE);
mAddressLayout.setVisibility(View.GONE);
@@ -522,6 +522,12 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
mSpeaker.setChecked(false);
}
}
+
+ private void resetCameraFromPreferences() {
+ boolean useFrontCam = mPref.getBoolean(getString(R.string.pref_video_use_front_camera_key), false);
+ AndroidCameraRecordManager.getInstance().setUseFrontCamera(useFrontCam);
+ }
+
private void exitCallMode() {
mCallControlRow.setVisibility(View.VISIBLE);
mInCallControlRow.setVisibility(View.GONE);
@@ -539,6 +545,7 @@ public class DialerActivity extends Activity implements LinphoneCoreListener {
mSpeaker.setChecked(false);
routeAudioToReceiver();
BandwidthManager.getInstance().setUserRestriction(false);
+ resetCameraFromPreferences();
}
private void routeAudioToSpeaker() {
if (Integer.parseInt(Build.VERSION.SDK) <= 4 /* supportedVideoSizes;
+ private Size currentPreviewSize;
public AndroidCameraRecord(RecorderParams parameters) {
this.params = parameters;
- setRotation(parameters.rotation);
+ setDisplayOrientation(parameters.rotation);
}
protected List getSupportedPreviewSizes(Camera.Parameters parameters) {
@@ -75,11 +76,14 @@ public abstract class AndroidCameraRecord {
Camera.Parameters parameters=camera.getParameters();
+ parameters.set("camera-id",params.cameraId);
+ camera.setParameters(parameters);
+ parameters = camera.getParameters();
if (supportedVideoSizes == null) {
- supportedVideoSizes = getSupportedPreviewSizes(camera.getParameters());
+ supportedVideoSizes = new ArrayList(getSupportedPreviewSizes(parameters));
}
- parameters.set("camera-id", params.cameraId);
+
if (!params.videoDimensionsInverted) {
parameters.setPreviewSize(params.width, params.height);
} else {
@@ -91,6 +95,7 @@ public abstract class AndroidCameraRecord {
onSettingCameraParameters(parameters);
camera.setParameters(parameters);
+ currentPreviewSize = camera.getParameters().getPreviewSize();
SurfaceHolder holder = params.surfaceView.getHolder();
try {
@@ -140,12 +145,13 @@ public abstract class AndroidCameraRecord {
}
- void stopPreview() {
+ public void stopPreview() {
if (!previewStarted) return;
lowLevelSetPreviewCallback(camera, null);
camera.stopPreview();
camera.release();
camera=null;
+ if (currentPreviewSize != null) currentPreviewSize = null;
previewStarted = false;
}
@@ -158,12 +164,16 @@ public abstract class AndroidCameraRecord {
protected abstract void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb);
- public void setRotation(int rotation) {
- orientationCode = (4 + 1 - rotation) % 4;
+ public void setDisplayOrientation(int rotation) {
+ displayOrientation = rotation;
}
- protected int getOrientationCode() {
- return orientationCode;
+ protected int rotateCapturedFrame() {
+ if (params.cameraId == 2) {
+ return 0;
+ } else {
+ return (4 + 1 - displayOrientation) % 4;
+ }
}
@@ -175,10 +185,10 @@ public abstract class AndroidCameraRecord {
public int width;
final long filterDataNativePtr;
- int cameraId;
- int rotation;
+ public int cameraId;
+ public int rotation;
public SurfaceView surfaceView;
- boolean videoDimensionsInverted;
+ public boolean videoDimensionsInverted;
public RecorderParams(long ptr) {
filterDataNativePtr = ptr;
@@ -195,4 +205,11 @@ public abstract class AndroidCameraRecord {
public List getSupportedVideoSizes() {
return new ArrayList(supportedVideoSizes);
}
+
+
+ protected int getExpectedBufferLength() {
+ if (currentPreviewSize == null) return -1;
+
+ return currentPreviewSize.width * currentPreviewSize.height * 3 /2;
+ }
}
diff --git a/src/org/linphone/core/AndroidCameraRecordBufferedImpl.java b/src/org/linphone/core/AndroidCameraRecordBufferedImpl.java
index 9f8b2d1c0..232d15970 100644
--- a/src/org/linphone/core/AndroidCameraRecordBufferedImpl.java
+++ b/src/org/linphone/core/AndroidCameraRecordBufferedImpl.java
@@ -66,7 +66,7 @@ public class AndroidCameraRecordBufferedImpl extends AndroidCameraRecordImplAPI5
protected void onSettingCameraParameters(Parameters parameters) {
super.onSettingCameraParameters(parameters);
// Only on v8 hardware
- camera.setDisplayOrientation(90 * orientationCode);
+ camera.setDisplayOrientation(90 * displayOrientation);
}
diff --git a/src/org/linphone/core/AndroidCameraRecordImpl.java b/src/org/linphone/core/AndroidCameraRecordImpl.java
index 2d3087854..daf26ea4e 100644
--- a/src/org/linphone/core/AndroidCameraRecordImpl.java
+++ b/src/org/linphone/core/AndroidCameraRecordImpl.java
@@ -20,7 +20,6 @@ package org.linphone.core;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
-import android.hardware.Camera.Size;
import android.util.Log;
/**
@@ -35,19 +34,19 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
private double timeElapsedBetweenFrames = 0;
private long lastFrameTime = 0;
private final double expectedTimeBetweenFrames;
- private boolean videoDimensionsInverted;
+ private boolean sizesInverted;
public AndroidCameraRecordImpl(RecorderParams parameters) {
super(parameters);
expectedTimeBetweenFrames = 1d / Math.round(parameters.fps);
filterCtxPtr = parameters.filterDataNativePtr;
- videoDimensionsInverted = parameters.videoDimensionsInverted;
+ sizesInverted = parameters.videoDimensionsInverted;
storePreviewCallBack(this);
}
- private native void putImage(long filterCtxPtr, byte[] buffer, int orientation, boolean videoDimensionsInverted);
+ private native void putImage(long filterCtxPtr, byte[] buffer, int rotate, boolean sizesInverted);
public void onPreviewFrame(byte[] data, Camera camera) {
@@ -60,8 +59,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
return;
}
- Size s = camera.getParameters().getPreviewSize();
- int expectedBuffLength = s.width * s.height * 3 /2;
+ int expectedBuffLength = getExpectedBufferLength();
if (expectedBuffLength != data.length) {
Log.e("Linphone", "onPreviewFrame called with bad buffer length " + data.length
+ " whereas expected is " + expectedBuffLength + " don't calling putImage");
@@ -71,7 +69,7 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
long curTime = System.currentTimeMillis();
if (lastFrameTime == 0) {
lastFrameTime = curTime;
- putImage(filterCtxPtr, data, getOrientationCode(), videoDimensionsInverted);
+ putImage(filterCtxPtr, data, rotateCapturedFrame(), sizesInverted);
return;
}
@@ -84,10 +82,11 @@ public class AndroidCameraRecordImpl extends AndroidCameraRecord implements Prev
timeElapsedBetweenFrames = currentTimeElapsed;
// Log.d("onPreviewFrame: ", Integer.toString(data.length));
- putImage(filterCtxPtr, data, getOrientationCode(), videoDimensionsInverted);
+ putImage(filterCtxPtr, data, rotateCapturedFrame(), sizesInverted);
}
+
@Override
protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) {
camera.setPreviewCallback(cb);
diff --git a/src/org/linphone/core/AndroidCameraRecordManager.java b/src/org/linphone/core/AndroidCameraRecordManager.java
index c6bae18da..a19413eb7 100644
--- a/src/org/linphone/core/AndroidCameraRecordManager.java
+++ b/src/org/linphone/core/AndroidCameraRecordManager.java
@@ -18,9 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import org.linphone.core.AndroidCameraRecord.RecorderParams;
@@ -41,38 +39,21 @@ import android.view.SurfaceHolder.Callback;
*/
public class AndroidCameraRecordManager {
private static final int version = Integer.parseInt(Build.VERSION.SDK);
- private static Map instances = new HashMap();
-
+ private static final String tag = "Linphone";
+ private static AndroidCameraRecordManager instance;
// singleton
- private AndroidCameraRecordManager(int cameraId) {
- this.cameraId = cameraId;
- }
+ private AndroidCameraRecordManager() {}
- /**
- * Instance for a given camera
- * @param cameraId : starting from 0
- * @return
- */
- public static final synchronized AndroidCameraRecordManager getInstance(int cameraId) {
- if (cameraId < 0) {
- Log.e("Linphone", "Asking unmanageable camera " + cameraId);
- return null;
- }
-
- AndroidCameraRecordManager m = instances.get(cameraId);
- if (m == null) {
- m = new AndroidCameraRecordManager(cameraId);
- instances.put(cameraId, m);
- }
- return m;
- }
/**
- * @return instance for the default camera
+ * @return instance
*/
public static final synchronized AndroidCameraRecordManager getInstance() {
- return getInstance(0);
+ if (instance == null) {
+ instance = new AndroidCameraRecordManager();
+ }
+ return instance;
}
private AndroidCameraRecord.RecorderParams parameters;
@@ -81,11 +62,26 @@ public class AndroidCameraRecordManager {
private AndroidCameraRecord recorder;
- private final Integer cameraId;
+
private List supportedVideoSizes;
private int rotation;
- private static final String tag = "Linphone";
+
+ private boolean useFrontCamera;
+ public void setUseFrontCamera(boolean value) {
+ if (useFrontCamera == value) return;
+ this.useFrontCamera = value;
+
+ if (parameters != null) {
+ parameters.cameraId = cameraId();
+ if (isRecording()) {
+ stopVideoRecording();
+ tryToStartVideoRecording();
+ }
+ }
+ }
+ public boolean isUseFrontCamera() {return useFrontCamera;}
+
public void setParametersFromFilter(long filterDataPtr, int height, int width, float fps) {
@@ -94,15 +90,16 @@ public class AndroidCameraRecordManager {
p.fps = fps;
p.width = width;
p.height = height;
- p.cameraId = cameraId;
+ p.cameraId = cameraId();
p.videoDimensionsInverted = width < height;
+ // width and height will be inverted in Recorder on startPreview
parameters = p;
tryToStartVideoRecording();
}
public final void setSurfaceView(final SurfaceView sv, final int rotation) {
- this.rotation = rotation;
+ this.rotation = useFrontCamera ? 1 : rotation;
SurfaceHolder holder = sv.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
@@ -206,4 +203,22 @@ public class AndroidCameraRecordManager {
parameters = null;
}
+ public int[] doYouSupportThisVideoSize(int[] askedSize) {
+ final int askedW = askedSize[0];
+ final int askedH = askedSize[1];
+ Log.d(tag, "w"+askedW);
+ Log.d(tag, "h"+askedH);
+ if (useFrontCamera && isPortraitSize(askedW, askedH)) {
+ return new int[] {askedH, askedW}; // only landscape supported
+ } else {
+ return askedSize;
+ }
+ }
+ private boolean isPortraitSize(int width, int height) {
+ return width < height;
+ }
+
+ private static final int rearCamId() {return 1;}
+ private static final int frontCamId() {return 2;}
+ private final int cameraId() {return useFrontCamera? frontCamId() : rearCamId(); }
}
diff --git a/src/org/linphone/core/LinphoneCallParamsImpl.java b/src/org/linphone/core/LinphoneCallParamsImpl.java
index 33d460697..ef05eb228 100644
--- a/src/org/linphone/core/LinphoneCallParamsImpl.java
+++ b/src/org/linphone/core/LinphoneCallParamsImpl.java
@@ -27,6 +27,7 @@ public class LinphoneCallParamsImpl implements LinphoneCallParams {
private native void enableVideo(long nativePtr, boolean b);
private native boolean getVideoEnabled(long nativePtr);
+ private native void audioBandwidth(long nativePtr, int bw);
private native void destroy(long nativePtr);
@@ -43,4 +44,8 @@ public class LinphoneCallParamsImpl implements LinphoneCallParams {
destroy(nativePtr);
super.finalize();
}
+
+ public void setAudioBandwidth(int value) {
+ audioBandwidth(nativePtr, value);
+ }
}
diff --git a/submodules/linphone b/submodules/linphone
index 9fc45b990..684c6fa54 160000
--- a/submodules/linphone
+++ b/submodules/linphone
@@ -1 +1 @@
-Subproject commit 9fc45b990045768c65a346e5b41a37ab8087d0b5
+Subproject commit 684c6fa545f0875b943b6d6741cd01ef05febfe4