author | Gian-Carlo Pascutto <gpascutto@mozilla.com> |
Wed, 25 Sep 2013 08:08:37 +0200 | |
changeset 148639 | c57b52c33aabb03be19bd3f2deccb1a66d3268f6 |
parent 148638 | ca438424df3a272ec3acca0b46f2927c06b3fe8d |
child 148640 | a76652f60ecb0aea709ecbb246d056394753ca30 |
push id | 25349 |
push user | ryanvm@gmail.com |
push date | Wed, 25 Sep 2013 18:52:12 +0000 |
treeherder | mozilla-central@39f30376058c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | blassey |
bugs | 918372 |
milestone | 27.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/device_info_android.cc +++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/device_info_android.cc @@ -49,67 +49,60 @@ DeviceInfoAndroid::DeviceInfoAndroid(con int32_t DeviceInfoAndroid::Init() { return 0; } DeviceInfoAndroid::~DeviceInfoAndroid() { } uint32_t DeviceInfoAndroid::NumberOfDevices() { - JNIEnv *env; - jclass javaCmDevInfoClass; - jobject javaCmDevInfoObject; - bool attached = false; - if (VideoCaptureAndroid::AttachAndUseAndroidDeviceInfoObjects( - env, - javaCmDevInfoClass, - javaCmDevInfoObject, - attached) != 0) - return 0; + AutoLocalJNIFrame jniFrame; + JNIEnv* env = jniFrame.GetEnv(); + if (!env) + return 0; + + jclass javaCmDevInfoClass = jniFrame.GetCmDevInfoClass(); + jobject javaCmDevInfoObject = jniFrame.GetCmDevInfoObject(); 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; } int32_t DeviceInfoAndroid::GetDeviceName( uint32_t deviceNumber, char* deviceNameUTF8, uint32_t deviceNameLength, char* deviceUniqueIdUTF8, uint32_t deviceUniqueIdUTF8Length, char* /*productUniqueIdUTF8*/, uint32_t /*productUniqueIdUTF8Length*/) { - JNIEnv *env; - jclass javaCmDevInfoClass; - jobject javaCmDevInfoObject; int32_t result = 0; - bool attached = false; - if (VideoCaptureAndroid::AttachAndUseAndroidDeviceInfoObjects( - env, - javaCmDevInfoClass, - javaCmDevInfoObject, - attached)!= 0) - return -1; + AutoLocalJNIFrame jniFrame; + JNIEnv* env = jniFrame.GetEnv(); + if (!env) + return -1; + + jclass javaCmDevInfoClass = jniFrame.GetCmDevInfoClass(); + jobject javaCmDevInfoObject = jniFrame.GetCmDevInfoObject(); // 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) { @@ -148,90 +141,80 @@ int32_t DeviceInfoAndroid::GetDeviceName } 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; } int32_t 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; + AutoLocalJNIFrame jniFrame; + JNIEnv* env = jniFrame.GetEnv(); + if (!env) + return -1; + + jclass javaCmDevInfoClass = jniFrame.GetCmDevInfoClass(); + jobject javaCmDevInfoObject = jniFrame.GetCmDevInfoObject(); // Find the capability class jclass javaCapClass = jsjni_GetGlobalClassRef(AndroidJavaCaptureCapabilityClass); if (javaCapClass == NULL) { - VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, "%s: SetAndroidCaptureClasses must be called first!", __FUNCTION__); return -1; } // get the method ID for the Android Java GetCapabilityArray . jmethodID cid = env->GetMethodID( javaCmDevInfoClass, "GetCapabilityArray", "(Ljava/lang/String;)[Lorg/webrtc/videoengine/CaptureCapabilityAndroid;"); 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(javaCapClass, "width", "I"); jfieldID heigtField = env->GetFieldID(javaCapClass, "height", "I"); jfieldID maxFpsField = env->GetFieldID(javaCapClass, "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); @@ -256,59 +239,52 @@ int32_t DeviceInfoAndroid::CreateCapabil _lastUsedDeviceName = (char*) realloc(_lastUsedDeviceName, _lastUsedDeviceNameLength + 1); memcpy(_lastUsedDeviceName, deviceUniqueIdUTF8, _lastUsedDeviceNameLength + 1); env->DeleteGlobalRef(javaCapClass); - VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(attached); WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, "CreateCapabilityMap %d", _captureCapabilities.Size()); return _captureCapabilities.Size(); } int32_t 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; + AutoLocalJNIFrame jniFrame; + JNIEnv* env = jniFrame.GetEnv(); + if (!env) + return -1; + + jclass javaCmDevInfoClass = jniFrame.GetCmDevInfoClass(); + jobject javaCmDevInfoObject = jniFrame.GetCmDevInfoObject(); // 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); int32_t retValue = 0; switch (jorientation) { case -1: // Error orientation = kCameraRotate0; retValue = -1; break; case 0:
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc +++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc @@ -211,72 +211,16 @@ int32_t VideoCaptureAndroid::SetAndroidO return -1; } return 0; env = (JNIEnv *) NULL; } return 0; } -int32_t VideoCaptureAndroid::AttachAndUseAndroidDeviceInfoObjects( - JNIEnv*& env, - jclass& javaCmDevInfoClass, - jobject& javaCmDevInfoObject, - bool& attached) { - - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, - "%s: AttachAndUseAndroidDeviceInfoObj.", - __FUNCTION__); - - // get the JNI env for this thread - if (!g_jvm) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, - "%s: SetAndroidObjects not called with a valid JVM.", - __FUNCTION__); - return -1; - } - attached = false; - if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { - // try to attach the thread and get the env - // Attach this thread to JVM - jint res = g_jvm->AttachCurrentThread(&env, NULL); - if ((res < 0) || !env) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, - "%s: Could not attach thread to JVM (%d, %p)", - __FUNCTION__, res, env); - return -1; - } - attached = true; - WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, - "%s: attach success", __FUNCTION__); - } else { - WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, - "%s: did not attach because JVM Env present", __FUNCTION__); - } - MOZ_ASSERT(g_javaCmDevInfoClass != nullptr); - MOZ_ASSERT(g_javaCmDevInfoObject != nullptr); - javaCmDevInfoClass = g_javaCmDevInfoClass; - javaCmDevInfoObject = g_javaCmDevInfoObject; - return 0; - -} - -int32_t VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects( - bool attached) { - if (attached && g_jvm->DetachCurrentThread() < 0) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, -1, - "%s: Could not detach thread from JVM", __FUNCTION__); - return -1; - } else if (!attached) { - WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, - "%s: not attached, no detach", __FUNCTION__); - } - return 0; -} - /* * JNI callback from Java class. Called * when the camera has a new frame to deliver * Class: org_webrtc_capturemodule_VideoCaptureAndroid * Method: ProvideCameraFrame * Signature: ([BIJ)V */ void JNICALL VideoCaptureAndroid::ProvideCameraFrame(JNIEnv * env, @@ -350,54 +294,45 @@ int32_t VideoCaptureAndroid::Init(const WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1, "%s:", __FUNCTION__); // use the jvm that has been set if (!g_jvm) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, "%s: Not a valid Java VM pointer", __FUNCTION__); return -1; } - // get the JNI env for this thread - JNIEnv *env; - bool isAttached = false; - int32_t rotation = 0; - // get the JNI env for this thread - if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { - // try to attach the thread and get the env - // Attach this thread to JVM - jint res = g_jvm->AttachCurrentThread(&env, NULL); - if ((res < 0) || !env) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, - "%s: Could not attach thread to JVM (%d, %p)", - __FUNCTION__, res, env); + AutoLocalJNIFrame jniFrame; + JNIEnv* env = jniFrame.GetEnv(); + if (!env) return -1; - } - isAttached = true; - } + + jclass javaCmDevInfoClass = jniFrame.GetCmDevInfoClass(); + jobject javaCmDevInfoObject = jniFrame.GetCmDevInfoObject(); + + int32_t rotation = 0; WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, _id, "get method id"); - // get the method ID for the Android Java // CaptureDeviceInfoClass AllocateCamera factory method. char signature[256]; sprintf(signature, "(IJLjava/lang/String;)L%s;", AndroidJavaCaptureClass); - jmethodID cid = env->GetMethodID(g_javaCmDevInfoClass, "AllocateCamera", + jmethodID cid = env->GetMethodID(javaCmDevInfoClass, "AllocateCamera", signature); if (cid == NULL) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, "%s: could not get constructor ID", __FUNCTION__); return -1; /* exception thrown */ } jstring capureIdString = env->NewStringUTF((char*) deviceUniqueIdUTF8); // construct the object by calling the static constructor object - jobject javaCameraObjLocal = env->CallObjectMethod(g_javaCmDevInfoObject, + jobject javaCameraObjLocal = env->CallObjectMethod(javaCmDevInfoObject, cid, (jint) id, (jlong) this, capureIdString); if (!javaCameraObjLocal) { WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id, "%s: could not create Java Capture object", __FUNCTION__); return -1; } @@ -407,117 +342,68 @@ int32_t VideoCaptureAndroid::Init(const _javaCaptureObj = env->NewGlobalRef(javaCameraObjLocal); if (!_javaCaptureObj) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioDevice, _id, "%s: could not create Java camera object reference", __FUNCTION__); return -1; } - // Delete local object ref, we only use the global ref - env->DeleteLocalRef(javaCameraObjLocal); - - // Detach this thread if it was attached - if (isAttached) { - if (g_jvm->DetachCurrentThread() < 0) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice, _id, - "%s: Could not detach thread from JVM", __FUNCTION__); - } - } - return 0; } VideoCaptureAndroid::~VideoCaptureAndroid() { WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1, "%s:", __FUNCTION__); if (_javaCaptureObj == NULL || g_jvm == NULL) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, "%s: Nothing to clean", __FUNCTION__); } else { - bool isAttached = false; - // get the JNI env for this thread - JNIEnv *env; - if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { - // try to attach the thread and get the env - // Attach this thread to JVM - jint res = g_jvm->AttachCurrentThread(&env, NULL); - if ((res < 0) || !env) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, - _id, - "%s: Could not attach thread to JVM (%d, %p)", - __FUNCTION__, res, env); - } - else { - isAttached = true; - } - } + AutoLocalJNIFrame jniFrame; + JNIEnv* env = jniFrame.GetEnv(); + if (!env) + return; - if (env) { - // get the method ID for the Android Java CaptureClass static - // DeleteVideoCaptureAndroid method. Call this to release the camera so - // another application can use it. - jmethodID cid = env->GetStaticMethodID( - g_javaCmClass, - "DeleteVideoCaptureAndroid", - "(Lorg/webrtc/videoengine/VideoCaptureAndroid;)V"); - if (cid != NULL) { - WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1, - "%s: Call DeleteVideoCaptureAndroid", __FUNCTION__); - // Close the camera by calling the static destruct function. - env->CallStaticVoidMethod(g_javaCmClass, cid, _javaCaptureObj); + // get the method ID for the Android Java CaptureClass static + // DeleteVideoCaptureAndroid method. Call this to release the camera so + // another application can use it. + jmethodID cid = env->GetStaticMethodID(g_javaCmClass, + "DeleteVideoCaptureAndroid", + "(Lorg/webrtc/videoengine/VideoCaptureAndroid;)V"); + if (cid != NULL) { + WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1, + "%s: Call DeleteVideoCaptureAndroid", __FUNCTION__); + // Close the camera by calling the static destruct function. + env->CallStaticVoidMethod(g_javaCmClass, cid, _javaCaptureObj); - // Delete global object ref to the camera. - env->DeleteGlobalRef(_javaCaptureObj); - - _javaCaptureObj = NULL; - } - else { + // Delete global object ref to the camera. + env->DeleteGlobalRef(_javaCaptureObj); + _javaCaptureObj = NULL; + } else { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, "%s: Failed to find DeleteVideoCaptureAndroid id", __FUNCTION__); - } - } - - // Detach this thread if it was attached - if (isAttached) { - if (g_jvm->DetachCurrentThread() < 0) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice, - _id, "%s: Could not detach thread from JVM", - __FUNCTION__); - } } } } int32_t VideoCaptureAndroid::StartCapture( const VideoCaptureCapability& capability) { CriticalSectionScoped cs(&_apiCs); WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, "%s: ", __FUNCTION__); - bool isAttached = false; int32_t result = 0; int32_t rotation = 0; - // get the JNI env for this thread - JNIEnv *env; - if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { - // try to attach the thread and get the env - // Attach this thread to JVM - jint res = g_jvm->AttachCurrentThread(&env, NULL); - if ((res < 0) || !env) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, - "%s: Could not attach thread to JVM (%d, %p)", - __FUNCTION__, res, env); - } - else { - isAttached = true; - } - } + + AutoLocalJNIFrame jniFrame; + JNIEnv* env = jniFrame.GetEnv(); + if (!env) + return -1; if (_capInfo.GetBestMatchedCapability(_deviceUniqueId, capability, _frameInfo) < 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, "%s: GetBestMatchedCapability failed. Req cap w%d h%d", __FUNCTION__, capability.width, capability.height); return -1; } @@ -539,55 +425,36 @@ int32_t VideoCaptureAndroid::StartCaptur result = env->CallIntMethod(_javaCaptureObj, cid, _frameInfo.width, _frameInfo.height, _frameInfo.maxFPS); } else { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, "%s: Failed to find StartCapture id", __FUNCTION__); } - // Detach this thread if it was attached - if (isAttached) { - if (g_jvm->DetachCurrentThread() < 0) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice, _id, - "%s: Could not detach thread from JVM", __FUNCTION__); - } - } - if (result == 0) { _requestedCapability = capability; _captureStarted = true; } WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, "%s: result %d", __FUNCTION__, result); return result; } int32_t VideoCaptureAndroid::StopCapture() { CriticalSectionScoped cs(&_apiCs); WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, "%s: ", __FUNCTION__); - bool isAttached = false; int32_t result = 0; - // get the JNI env for this thread - JNIEnv *env = NULL; - if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { - // try to attach the thread and get the env - // Attach this thread to JVM - jint res = g_jvm->AttachCurrentThread(&env, NULL); - if ((res < 0) || !env) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, - "%s: Could not attach thread to JVM (%d, %p)", - __FUNCTION__, res, env); - } - else { - isAttached = true; - } - } + + AutoLocalJNIFrame jniFrame; + JNIEnv* env = jniFrame.GetEnv(); + if (!env) + return -1; memset(&_requestedCapability, 0, sizeof(_requestedCapability)); memset(&_frameInfo, 0, sizeof(_frameInfo)); // get the method ID for the Android Java CaptureClass StopCapture method. jmethodID cid = env->GetMethodID(g_javaCmClass, "StopCapture", "()I"); if (cid != NULL) { WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1, @@ -595,23 +462,16 @@ int32_t VideoCaptureAndroid::StopCapture // Close the camera by calling the static destruct function. result = env->CallIntMethod(_javaCaptureObj, cid); } else { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, "%s: Failed to find StopCapture id", __FUNCTION__); } - // Detach this thread if it was attached - if (isAttached) { - if (g_jvm->DetachCurrentThread() < 0) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice, _id, - "%s: Could not detach thread from JVM", __FUNCTION__); - } - } _captureStarted = false; WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, "%s: result %d", __FUNCTION__, result); return result; } bool VideoCaptureAndroid::CaptureStarted() {
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.h +++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.h @@ -7,60 +7,169 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_ANDROID_VIDEO_CAPTURE_ANDROID_H_ #define WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_ANDROID_VIDEO_CAPTURE_ANDROID_H_ #include <jni.h> +#include <assert.h> +#include "trace.h" #include "device_info_android.h" #include "../video_capture_impl.h" #define AndroidJavaCaptureClass "org/webrtc/videoengine/VideoCaptureAndroid" namespace webrtc { namespace videocapturemodule { class VideoCaptureAndroid : public VideoCaptureImpl { public: static int32_t SetAndroidObjects(void* javaVM, void* javaContext); - static int32_t AttachAndUseAndroidDeviceInfoObjects( - JNIEnv*& env, - jclass& javaCmDevInfoClass, - jobject& javaCmDevInfoObject, - bool& attached); - static int32_t ReleaseAndroidDeviceInfoObjects(bool attached); - VideoCaptureAndroid(const int32_t id); virtual int32_t Init(const int32_t id, const char* deviceUniqueIdUTF8); - virtual int32_t StartCapture( const VideoCaptureCapability& capability); virtual int32_t StopCapture(); virtual bool CaptureStarted(); virtual int32_t CaptureSettings(VideoCaptureCapability& settings); virtual int32_t SetCaptureRotation(VideoCaptureRotation rotation); + friend class AutoLocalJNIFrame; + protected: virtual ~VideoCaptureAndroid(); static void JNICALL ProvideCameraFrame (JNIEnv * env, jobject, jbyteArray javaCameraFrame, jint length, jint rotation, jlong context); DeviceInfoAndroid _capInfo; jobject _javaCaptureObj; // Java Camera object. VideoCaptureCapability _frameInfo; bool _captureStarted; - static JavaVM* g_jvm; static jclass g_javaCmClass; static jclass g_javaCmDevInfoClass; //Static java object implementing the needed device info functions; static jobject g_javaCmDevInfoObject; }; +// Reworked version of what is available in AndroidBridge, +// can attach/deatch in addition to push/pop frames. +class AutoLocalJNIFrame { +public: + AutoLocalJNIFrame(int nEntries = 128) + : mEntries(nEntries), mHasFrameBeenPushed(false), mAttached(false) + { + mJNIEnv = InitJNIEnv(); + Push(); + } + + JNIEnv* GetEnv() { + return mJNIEnv; + } + + jclass GetCmDevInfoClass() { + assert(VideoCaptureAndroid::g_javaCmDevInfoClass != nullptr); + return VideoCaptureAndroid::g_javaCmDevInfoClass; + } + + jobject GetCmDevInfoObject() { + assert(VideoCaptureAndroid::g_javaCmDevInfoObject != nullptr); + return VideoCaptureAndroid::g_javaCmDevInfoObject; + } + + bool CheckForException() { + if (mJNIEnv->ExceptionCheck()) { + mJNIEnv->ExceptionDescribe(); + mJNIEnv->ExceptionClear(); + return true; + } + + return false; + } + + ~AutoLocalJNIFrame() { + if (!mJNIEnv) + return; + + CheckForException(); + + if (mHasFrameBeenPushed) + mJNIEnv->PopLocalFrame(NULL); + + if (mAttached) { + int res = VideoCaptureAndroid::g_jvm->DetachCurrentThread(); + if (res < 0) { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, + "%s: JVM Detach failed.", __FUNCTION__); + } + } + } + +private: + void Push() { + if (!mJNIEnv) + return; + + // Make sure there is enough space to store a local ref to the + // exception. I am not completely sure this is needed, but does + // not hurt. + jint ret = mJNIEnv->PushLocalFrame(mEntries + 1); + assert(ret == 0); + if (ret < 0) + CheckForException(); + else + mHasFrameBeenPushed = true; + } + + JNIEnv* InitJNIEnv() + { + JNIEnv* env = nullptr; + + // Get the JNI env for this thread. + if (!VideoCaptureAndroid::g_jvm) { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, + "%s: SetAndroidObjects not called with a valid JVM.", + __FUNCTION__); + return nullptr; + } + + jint res = VideoCaptureAndroid::g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4); + if (res == JNI_EDETACHED) { + // Try to attach this thread to the JVM and get the env. + res = VideoCaptureAndroid::g_jvm->AttachCurrentThread(&env, NULL); + if ((res < 0) || !env) { + // Attaching failed, error out. + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, + "%s: Could not attach thread to JVM (%d, %p)", + __FUNCTION__, res, env); + return nullptr; + } + mAttached = true; + WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, + "%s: attach success", __FUNCTION__); + } else if (res == JNI_OK) { + // Already attached, GetEnv succeeded. + WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1, + "%s: did not attach because JVM Env already present", + __FUNCTION__); + } else { + // Non-recoverable error in GetEnv. + return nullptr; + } + + return env; + } + + int mEntries; + JNIEnv* mJNIEnv; + bool mHasFrameBeenPushed; + bool mAttached; +}; + } // namespace videocapturemodule } // namespace webrtc #endif // WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_ANDROID_VIDEO_CAPTURE_ANDROID_H_