From 1c113d30745dfea43656298f985c7183772eeda2 Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Thu, 9 Dec 2010 09:13:12 +0100 Subject: [PATCH] Preliminary support for front camera. --- res/menu/videocall_activity_menu.xml | 1 + res/values/strings.xml | 3 + res/xml/preferences.xml | 4 +- src/org/linphone/BandwidthManager.java | 4 +- src/org/linphone/DialerActivity.java | 9 ++- src/org/linphone/VideoCallActivity.java | 14 +++- .../linphone/core/AndroidCameraRecord.java | 41 +++++++--- .../core/AndroidCameraRecordBufferedImpl.java | 2 +- .../core/AndroidCameraRecordImpl.java | 15 ++-- .../core/AndroidCameraRecordManager.java | 77 +++++++++++-------- .../linphone/core/LinphoneCallParamsImpl.java | 5 ++ submodules/linphone | 2 +- 12 files changed, 119 insertions(+), 58 deletions(-) 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