| /* |
| * Copyright (c) 2012 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. |
| */ |
| |
| #include "device_info_android.h" |
| |
| #include <stdio.h> |
| |
| #include "ref_count.h" |
| #include "trace.h" |
| #include "video_capture_android.h" |
| |
| namespace webrtc |
| { |
| |
| namespace videocapturemodule |
| { |
| |
| VideoCaptureModule::DeviceInfo* |
| VideoCaptureImpl::CreateDeviceInfo (const WebRtc_Word32 id) { |
| videocapturemodule::DeviceInfoAndroid *deviceInfo = |
| new videocapturemodule::DeviceInfoAndroid(id); |
| if (deviceInfo && deviceInfo->Init() != 0) { |
| delete deviceInfo; |
| deviceInfo = NULL; |
| } |
| return deviceInfo; |
| } |
| |
| DeviceInfoAndroid::DeviceInfoAndroid(const WebRtc_Word32 id) : |
| DeviceInfoImpl(id) { |
| } |
| |
| WebRtc_Word32 DeviceInfoAndroid::Init() { |
| return 0; |
| } |
| |
| DeviceInfoAndroid::~DeviceInfoAndroid() { |
| } |
| |
| WebRtc_UWord32 DeviceInfoAndroid::NumberOfDevices() { |
| JNIEnv *env; |
| jclass javaCmDevInfoClass; |
| jobject javaCmDevInfoObject; |
| bool attached = false; |
| if (VideoCaptureAndroid::AttachAndUseAndroidDeviceInfoObjects( |
| env, |
| javaCmDevInfoClass, |
| javaCmDevInfoObject, |
| attached) != 0) |
| return 0; |
| |
| WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, _id, |
| "%s GetMethodId", __FUNCTION__); |
| // get the method ID for the Android Java GetDeviceUniqueName name. |
| jmethodID cid = env->GetMethodID(javaCmDevInfoClass, |
| "NumberOfDevices", |
| "()I"); |
| |
| jint numberOfDevices = 0; |
| if (cid != NULL) { |
| WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, _id, |
| "%s Calling Number of devices", __FUNCTION__); |
| numberOfDevices = env->CallIntMethod(javaCmDevInfoObject, cid); |
| } |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| |
| if (numberOfDevices > 0) |
| return numberOfDevices; |
| return 0; |
| } |
| |
| WebRtc_Word32 DeviceInfoAndroid::GetDeviceName( |
| WebRtc_UWord32 deviceNumber, |
| char* deviceNameUTF8, |
| WebRtc_UWord32 deviceNameLength, |
| char* deviceUniqueIdUTF8, |
| WebRtc_UWord32 deviceUniqueIdUTF8Length, |
| char* /*productUniqueIdUTF8*/, |
| WebRtc_UWord32 /*productUniqueIdUTF8Length*/) { |
| |
| JNIEnv *env; |
| jclass javaCmDevInfoClass; |
| jobject javaCmDevInfoObject; |
| WebRtc_Word32 result = 0; |
| bool attached = false; |
| if (VideoCaptureAndroid::AttachAndUseAndroidDeviceInfoObjects( |
| env, |
| javaCmDevInfoClass, |
| javaCmDevInfoObject, |
| attached)!= 0) |
| return -1; |
| |
| // get the method ID for the Android Java GetDeviceUniqueName name. |
| jmethodID cid = env->GetMethodID(javaCmDevInfoClass, "GetDeviceUniqueName", |
| "(I)Ljava/lang/String;"); |
| if (cid != NULL) { |
| jobject javaDeviceNameObj = env->CallObjectMethod(javaCmDevInfoObject, |
| cid, deviceNumber); |
| if (javaDeviceNameObj == NULL) { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, |
| "%s: Failed to get device name for device %d.", |
| __FUNCTION__, (int) deviceNumber); |
| result = -1; |
| } else { |
| jboolean isCopy; |
| const char* javaDeviceNameChar = env->GetStringUTFChars( |
| (jstring) javaDeviceNameObj |
| ,&isCopy); |
| const jsize javaDeviceNameCharLength = |
| env->GetStringUTFLength((jstring) javaDeviceNameObj); |
| if ((WebRtc_UWord32) javaDeviceNameCharLength < |
| deviceUniqueIdUTF8Length) { |
| memcpy(deviceUniqueIdUTF8, |
| javaDeviceNameChar, |
| javaDeviceNameCharLength + 1); |
| } |
| else { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, |
| _id, "%s: deviceUniqueIdUTF8 to short.", |
| __FUNCTION__); |
| result = -1; |
| } |
| if ((WebRtc_UWord32) javaDeviceNameCharLength < deviceNameLength) { |
| memcpy(deviceNameUTF8, |
| javaDeviceNameChar, |
| javaDeviceNameCharLength + 1); |
| } |
| env->ReleaseStringUTFChars((jstring) javaDeviceNameObj, |
| javaDeviceNameChar); |
| } // javaDeviceNameObj == NULL |
| |
| } |
| else { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, |
| "%s: Failed to find GetDeviceUniqueName function id", |
| __FUNCTION__); |
| result = -1; |
| } |
| |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| |
| WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, |
| "%s: result %d", __FUNCTION__, (int) result); |
| return result; |
| |
| } |
| |
| WebRtc_Word32 DeviceInfoAndroid::CreateCapabilityMap( |
| const char* deviceUniqueIdUTF8) { |
| MapItem* item = NULL; |
| while ((item = _captureCapabilities.Last())) { |
| delete (VideoCaptureCapability*) item->GetItem(); |
| _captureCapabilities.Erase(item); |
| } |
| |
| JNIEnv *env; |
| jclass javaCmDevInfoClass; |
| jobject javaCmDevInfoObject; |
| bool attached = false; |
| if (VideoCaptureAndroid::AttachAndUseAndroidDeviceInfoObjects( |
| env, |
| javaCmDevInfoClass, |
| javaCmDevInfoObject, |
| attached) != 0) |
| return -1; |
| |
| // Find the capability class |
| jclass javaCapClassLocal = env->FindClass(AndroidJavaCaptureCapabilityClass); |
| if (javaCapClassLocal == NULL) { |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, |
| "%s: Can't find java class VideoCaptureCapabilityAndroid.", |
| __FUNCTION__); |
| return -1; |
| } |
| |
| // get the method ID for the Android Java GetCapabilityArray . |
| char signature[256]; |
| sprintf(signature, |
| "(Ljava/lang/String;)[L%s;", |
| AndroidJavaCaptureCapabilityClass); |
| jmethodID cid = env->GetMethodID(javaCmDevInfoClass, |
| "GetCapabilityArray", |
| signature); |
| if (cid == NULL) { |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, |
| "%s: Can't find method GetCapabilityArray.", __FUNCTION__); |
| return -1; |
| } |
| // Create a jstring so we can pass the deviceUniquName to the java method. |
| jstring capureIdString = env->NewStringUTF((char*) deviceUniqueIdUTF8); |
| |
| if (capureIdString == NULL) { |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, |
| "%s: Can't create string for method GetCapabilityArray.", |
| __FUNCTION__); |
| return -1; |
| } |
| // Call the java class and get an array with capabilities back. |
| jobject javaCapabilitiesObj = env->CallObjectMethod(javaCmDevInfoObject, |
| cid, capureIdString); |
| if (!javaCapabilitiesObj) { |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, |
| "%s: Failed to call java GetCapabilityArray.", |
| __FUNCTION__); |
| return -1; |
| } |
| |
| jfieldID widthField = env->GetFieldID(javaCapClassLocal, "width", "I"); |
| jfieldID heigtField = env->GetFieldID(javaCapClassLocal, "height", "I"); |
| jfieldID maxFpsField = env->GetFieldID(javaCapClassLocal, "maxFPS", "I"); |
| if (widthField == NULL || heigtField == NULL || maxFpsField == NULL) { |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, |
| "%s: Failed to get field Id.", __FUNCTION__); |
| return -1; |
| } |
| |
| const jsize numberOfCapabilities = |
| env->GetArrayLength((jarray) javaCapabilitiesObj); |
| |
| for (jsize i = 0; i < numberOfCapabilities; ++i) { |
| VideoCaptureCapability *cap = new VideoCaptureCapability(); |
| jobject capabilityElement = env->GetObjectArrayElement( |
| (jobjectArray) javaCapabilitiesObj, |
| i); |
| |
| cap->width = env->GetIntField(capabilityElement, widthField); |
| cap->height = env->GetIntField(capabilityElement, heigtField); |
| cap->expectedCaptureDelay = _expectedCaptureDelay; |
| cap->rawType = kVideoNV21; |
| cap->maxFPS = env->GetIntField(capabilityElement, maxFpsField); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, |
| "%s: Cap width %d, height %d, fps %d", __FUNCTION__, |
| cap->width, cap->height, cap->maxFPS); |
| _captureCapabilities.Insert(i, cap); |
| } |
| |
| _lastUsedDeviceNameLength = strlen((char*) deviceUniqueIdUTF8); |
| _lastUsedDeviceName = (char*) realloc(_lastUsedDeviceName, |
| _lastUsedDeviceNameLength + 1); |
| memcpy(_lastUsedDeviceName, |
| deviceUniqueIdUTF8, |
| _lastUsedDeviceNameLength + 1); |
| |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, |
| "CreateCapabilityMap %d", _captureCapabilities.Size()); |
| |
| return _captureCapabilities.Size(); |
| } |
| |
| WebRtc_Word32 DeviceInfoAndroid::GetOrientation( |
| const char* deviceUniqueIdUTF8, |
| VideoCaptureRotation& orientation) { |
| JNIEnv *env; |
| jclass javaCmDevInfoClass; |
| jobject javaCmDevInfoObject; |
| bool attached = false; |
| if (VideoCaptureAndroid::AttachAndUseAndroidDeviceInfoObjects( |
| env, |
| javaCmDevInfoClass, |
| javaCmDevInfoObject, |
| attached) != 0) |
| return -1; |
| |
| // get the method ID for the Android Java GetOrientation . |
| jmethodID cid = env->GetMethodID(javaCmDevInfoClass, "GetOrientation", |
| "(Ljava/lang/String;)I"); |
| if (cid == NULL) { |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, |
| "%s: Can't find method GetOrientation.", __FUNCTION__); |
| return -1; |
| } |
| // Create a jstring so we can pass the deviceUniquName to the java method. |
| jstring capureIdString = env->NewStringUTF((char*) deviceUniqueIdUTF8); |
| if (capureIdString == NULL) { |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, |
| "%s: Can't create string for method GetCapabilityArray.", |
| __FUNCTION__); |
| return -1; |
| } |
| // Call the java class and get the orientation. |
| jint jorientation = env->CallIntMethod(javaCmDevInfoObject, cid, |
| capureIdString); |
| VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); |
| |
| WebRtc_Word32 retValue = 0; |
| switch (jorientation) { |
| case -1: // Error |
| orientation = kCameraRotate0; |
| retValue = -1; |
| break; |
| case 0: |
| orientation = kCameraRotate0; |
| break; |
| case 90: |
| orientation = kCameraRotate90; |
| break; |
| case 180: |
| orientation = kCameraRotate180; |
| break; |
| case 270: |
| orientation = kCameraRotate270; |
| break; |
| case 360: |
| orientation = kCameraRotate0; |
| break; |
| } |
| return retValue; |
| } |
| |
| } // namespace videocapturemodule |
| } // namespace webrtc |