1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.media;
7 import android.content.Context;
8 import android.content.pm.PackageManager;
9 import android.util.Log;
11 import org.chromium.base.CalledByNative;
12 import org.chromium.base.JNINamespace;
13 // Needed for jni_generator.py to guess correctly the origin of
14 // VideoCapture.CaptureFormat.
15 import org.chromium.media.VideoCapture;
18 * This class implements a factory of Android Video Capture objects for Chrome.
19 * The static createVideoCapture() returns either a "normal" VideoCaptureAndroid
20 * or a "special" VideoCaptureTango. Cameras are identified by |id|, where Tango
21 * cameras have |id| above the standard ones. Video Capture objects allocated
22 * via createVideoCapture() are explicitly owned by the caller.
23 * ChromiumCameraInfo is an internal class with some static methods needed from
24 * the native side to enumerate devices and collect their names and info. It
25 * takes into account the mentioned special devices.
27 @JNINamespace("media")
28 @SuppressWarnings("deprecation")
29 class VideoCaptureFactory {
31 static class CamParams {
37 CamParams(int id, String name, int width, int height) {
45 static class ChromiumCameraInfo {
46 private final int mId;
47 private final android.hardware.Camera.CameraInfo mCameraInfo;
48 // Special devices have more cameras than usual. Those devices are
49 // identified by model & device. Currently only the Tango is supported.
50 // Note that these devices have no Camera.CameraInfo.
51 private static final String[][] SPECIAL_DEVICE_LIST = {
54 private static final String TAG = "ChromiumCameraInfo";
56 private static int sNumberOfSystemCameras = -1;
58 private static boolean isSpecialDevice() {
59 for (String[] device : SPECIAL_DEVICE_LIST) {
60 if (device[0].contentEquals(android.os.Build.MODEL) &&
61 device[1].contentEquals(android.os.Build.DEVICE)) {
68 private static boolean isSpecialCamera(int id) {
69 return id >= sNumberOfSystemCameras;
72 private static int toSpecialCameraId(int id) {
73 assert isSpecialCamera(id);
74 return id - sNumberOfSystemCameras;
77 private ChromiumCameraInfo(int index) {
79 mCameraInfo = isSpecialCamera(index) ? null : getCameraInfo(mId);
82 @CalledByNative("ChromiumCameraInfo")
83 private static int getNumberOfCameras(Context appContext) {
84 // Camera.getNumberOfCammeras() will not fail without permission, but the
85 // following operation on camera will do. Without permission isn't fatal
86 // error in WebView, specially for those application which has no purpose
87 // to use camera, but happens to load page required it.
88 // So, we output a warning log and pretend system have no camera at all.
89 if (sNumberOfSystemCameras == -1) {
90 if (PackageManager.PERMISSION_GRANTED ==
91 appContext.getPackageManager().checkPermission(
92 "android.permission.CAMERA", appContext.getPackageName())) {
93 sNumberOfSystemCameras = android.hardware.Camera.getNumberOfCameras();
95 sNumberOfSystemCameras = 0;
96 Log.w(TAG, "Missing android.permission.CAMERA permission, "
97 + "no system camera available.");
100 if (isSpecialDevice()) {
101 Log.d(TAG, "Special device: " + android.os.Build.MODEL);
102 return sNumberOfSystemCameras +
103 VideoCaptureTango.numberOfCameras();
105 return sNumberOfSystemCameras;
109 @CalledByNative("ChromiumCameraInfo")
110 private static ChromiumCameraInfo getAt(int index) {
111 return new ChromiumCameraInfo(index);
114 @CalledByNative("ChromiumCameraInfo")
115 private int getId() {
119 @CalledByNative("ChromiumCameraInfo")
120 private String getDeviceName() {
121 if (isSpecialCamera(mId)) {
122 return VideoCaptureTango.getCamParams(toSpecialCameraId(mId)).mName;
124 if (mCameraInfo == null) {
127 Log.d(TAG, "Camera enumerated: " + (mCameraInfo.facing ==
128 android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT ? "front" :
130 return "camera " + mId + ", facing " + (mCameraInfo.facing ==
131 android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT ? "front" :
136 @CalledByNative("ChromiumCameraInfo")
137 private int getOrientation() {
138 if (isSpecialCamera(mId)) {
139 return android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK;
141 return (mCameraInfo == null ? 0 : mCameraInfo.orientation);
145 private android.hardware.Camera.CameraInfo getCameraInfo(int id) {
146 android.hardware.Camera.CameraInfo cameraInfo =
147 new android.hardware.Camera.CameraInfo();
149 android.hardware.Camera.getCameraInfo(id, cameraInfo);
150 } catch (RuntimeException ex) {
151 Log.e(TAG, "getCameraInfo: android.hardware.Camera.getCameraInfo: " + ex);
160 static VideoCapture createVideoCapture(
161 Context context, int id, long nativeVideoCaptureDeviceAndroid) {
162 if (ChromiumCameraInfo.isSpecialCamera(id)) {
163 return new VideoCaptureTango(context, ChromiumCameraInfo.toSpecialCameraId(id),
164 nativeVideoCaptureDeviceAndroid);
166 return new VideoCaptureAndroid(context, id,
167 nativeVideoCaptureDeviceAndroid);
172 static VideoCapture.CaptureFormat[] getDeviceSupportedFormats(int id) {
173 return ChromiumCameraInfo.isSpecialCamera(id) ?
174 VideoCaptureTango.getDeviceSupportedFormats(
175 ChromiumCameraInfo.toSpecialCameraId(id)) :
176 VideoCaptureAndroid.getDeviceSupportedFormats(id);
180 static int getCaptureFormatWidth(VideoCapture.CaptureFormat format) {
181 return format.getWidth();
185 static int getCaptureFormatHeight(VideoCapture.CaptureFormat format) {
186 return format.getHeight();
190 static int getCaptureFormatFramerate(VideoCapture.CaptureFormat format) {
191 return format.getFramerate();
195 static int getCaptureFormatPixelFormat(VideoCapture.CaptureFormat format) {
196 return format.getPixelFormat();