From 7f43de8dc9298bc3899e869311bda29ec059c82a Mon Sep 17 00:00:00 2001 From: "leozwang@google.com" Date: Tue, 7 Jun 2011 17:58:15 +0000 Subject: [PATCH] refactor java code Review URL: http://webrtc-codereview.appspot.com/29011 git-svn-id: http://webrtc.googlecode.com/svn/trunk@55 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../videoengine/CaptureCapabilityAndroid.java | 24 +- .../videoengine/VideoCaptureAndroid.java | 528 ++++++----- .../VideoCaptureDeviceInfoAndroid.java | 878 +++++++++--------- 3 files changed, 711 insertions(+), 719 deletions(-) diff --git a/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/CaptureCapabilityAndroid.java b/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/CaptureCapabilityAndroid.java index 464a5ff2ec..0443953677 100644 --- a/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/CaptureCapabilityAndroid.java +++ b/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/CaptureCapabilityAndroid.java @@ -1,7 +1,17 @@ -package org.webrtc.videoengine; - -public class CaptureCapabilityAndroid { - public int width = 0; - public int height = 0; - public int maxFPS = 0; -} +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +package org.webrtc.videoengine; + +public class CaptureCapabilityAndroid { + public int width = 0; + public int height = 0; + public int maxFPS = 0; +} diff --git a/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/VideoCaptureAndroid.java b/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/VideoCaptureAndroid.java index 969b980c6a..a4c39a8c26 100644 --- a/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/VideoCaptureAndroid.java +++ b/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/VideoCaptureAndroid.java @@ -1,266 +1,262 @@ -/** - * - */ -package org.webrtc.videoengine; -import java.io.IOException; -import java.util.Locale; -import java.util.concurrent.locks.ReentrantLock; - -import org.webrtc.videoengine.CaptureCapabilityAndroid; -import org.webrtc.videoengine.VideoCaptureDeviceInfoAndroid.AndroidVideoCaptureDevice; - -import android.graphics.ImageFormat; -import android.graphics.PixelFormat; -import android.hardware.Camera; -import android.hardware.Camera.PreviewCallback; -import android.util.Log; -import android.view.SurfaceHolder; -import android.view.SurfaceHolder.Callback; - - -public class VideoCaptureAndroid implements - PreviewCallback, Callback{ - - private Camera _camera; - private AndroidVideoCaptureDevice _currentDevice=null; - public ReentrantLock _previewBufferLock = new ReentrantLock(); - private int PIXEL_FORMAT = ImageFormat.NV21; - PixelFormat _pixelFormat = new PixelFormat(); - private boolean _isRunning=false; // True when the C++ layer has ordered the camera to be started. - - private final int _numCaptureBuffers = 3; - private int _expectedFrameSize = 0; - private int _orientation = 0; - private int _id=0; - private long _context=0; // C++ callback context variable. - private SurfaceHolder _localPreview=null; - private boolean _ownsBuffers=false; // True if this class owns the preview video buffers. - - - //Logging - private static int LOGLEVEL = 0; // Set this to 2 for VERBOSE logging. 1 for DEBUG - private static boolean VERBOSE = LOGLEVEL > 2; - private static boolean DEBUG = LOGLEVEL > 1; - - - CaptureCapabilityAndroid _currentCapability=null; - - public static void DeleteVideoCaptureAndroid(VideoCaptureAndroid captureAndroid) - { - if(DEBUG) Log.d("*WEBRTC*", "DeleteVideoCaptureAndroid"); - - captureAndroid.StopCapture(); - captureAndroid._camera.release(); - captureAndroid._camera=null; - captureAndroid._context=0; - - if(DEBUG) Log.v("*WEBRTC*", "DeleteVideoCaptureAndroid ended"); - - } - - public VideoCaptureAndroid(int id, long context,Camera camera,AndroidVideoCaptureDevice device) - { - _id=id; - _context=context; - _camera=camera; - _currentDevice=device; - } - - public int StartCapture(int width, int height, int frameRate) - { - if(DEBUG) Log.d("*WEBRTC*", "StartCapture width" + width + " height " + height +" frame rate " + frameRate); - try - { - if (_camera == null) - { - Log.e("*WEBRTC*",String.format(Locale.US,"Camera not initialized %d",_id)); - return -1; - } - _currentCapability=new CaptureCapabilityAndroid(); - _currentCapability.width=width; - _currentCapability.height=height; - _currentCapability.maxFPS=frameRate; - PixelFormat.getPixelFormatInfo(PIXEL_FORMAT, _pixelFormat); - - Camera.Parameters parameters = _camera.getParameters(); - parameters.setPreviewSize(_currentCapability.width, _currentCapability.height); - parameters.setPreviewFormat(PIXEL_FORMAT ); - parameters.setPreviewFrameRate(_currentCapability.maxFPS); - _camera.setParameters(parameters); - - _localPreview=ViERenderer.GetLocalRenderer(); // Get the local preview SurfaceHolder from the static render class - if(_localPreview!=null) - { - _localPreview.addCallback(this); - } - - - - int bufSize = width * height * _pixelFormat.bitsPerPixel / 8; - if(android.os.Build.VERSION.SDK_INT>=7) - { - //According to Doc addCallbackBuffer belongs to API level 8. But it seems like it works on Android 2.1 as well. - //At least SE X10 and Milestone - byte[] buffer = null; - for (int i = 0; i < _numCaptureBuffers; i++) - { - buffer = new byte[bufSize]; - _camera.addCallbackBuffer(buffer); - } - - _camera.setPreviewCallbackWithBuffer(this); - _ownsBuffers=true; - } - else - { - _camera.setPreviewCallback(this); - } - - _camera.startPreview(); - _previewBufferLock.lock(); - _expectedFrameSize = bufSize; - _isRunning=true; - _previewBufferLock.unlock(); - - } - catch (Exception ex) { - Log.e("*WEBRTC*", "Failed to start camera"); - return -1; - } - return 0; - } - - public int StopCapture() - { - if(DEBUG) Log.d("*WEBRTC*", "StopCapture"); - try - { - _previewBufferLock.lock(); - _isRunning=false; - _previewBufferLock.unlock(); - - _camera.stopPreview(); - - if(android.os.Build.VERSION.SDK_INT>7) - { - _camera.setPreviewCallbackWithBuffer(null); - } - else - { - _camera.setPreviewCallback(null); - } - } catch (Exception ex) { - Log.e("*WEBRTC*", "Failed to stop camera"); - return -1; - } - - if(DEBUG) Log.d("*WEBRTC*", "StopCapture ended"); - return 0; - } - - native void ProvideCameraFrame(byte[] data,int length, long captureObject); - - public void onPreviewFrame(byte[] data, Camera camera) { - _previewBufferLock.lock(); - - if(VERBOSE) Log.v("*WEBRTC*",String.format(Locale.US,"preview frame length %d context %x",data.length,_context)); - if(_isRunning) - { - // If StartCapture has been called but not StopCapture - // Call the C++ layer with the captured frame - if (data.length == _expectedFrameSize) - { - ProvideCameraFrame(data, _expectedFrameSize, _context); - if (VERBOSE) Log.v("*WEBRTC*", String.format(Locale.US, "frame delivered")); - if(_ownsBuffers) - { - // Give the video buffer to the camera service again. - _camera.addCallbackBuffer(data); - } - } - } - _previewBufferLock.unlock(); - - } - - - public void surfaceChanged(SurfaceHolder holder, int format, int width, - int height) { - - try { - if(_camera!=null) - { - _camera.setPreviewDisplay(_localPreview); - } - } catch (IOException e) { - Log.e("*WEBRTC*", String.format(Locale.US, "Failed to set Local preview. "+ e.getMessage())); - } - } - /* - * Sets the rotation of the preview render window. - * Does not affect the captured video image. - */ - public void SetPreviewRotation(int rotation) - { - if(_camera!=null) - { - _previewBufferLock.lock(); - final boolean running=_isRunning; - int width=0; - int height=0; - int framerate=0; - - if(running) - { - width=_currentCapability.width; - height=_currentCapability.height; - framerate=_currentCapability.maxFPS; - - StopCapture(); - - } - - - int resultRotation=0; - if(_currentDevice._frontCameraType==VideoCaptureDeviceInfoAndroid.FrontFacingCameraType.Android23) - { - // this is a 2.3 or later front facing camera. SetDisplayOrientation will flip the image horizontally before doing the rotation. - resultRotation=(360-rotation) % 360; // compensate the mirror - } - else - { // Back facing or 2.2 or previous front camera - resultRotation=rotation; - } - if(android.os.Build.VERSION.SDK_INT>7) - { - _camera.setDisplayOrientation(resultRotation); - } - else // Android 2.1 and previous - { - // This rotation unfortunately does not seems to work. - //http://code.google.com/p/android/issues/detail?id=1193 - Camera.Parameters parameters = _camera.getParameters(); - parameters.setRotation(resultRotation); - _camera.setParameters(parameters); - } - - if(running) - { - StartCapture(width, height, framerate); - } - _previewBufferLock.unlock(); - } - } - - - - public void surfaceCreated(SurfaceHolder holder) { - - } - - - public void surfaceDestroyed(SurfaceHolder holder) { // - - } - -} +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +package org.webrtc.videoengine; + +import java.io.IOException; +import java.util.Locale; +import java.util.concurrent.locks.ReentrantLock; + +import org.webrtc.videoengine.CaptureCapabilityAndroid; +import org.webrtc.videoengine.VideoCaptureDeviceInfoAndroid.AndroidVideoCaptureDevice; + +import android.graphics.ImageFormat; +import android.graphics.PixelFormat; +import android.hardware.Camera; +import android.hardware.Camera.PreviewCallback; +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceHolder.Callback; + +public class VideoCaptureAndroid implements PreviewCallback, Callback { + + private Camera camera; + private AndroidVideoCaptureDevice currentDevice = null; + public ReentrantLock previewBufferLock = new ReentrantLock(); + private int PIXEL_FORMAT = ImageFormat.NV21; + PixelFormat pixelFormat = new PixelFormat(); + // True when the C++ layer has ordered the camera to be started. + private boolean isRunning=false; + + private final int numCaptureBuffers = 3; + private int expectedFrameSize = 0; + private int orientation = 0; + private int id = 0; + // C++ callback context variable. + private long context = 0; + private SurfaceHolder localPreview = null; + // True if this class owns the preview video buffers. + private boolean ownsBuffers = false; + + // Set this to 2 for VERBOSE logging. 1 for DEBUG + private static int LOGLEVEL = 0; + private static boolean VERBOSE = LOGLEVEL > 2; + private static boolean DEBUG = LOGLEVEL > 1; + + CaptureCapabilityAndroid currentCapability = null; + + public static + void DeleteVideoCaptureAndroid(VideoCaptureAndroid captureAndroid) { + if(DEBUG) Log.d("*WEBRTC*", "DeleteVideoCaptureAndroid"); + + captureAndroid.StopCapture(); + captureAndroid.camera.release(); + captureAndroid.camera = null; + captureAndroid.context = 0; + + if(DEBUG) Log.v("*WEBRTC*", "DeleteVideoCaptureAndroid ended"); + + } + + public VideoCaptureAndroid(int in_id, + long in_context, + Camera in_camera, + AndroidVideoCaptureDevice in_device) { + id = in_id; + context = in_context; + camera = in_camera; + currentDevice = in_device; + } + + public int StartCapture(int width, int height, int frameRate) { + if(DEBUG) Log.d("*WEBRTC*", "StartCapture width" + width + + " height " + height +" frame rate " + frameRate); + try { + if (camera == null) { + Log.e("*WEBRTC*", + String.format(Locale.US,"Camera not initialized %d",id)); + return -1; + } + currentCapability = new CaptureCapabilityAndroid(); + currentCapability.width = width; + currentCapability.height = height; + currentCapability.maxFPS = frameRate; + PixelFormat.getPixelFormatInfo(PIXEL_FORMAT, pixelFormat); + + Camera.Parameters parameters = camera.getParameters(); + parameters.setPreviewSize(currentCapability.width, + currentCapability.height); + parameters.setPreviewFormat(PIXEL_FORMAT ); + parameters.setPreviewFrameRate(currentCapability.maxFPS); + camera.setParameters(parameters); + + // Get the local preview SurfaceHolder from the static render class + localPreview = ViERenderer.GetLocalRenderer(); + if(localPreview != null) { + localPreview.addCallback(this); + } + + int bufSize = width * height * pixelFormat.bitsPerPixel / 8; + if(android.os.Build.VERSION.SDK_INT >= 7) { + // According to Doc addCallbackBuffer belongs to API level 8. + // But it seems like it works on Android 2.1 as well. + // At least SE X10 and Milestone + byte[] buffer = null; + for (int i = 0; i < numCaptureBuffers; i++) { + buffer = new byte[bufSize]; + camera.addCallbackBuffer(buffer); + } + + camera.setPreviewCallbackWithBuffer(this); + ownsBuffers = true; + } + else { + camera.setPreviewCallback(this); + } + + camera.startPreview(); + previewBufferLock.lock(); + expectedFrameSize = bufSize; + isRunning = true; + previewBufferLock.unlock(); + } + catch (Exception ex) { + Log.e("*WEBRTC*", "Failed to start camera"); + return -1; + } + return 0; + } + + public int StopCapture() { + if(DEBUG) Log.d("*WEBRTC*", "StopCapture"); + try { + previewBufferLock.lock(); + isRunning = false; + previewBufferLock.unlock(); + + camera.stopPreview(); + + if(android.os.Build.VERSION.SDK_INT > 7) { + camera.setPreviewCallbackWithBuffer(null); + } + else { + camera.setPreviewCallback(null); + } + } + catch (Exception ex) { + Log.e("*WEBRTC*", "Failed to stop camera"); + return -1; + } + + if(DEBUG) { + Log.d("*WEBRTC*", "StopCapture ended"); + } + return 0; + } + + native void ProvideCameraFrame(byte[] data,int length, long captureObject); + + public void onPreviewFrame(byte[] data, Camera camera) { + previewBufferLock.lock(); + + if(VERBOSE) { + Log.v("*WEBRTC*", + String.format(Locale.US, "preview frame length %d context %x", + data.length, context)); + } + if(isRunning) { + // If StartCapture has been called but not StopCapture + // Call the C++ layer with the captured frame + if (data.length == expectedFrameSize) { + ProvideCameraFrame(data, expectedFrameSize, context); + if (VERBOSE) { + Log.v("*WEBRTC*", String.format(Locale.US, "frame delivered")); + } + if(ownsBuffers) { + // Give the video buffer to the camera service again. + camera.addCallbackBuffer(data); + } + } + } + previewBufferLock.unlock(); + } + + + public void surfaceChanged(SurfaceHolder holder, + int format, int width, int height) { + + try { + if(camera != null) { + camera.setPreviewDisplay(localPreview); + } + } catch (IOException e) { + Log.e("*WEBRTC*", + String.format(Locale.US, + "Failed to set Local preview. " + e.getMessage())); + } + } + + // Sets the rotation of the preview render window. + // Does not affect the captured video image. + public void SetPreviewRotation(int rotation) { + if(camera != null) { + previewBufferLock.lock(); + final boolean running = isRunning; + int width = 0; + int height = 0; + int framerate = 0; + + if(running) { + width = currentCapability.width; + height = currentCapability.height; + framerate = currentCapability.maxFPS; + + StopCapture(); + } + + int resultRotation = 0; + if(currentDevice.frontCameraType == + VideoCaptureDeviceInfoAndroid.FrontFacingCameraType.Android23) { + // this is a 2.3 or later front facing camera. + // SetDisplayOrientation will flip the image horizontally + // before doing the rotation. + resultRotation=(360-rotation) % 360; // compensate the mirror + } + else { + // Back facing or 2.2 or previous front camera + resultRotation=rotation; + } + if(android.os.Build.VERSION.SDK_INT>7) { + camera.setDisplayOrientation(resultRotation); + } + else { + // Android 2.1 and previous + // This rotation unfortunately does not seems to work. + // http://code.google.com/p/android/issues/detail?id=1193 + Camera.Parameters parameters = camera.getParameters(); + parameters.setRotation(resultRotation); + camera.setParameters(parameters); + } + + if(running) { + StartCapture(width, height, framerate); + } + previewBufferLock.unlock(); + } + } + + public void surfaceCreated(SurfaceHolder holder) { + } + + + public void surfaceDestroyed(SurfaceHolder holder) { + } + +} diff --git a/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java b/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java index e4e7bc7b82..4ccf06013a 100644 --- a/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java +++ b/modules/video_capture/main/source/Android/java/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java @@ -1,446 +1,432 @@ -package org.webrtc.videoengine; - -import java.io.File; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import dalvik.system.DexClassLoader; - -import android.content.Context; -import android.hardware.Camera; -import android.hardware.Camera.Size; -import android.util.Log; - -public class VideoCaptureDeviceInfoAndroid { - - //Context - Context _context; - - //Logging - private static int LOGLEVEL = 0; // Set this to 2 for VERBOSE logging. 1 for DEBUG - private static boolean VERBOSE = LOGLEVEL > 2; - private static boolean DEBUG = LOGLEVEL > 1; - - /* Private class with info about all available cameras and the capabilities*/ - public class AndroidVideoCaptureDevice - { - AndroidVideoCaptureDevice() - { - _frontCameraType=FrontFacingCameraType.None; - _index=0; - } - - public String _deviceUniqueName; - public CaptureCapabilityAndroid _captureCapabilies[]; - public FrontFacingCameraType _frontCameraType; - - public int _orientation; //Orientation of camera as described in android.hardware.Camera.CameraInfo.Orientation - public int _index; // Camera index used in Camera.Open on Android 2.3 and onwards - } - public enum FrontFacingCameraType - { - None, // This is not a front facing camera - GalaxyS, // Galaxy S front facing camera. - HTCEvo, // HTC Evo front facing camera - Android23 // Android 2.3 front facing camera. - } - - - String _currentDeviceUniqueId; - int _id; - List _deviceList; - - - public static VideoCaptureDeviceInfoAndroid CreateVideoCaptureDeviceInfoAndroid(int id, Context context) - { - if(DEBUG) Log.d("*WEBRTC*",String.format(Locale.US,"VideoCaptureDeviceInfoAndroid")); - - VideoCaptureDeviceInfoAndroid self = new VideoCaptureDeviceInfoAndroid(id,context); - if(self!=null && self.Init()==0) - { - return self; - } - else - { - if(DEBUG) Log.d("*WEBRTC*", "Failed to create VideoCaptureDeviceInfoAndroid."); - } - return null; - } - - private VideoCaptureDeviceInfoAndroid(int id, Context context) - { - _id=id; - _context=context; - _deviceList= new ArrayList(); - } - - private int Init() - { - // Populate the _deviceList with available cameras and their capabilities. - Camera camera=null; - try{ - if(android.os.Build.VERSION.SDK_INT>8) // From Android 2.3 and onwards - { - for(int i=0; i sizes=parameters.getSupportedPreviewSizes(); - List frameRates=parameters.getSupportedPreviewFrameRates(); - int maxFPS=0; - for(Integer frameRate:frameRates) - { - if(VERBOSE) Log.v("*WEBRTC*", "VideoCaptureDeviceInfoAndroid:Init supports frameRate "+ frameRate); - if(frameRate>maxFPS) - { - maxFPS=frameRate; - } - - } - - newDevice._captureCapabilies= new CaptureCapabilityAndroid[sizes.size()]; - for(int i=0;i=_deviceList.size()) - { - return null; - } - return _deviceList.get(deviceNumber)._deviceUniqueName; - } - - public CaptureCapabilityAndroid[] - GetCapabilityArray (String deviceUniqueId) - { - for (AndroidVideoCaptureDevice device: _deviceList) - { - if(device._deviceUniqueName.equals(deviceUniqueId)) - { - return (CaptureCapabilityAndroid[]) device._captureCapabilies; - } - } - return null; - } - - /* Returns the camera orientation as described by - * android.hardware.Camera.CameraInfo.orientation - */ - public int GetOrientation(String deviceUniqueId) - { - for (AndroidVideoCaptureDevice device: _deviceList) - { - if(device._deviceUniqueName.equals(deviceUniqueId)) - { - return device._orientation; - } - } - return -1; - } - - /* - * Returns an instance of VideoCaptureAndroid. - */ - public VideoCaptureAndroid AllocateCamera(int id, long context,String deviceUniqueId) - { - try - { - if(DEBUG) Log.d("*WEBRTC*", "AllocateCamera " + deviceUniqueId); - - Camera camera=null; - AndroidVideoCaptureDevice deviceToUse=null; - for (AndroidVideoCaptureDevice device: _deviceList) - { - if(device._deviceUniqueName.equals(deviceUniqueId)) // Found the wanted camera - { - deviceToUse=device; - switch(device._frontCameraType) - { - case GalaxyS: - camera= AllocateGalaxySFrontCamera(); - break; - case HTCEvo: - camera= AllocateEVOFrontFacingCamera(); - break; - default: - if(android.os.Build.VERSION.SDK_INT>8) // From Android 2.3 and onwards) - camera=Camera.open(device._index); - else - camera=Camera.open(); // Default camera - } - } - } - - if(camera==null) - { - return null; - } - if(VERBOSE) Log.v("*WEBRTC*", "AllocateCamera - creating VideoCaptureAndroid"); - - return new VideoCaptureAndroid(id,context,camera,deviceToUse); - - }catch (Exception ex) { - Log.e("*WEBRTC*", "AllocateCamera Failed to open camera- ex " +ex.getLocalizedMessage()); - } - return null; - } - - /* - * Searches for a front facing camera device. This is device specific code. - */ - private Camera.Parameters SearchOldFrontFacingCameras(AndroidVideoCaptureDevice newDevice) throws SecurityException, IllegalArgumentException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException - { - //Check the id of the opened camera device (Returns null on X10 and 1 on Samsung Galaxy S. - Camera camera=Camera.open(); - Camera.Parameters parameters=camera.getParameters(); - String cameraId=parameters.get("camera-id"); - if(cameraId!=null && cameraId.equals("1")) // This might be a Samsung Galaxy S with a front facing camera. - { - try - { - parameters.set("camera-id", 2); - camera.setParameters(parameters); - parameters = camera.getParameters(); - newDevice._frontCameraType=FrontFacingCameraType.GalaxyS; - newDevice._orientation=0; - camera.release(); - return parameters; - } - catch (Exception ex) { - //Nope - it did not work. - Log.e("*WEBRTC*", "VideoCaptureDeviceInfoAndroid:Init Failed to open front camera camera - ex " +ex.getLocalizedMessage()); - } - } - camera.release(); - - //Check for Evo front facing camera. - File file = new File("/system/framework/com.htc.hardware.twinCamDevice.jar"); - boolean exists = file.exists(); - if (!exists){ - file = new File("/system/framework/com.sprint.hardware.twinCamDevice.jar"); - exists = file.exists(); - } - if(exists) - { - newDevice._frontCameraType=FrontFacingCameraType.HTCEvo; - newDevice._orientation=0; - Camera evCamera=AllocateEVOFrontFacingCamera(); - parameters=evCamera.getParameters(); - evCamera.release(); - return parameters; - } - return null; - } - - - /* - * Returns a handle to HTC front facing camera. - * The caller is responsible to release it on completion. - */ - private Camera AllocateEVOFrontFacingCamera() throws SecurityException, NoSuchMethodException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException - { - - String classPath=null; - File file = new File("/system/framework/com.htc.hardware.twinCamDevice.jar"); - classPath = "com.htc.hardware.twinCamDevice.FrontFacingCamera"; - boolean exists = file.exists(); - if (!exists){ - file = new File("/system/framework/com.sprint.hardware.twinCamDevice.jar"); - classPath = "com.sprint.hardware.twinCamDevice.FrontFacingCamera"; - exists = file.exists(); - } - if(!exists) - { - return null; - } - - String dexOutputDir=""; - if(_context!=null){ - dexOutputDir = _context.getFilesDir().getAbsolutePath(); - File mFilesDir = new File(dexOutputDir, "dexfiles"); - if(!mFilesDir.exists()){ - //Log.e("*WEBRTCN*", "Directory doesn't exists"); - if(!mFilesDir.mkdirs()) { - //Log.e("*WEBRTCN*", "Unable to create files directory"); - } - } - } - - dexOutputDir += "/dexfiles"; - - DexClassLoader loader = new DexClassLoader( - file.getAbsolutePath(), - dexOutputDir, - null, - ClassLoader.getSystemClassLoader() - ); - - Method method = loader.loadClass(classPath).getDeclaredMethod("getFrontFacingCamera", (Class[]) null); - Camera camera = (Camera) method.invoke((Object[])null,(Object[]) null); - return camera; - } - - /* - * Returns a handle to Galaxy S front camera. - * The caller is responsible to release it on completion. - */ - private Camera AllocateGalaxySFrontCamera() - { - Camera camera=Camera.open(); - Camera.Parameters parameters = camera.getParameters(); - parameters.set("camera-id",2); - camera.setParameters(parameters); - return camera; - } - - -} +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +package org.webrtc.videoengine; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import dalvik.system.DexClassLoader; + +import android.content.Context; +import android.hardware.Camera; +import android.hardware.Camera.Size; +import android.util.Log; + +public class VideoCaptureDeviceInfoAndroid { + + //Context + Context context; + + // Set this to 2 for VERBOSE logging. 1 for DEBUG + private static int LOGLEVEL = 0; + private static boolean VERBOSE = LOGLEVEL > 2; + private static boolean DEBUG = LOGLEVEL > 1; + + // Private class with info about all available cameras and the capabilities + public class AndroidVideoCaptureDevice { + AndroidVideoCaptureDevice() { + frontCameraType = FrontFacingCameraType.None; + index = 0; + } + + public String deviceUniqueName; + public CaptureCapabilityAndroid captureCapabilies[]; + public FrontFacingCameraType frontCameraType; + + // Orientation of camera as described in + // android.hardware.Camera.CameraInfo.Orientation + public int orientation; + // Camera index used in Camera.Open on Android 2.3 and onwards + public int index; + } + + public enum FrontFacingCameraType { + None, // This is not a front facing camera + GalaxyS, // Galaxy S front facing camera. + HTCEvo, // HTC Evo front facing camera + Android23, // Android 2.3 front facing camera. + } + + String currentDeviceUniqueId; + int id; + List deviceList; + + public static VideoCaptureDeviceInfoAndroid + CreateVideoCaptureDeviceInfoAndroid(int in_id, Context in_context) { + if(DEBUG) { + Log.d("*WEBRTC*", + String.format(Locale.US, "VideoCaptureDeviceInfoAndroid")); + } + + VideoCaptureDeviceInfoAndroid self = + new VideoCaptureDeviceInfoAndroid(in_id, in_context); + if(self != null && self.Init() == 0) { + return self; + } + else { + if(DEBUG) { + Log.d("*WEBRTC*", "Failed to create VideoCaptureDeviceInfoAndroid."); + } + } + return null; + } + + private VideoCaptureDeviceInfoAndroid(int in_id, + Context in_context) { + id = in_id; + context = in_context; + deviceList = new ArrayList(); + } + + private int Init() { + // Populate the deviceList with available cameras and their capabilities. + Camera camera = null; + try{ + if(android.os.Build.VERSION.SDK_INT > 8) { + // From Android 2.3 and onwards + for(int i = 0; i < Camera.getNumberOfCameras(); ++i) { + AndroidVideoCaptureDevice newDevice = new AndroidVideoCaptureDevice(); + + Camera.CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(i, info); + newDevice.index = i; + newDevice.orientation=info.orientation; + if(info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { + newDevice.deviceUniqueName = + "Camera " + i +", Facing back, Orientation "+ info.orientation; + } + else { + newDevice.deviceUniqueName = + "Camera " + i +", Facing front, Orientation "+ info.orientation; + newDevice.frontCameraType = FrontFacingCameraType.Android23; + } + + camera = Camera.open(i); + Camera.Parameters parameters = camera.getParameters(); + AddDeviceInfo(newDevice, parameters); + camera.release(); + camera = null; + deviceList.add(newDevice); + } + } + else { + // Prior to Android 2.3 + AndroidVideoCaptureDevice newDevice; + Camera.Parameters parameters; + + newDevice = new AndroidVideoCaptureDevice(); + camera = Camera.open(); + parameters = camera.getParameters(); + newDevice.deviceUniqueName = "Camera 1, Facing back"; + newDevice.orientation = 90; + AddDeviceInfo(newDevice, parameters); + + deviceList.add(newDevice); + camera.release(); + camera=null; + + newDevice = new AndroidVideoCaptureDevice(); + newDevice.deviceUniqueName = "Camera 2, Facing front"; + parameters = SearchOldFrontFacingCameras(newDevice); + if(parameters != null) { + AddDeviceInfo(newDevice, parameters); + deviceList.add(newDevice); + } + } + } + catch (Exception ex) { + Log.e("*WEBRTC*", "Failed to init VideoCaptureDeviceInfo ex" + + ex.getLocalizedMessage()); + return -1; + } + VerifyCapabilities(); + return 0; + } + + // Adds the capture capabilities of the currently opened device + private void AddDeviceInfo(AndroidVideoCaptureDevice newDevice, + Camera.Parameters parameters) { + + List sizes = parameters.getSupportedPreviewSizes(); + List frameRates = parameters.getSupportedPreviewFrameRates(); + int maxFPS=0; + for(Integer frameRate:frameRates) { + if(VERBOSE) { + Log.v("*WEBRTC*", + "VideoCaptureDeviceInfoAndroid:frameRate " + frameRate); + } + if(frameRate > maxFPS) { + maxFPS = frameRate; + } + } + + newDevice.captureCapabilies = new CaptureCapabilityAndroid[sizes.size()]; + for(int i = 0; i < sizes.size(); ++i) { + Size s = sizes.get(i); + newDevice.captureCapabilies[i] = new CaptureCapabilityAndroid(); + newDevice.captureCapabilies[i].height = s.height; + newDevice.captureCapabilies[i].width = s.width; + newDevice.captureCapabilies[i].maxFPS = maxFPS; + } + } + + // Function that make sure device specific capabilities are + // in the capability list. + // Ie Galaxy S supports CIF but does not list CIF as a supported capability. + // Motorola Droid Camera does not work with frame rate above 15fps. + // http://code.google.com/p/android/issues/detail?id=5514#c0 + private void VerifyCapabilities() { + // Nexus S or Galaxy S + if(android.os.Build.DEVICE.equals("GT-I9000") || + android.os.Build.DEVICE.equals("crespo")) { + CaptureCapabilityAndroid specificCapability = + new CaptureCapabilityAndroid(); + specificCapability.width = 352; + specificCapability.height = 288; + specificCapability.maxFPS = 15; + AddDeviceSpecificCapability(specificCapability); + + specificCapability = new CaptureCapabilityAndroid(); + specificCapability.width = 176; + specificCapability.height = 144; + specificCapability.maxFPS = 15; + AddDeviceSpecificCapability(specificCapability); + + specificCapability = new CaptureCapabilityAndroid(); + specificCapability.width = 320; + specificCapability.height = 240; + specificCapability.maxFPS = 15; + AddDeviceSpecificCapability(specificCapability); + } + // Motorola Milestone Camera server does not work at 30fps + // even though it reports that it can + if(android.os.Build.MANUFACTURER.equals("motorola") && + android.os.Build.DEVICE.equals("umts_sholes")) { + for(AndroidVideoCaptureDevice device:deviceList) { + for(CaptureCapabilityAndroid capability:device.captureCapabilies) { + capability.maxFPS=15; + } + } + } + } + + private void AddDeviceSpecificCapability( + CaptureCapabilityAndroid specificCapability) { + for(AndroidVideoCaptureDevice device:deviceList) { + boolean foundCapability = false; + for(CaptureCapabilityAndroid capability:device.captureCapabilies) { + if(capability.width == specificCapability.width && + capability.height == specificCapability.height) { + foundCapability = true; + break; + } + } + if(foundCapability==false) { + CaptureCapabilityAndroid newCaptureCapabilies[]= + new CaptureCapabilityAndroid[device.captureCapabilies.length+1]; + for(int i = 0; i < device.captureCapabilies.length; ++i) { + newCaptureCapabilies[i+1] = device.captureCapabilies[i]; + } + newCaptureCapabilies[0] = specificCapability; + device.captureCapabilies = newCaptureCapabilies; + } + } + } + + // Returns the number of Capture devices that is supported + public int NumberOfDevices() { + return deviceList.size(); + } + + public String GetDeviceUniqueName(int deviceNumber) { + if(deviceNumber < 0 || deviceNumber >= deviceList.size()) { + return null; + } + return deviceList.get(deviceNumber).deviceUniqueName; + } + + public CaptureCapabilityAndroid[] GetCapabilityArray (String deviceUniqueId) + { + for (AndroidVideoCaptureDevice device: deviceList) { + if(device.deviceUniqueName.equals(deviceUniqueId)) { + return (CaptureCapabilityAndroid[]) device.captureCapabilies; + } + } + return null; + } + + // Returns the camera orientation as described by + // android.hardware.Camera.CameraInfo.orientation + public int GetOrientation(String deviceUniqueId) { + for (AndroidVideoCaptureDevice device: deviceList) { + if(device.deviceUniqueName.equals(deviceUniqueId)) { + return device.orientation; + } + } + return -1; + } + + // Returns an instance of VideoCaptureAndroid. + public VideoCaptureAndroid AllocateCamera(int id, long context, + String deviceUniqueId) { + try { + if(DEBUG) Log.d("*WEBRTC*", "AllocateCamera " + deviceUniqueId); + + Camera camera = null; + AndroidVideoCaptureDevice deviceToUse = null; + for (AndroidVideoCaptureDevice device: deviceList) { + if(device.deviceUniqueName.equals(deviceUniqueId)) { + // Found the wanted camera + deviceToUse = device; + switch(device.frontCameraType) { + case GalaxyS: + camera = AllocateGalaxySFrontCamera(); + break; + case HTCEvo: + camera = AllocateEVOFrontFacingCamera(); + break; + default: + // From Android 2.3 and onwards) + if(android.os.Build.VERSION.SDK_INT>8) + camera=Camera.open(device.index); + else + camera=Camera.open(); // Default camera + } + } + } + + if(camera == null) { + return null; + } + if(VERBOSE) { + Log.v("*WEBRTC*", "AllocateCamera - creating VideoCaptureAndroid"); + } + + return new VideoCaptureAndroid(id,context,camera,deviceToUse); + + }catch (Exception ex) { + Log.e("*WEBRTC*", "AllocateCamera Failed to open camera- ex " + + ex.getLocalizedMessage()); + } + return null; + } + + // Searches for a front facing camera device. This is device specific code. + private Camera.Parameters + SearchOldFrontFacingCameras(AndroidVideoCaptureDevice newDevice) + throws SecurityException, IllegalArgumentException, + NoSuchMethodException, ClassNotFoundException, + IllegalAccessException, InvocationTargetException { + // Check the id of the opened camera device + // Returns null on X10 and 1 on Samsung Galaxy S. + Camera camera = Camera.open(); + Camera.Parameters parameters = camera.getParameters(); + String cameraId = parameters.get("camera-id"); + if(cameraId != null && cameraId.equals("1")) { + // This might be a Samsung Galaxy S with a front facing camera. + try { + parameters.set("camera-id", 2); + camera.setParameters(parameters); + parameters = camera.getParameters(); + newDevice.frontCameraType = FrontFacingCameraType.GalaxyS; + newDevice.orientation = 0; + camera.release(); + return parameters; + } + catch (Exception ex) { + //Nope - it did not work. + Log.e("*WEBRTC*", "Init Failed to open front camera camera - ex " + + ex.getLocalizedMessage()); + } + } + camera.release(); + + //Check for Evo front facing camera + File file = + new File("/system/framework/com.htc.hardware.twinCamDevice.jar"); + boolean exists = file.exists(); + if (!exists){ + file = + new File("/system/framework/com.sprint.hardware.twinCamDevice.jar"); + exists = file.exists(); + } + if(exists) { + newDevice.frontCameraType = FrontFacingCameraType.HTCEvo; + newDevice.orientation = 0; + Camera evCamera = AllocateEVOFrontFacingCamera(); + parameters = evCamera.getParameters(); + evCamera.release(); + return parameters; + } + return null; + } + + // Returns a handle to HTC front facing camera. + // The caller is responsible to release it on completion. + private Camera AllocateEVOFrontFacingCamera() + throws SecurityException, NoSuchMethodException, + ClassNotFoundException, IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + String classPath = null; + File file = + new File("/system/framework/com.htc.hardware.twinCamDevice.jar"); + classPath = "com.htc.hardware.twinCamDevice.FrontFacingCamera"; + boolean exists = file.exists(); + if (!exists){ + file = + new File("/system/framework/com.sprint.hardware.twinCamDevice.jar"); + classPath = "com.sprint.hardware.twinCamDevice.FrontFacingCamera"; + exists = file.exists(); + } + if(!exists) { + return null; + } + + String dexOutputDir = ""; + if(context != null) { + dexOutputDir = context.getFilesDir().getAbsolutePath(); + File mFilesDir = new File(dexOutputDir, "dexfiles"); + if(!mFilesDir.exists()){ + //Log.e("*WEBRTCN*", "Directory doesn't exists"); + if(!mFilesDir.mkdirs()) { + //Log.e("*WEBRTCN*", "Unable to create files directory"); + } + } + } + + dexOutputDir += "/dexfiles"; + + DexClassLoader loader = + new DexClassLoader(file.getAbsolutePath(), dexOutputDir, + null, ClassLoader.getSystemClassLoader()); + + Method method = loader.loadClass(classPath).getDeclaredMethod( + "getFrontFacingCamera", (Class[]) null); + Camera camera = (Camera) method.invoke((Object[])null,(Object[]) null); + return camera; + } + + // Returns a handle to Galaxy S front camera. + // The caller is responsible to release it on completion. + private Camera AllocateGalaxySFrontCamera() + { + Camera camera = Camera.open(); + Camera.Parameters parameters = camera.getParameters(); + parameters.set("camera-id",2); + camera.setParameters(parameters); + return camera; + } + +}