blob: a3d1ef43dbddbb451bc77dee4dedc97c510ebe39 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.media;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
// Needed for jni_generator.py to guess correctly the origin of
// VideoCapture.CaptureFormat.
import org.chromium.media.VideoCapture;
/**
* This class implements a factory of Android Video Capture objects for Chrome.
* The static createVideoCapture() returns either a "normal" VideoCaptureAndroid
* or a "special" VideoCaptureTango. Cameras are identified by |id|, where Tango
* cameras have |id| above the standard ones. Video Capture objects allocated
* via createVideoCapture() are explicitly owned by the caller.
* ChromiumCameraInfo is an internal class with some static methods needed from
* the rest of the class to manipulate the |id|s of normal and special devices.
**/
@JNINamespace("media")
@SuppressWarnings("deprecation")
class VideoCaptureFactory {
// Internal class to encapsulate camera device id manipulations.
static class ChromiumCameraInfo {
// Special devices have more cameras than usual. Those devices are
// identified by model & device. Currently only the Tango is supported.
// Note that these devices have no Camera.CameraInfo.
private static final String[][] SPECIAL_DEVICE_LIST = {
{"Peanut", "peanut"},
};
private static int sNumberOfSystemCameras = -1;
private static final String TAG = "ChromiumCameraInfo";
private static boolean isSpecialDevice() {
for (String[] device : SPECIAL_DEVICE_LIST) {
if (device[0].contentEquals(android.os.Build.MODEL)
&& device[1].contentEquals(android.os.Build.DEVICE)) {
return true;
}
}
return false;
}
private static boolean isSpecialCamera(int id) {
return id >= sNumberOfSystemCameras;
}
private static int toSpecialCameraId(int id) {
assert isSpecialCamera(id);
return id - sNumberOfSystemCameras;
}
private static int getNumberOfCameras(Context appContext) {
// getNumberOfCameras() would not fail due to lack of permission, but the
// following operations on camera would. "No permission" isn't a fatal
// error in WebView, specially for those applications which have no purpose
// to use a camera, but "load page" requires it. So, output a warning log
// and carry on pretending the system has no camera(s).
if (sNumberOfSystemCameras == -1) {
if (PackageManager.PERMISSION_GRANTED
== appContext.getPackageManager().checkPermission(
"android.permission.CAMERA", appContext.getPackageName())) {
if (isLReleaseOrLater()) {
sNumberOfSystemCameras =
VideoCaptureCamera2.getNumberOfCameras(appContext);
} else {
sNumberOfSystemCameras = VideoCaptureAndroid.getNumberOfCameras();
if (isSpecialDevice()) {
Log.d(TAG, "Special device: " + android.os.Build.MODEL);
sNumberOfSystemCameras += VideoCaptureTango.numberOfCameras();
}
}
} else {
sNumberOfSystemCameras = 0;
Log.w(TAG, "Missing android.permission.CAMERA permission, "
+ "no system camera available.");
}
}
return sNumberOfSystemCameras;
}
}
private static boolean isLReleaseOrLater() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
}
// Factory methods.
@CalledByNative
static VideoCapture createVideoCapture(
Context context, int id, long nativeVideoCaptureDeviceAndroid) {
if (ChromiumCameraInfo.isSpecialCamera(id)) {
return new VideoCaptureTango(context, ChromiumCameraInfo.toSpecialCameraId(id),
nativeVideoCaptureDeviceAndroid);
} else {
return new VideoCaptureAndroid(context, id,
nativeVideoCaptureDeviceAndroid);
}
}
@CalledByNative
static int getNumberOfCameras(Context appContext) {
return ChromiumCameraInfo.getNumberOfCameras(appContext);
}
@CalledByNative
static String getDeviceName(int id, Context appContext) {
if (isLReleaseOrLater()) {
return VideoCaptureCamera2.getName(id, appContext);
}
return (ChromiumCameraInfo.isSpecialCamera(id))
? VideoCaptureTango.getName(ChromiumCameraInfo.toSpecialCameraId(id))
: VideoCaptureAndroid.getName(id);
}
@CalledByNative
static VideoCapture.CaptureFormat[] getDeviceSupportedFormats(Context appContext, int id) {
if (isLReleaseOrLater()) {
return VideoCaptureCamera2.getDeviceSupportedFormats(appContext, id);
}
return ChromiumCameraInfo.isSpecialCamera(id)
? VideoCaptureTango.getDeviceSupportedFormats(
ChromiumCameraInfo.toSpecialCameraId(id))
: VideoCaptureAndroid.getDeviceSupportedFormats(id);
}
@CalledByNative
static int getCaptureFormatWidth(VideoCapture.CaptureFormat format) {
return format.getWidth();
}
@CalledByNative
static int getCaptureFormatHeight(VideoCapture.CaptureFormat format) {
return format.getHeight();
}
@CalledByNative
static int getCaptureFormatFramerate(VideoCapture.CaptureFormat format) {
return format.getFramerate();
}
@CalledByNative
static int getCaptureFormatPixelFormat(VideoCapture.CaptureFormat format) {
return format.getPixelFormat();
}
}