From 2a4634c8e713cf6a781136f7bc3059db3104de97 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Mon, 23 Mar 2015 06:28:40 +0000 Subject: Re #1822: Moved Android camera helper (PjCamera.java and PjCameraInfo.java) from sample app to pjmedia-video dev dir. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5018 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/src/pjmedia-videodev/android/PjCamera.java | 210 +++++++++++++++++++++ .../src/pjmedia-videodev/android/PjCameraInfo.java | 110 +++++++++++ pjsip-apps/src/pjsua/android/jni/Android.mk | 7 +- .../src/pjsua/android/src/org/pjsip/PjCamera.java | 192 ------------------- .../pjsua/android/src/org/pjsip/PjCameraInfo.java | 92 --------- pjsip-apps/src/swig/java/Makefile | 4 + 6 files changed, 330 insertions(+), 285 deletions(-) create mode 100644 pjmedia/src/pjmedia-videodev/android/PjCamera.java create mode 100644 pjmedia/src/pjmedia-videodev/android/PjCameraInfo.java delete mode 100644 pjsip-apps/src/pjsua/android/src/org/pjsip/PjCamera.java delete mode 100644 pjsip-apps/src/pjsua/android/src/org/pjsip/PjCameraInfo.java diff --git a/pjmedia/src/pjmedia-videodev/android/PjCamera.java b/pjmedia/src/pjmedia-videodev/android/PjCamera.java new file mode 100644 index 00000000..a192a9b3 --- /dev/null +++ b/pjmedia/src/pjmedia-videodev/android/PjCamera.java @@ -0,0 +1,210 @@ +/* $Id$ */ +/* + * Copyright (C) 2015 Teluu Inc. (http://www.teluu.com) + * + * 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.pjsip; + +import android.graphics.SurfaceTexture; +import android.hardware.Camera; +import android.util.Log; +import android.view.SurfaceView; +import android.view.SurfaceHolder; + +import java.io.IOException; + +public class PjCamera implements Camera.PreviewCallback, SurfaceHolder.Callback +{ + private final String TAG = "PjCamera"; + + public class Param { + public int width; + public int height; + public int format; + public int fps1000; + } + + private Camera camera = null; + private boolean isRunning = false; + private int camIdx; + private long userData; + + private Param param = null; + + private SurfaceView surfaceView = null; + private SurfaceHolder surfaceHolder = null; + private SurfaceTexture surfaceTexture = null; + + public PjCamera(int idx, int w, int h, int fmt, int fps, + long userData_, SurfaceView surface) + { + camIdx = idx; + userData = userData_; + + param = new Param(); + param.width = w; + param.height = h; + param.format = fmt; + param.fps1000 = fps; + + SetSurfaceView(surface); + } + + public void SetSurfaceView(SurfaceView surface) + { + boolean isCaptureRunning = isRunning; + + if (isCaptureRunning) + Stop(); + + if (surface != null) { + surfaceView = surface; + surfaceHolder = surfaceView.getHolder(); + } else { + // Create dummy texture + surfaceHolder = null; + surfaceView = null; + if (surfaceTexture == null) { + surfaceTexture = new SurfaceTexture(10); + } + } + + if (isCaptureRunning) + Start(); + } + + public int SwitchDevice(int idx) + { + boolean isCaptureRunning = isRunning; + int oldIdx = camIdx; + + if (isCaptureRunning) + Stop(); + + camIdx = idx; + + if (isCaptureRunning) { + int ret = Start(); + if (ret != 0) { + /* Try to revert back */ + camIdx = oldIdx; + Start(); + return ret; + } + } + + return 0; + } + + public int Start() + { + try { + camera = Camera.open(camIdx); + } catch (Exception e) { + Log.d("IOException", e.getMessage()); + return -10; + } + + try { + if (surfaceHolder != null) { + camera.setPreviewDisplay(surfaceHolder); + surfaceHolder.addCallback(this); + } else { + camera.setPreviewTexture(surfaceTexture); + } + } catch (IOException e) { + Log.d("IOException", e.getMessage()); + return -20; + } + + Camera.Parameters cp = camera.getParameters(); + cp.setPreviewSize(param.width, param.height); + cp.setPreviewFormat(param.format); + // Some devices such as Nexus require an exact FPS range from the + // supported FPS ranges, specifying a subset range will raise + // exception. + //cp.setPreviewFpsRange(param.fps1000, param.fps1000); + try { + camera.setParameters(cp); + } catch (RuntimeException e) { + Log.d("RuntimeException", e.getMessage()); + return -30; + } + + camera.setPreviewCallback(this); + camera.startPreview(); + isRunning = true; + + return 0; + } + + public void Stop() + { + isRunning = false; + if (camera == null) + return; + + if (surfaceHolder != null) + surfaceHolder.removeCallback(this); + + camera.setPreviewCallback(null); + camera.stopPreview(); + camera.release(); + camera = null; + } + + native void PushFrame(byte[] data, int length, long userData_); + + public void onPreviewFrame(byte[] data, Camera camera) + { + if (isRunning) { + PushFrame(data, data.length, userData); + } + } + + public void surfaceChanged(SurfaceHolder holder, + int format, int width, int height) + { + Log.d(TAG, "VideoCaptureAndroid::surfaceChanged"); + } + + public void surfaceCreated(SurfaceHolder holder) + { + Log.d(TAG, "VideoCaptureAndroid::surfaceCreated"); + try { + if(camera != null) { + camera.setPreviewDisplay(holder); + } + } catch (IOException e) { + Log.e(TAG, "Failed to set preview surface!", e); + } + } + + public void surfaceDestroyed(SurfaceHolder holder) + { + Log.d(TAG, "VideoCaptureAndroid::surfaceDestroyed"); + try { + if(camera != null) { + camera.setPreviewDisplay(null); + } + } catch (IOException e) { + Log.e(TAG, "Failed to clear preview surface!", e); + } catch (RuntimeException e) { + Log.w(TAG, "Clear preview surface useless", e); + } + } + +} diff --git a/pjmedia/src/pjmedia-videodev/android/PjCameraInfo.java b/pjmedia/src/pjmedia-videodev/android/PjCameraInfo.java new file mode 100644 index 00000000..d1c71939 --- /dev/null +++ b/pjmedia/src/pjmedia-videodev/android/PjCameraInfo.java @@ -0,0 +1,110 @@ +/* $Id$ */ +/* + * Copyright (C) 2015 Teluu Inc. (http://www.teluu.com) + * + * 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.pjsip; + +import java.util.List; + +import android.hardware.Camera; +import android.util.Log; + +public class PjCameraInfo { + public int facing; + public int orient; + public int[] supportedSize; // [w1, h1, w2, h2, ...] + public int[] supportedFps1000; // [min1, max1, min2, max2, ...] + public int[] supportedFormat; // [fmt1, fmt2, ...] + + // convert Format list {fmt1, fmt2, ...} to [fmt1, fmt2, ...] + private static int[] IntegerListToIntArray(List list) + { + int[] li = new int[list.size()]; + int i = 0; + for (Integer e : list) { + li[i++] = e.intValue(); + } + return li; + } + + // convert Fps list {[min1, max1], [min2, max2], ...} to + // [min1, max1, min2, max2, ...] + private static int[] IntArrayListToIntArray(List list) + { + int[] li = new int[list.size() * 2]; + int i = 0; + for (int[] e : list) { + li[i++] = e[0]; + li[i++] = e[1]; + } + return li; + } + + // convert Size list {{w1, h1}, {w2, h2}, ...} to [w1, h1, w2, h2, ...] + private static int[] CameraSizeListToIntArray(List list) + { + int[] li = new int[list.size() * 2]; + int i = 0; + for (Camera.Size e : list) { + li[i++] = e.width; + li[i++] = e.height; + } + return li; + } + + public static int GetCameraCount() + { + return Camera.getNumberOfCameras(); + } + + // Get camera info: facing, orientation, supported size/fps/format. + // Camera must not be opened. + public static PjCameraInfo GetCameraInfo(int idx) + { + if (idx < 0 || idx >= GetCameraCount()) + return null; + + Camera cam; + try { + cam = Camera.open(idx); + } catch (Exception e) { + Log.d("IOException", e.getMessage()); + return null; + } + + PjCameraInfo pjci = new PjCameraInfo(); + + Camera.CameraInfo ci = new Camera.CameraInfo(); + Camera.getCameraInfo(idx, ci); + + pjci.facing = ci.facing; + pjci.orient = ci.orientation; + + Camera.Parameters param = cam.getParameters(); + cam.release(); + cam = null; + + pjci.supportedFormat = IntegerListToIntArray( + param.getSupportedPreviewFormats()); + pjci.supportedFps1000 = IntArrayListToIntArray( + param.getSupportedPreviewFpsRange()); + pjci.supportedSize = CameraSizeListToIntArray( + param.getSupportedPreviewSizes()); + + return pjci; + } +} diff --git a/pjsip-apps/src/pjsua/android/jni/Android.mk b/pjsip-apps/src/pjsua/android/jni/Android.mk index b1f99af6..826da8d3 100644 --- a/pjsip-apps/src/pjsua/android/jni/Android.mk +++ b/pjsip-apps/src/pjsua/android/jni/Android.mk @@ -28,8 +28,13 @@ LOCAL_LDFLAGS := $(APP_LDFLAGS) LOCAL_LDLIBS := $(MY_MODULES) $(APP_LDLIBS) LOCAL_SRC_FILES := $(MY_JNI_WRAP) pjsua_app_callback.cpp +# Copy Java Camera helper components from pjmedia/src/pjmedia-videodev/android +src/org/pjsip/PjCamera.java: + @echo "Copying Android camera helper components..." + cp -u $(PJDIR)/pjmedia/src/pjmedia-videodev/android/PjCamera*.java src/org/pjsip + # Invoke SWIG -$(MY_JNI_DIR)/$(MY_JNI_WRAP): +$(MY_JNI_DIR)/$(MY_JNI_WRAP): src/org/pjsip/PjCamera.java @echo "Invoking SWIG..." $(MY_SWIG) -c++ -o $(MY_JNI_DIR)/$(MY_JNI_WRAP) -package org.pjsip.pjsua -outdir src/org/pjsip/pjsua -java $(MY_JNI_DIR)/pjsua.i diff --git a/pjsip-apps/src/pjsua/android/src/org/pjsip/PjCamera.java b/pjsip-apps/src/pjsua/android/src/org/pjsip/PjCamera.java deleted file mode 100644 index 1beffa49..00000000 --- a/pjsip-apps/src/pjsua/android/src/org/pjsip/PjCamera.java +++ /dev/null @@ -1,192 +0,0 @@ -package org.pjsip; - -import android.graphics.SurfaceTexture; -import android.hardware.Camera; -import android.util.Log; -import android.view.SurfaceView; -import android.view.SurfaceHolder; - -import java.io.IOException; - -public class PjCamera implements Camera.PreviewCallback, SurfaceHolder.Callback -{ - private final String TAG = "PjCamera"; - - public class Param { - public int width; - public int height; - public int format; - public int fps1000; - } - - private Camera camera = null; - private boolean isRunning = false; - private int camIdx; - private long userData; - - private Param param = null; - - private SurfaceView surfaceView = null; - private SurfaceHolder surfaceHolder = null; - private SurfaceTexture surfaceTexture = null; - - public PjCamera(int idx, int w, int h, int fmt, int fps, - long userData_, SurfaceView surface) - { - camIdx = idx; - userData = userData_; - - param = new Param(); - param.width = w; - param.height = h; - param.format = fmt; - param.fps1000 = fps; - - SetSurfaceView(surface); - } - - public void SetSurfaceView(SurfaceView surface) - { - boolean isCaptureRunning = isRunning; - - if (isCaptureRunning) - Stop(); - - if (surface != null) { - surfaceView = surface; - surfaceHolder = surfaceView.getHolder(); - } else { - // Create dummy texture - surfaceHolder = null; - surfaceView = null; - if (surfaceTexture == null) { - surfaceTexture = new SurfaceTexture(10); - } - } - - if (isCaptureRunning) - Start(); - } - - public int SwitchDevice(int idx) - { - boolean isCaptureRunning = isRunning; - int oldIdx = camIdx; - - if (isCaptureRunning) - Stop(); - - camIdx = idx; - - if (isCaptureRunning) { - int ret = Start(); - if (ret != 0) { - /* Try to revert back */ - camIdx = oldIdx; - Start(); - return ret; - } - } - - return 0; - } - - public int Start() - { - try { - camera = Camera.open(camIdx); - } catch (Exception e) { - Log.d("IOException", e.getMessage()); - return -10; - } - - try { - if (surfaceHolder != null) { - camera.setPreviewDisplay(surfaceHolder); - surfaceHolder.addCallback(this); - } else { - camera.setPreviewTexture(surfaceTexture); - } - } catch (IOException e) { - Log.d("IOException", e.getMessage()); - return -20; - } - - Camera.Parameters cp = camera.getParameters(); - cp.setPreviewSize(param.width, param.height); - cp.setPreviewFormat(param.format); - // Some devices such as Nexus require an exact FPS range from the - // supported FPS ranges, specifying a subset range will raise - // exception. - //cp.setPreviewFpsRange(param.fps1000, param.fps1000); - try { - camera.setParameters(cp); - } catch (RuntimeException e) { - Log.d("RuntimeException", e.getMessage()); - return -30; - } - - camera.setPreviewCallback(this); - camera.startPreview(); - isRunning = true; - - return 0; - } - - public void Stop() - { - isRunning = false; - if (camera == null) - return; - - if (surfaceHolder != null) - surfaceHolder.removeCallback(this); - - camera.setPreviewCallback(null); - camera.stopPreview(); - camera.release(); - camera = null; - } - - native void PushFrame(byte[] data, int length, long userData_); - - public void onPreviewFrame(byte[] data, Camera camera) - { - if (isRunning) { - PushFrame(data, data.length, userData); - } - } - - public void surfaceChanged(SurfaceHolder holder, - int format, int width, int height) - { - Log.d(TAG, "VideoCaptureAndroid::surfaceChanged"); - } - - public void surfaceCreated(SurfaceHolder holder) - { - Log.d(TAG, "VideoCaptureAndroid::surfaceCreated"); - try { - if(camera != null) { - camera.setPreviewDisplay(holder); - } - } catch (IOException e) { - Log.e(TAG, "Failed to set preview surface!", e); - } - } - - public void surfaceDestroyed(SurfaceHolder holder) - { - Log.d(TAG, "VideoCaptureAndroid::surfaceDestroyed"); - try { - if(camera != null) { - camera.setPreviewDisplay(null); - } - } catch (IOException e) { - Log.e(TAG, "Failed to clear preview surface!", e); - } catch (RuntimeException e) { - Log.w(TAG, "Clear preview surface useless", e); - } - } - -} diff --git a/pjsip-apps/src/pjsua/android/src/org/pjsip/PjCameraInfo.java b/pjsip-apps/src/pjsua/android/src/org/pjsip/PjCameraInfo.java deleted file mode 100644 index 2f4e9cf5..00000000 --- a/pjsip-apps/src/pjsua/android/src/org/pjsip/PjCameraInfo.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.pjsip; - -import java.util.List; - -import android.hardware.Camera; -import android.util.Log; - -public class PjCameraInfo { - public int facing; - public int orient; - public int[] supportedSize; // [w1, h1, w2, h2, ...] - public int[] supportedFps1000; // [min1, max1, min2, max2, ...] - public int[] supportedFormat; // [fmt1, fmt2, ...] - - // convert Format list {fmt1, fmt2, ...} to [fmt1, fmt2, ...] - private static int[] IntegerListToIntArray(List list) - { - int[] li = new int[list.size()]; - int i = 0; - for (Integer e : list) { - li[i++] = e.intValue(); - } - return li; - } - - // convert Fps list {[min1, max1], [min2, max2], ...} to - // [min1, max1, min2, max2, ...] - private static int[] IntArrayListToIntArray(List list) - { - int[] li = new int[list.size() * 2]; - int i = 0; - for (int[] e : list) { - li[i++] = e[0]; - li[i++] = e[1]; - } - return li; - } - - // convert Size list {{w1, h1}, {w2, h2}, ...} to [w1, h1, w2, h2, ...] - private static int[] CameraSizeListToIntArray(List list) - { - int[] li = new int[list.size() * 2]; - int i = 0; - for (Camera.Size e : list) { - li[i++] = e.width; - li[i++] = e.height; - } - return li; - } - - public static int GetCameraCount() - { - return Camera.getNumberOfCameras(); - } - - // Get camera info: facing, orientation, supported size/fps/format. - // Camera must not be opened. - public static PjCameraInfo GetCameraInfo(int idx) - { - if (idx < 0 || idx >= GetCameraCount()) - return null; - - Camera cam; - try { - cam = Camera.open(idx); - } catch (Exception e) { - Log.d("IOException", e.getMessage()); - return null; - } - - PjCameraInfo pjci = new PjCameraInfo(); - - Camera.CameraInfo ci = new Camera.CameraInfo(); - Camera.getCameraInfo(idx, ci); - - pjci.facing = ci.facing; - pjci.orient = ci.orientation; - - Camera.Parameters param = cam.getParameters(); - cam.release(); - cam = null; - - pjci.supportedFormat = IntegerListToIntArray( - param.getSupportedPreviewFormats()); - pjci.supportedFps1000 = IntArrayListToIntArray( - param.getSupportedPreviewFpsRange()); - pjci.supportedSize = CameraSizeListToIntArray( - param.getSupportedPreviewSizes()); - - return pjci; - } -} diff --git a/pjsip-apps/src/swig/java/Makefile b/pjsip-apps/src/swig/java/Makefile index f24bdddd..19da66dc 100644 --- a/pjsip-apps/src/swig/java/Makefile +++ b/pjsip-apps/src/swig/java/Makefile @@ -176,6 +176,10 @@ clean distclean realclean: $(MY_PACKAGE_PATH)/*.java $(MY_PACKAGE_PATH)/*.class java: $(MY_PACKAGE_PATH)/Error.class $(MY_PACKAGE_PATH)/test.class $(MY_PACKAGE_PATH)/sample.class +ifeq ($(OS),android) + @echo "Copying Android camera helper components..." + cp -u $(PJDIR)/pjmedia/src/pjmedia-videodev/android/PjCamera*.java $(MY_PACKAGE_PATH)/.. +endif $(MY_PACKAGE_PATH)/Error.class: $(MY_PACKAGE_PATH)/Error.java $(MY_JAVAC) -d $(OUT_DIR) $(MY_PACKAGE_PATH)/*.java $(MY_APP_JAVA) -- cgit v1.2.3