From 90a5674b978b020637a89782fc90321027a3e629 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. --- AndroidCameraRecord.java | 41 ++++++++++----- AndroidCameraRecordBufferedImpl.java | 2 +- AndroidCameraRecordImpl.java | 15 +++--- AndroidCameraRecordManager.java | 77 +++++++++++++++++----------- LinphoneCallParamsImpl.java | 5 ++ 5 files changed, 88 insertions(+), 52 deletions(-) diff --git a/AndroidCameraRecord.java b/AndroidCameraRecord.java index 7fa4746bb..a34322f7f 100644 --- a/AndroidCameraRecord.java +++ b/AndroidCameraRecord.java @@ -39,13 +39,14 @@ public abstract class AndroidCameraRecord { private PreviewCallback storedPreviewCallback; private boolean previewStarted; - protected int orientationCode; + protected int displayOrientation; protected static final String tag="Linphone"; private List 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/AndroidCameraRecordBufferedImpl.java b/AndroidCameraRecordBufferedImpl.java index 9f8b2d1c0..232d15970 100644 --- a/AndroidCameraRecordBufferedImpl.java +++ b/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/AndroidCameraRecordImpl.java b/AndroidCameraRecordImpl.java index 2d3087854..daf26ea4e 100644 --- a/AndroidCameraRecordImpl.java +++ b/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/AndroidCameraRecordManager.java b/AndroidCameraRecordManager.java index c6bae18da..a19413eb7 100644 --- a/AndroidCameraRecordManager.java +++ b/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/LinphoneCallParamsImpl.java b/LinphoneCallParamsImpl.java index 33d460697..ef05eb228 100644 --- a/LinphoneCallParamsImpl.java +++ b/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); + } }