Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / media / base / android / java / src / org / chromium / media / VideoCaptureFactory.java
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.
4
5 package org.chromium.media;
6
7 import android.content.Context;
8 import android.content.pm.PackageManager;
9 import android.hardware.Camera;
10 import android.util.Log;
11
12 import org.chromium.base.CalledByNative;
13 import org.chromium.base.JNINamespace;
14 // Needed for jni_generator.py to guess correctly the origin of
15 // VideoCapture.CaptureFormat.
16 import org.chromium.media.VideoCapture;
17
18 /**
19  * This class implements a factory of Android Video Capture objects for Chrome.
20  * The static createVideoCapture() returns either a "normal" VideoCaptureAndroid
21  * or a "special" VideoCaptureTango. Cameras are identified by |id|, where Tango
22  * cameras have |id| above the standard ones. Video Capture objects allocated
23  * via createVideoCapture() are explicitly owned by the caller.
24  * ChromiumCameraInfo is an internal class with some static methods needed from
25  * the native side to enumerate devices and collect their names and info. It
26  * takes into account the mentioned special devices.
27  **/
28 @JNINamespace("media")
29 class VideoCaptureFactory {
30
31     static class CamParams {
32         final int mId;
33         final String mName;
34         final int mWidth;
35         final int mHeight;
36
37         CamParams(int id, String name, int width, int height) {
38             mId = id;
39             mName = name;
40             mWidth = width;
41             mHeight = height;
42         }
43     }
44
45     static class ChromiumCameraInfo {
46         private final int mId;
47         private final 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 = {
52             {"Peanut", "peanut"},
53         };
54         private static final String TAG = "ChromiumCameraInfo";
55
56         private static int sNumberOfSystemCameras = -1;
57
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)) {
62                     return true;
63                 }
64             }
65             return false;
66         }
67
68         private static boolean isSpecialCamera(int id) {
69             return id >= sNumberOfSystemCameras;
70         }
71
72         private static int toSpecialCameraId(int id) {
73             assert isSpecialCamera(id);
74             return id - sNumberOfSystemCameras;
75         }
76
77         private ChromiumCameraInfo(int index) {
78             mId = index;
79             mCameraInfo = isSpecialCamera(index) ? null : getCameraInfo(mId);
80         }
81
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 = Camera.getNumberOfCameras();
94                 } else {
95                     sNumberOfSystemCameras = 0;
96                     Log.w(TAG, "Missing android.permission.CAMERA permission, "
97                             + "no system camera available.");
98                 }
99             }
100             if (isSpecialDevice()) {
101                 Log.d(TAG, "Special device: " + android.os.Build.MODEL);
102                 return sNumberOfSystemCameras +
103                        VideoCaptureTango.numberOfCameras();
104             } else {
105                 return sNumberOfSystemCameras;
106             }
107         }
108
109         @CalledByNative("ChromiumCameraInfo")
110         private static ChromiumCameraInfo getAt(int index) {
111             return new ChromiumCameraInfo(index);
112         }
113
114         @CalledByNative("ChromiumCameraInfo")
115         private int getId() {
116             return mId;
117         }
118
119         @CalledByNative("ChromiumCameraInfo")
120         private String getDeviceName() {
121             if (isSpecialCamera(mId)) {
122                 return VideoCaptureTango.getCamParams(toSpecialCameraId(mId)).mName;
123             } else {
124                 if (mCameraInfo == null) {
125                     return "";
126                 }
127                 Log.d(TAG, "Camera enumerated: " + (mCameraInfo.facing ==
128                         Camera.CameraInfo.CAMERA_FACING_FRONT ? "front" :
129                         "back"));
130                 return "camera " + mId + ", facing " + (mCameraInfo.facing ==
131                         Camera.CameraInfo.CAMERA_FACING_FRONT ? "front" :
132                         "back");
133             }
134         }
135
136         @CalledByNative("ChromiumCameraInfo")
137         private int getOrientation() {
138             if (isSpecialCamera(mId)) {
139                 return Camera.CameraInfo.CAMERA_FACING_BACK;
140             } else {
141                 return (mCameraInfo == null ? 0 : mCameraInfo.orientation);
142             }
143         }
144
145         private Camera.CameraInfo getCameraInfo(int id) {
146             Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
147             try {
148                 Camera.getCameraInfo(id, cameraInfo);
149             } catch (RuntimeException ex) {
150                 Log.e(TAG, "getCameraInfo: Camera.getCameraInfo: " + ex);
151                 return null;
152             }
153             return cameraInfo;
154         }
155     }
156
157     // Factory methods.
158     @CalledByNative
159     static VideoCapture createVideoCapture(
160             Context context, int id, long nativeVideoCaptureDeviceAndroid) {
161       if (ChromiumCameraInfo.isSpecialCamera(id)) {
162           return new VideoCaptureTango(context, ChromiumCameraInfo.toSpecialCameraId(id),
163                   nativeVideoCaptureDeviceAndroid);
164       } else {
165           return new VideoCaptureAndroid(context, id,
166                   nativeVideoCaptureDeviceAndroid);
167       }
168     }
169
170     @CalledByNative
171     static VideoCapture.CaptureFormat[] getDeviceSupportedFormats(int id) {
172         return ChromiumCameraInfo.isSpecialCamera(id) ?
173                 VideoCaptureTango.getDeviceSupportedFormats(
174                         ChromiumCameraInfo.toSpecialCameraId(id)) :
175                 VideoCaptureAndroid.getDeviceSupportedFormats(id);
176     }
177
178     @CalledByNative
179     static int getCaptureFormatWidth(VideoCapture.CaptureFormat format) {
180         return format.getWidth();
181     }
182
183     @CalledByNative
184     static int getCaptureFormatHeight(VideoCapture.CaptureFormat format) {
185         return format.getHeight();
186     }
187
188     @CalledByNative
189     static int getCaptureFormatFramerate(VideoCapture.CaptureFormat format) {
190         return format.getFramerate();
191     }
192
193     @CalledByNative
194     static int getCaptureFormatPixelFormat(VideoCapture.CaptureFormat format) {
195         return format.getPixelFormat();
196     }
197 }