diff --git a/AndroidVideoWindowImpl.java b/AndroidVideoWindowImpl.java deleted file mode 100644 index 4fc213f5f..000000000 --- a/AndroidVideoWindowImpl.java +++ /dev/null @@ -1,162 +0,0 @@ -package org.linphone.core; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import org.linphone.OpenGLESDisplay; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Bitmap.Config; -import android.opengl.GLSurfaceView; -import android.view.Surface; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.Surface.OutOfResourcesException; -import android.view.SurfaceHolder.Callback; - -public class AndroidVideoWindowImpl { - private boolean useGLrendering; - private Bitmap mBitmap; - private SurfaceView mView; - private Surface mSurface; - private VideoWindowListener mListener; - private Renderer renderer; - public static interface VideoWindowListener{ - void onSurfaceReady(AndroidVideoWindowImpl vw); - void onSurfaceDestroyed(AndroidVideoWindowImpl vw); - }; - public AndroidVideoWindowImpl(SurfaceView view){ - useGLrendering = (view instanceof GLSurfaceView); - mView=view; - mBitmap=null; - mSurface=null; - mListener=null; - view.getHolder().addCallback(new Callback(){ - public void surfaceChanged(SurfaceHolder holder, int format, - int width, int height) { - Log.i("Surface is being changed."); - if (!useGLrendering) { - synchronized(AndroidVideoWindowImpl.this){ - mBitmap=Bitmap.createBitmap(width,height,Config.RGB_565); - mSurface=holder.getSurface(); - } - } - if (mListener!=null) mListener.onSurfaceReady(AndroidVideoWindowImpl.this); - Log.w("Video display surface changed"); - } - - public void surfaceCreated(SurfaceHolder holder) { - Log.w("Video display surface created"); - } - - public void surfaceDestroyed(SurfaceHolder holder) { - if (!useGLrendering) { - synchronized(AndroidVideoWindowImpl.this){ - mSurface=null; - mBitmap=null; - } - } - if (mListener!=null) - mListener.onSurfaceDestroyed(AndroidVideoWindowImpl.this); - Log.d("Video display surface destroyed"); - } - }); - - if (useGLrendering) { - renderer = new Renderer(); - ((GLSurfaceView)mView).setRenderer(renderer); - ((GLSurfaceView)mView).setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - } - } - static final int LANDSCAPE=0; - static final int PORTRAIT=1; - public void requestOrientation(int orientation){ - //Surface.setOrientation(0, orientation==LANDSCAPE ? 1 : 0); - //Log.d("Orientation changed."); - } - public void setListener(VideoWindowListener l){ - mListener=l; - } - public Surface getSurface(){ - if (useGLrendering) - Log.e("View class does not match Video display filter used (you must use a non-GL View)"); - return mView.getHolder().getSurface(); - } - public Bitmap getBitmap(){ - if (useGLrendering) - Log.e("View class does not match Video display filter used (you must use a non-GL View)"); - return mBitmap; - } - - public void setOpenGLESDisplay(int ptr) { - if (!useGLrendering) - Log.e("View class does not match Video display filter used (you must use a GL View)"); - renderer.setOpenGLESDisplay(ptr); - } - - public void requestRender() { - ((GLSurfaceView)mView).requestRender(); - } - - //Called by the mediastreamer2 android display filter - public synchronized void update(){ - if (mSurface!=null){ - try { - Canvas canvas=mSurface.lockCanvas(null); - canvas.drawBitmap(mBitmap, 0, 0, null); - mSurface.unlockCanvasAndPost(canvas); - - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (OutOfResourcesException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - private static class Renderer implements GLSurfaceView.Renderer { - int ptr; - boolean initPending; - int width=-1, height=-1; - - public Renderer() { - ptr = 0; - initPending = false; - } - - public void setOpenGLESDisplay(int ptr) { - this.ptr = ptr; - // if dimension are set, we are recreating MS2 graph without - // recreating the surface => need to force init - if (width > 0 && height > 0) { - initPending = true; - } - } - - public void onDrawFrame(GL10 gl) { - if (ptr == 0) - return; - if (initPending) { - OpenGLESDisplay.init(ptr, width, height); - initPending = false; - } - OpenGLESDisplay.render(ptr); - } - - public void onSurfaceChanged(GL10 gl, int width, int height) { - /* delay init until ptr is set */ - this.width = width; - this.height = height; - initPending = true; - } - - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - - } - } -} - - diff --git a/Hacks.java b/Hacks.java deleted file mode 100644 index ceca9ee80..000000000 --- a/Hacks.java +++ /dev/null @@ -1,146 +0,0 @@ -/* -Hacks.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; -import android.media.AudioManager; -import android.os.Build; - -public final class Hacks { - - private Hacks() {} - - - public static boolean isGalaxySOrTabWithFrontCamera() { - return isGalaxySOrTab() && !isGalaxySOrTabWithoutFrontCamera(); - } - private static boolean isGalaxySOrTabWithoutFrontCamera() { - return isSC02B() || isSGHI896(); - } - - - public static boolean isGalaxySOrTab() { - return isGalaxyS() || isGalaxyTab(); - } - - public static boolean isGalaxyTab() { - return isGTP1000(); - } - private static boolean isGalaxyS() { - return isGT9000() || isSC02B() || isSGHI896() || isSPHD700(); - } - - public static final boolean hasTwoCamerasRear0Front1() { - return isSPHD700() || isADR6400(); - } - - // HTC - private static final boolean isADR6400() { - return Build.MODEL.startsWith("ADR6400") || Build.DEVICE.startsWith("ADR6400"); - } // HTC Thunderbolt - - // Galaxy S variants - private static final boolean isSPHD700() {return Build.DEVICE.startsWith("SPH-D700");} // Epic - private static boolean isSGHI896() {return Build.DEVICE.startsWith("SGH-I896");} // Captivate - private static boolean isGT9000() {return Build.DEVICE.startsWith("GT-I9000");} // Galaxy S - private static boolean isSC02B() {return Build.DEVICE.startsWith("SC-02B");} // Docomo - private static boolean isGTP1000() {return Build.DEVICE.startsWith("GT-P1000");} // Tab - - -/* private static final boolean log(final String msg) { - Log.d(msg); - return true; - }*/ - - /* Not working as now - * Calling from Galaxy S to PC is "usable" even with no hack; other side is not even with this one*/ - public static void galaxySSwitchToCallStreamUnMuteLowerVolume(AudioManager am) { - // Switch to call audio channel (Galaxy S) - am.setSpeakerphoneOn(false); - sleep(200); - - // Lower volume - am.setStreamVolume(AudioManager.STREAM_VOICE_CALL, 1, 0); - - // Another way to select call channel - am.setMode(AudioManager.MODE_NORMAL); - sleep(200); - - // Mic is muted if not doing this - am.setMicrophoneMute(true); - sleep(200); - am.setMicrophoneMute(false); - sleep(200); - } - - public static final void sleep(int time) { - try { - Thread.sleep(time); - } catch(InterruptedException ie){} - } - - public static void dumpDeviceInformation() { - StringBuilder sb = new StringBuilder(" ==== Phone information dump ====\n"); - sb.append("DEVICE=").append(Build.DEVICE).append("\n"); - sb.append("MODEL=").append(Build.MODEL).append("\n"); - //MANUFACTURER doesn't exist in android 1.5. - //sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n"); - sb.append("SDK=").append(Build.VERSION.SDK); - - Log.i(sb.toString()); - } - - public static boolean needSoftvolume() { - return isGalaxySOrTab(); - } - - public static boolean needRoutingAPI() { - return Version.sdkStrictlyBelow(5) /* 0; - } - - Log.i("Hack: considering there IS a camera.\n" - + "If it is not the case, report DEVICE and MODEL to linphone-users@nongnu.org"); - return true; - } - -} diff --git a/LinphoneCallImpl.java b/LinphoneCallImpl.java index 55d3baedf..b027e2170 100644 --- a/LinphoneCallImpl.java +++ b/LinphoneCallImpl.java @@ -20,7 +20,7 @@ package org.linphone.core; class LinphoneCallImpl implements LinphoneCall { - + protected final long nativePtr; boolean ownPtr = false; native private void ref(long ownPtr); @@ -31,6 +31,7 @@ class LinphoneCallImpl implements LinphoneCall { native private int getState(long nativePtr); private native long getCurrentParamsCopy(long nativePtr); private native void enableCamera(long nativePtr, boolean enabled); + private native boolean cameraEnabled(long nativePtr); private native void enableEchoCancellation(long nativePtr,boolean enable); private native boolean isEchoCancellationEnabled(long nativePtr) ; private native void enableEchoLimiter(long nativePtr,boolean enable); @@ -48,7 +49,7 @@ class LinphoneCallImpl implements LinphoneCall { ref(nativePtr); } protected void finalize() throws Throwable { - unref(nativePtr); + unref(nativePtr); } public LinphoneCallLog getCallLog() { long lNativePtr = getCallLog(nativePtr); @@ -79,6 +80,10 @@ class LinphoneCallImpl implements LinphoneCall { public void enableCamera(boolean enabled) { enableCamera(nativePtr, enabled); } + @Override + public boolean cameraEnabled() { + return cameraEnabled(nativePtr); + } public boolean equals(Object call) { return nativePtr == ((LinphoneCallImpl)call).nativePtr; } diff --git a/LinphoneCoreImpl.java b/LinphoneCoreImpl.java index 23a8d3914..d4b54b663 100644 --- a/LinphoneCoreImpl.java +++ b/LinphoneCoreImpl.java @@ -22,7 +22,8 @@ import java.io.File; import java.io.IOException; import java.util.Vector; -import android.view.SurfaceView; +import org.linphone.LinphoneManager; +import org.linphone.mediastream.video.AndroidVideoWindowImpl; class LinphoneCoreImpl implements LinphoneCore { @@ -68,8 +69,7 @@ class LinphoneCoreImpl implements LinphoneCore { private native void stopDtmf(long nativePtr); private native void setVideoWindowId(long nativePtr, Object wid); private native void setPreviewWindowId(long nativePtr, Object wid); - private AndroidVideoWindowImpl mVideoWindow; - private AndroidVideoWindowImpl mPreviewWindow; + private native void setDeviceRotation(long nativePtr, int rotation); private native void addFriend(long nativePtr,long friend); private native void setPresenceInfo(long nativePtr,int minute_away, String alternative_contact,int status); private native long createChatRoom(long nativePtr,String to); @@ -104,6 +104,8 @@ class LinphoneCoreImpl implements LinphoneCore { private native void setDownloadPtime(long nativePtr, int ptime); private native void setZrtpSecretsCache(long nativePtr, String file); private native void enableEchoLimiter(long nativePtr2, boolean val); + private native int setVideoDevice(long nativePtr2, int id); + private native int getVideoDevice(long nativePtr2); LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object userdata) throws IOException { mListener=listener; @@ -327,33 +329,15 @@ class LinphoneCoreImpl implements LinphoneCore { return new LinphoneChatRoomImpl(createChatRoom(nativePtr,to)); } public synchronized void setPreviewWindow(Object w) { - if (mPreviewWindow!=null) - mPreviewWindow.setListener(null); - mPreviewWindow=new AndroidVideoWindowImpl((SurfaceView)w); - mPreviewWindow.setListener(new AndroidVideoWindowImpl.VideoWindowListener(){ - public void onSurfaceDestroyed(AndroidVideoWindowImpl vw) { - setPreviewWindowId(nativePtr,null); - } - - public void onSurfaceReady(AndroidVideoWindowImpl vw) { - setPreviewWindowId(nativePtr,vw); - } - }); + setPreviewWindowId(nativePtr,w); } public synchronized void setVideoWindow(Object w) { - if (mVideoWindow!=null) - mVideoWindow.setListener(null); - mVideoWindow=new AndroidVideoWindowImpl((SurfaceView) w); - mVideoWindow.setListener(new AndroidVideoWindowImpl.VideoWindowListener(){ - public void onSurfaceDestroyed(AndroidVideoWindowImpl vw) { - setVideoWindowId(nativePtr,null); - } - - public void onSurfaceReady(AndroidVideoWindowImpl vw) { - setVideoWindowId(nativePtr,vw); - } - }); + setVideoWindowId(nativePtr, w); } + public synchronized void setDeviceRotation(int rotation) { + setDeviceRotation(nativePtr, rotation); + } + public synchronized void enableVideo(boolean vcap_enabled, boolean display_enabled) { enableVideo(nativePtr,vcap_enabled, display_enabled); } @@ -507,5 +491,16 @@ class LinphoneCoreImpl implements LinphoneCore { public void enableEchoLimiter(boolean val) { enableEchoLimiter(nativePtr,val); } + @Override + public void setVideoDevice(int id) { + Log.i("Setting camera id :", id); + if (setVideoDevice(nativePtr, id) != 0) { + Log.e("Failed to set video device to id:", id); + } + } + @Override + public int getVideoDevice() { + return getVideoDevice(nativePtr); + } } diff --git a/Version.java b/Version.java index 53ae2e05f..edbb25e8e 100644 --- a/Version.java +++ b/Version.java @@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.linphone.core; +import org.linphone.mediastream.video.capture.hwconf.Hacks; + import android.os.Build; /** diff --git a/tutorials/JavaCameraRecordImpl.java b/tutorials/JavaCameraRecordImpl.java deleted file mode 100644 index 4772c7a5b..000000000 --- a/tutorials/JavaCameraRecordImpl.java +++ /dev/null @@ -1,87 +0,0 @@ -/* -JavaCameraRecordImpl.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.tutorials; - -import org.linphone.core.Log; -import org.linphone.core.video.AndroidCameraRecord; - -import android.hardware.Camera; -import android.hardware.Camera.PreviewCallback; -import android.hardware.Camera.Size; -import android.widget.TextView; - -/** - * This is an helper class, not a test activity. - * - * @author Guillaume Beraudo - * - */ -class JavaCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback { - - private TextView debug; - private long count = 0; - private float averageCalledRate; - - private long startTime; - private long endTime; - private int fps; - - - public JavaCameraRecordImpl(AndroidCameraRecord.RecorderParams parameters) { - super(parameters); - storePreviewCallBack(this); - fps = Math.round(parameters.fps); - } - - - public void setDebug(TextView debug) { - this.debug = debug; - } - - public void onPreviewFrame(byte[] data, Camera camera) { - - Size s = camera.getParameters().getPreviewSize(); - int expectedBuffLength = s.width * s.height * 3 /2; - if (expectedBuffLength != data.length) { - Log.e("onPreviewFrame called with bad buffer length ", data.length, - " whereas expected is ", expectedBuffLength, " don't calling putImage"); - return; - } - - if ((count % 2 * fps) == 0) { - endTime = System.currentTimeMillis(); - averageCalledRate = (100000 * 2 * fps) / (endTime - startTime); - averageCalledRate /= 100f; - startTime = endTime; - } - - count++; - - String msg = "Frame " + count + ": " + data.length + "bytes (avg="+averageCalledRate+"frames/s)"; - if (debug != null) debug.setText(msg); - Log.d("onPreviewFrame:", msg); - } - - - @Override - protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) { - camera.setPreviewCallback(cb); - } - -} diff --git a/tutorials/TestVideoActivity.java b/tutorials/TestVideoActivity.java deleted file mode 100644 index 7523cb0ff..000000000 --- a/tutorials/TestVideoActivity.java +++ /dev/null @@ -1,194 +0,0 @@ -/* -TutorialHelloWorldActivity.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.tutorials; - -import static org.linphone.core.VideoSize.CIF; -import static org.linphone.core.VideoSize.HVGA; -import static org.linphone.core.VideoSize.QCIF; -import static org.linphone.core.VideoSize.QVGA; - -import java.util.Stack; - -import org.linphone.R; -import org.linphone.core.Log; -import org.linphone.core.VideoSize; -import org.linphone.core.video.AndroidCameraRecord; - -import android.app.Activity; -import android.os.Bundle; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.View; -import android.view.SurfaceHolder.Callback; -import android.view.View.OnClickListener; -import android.view.ViewGroup.LayoutParams; -import android.widget.Button; -import android.widget.TextView; - -/** - * Activity for displaying and starting the HelloWorld example on Android phone. - * - * @author Guillaume Beraudo - * - */ -public class TestVideoActivity extends Activity implements Callback, OnClickListener { - - private SurfaceView surfaceView; - private static final int rate = 7; - private JavaCameraRecordImpl recorder; - private TextView debugView; - private Button nextSize; - private Button changeCamera; - private Button changeOrientation; - private AndroidCameraRecord.RecorderParams params; - - private Stack videoSizes = createSizesToTest(); - private int currentCameraId = 2; - private boolean currentOrientationIsPortrait = false; - private int width; - private int height; - private boolean started; - - - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.videotest); - - surfaceView=(SurfaceView)findViewById(R.id.videotest_surfaceView); - - nextSize = (Button) findViewById(R.id.test_video_size); - nextSize.setOnClickListener(this); - - changeCamera = (Button) findViewById(R.id.test_video_camera); - changeCamera.setText("Cam"+otherCameraId(currentCameraId)); - changeCamera.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - changeCamera.setText("Cam"+currentCameraId); - currentCameraId = otherCameraId(currentCameraId); - updateRecording(); - } - }); - - changeOrientation = (Button) findViewById(R.id.test_video_orientation); - changeOrientation.setText(orientationToString(!currentOrientationIsPortrait)); - changeOrientation.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - currentOrientationIsPortrait = !currentOrientationIsPortrait; - changeOrientation.setText(orientationToString(!currentOrientationIsPortrait)); - - if (width == 0 || height == 0) return; - int newWidth = currentOrientationIsPortrait? Math.min(height, width) : Math.max(height, width); - int newHeight = currentOrientationIsPortrait? Math.max(height, width) : Math.min(height, width); - changeSurfaceViewLayout(newWidth, newHeight); // will change width and height on surfaceChanged - } - }); - - SurfaceHolder holder = surfaceView.getHolder(); - holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); - holder.addCallback(this); - - - debugView = (TextView) findViewById(R.id.videotest_debug); - } - - protected void updateRecording() { - if (width == 0 || height == 0) return; - if (recorder != null) recorder.stopPreview(); - - params = new AndroidCameraRecord.RecorderParams(0); - params.surfaceView = surfaceView; - params.width = width; - params.height = height; - params.fps = rate; - params.cameraId = currentCameraId; - - recorder = new JavaCameraRecordImpl(params); -// recorder.setDebug(debugView); - debugView.setText(orientationToString(currentOrientationIsPortrait) - + " w="+width + " h="+height+ " cam"+currentCameraId); - recorder.startPreview(); - - } - - private String orientationToString(boolean orientationIsPortrait) { - return orientationIsPortrait? "Por" : "Lan"; - } - private int otherCameraId(int currentId) { - return (currentId == 2) ? 1 : 2; - } - public void onClick(View v) { - nextSize.setText("Next"); - started=true; - if (videoSizes.isEmpty()) { - videoSizes = createSizesToTest(); - } - - VideoSize size = videoSizes.pop(); - changeSurfaceViewLayout(size.width, size.height); - - // on surface changed the recorder will be restarted with new values - // and the surface will be resized - } - - - private void changeSurfaceViewLayout(int width, int height) { - LayoutParams params = surfaceView.getLayoutParams(); - params.height = height; - params.width = width; - surfaceView.setLayoutParams(params); - - } - - private Stack createSizesToTest() { - Stack stack = new Stack(); - - stack.push(VideoSize.createStandard(QCIF, false)); - stack.push(VideoSize.createStandard(CIF, false)); - stack.push(VideoSize.createStandard(QVGA, false)); - stack.push(VideoSize.createStandard(HVGA, false)); - stack.push(new VideoSize(640,480)); - stack.push(new VideoSize(800,480)); - return stack; - } - - - - - public void surfaceDestroyed(SurfaceHolder holder) { - surfaceView = null; - Log.d("Video capture surface destroyed"); - if (recorder != null) recorder.stopPreview(); - } - - public void surfaceCreated(SurfaceHolder holder) { - Log.d("Video capture surface created"); - } - - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - if (!started) return; - if (recorder != null) recorder.stopPreview(); - - this.width = width; - this.height = height; - - updateRecording(); - } -} diff --git a/video/AndroidCameraConf.java b/video/AndroidCameraConf.java deleted file mode 100644 index 874a6d2da..000000000 --- a/video/AndroidCameraConf.java +++ /dev/null @@ -1,66 +0,0 @@ -/* -AndroidCameraConf.java -Copyright (C) 2011 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.video; - -import java.util.List; - -import org.linphone.core.VideoSize; - - -/** - * @author Guillaume Beraudo - * - */ -interface AndroidCameraConf { - - AndroidCameras getFoundCameras(); - - int getNumberOfCameras(); - - int getCameraOrientation(int cameraId); - - boolean isFrontCamera(int cameraId); - - List getSupportedPreviewSizes(int cameraId); - - /** - * Default: no front; rear=0; default=rear - * @author Guillaume Beraudo - * - */ - class AndroidCameras { - Integer front; - Integer rear = 0; - Integer defaultC = rear; - - boolean hasFrontCamera() { return front != null; } - boolean hasRearCamera() { return rear != null; } - boolean hasSeveralCameras() { return front != rear && front != null; } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Cameras :"); - if (rear != null) sb.append(" rear=").append(rear); - if (front != null) sb.append(" front=").append(front); - if (defaultC != null) sb.append(" default=").append(defaultC); - return sb.toString(); - } - } -} \ No newline at end of file diff --git a/video/AndroidCameraConf5.java b/video/AndroidCameraConf5.java deleted file mode 100644 index 06c266d7a..000000000 --- a/video/AndroidCameraConf5.java +++ /dev/null @@ -1,113 +0,0 @@ -/* -AndroidCameraConf.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.video; - -import java.util.List; - -import org.linphone.core.Hacks; -import org.linphone.core.Log; -import org.linphone.core.VideoSize; - -import android.hardware.Camera; - - -class AndroidCameraConf5 implements AndroidCameraConf { - private AndroidCameras foundCameras; - public AndroidCameras getFoundCameras() {return foundCameras;} - - public AndroidCameraConf5() { - // Defaults - foundCameras = new AndroidCameras(); - - if (Hacks.isGalaxySOrTab()) { - Log.d("Hack Galaxy S : has one or more cameras"); - if (Hacks.isGalaxySOrTabWithFrontCamera()) { - Log.d("Hack Galaxy S : HAS a front camera with id=2"); - foundCameras.front = 2; - } else { - Log.d("Hack Galaxy S : NO front camera"); - } - Log.d("Hack Galaxy S : HAS a rear camera with id=1"); - foundCameras.rear = 1; - foundCameras.defaultC = foundCameras.rear; - } else if (Hacks.hasTwoCamerasRear0Front1()) { - Log.d("Hack SPHD700 has 2 cameras a rear with id=0 and a front with id=1"); - foundCameras.front = 1; - } - - } - - public int getNumberOfCameras() { - Log.i("Detecting the number of cameras"); - if (Hacks.hasTwoCamerasRear0Front1() || Hacks.isGalaxySOrTabWithFrontCamera()) { - Log.d("Hack: we know this model has 2 cameras"); - return 2; - } else - return 1; - } - - - - public int getCameraOrientation(int cameraId) { - // Use hacks to guess orientation of the camera - if (Hacks.isGalaxySOrTab() && isFrontCamera(cameraId)) { - Log.d("Hack Galaxy S : front camera mounted landscape"); - // mounted in landscape for a portrait phone orientation - // |^^^^^^^^| - // | ____ | - // | |____| | - // | | - // | | - // | Phone | - // |________| - return 180; - } - return 90; - } - - - - public boolean isFrontCamera(int cameraId) { - // Use hacks to guess facing of the camera - if (cameraId == 2 && Hacks.isGalaxySOrTab()) { - Log.d("Hack Galaxy S : front camera has id=2"); - return true; - } else if (cameraId == 1 && Hacks.hasTwoCamerasRear0Front1()) { - Log.d("Hack SPHD700 : front camera has id=1"); - return true; - } - - return false; - } - - public List getSupportedPreviewSizes(int cameraId) { - if (getNumberOfCameras() >1) { - Log.w("Hack: on older devices, using video formats supported by default camera"); - } - Log.i("Opening camera to retrieve supported video sizes"); - Camera c = Camera.open(); - List sizes=VideoUtil.createList(c.getParameters().getSupportedPreviewSizes()); - c.release(); - Log.i("Camera opened to retrieve supported video sizes released"); - return sizes; - } - - - -} diff --git a/video/AndroidCameraConf9.java b/video/AndroidCameraConf9.java deleted file mode 100644 index 02e909895..000000000 --- a/video/AndroidCameraConf9.java +++ /dev/null @@ -1,81 +0,0 @@ -/* -AndroidCameraConf9.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.video; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.linphone.core.Log; -import org.linphone.core.VideoSize; - -import android.hardware.Camera; - -class AndroidCameraConf9 implements AndroidCameraConf { - private AndroidCameras foundCameras; - private Map> supportedSizes = new HashMap>(); - public AndroidCameras getFoundCameras() {return foundCameras;} - - public AndroidCameraConf9() { - foundCameras = new AndroidCameras(); - - for (int id=0; id < getNumberOfCameras(); id++) { - if (foundCameras.defaultC == null) - foundCameras.defaultC = id; - - if (isFrontCamera(id)) { - foundCameras.front = id; - } else { - foundCameras.rear = id; - } - supportedSizes.put(id, findSupportedVideoSizes(id)); - } - } - - private List findSupportedVideoSizes(int id) { - Log.i("Opening camera ",id," to retrieve supported video sizes"); - Camera c = Camera.open(id); - List sizes=VideoUtil.createList(c.getParameters().getSupportedPreviewSizes()); - c.release(); - Log.i("Camera ",id," opened to retrieve supported video sizes released"); - return sizes; - } - - public int getNumberOfCameras() { - return Camera.getNumberOfCameras(); - } - - public int getCameraOrientation(int cameraId) { - android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); - Camera.getCameraInfo(cameraId, info); - Log.d("Camera info for ",cameraId,": orientation=",info.orientation); - return info.orientation; - } - - public boolean isFrontCamera(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; - } - - public List getSupportedPreviewSizes(int cameraId) { - return supportedSizes.get(cameraId); - } - -} diff --git a/video/AndroidCameraRecord.java b/video/AndroidCameraRecord.java deleted file mode 100644 index 9d4dd29fe..000000000 --- a/video/AndroidCameraRecord.java +++ /dev/null @@ -1,279 +0,0 @@ -/* -AndroidCameraRecordImpl.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.video; - -import java.util.Collections; -import java.util.List; - -import org.linphone.core.Log; -import org.linphone.core.Version; -import org.linphone.core.VideoSize; - -import android.hardware.Camera; -import android.hardware.Camera.AutoFocusCallback; -import android.hardware.Camera.ErrorCallback; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.PreviewCallback; -import android.hardware.Camera.Size; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.View; -import android.view.View.OnClickListener; - - -public abstract class AndroidCameraRecord implements AutoFocusCallback { - - protected Camera camera; - private RecorderParams params; - - private PreviewCallback storedPreviewCallback; - private boolean previewStarted; - private List supportedVideoSizes; - private Size currentPreviewSize; - - public AndroidCameraRecord(RecorderParams parameters) { - this.params = parameters; - } - - protected List getSupportedPreviewSizes(Camera.Parameters parameters) { - return Collections.emptyList(); - } - - private int[] findClosestEnclosingFpsRange(int expectedFps, List fpsRanges) { - Log.d("Searching for closest fps range from ",expectedFps); - int measure = Integer.MAX_VALUE; - int[] closestRange = fpsRanges.get(0); - for (int[] curRange : fpsRanges) { - if (curRange[0] > expectedFps || curRange[1] < expectedFps) continue; - int curMeasure = Math.abs(curRange[0] - expectedFps) - + Math.abs(curRange[1] - expectedFps); - if (curMeasure < measure) { - closestRange=curRange; - Log.d("a better range has been found: w=",closestRange[0],",h=",closestRange[1]); - } - } - Log.d("The closest fps range is w=",closestRange[0],",h=",closestRange[1]); - return closestRange; - } - - public synchronized void startPreview() { // FIXME throws exception? - if (previewStarted) { - Log.w("Already started"); - throw new RuntimeException("Video recorder already started"); - // return - } - - if (params.surfaceView.getVisibility() != SurfaceView.VISIBLE) { - // Illegal state - Log.e("Illegal state: video capture surface view is not visible"); - return; - } - - - Log.d("Trying to open camera with id ", params.cameraId); - if (camera != null) { - Log.e("Camera is not null, ?already open? : aborting"); - return; - } - camera = openCamera(params.cameraId); - camera.setErrorCallback(new ErrorCallback() { - public void onError(int error, Camera camera) { - Log.e("Camera error : ", error); - } - }); - - - Camera.Parameters parameters=camera.getParameters(); - if (Version.sdkStrictlyBelow(Version.API09_GINGERBREAD_23)) { - parameters.set("camera-id",params.cameraId); - } - - if (supportedVideoSizes == null) { - supportedVideoSizes = VideoUtil.createList(getSupportedPreviewSizes(parameters)); - } - - - if (params.width >= params.height) { - parameters.setPreviewSize(params.width, params.height); - } else { - // invert height and width - parameters.setPreviewSize(params.height, params.width); - } - // should setParameters and get again to have the real one?? - currentPreviewSize = parameters.getPreviewSize(); - - // Frame rate - if (Version.sdkStrictlyBelow(Version.API09_GINGERBREAD_23)) { - // Select the supported fps just faster than the target rate - List supportedFrameRates=parameters.getSupportedPreviewFrameRates(); - if (supportedFrameRates != null && supportedFrameRates.size() > 0) { - Collections.sort(supportedFrameRates); - int selectedRate = -1; - for (Integer rate : supportedFrameRates) { - selectedRate=rate; - if (rate >= params.fps) break; - } - parameters.setPreviewFrameRate(selectedRate); - } - } else { - List supportedRanges = parameters.getSupportedPreviewFpsRange(); - int[] range=findClosestEnclosingFpsRange((int)(1000*params.fps), supportedRanges); - parameters.setPreviewFpsRange(range[0], range[1]); - } - - - onSettingCameraParameters(parameters); - camera.setParameters(parameters); - - SurfaceHolder holder = params.surfaceView.getHolder(); - try { - camera.setPreviewDisplay(holder); - } - catch (Throwable t) { - Log.e(t,"Exception in Video capture setPreviewDisplay()"); - } - - - try { - camera.startPreview(); - } catch (Throwable e) { - Log.e("Error, can't start camera preview. Releasing camera!"); - camera.release(); - camera = null; - return; - } - - previewStarted = true; - - // Activate autofocus - if (Camera.Parameters.FOCUS_MODE_AUTO.equals(parameters.getFocusMode())) { - OnClickListener svClickListener = new OnClickListener() { - public void onClick(View v) { - Log.i("Auto focus requested"); - camera.autoFocus(AndroidCameraRecord.this); - } - }; - params.surfaceView.setOnClickListener(svClickListener); - // svClickListener.onClick(null); - } else { - params.surfaceView.setOnClickListener(null); - } - - // Register callback to get capture buffer - lowLevelSetPreviewCallback(camera, storedPreviewCallback); - - - onPreviewStarted(camera); - } - - - - - protected Camera openCamera(int cameraId) { - return Camera.open(); - } - - protected void onSettingCameraParameters(Parameters parameters) {} - - /** - * Hook. - * @param camera - */ - public void onPreviewStarted(Camera camera) {} - - public void storePreviewCallBack(PreviewCallback cb) { - this.storedPreviewCallback = cb; - if (camera == null) { - Log.w("Capture camera not ready, storing preview callback"); - return; - } - - lowLevelSetPreviewCallback(camera, cb); - } - - - public void stopPreview() { - if (!previewStarted) return; - lowLevelSetPreviewCallback(camera, null); - camera.stopPreview(); - camera.release(); - camera=null; - Log.d("Camera released"); - currentPreviewSize = null; - previewStarted = false; - } - - - public void stopCaptureCallback() { - if (camera != null) { - lowLevelSetPreviewCallback(camera, null); - } - } - - protected abstract void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb); - - - - public static class RecorderParams { - public static enum MirrorType {NO, HORIZONTAL, CENTRAL, VERTICAL}; - - public float fps; - public int height; - public int width; - - final long filterDataNativePtr; - public int cameraId; - public boolean isFrontCamera; - public int rotation; - public SurfaceView surfaceView; - - public MirrorType mirror = MirrorType.NO; - public int phoneOrientation; - - public RecorderParams(long ptr) { - filterDataNativePtr = ptr; - } - } - - - - public boolean isStarted() { - return previewStarted; - } - - public List getSupportedVideoSizes() { - return supportedVideoSizes; - } - - - protected int getExpectedBufferLength() { - if (currentPreviewSize == null) return -1; - - return currentPreviewSize.width * currentPreviewSize.height * 3 /2; - } - - public void onAutoFocus(boolean success, Camera camera) { - if (success) Log.i("Autofocus success"); - else Log.i("Autofocus failure"); - } - - public int getStoredPhoneOrientation() { - return params.phoneOrientation; - } -} diff --git a/video/AndroidCameraRecord5.java b/video/AndroidCameraRecord5.java deleted file mode 100644 index 45f94cd29..000000000 --- a/video/AndroidCameraRecord5.java +++ /dev/null @@ -1,139 +0,0 @@ -/* -AndroidCameraRecordImpl.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.video; - -import java.util.Arrays; -import java.util.List; - -import org.linphone.core.Log; -import org.linphone.core.video.AndroidCameraRecord.RecorderParams.MirrorType; - -import android.hardware.Camera; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.PreviewCallback; -import android.hardware.Camera.Size; - -/** - * Record from Android camera. - * Android >= 5 (2.0) version. - * - * @author Guillaume Beraudo - * - */ -class AndroidCameraRecord5 extends AndroidCameraRecord implements PreviewCallback { - - private long filterCtxPtr; - private double timeElapsedBetweenFrames = 0; - private long lastFrameTime = 0; - private final double expectedTimeBetweenFrames; - protected final int rotation; - private MirrorType mirror; -// private boolean isUsingFrontCamera; - - public AndroidCameraRecord5(RecorderParams parameters) { - super(parameters); - expectedTimeBetweenFrames = 1d / Math.round(parameters.fps); - filterCtxPtr = parameters.filterDataNativePtr; - rotation = parameters.rotation; - mirror = parameters.mirror; -// isUsingFrontCamera = parameters.isFrontCamera; - - storePreviewCallBack(this); - } - - - private native void putImage(long filterCtxPtr, byte[] buffer, int rotate, int mirror); - - - public void onPreviewFrame(byte[] data, Camera camera) { - if (data == null) { - Log.e("onPreviewFrame Called with null buffer"); - return; - } - if (filterCtxPtr == 0l) { - Log.e("onPreviewFrame Called with no filterCtxPtr set"); - return; - } - - int expectedBuffLength = getExpectedBufferLength(); - if (expectedBuffLength != data.length) { - Log.e("onPreviewFrame called with bad buffer length ", data.length, - " whereas expected is ", expectedBuffLength, " don't calling putImage"); - return; - } - - long curTime = System.currentTimeMillis(); - if (lastFrameTime == 0) { - lastFrameTime = curTime; - putImage(filterCtxPtr, data, rotation, mirror.ordinal()); - return; - } - - double currentTimeElapsed = 0.8 * (curTime - lastFrameTime) / 1000 + 0.2 * timeElapsedBetweenFrames; - if (currentTimeElapsed < expectedTimeBetweenFrames) { -// Log.d("Clipping frame ", Math.round(1 / currentTimeElapsed), " > ", fps); - return; - } - lastFrameTime = curTime; - timeElapsedBetweenFrames = currentTimeElapsed; - - // Log.d("onPreviewFrame: ", Integer.toString(data.length)); - putImage(filterCtxPtr, data, rotation, mirror.ordinal()); - } - - protected String selectFocusMode(final List supportedFocusModes) {/* - if (isUsingFrontCamera && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) { - return Camera.Parameters.FOCUS_MODE_FIXED; - } - if (!isUsingFrontCamera && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) { - return Camera.Parameters.FOCUS_MODE_INFINITY; - }*/ - - if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { - return Camera.Parameters.FOCUS_MODE_AUTO; - } - - return null; // Should not occur? - } - - @Override - protected void onSettingCameraParameters(Parameters parameters) { - super.onSettingCameraParameters(parameters); - List supportedFocusModes = parameters.getSupportedFocusModes(); - String focusMode = selectFocusMode(supportedFocusModes); - if (focusMode != null) { - Log.w("Selected focus mode: ", focusMode); - parameters.setFocusMode(focusMode); - } else { - Log.i("No suitable focus mode found in : ", Arrays.toString(supportedFocusModes.toArray())); - } - } - - @Override - protected List getSupportedPreviewSizes(Parameters parameters) { - return parameters.getSupportedPreviewSizes(); - } - - @Override - protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) { - camera.setPreviewCallback(cb); - } - - -} diff --git a/video/AndroidCameraRecord8.java b/video/AndroidCameraRecord8.java deleted file mode 100644 index c5fda6774..000000000 --- a/video/AndroidCameraRecord8.java +++ /dev/null @@ -1,82 +0,0 @@ -/* -AndroidCameraRecord8Impl.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.video; - -import java.util.List; - -import org.linphone.core.Log; - -import android.hardware.Camera; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.PreviewCallback; -import android.hardware.Camera.Size; - -/** - * - * Android >= 8 (2.2) version. - * @author Guillaume Beraudo - * - */ -class AndroidCameraRecord8 extends AndroidCameraRecord5 { - - - public AndroidCameraRecord8(RecorderParams parameters) { - super(parameters); - } - - @Override - protected void lowLevelSetPreviewCallback(Camera camera, PreviewCallback cb) { - if (cb != null) { - Log.d("Setting optimized callback with buffer (Android >= 8). Remember to manage the pool of buffers!!!"); - } - camera.setPreviewCallbackWithBuffer(cb); - } - - @Override - public void onPreviewStarted(Camera camera) { - super.onPreviewStarted(camera); - - Size s = camera.getParameters().getPreviewSize(); - int wishedBufferSize = s.height * s.width * 3 / 2; - - camera.addCallbackBuffer(new byte[wishedBufferSize]); - camera.addCallbackBuffer(new byte[wishedBufferSize]); - } - - @Override - public void onPreviewFrame(byte[] data, Camera camera) { - super.onPreviewFrame(data, camera); - camera.addCallbackBuffer(data); - } - - @Override - protected void onSettingCameraParameters(Parameters parameters) { - super.onSettingCameraParameters(parameters); - // Only on v8 hardware - camera.setDisplayOrientation(rotation); - } - - @Override - protected String selectFocusMode(final List supportedFocusModes) { - if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_EDOF)) { - return Camera.Parameters.FOCUS_MODE_EDOF; - } else - return super.selectFocusMode(supportedFocusModes); - } -} diff --git a/video/AndroidCameraRecord9.java b/video/AndroidCameraRecord9.java deleted file mode 100644 index f0023ef57..000000000 --- a/video/AndroidCameraRecord9.java +++ /dev/null @@ -1,50 +0,0 @@ -/* -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.video; - -import java.util.List; - -import android.hardware.Camera; - -/** - * - * Android >= 9 (2.3) version. - * @author Guillaume Beraudo - * - */ -class AndroidCameraRecord9 extends AndroidCameraRecord8 { - - - public AndroidCameraRecord9(RecorderParams parameters) { - super(parameters); - } - - @Override - protected Camera openCamera(int cameraId) { - return Camera.open(cameraId); - } - - @Override - protected String selectFocusMode(final List supportedFocusModes) { - if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { - return Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO; - } else - return super.selectFocusMode(supportedFocusModes); - } -} diff --git a/video/AndroidCameraRecordManager.java b/video/AndroidCameraRecordManager.java deleted file mode 100644 index 7e8e8b613..000000000 --- a/video/AndroidCameraRecordManager.java +++ /dev/null @@ -1,362 +0,0 @@ -/* -AndroidCameraRecordManager.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.video; - -import java.util.List; - -import org.linphone.core.LinphoneCore; -import org.linphone.core.Log; -import org.linphone.core.Version; -import org.linphone.core.VideoSize; -import org.linphone.core.video.AndroidCameraRecord.RecorderParams; - -import android.content.Context; -import android.view.OrientationEventListener; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.SurfaceHolder.Callback; - - - -/** - * Manage the video capture, only one for all cameras. - * - * @author Guillaume Beraudo - * - */ -public class AndroidCameraRecordManager { - private static AndroidCameraRecordManager instance; - private OrientationEventListener orientationEventListener; - private OnCapturingStateChangedListener capturingStateChangedListener; - - /** - * @return instance - */ - public static final synchronized AndroidCameraRecordManager getInstance() { - if (instance == null) { - instance = new AndroidCameraRecordManager(); - } - return instance; - } - - private AndroidCameraRecord.RecorderParams parameters; - private final AndroidCameraConf cc; - private SurfaceView surfaceView; - private boolean muted; - private int cameraId; - - private AndroidCameraRecord recorder; - private int mAlwaysChangingPhoneOrientation=0; - - - // singleton - private AndroidCameraRecordManager() { - if (!Version.isVideoCapable()) { // imply sdk>=5 - throw new RuntimeException("AndroidCameraRecordManager: hardware is not video capable"); - } - cc = Version.sdkAboveOrEqual(9) ? new AndroidCameraConf9() : new AndroidCameraConf5(); - Log.i("=== Detected " + cc.getFoundCameras()+ " ==="); - cameraId = cc.getFoundCameras().defaultC; - } - - - - - public boolean hasSeveralCameras() { - return cc.getFoundCameras().hasSeveralCameras(); - } - public boolean hasFrontCamera() { - return cc.getFoundCameras().front != null; - } - - - public void setUseFrontCamera(boolean value) { - if (!hasFrontCamera()) { - Log.e("setUseFrontCamera(true) while no front camera detected on device: using rear"); - value = false; - } - if (cc.isFrontCamera(cameraId) == value) return; // already OK - toggleUseFrontCamera(); - } - - public boolean isUseFrontCamera() {return cc.isFrontCamera(cameraId);} - public boolean toggleUseFrontCamera() { - boolean previousUseFront = cc.isFrontCamera(cameraId); - - cameraId = previousUseFront ? cc.getFoundCameras().rear : cc.getFoundCameras().front; - - if (parameters != null) { - parameters.cameraId = cameraId; - parameters.isFrontCamera = !previousUseFront; - if (isRecording()) { - stopVideoRecording(); - tryToStartVideoRecording(); - } - } - - return !previousUseFront; - } - - - - public void setParametersFromFilter(long filterDataPtr, int height, int width, float fps) { - if (recorder != null) { - Log.w("Recorder should not be running"); - stopVideoRecording(); - } - RecorderParams p = new RecorderParams(filterDataPtr); - p.fps = fps; - p.width = width; - p.height = height; - p.cameraId = cameraId; - p.isFrontCamera = isUseFrontCamera(); - parameters = p; - - // Mirror the sent frames in order to make them readable - // (otherwise it is mirrored and thus unreadable) - if (p.isFrontCamera) { - if (!isCameraMountedPortrait()) { - // Code for Nexus S - if (isFrameToBeShownPortrait()) - p.mirror = RecorderParams.MirrorType.CENTRAL; - } else { - // Code for Galaxy S like: camera mounted landscape when phone hold portrait - p.mirror = RecorderParams.MirrorType.HORIZONTAL; - } - } - - tryToStartVideoRecording(); - } - - - public final void setSurfaceView(final SurfaceView sv) { - SurfaceHolder holder = sv.getHolder(); - holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); - - holder.addCallback(new Callback() { - public void surfaceDestroyed(SurfaceHolder holder) { - surfaceView = null; - Log.d("Video capture surface destroyed"); - stopVideoRecording(); - } - - public void surfaceCreated(SurfaceHolder holder) { - surfaceView = sv; - Log.d("Video capture surface created"); - tryToStartVideoRecording(); - } - - public void surfaceChanged(SurfaceHolder holder, int format, int width, - int height) { - Log.d("Video capture surface changed"); - } - }); - } - - /** - * @param muteState - * @return true if mute state changed - */ - public boolean setMuted(boolean muteState) { - if (muteState == muted) return false; - muted = muteState; - if (muted) { - stopVideoRecording(); - } else { - tryToStartVideoRecording(); - } - return true; - } - public boolean toggleMute() { - setMuted(!muted); - return muted; - } - public boolean isMuted() { - return muted; - } - - public void tryResumingVideoRecording() { - if (isRecording()) return; - tryToStartVideoRecording(); - } - - private synchronized void tryToStartVideoRecording() { - if (orientationEventListener == null) { - throw new RuntimeException("startOrientationSensor was not called"); - } - - if (muted || surfaceView == null || parameters == null) return; - - if (recorder != null) { - Log.e("Recorder already present"); - stopVideoRecording(); - } - - parameters.rotation = bufferRotationToCompensateCameraAndPhoneOrientations(); - - parameters.surfaceView = surfaceView; - if (Version.sdkAboveOrEqual(9)) { - recorder = new AndroidCameraRecord9(parameters); - } else if (Version.sdkAboveOrEqual(8)) { - recorder = new AndroidCameraRecord8(parameters); - } else if (Version.sdkAboveOrEqual(5)) { - recorder = new AndroidCameraRecord5(parameters); - } else { - throw new RuntimeException("SDK version unsupported " + Version.sdk()); - } - - recorder.startPreview(); - - if (capturingStateChangedListener != null) { - capturingStateChangedListener.captureStarted(); - } - } - - public synchronized void stopVideoRecording() { - if (recorder != null) { - recorder.stopPreview(); - recorder = null; - if (capturingStateChangedListener != null) { - capturingStateChangedListener.captureStopped(); - } - } - } - - - - public List supportedVideoSizes() { - Log.d("Using supportedVideoSizes of camera ",cameraId); - return cc.getSupportedPreviewSizes(cameraId); - } - - - public boolean isRecording() { - if (recorder != null) { - return recorder.isStarted(); - } - - return false; - } - - - public void invalidateParameters() { - stopVideoRecording(); - parameters = null; - } - - /** Depends on currently selected camera, camera mounted portrait/landscape, current phone orientation */ - public boolean isFrameToBeShownPortrait() { - final int rotation = bufferRotationToCompensateCameraAndPhoneOrientations(); - - boolean isPortrait; - if (isCameraMountedPortrait()) { - // Nexus S - isPortrait = (rotation % 180) == 0; - } else { - isPortrait = (rotation % 180) == 90; - } - - Log.d("The frame to be shown and sent to remote is ", isPortrait? "portrait":"landscape"," orientation."); - return isPortrait; - } - - - - - - - public boolean isCameraMountedPortrait() { - return (cc.getCameraOrientation(cameraId) % 180) == 0; - } - - - - private int bufferRotationToCompensateCameraAndPhoneOrientations() { - if (Version.sdkStrictlyBelow(Version.API08_FROYO_22)) { - // Don't perform any rotation - // Phone screen should use fitting orientation - return 0; - } - - final int phoneOrientation = mAlwaysChangingPhoneOrientation; - final int cameraOrientation = cc.getCameraOrientation(cameraId); - int frontCameraCorrection = 0; - if (cc.isFrontCamera(cameraId)) { - frontCameraCorrection=180; // hack that "just works" on Galaxy S and Nexus S. - // See also magic with mirrors in setParametersFromFilter - } - final int rotation = (cameraOrientation + phoneOrientation + frontCameraCorrection) % 360; - Log.d("Capture video buffer of cameraId=",cameraId, - " will need a rotation of ",rotation, - " degrees: camera_orientation=",cameraOrientation, - " phone_orientation=", phoneOrientation); - return rotation; - } - - - /** - * Register a sensor to track phoneOrientation changes - */ - public void startOrientationSensor(Context c) { - if (orientationEventListener == null) { - orientationEventListener = new LocalOrientationEventListener(c); - orientationEventListener.enable(); - } - } - - private class LocalOrientationEventListener extends OrientationEventListener { - public LocalOrientationEventListener(Context context) { - super(context); - } - @Override - public void onOrientationChanged(final int o) { - if (o == OrientationEventListener.ORIENTATION_UNKNOWN) return; - - int degrees=270; - if (o < 45 || o >315) degrees=0; - else if (o<135) degrees=90; - else if (o<225) degrees=180; - - if (mAlwaysChangingPhoneOrientation == degrees) return; - - Log.i("Phone orientation changed to ", degrees); - mAlwaysChangingPhoneOrientation = degrees; - } - } - - /** - * @return true if linphone core configured to send a A buffer while phone orientation induces !A buffer (A=landscape or portrait) - */ - public boolean isOutputOrientationMismatch(LinphoneCore lc) { - final boolean currentlyPortrait = lc.getPreferredVideoSize().isPortrait(); - final boolean shouldBePortrait = isFrameToBeShownPortrait(); - return currentlyPortrait ^ shouldBePortrait; - } - - public void setOnCapturingStateChanged(OnCapturingStateChangedListener listener) { - this.capturingStateChangedListener=listener; - } - - public static interface OnCapturingStateChangedListener { - void captureStarted(); - void captureStopped(); - } - - -}