diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 77a1c1e62..1a97c69a5 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,6 +20,13 @@
+
+
+
+
+
+
@@ -60,7 +67,11 @@
-
+
+
+
+
+
@@ -103,5 +114,8 @@
+
+
+
diff --git a/res/layout/videotest.xml b/res/layout/videotest.xml
new file mode 100644
index 000000000..eafbbde1b
--- /dev/null
+++ b/res/layout/videotest.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/linphone/core/AndroidCameraRecord.java b/src/org/linphone/core/AndroidCameraRecord.java
new file mode 100644
index 000000000..ae07c6d56
--- /dev/null
+++ b/src/org/linphone/core/AndroidCameraRecord.java
@@ -0,0 +1,127 @@
+/*
+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;
+
+import android.hardware.Camera;
+import android.hardware.Camera.PreviewCallback;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+
+public abstract class AndroidCameraRecord implements SurfaceHolder.Callback {
+
+ protected Camera camera;
+ private static SurfaceView surfaceView; // should be initialized first...
+ protected int rate;
+ private int visibility = SurfaceView.GONE; // Automatically hidden
+ private boolean visibilityChangeable = false;
+
+ protected final SurfaceView getSurfaceView() {
+ return surfaceView;
+ }
+
+ /**
+ * AndroidCameraRecord.setSurfaceView() should be called first.
+ * @param rate
+ */
+ public AndroidCameraRecord(int rate) {
+ camera=Camera.open();
+ SurfaceHolder holder = surfaceView.getHolder();
+ holder.addCallback(this);
+
+ this.rate = rate;
+ }
+
+
+ /**
+ * AndroidCameraRecord.setSurfaceView() should be called first.
+ * @param rate
+ * @param visilibity
+ */
+ public AndroidCameraRecord(int rate, int visilibity) {
+ this(rate);
+ this.visibility = visilibity;
+ }
+
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ try {
+ camera.setPreviewDisplay(holder);
+ }
+ catch (Throwable t) {
+ Log.e("PictureDemo-surfaceCallback", "Exception in setPreviewDisplay()", t);
+ }
+
+
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ Camera.Parameters parameters=camera.getParameters();
+
+ parameters.setPreviewSize(width, height);
+ parameters.setPreviewFrameRate(rate);
+ camera.setParameters(parameters);
+
+ camera.startPreview();
+
+ visibilityChangeable = true;
+ if (surfaceView.getVisibility() != visibility) {
+ updateVisibility();
+ }
+
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ camera.stopPreview();
+ camera.release();
+ camera=null;
+ }
+
+ public void setPreviewCallBack(PreviewCallback cb) {
+ camera.setPreviewCallback(cb);
+ }
+
+ private void updateVisibility() {
+ if (!visibilityChangeable) {
+ throw new IllegalStateException("Visilibity not changeable now");
+ }
+
+ surfaceView.setVisibility(visibility);
+ }
+
+ public void setVisibility(int visibility) {
+ if (visibility == this.visibility) return;
+
+ this.visibility = visibility;
+ updateVisibility();
+ }
+
+ public static final void setSurfaceView(SurfaceView sv) {
+ AndroidCameraRecord.surfaceView = sv;
+ }
+
+
+ /**
+ * Hook to add back a buffer for reuse in capture.
+ * Override in a version supporting addPreviewCallBackWithBuffer()
+ * @param buffer buffer to reuse
+ */
+ public void addBackCaptureBuffer(byte[] buffer) {}
+}
diff --git a/src/org/linphone/core/AndroidCameraRecordImpl.java b/src/org/linphone/core/AndroidCameraRecordImpl.java
new file mode 100644
index 000000000..c9173d1da
--- /dev/null
+++ b/src/org/linphone/core/AndroidCameraRecordImpl.java
@@ -0,0 +1,49 @@
+/*
+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;
+
+import android.hardware.Camera;
+import android.hardware.Camera.PreviewCallback;
+import android.util.Log;
+
+/**
+ * Record from Android camera.
+ *
+ * @author Guillaume Beraudo
+ *
+ */
+public class AndroidCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
+
+ private long filterCtxPtr;
+
+ public AndroidCameraRecordImpl(long filterCtxPtr, int rate) {
+ super(rate);
+ this.filterCtxPtr = filterCtxPtr;
+ setPreviewCallBack(this);
+ }
+
+
+ private native void putImage(long filterCtxPtr, byte[] buffer);
+
+ public void onPreviewFrame(byte[] data, Camera camera) {
+ Log.d("onPreviewFrame: ", Integer.toString(data.length));
+ putImage(filterCtxPtr, data);
+ }
+
+}
diff --git a/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java b/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java
new file mode 100644
index 000000000..45499db78
--- /dev/null
+++ b/src/org/linphone/core/tutorials/JavaCameraRecordImpl.java
@@ -0,0 +1,69 @@
+/*
+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.AndroidCameraRecord;
+
+import android.hardware.Camera;
+import android.hardware.Camera.PreviewCallback;
+import android.util.Log;
+import android.widget.TextView;
+
+public class JavaCameraRecordImpl extends AndroidCameraRecord implements PreviewCallback {
+
+ private TextView debug;
+ private long count = 0;
+ private float averageCalledRate;
+ private int averageWindowSize = 2 * rate;
+
+ private long startTime;
+ private long endTime;
+
+
+ public JavaCameraRecordImpl(int rate) {
+ super(rate);
+ setPreviewCallBack(this);
+ }
+
+ public JavaCameraRecordImpl(int rate, int visilibity) {
+ super(rate, visilibity);
+ setPreviewCallBack(this);
+ }
+
+ public void setDebug(TextView debug) {
+ this.debug = debug;
+ }
+
+ public void onPreviewFrame(byte[] data, Camera camera) {
+
+ if ((count % averageWindowSize) == 0) {
+ endTime = System.currentTimeMillis();
+ averageCalledRate = (100000 * averageWindowSize) / (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);
+ }
+
+}
diff --git a/src/org/linphone/core/tutorials/TestVideoActivity.java b/src/org/linphone/core/tutorials/TestVideoActivity.java
new file mode 100644
index 000000000..6526e1cce
--- /dev/null
+++ b/src/org/linphone/core/tutorials/TestVideoActivity.java
@@ -0,0 +1,70 @@
+/*
+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 org.linphone.R;
+import org.linphone.core.AndroidCameraRecord;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.widget.TextView;
+
+/**
+ * Activity for displaying and starting the HelloWorld example on Android phone.
+ *
+ * @author Guillaume Beraudo
+ *
+ */
+public class TestVideoActivity extends Activity {
+
+ private SurfaceView surfaceView;
+ private static final int rate = 15;
+
+
+
+
+
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.videotest);
+
+ surfaceView=(SurfaceView)findViewById(R.id.videotest_surfaceView);
+
+ SurfaceHolder holder=surfaceView.getHolder();
+ holder.setFixedSize(320, 240);
+ holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+
+ AndroidCameraRecord.setSurfaceView(surfaceView);
+
+ JavaCameraRecordImpl manager = new JavaCameraRecordImpl(rate, SurfaceView.VISIBLE);
+ manager.setDebug((TextView) findViewById(R.id.videotest_debug));
+
+ }
+
+
+
+
+
+
+}