
- The usual elimination of main/source etc. - Fully qualify "public" includes. - Use lowercase for all directory names. Review URL: https://webrtc-codereview.appspot.com/933010 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3025 4adac7df-926f-26a2-2b94-8c16560cd09d
665 lines
24 KiB
C++
665 lines
24 KiB
C++
/*
|
|
* 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 "video_capture_android.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "critical_section_wrapper.h"
|
|
#include "ref_count.h"
|
|
#include "trace.h"
|
|
|
|
namespace webrtc
|
|
{
|
|
#if defined(WEBRTC_ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
|
|
// TODO(leozwang) These SetAndroidVM apis will be refactored, thus we only
|
|
// keep and reference java vm.
|
|
WebRtc_Word32 SetCaptureAndroidVM(void* javaVM, void* javaContext) {
|
|
return videocapturemodule::VideoCaptureAndroid::SetAndroidObjects(
|
|
javaVM,
|
|
javaContext);
|
|
}
|
|
#endif
|
|
|
|
namespace videocapturemodule
|
|
{
|
|
|
|
VideoCaptureModule* VideoCaptureImpl::Create(
|
|
const WebRtc_Word32 id,
|
|
const char* deviceUniqueIdUTF8) {
|
|
|
|
RefCountImpl<videocapturemodule::VideoCaptureAndroid>* implementation =
|
|
new RefCountImpl<videocapturemodule::VideoCaptureAndroid>(id);
|
|
|
|
if (!implementation || implementation->Init(id, deviceUniqueIdUTF8) != 0) {
|
|
delete implementation;
|
|
implementation = NULL;
|
|
}
|
|
return implementation;
|
|
}
|
|
|
|
// Android logging, uncomment to print trace to
|
|
// logcat instead of trace file/callback
|
|
// #include <android/log.h>
|
|
// #undef WEBRTC_TRACE
|
|
// #define WEBRTC_TRACE(a,b,c,...)
|
|
// __android_log_print(ANDROID_LOG_DEBUG, "*WEBRTCN*", __VA_ARGS__)
|
|
|
|
JavaVM* VideoCaptureAndroid::g_jvm = NULL;
|
|
//VideoCaptureAndroid.java
|
|
jclass VideoCaptureAndroid::g_javaCmClass = NULL;
|
|
//VideoCaptureDeviceInfoAndroid.java
|
|
jclass VideoCaptureAndroid::g_javaCmDevInfoClass = NULL;
|
|
//static instance of VideoCaptureDeviceInfoAndroid.java
|
|
jobject VideoCaptureAndroid::g_javaCmDevInfoObject = NULL;
|
|
jobject VideoCaptureAndroid::g_javaContext = NULL;
|
|
|
|
/*
|
|
* Register references to Java Capture class.
|
|
*/
|
|
WebRtc_Word32 VideoCaptureAndroid::SetAndroidObjects(void* javaVM,
|
|
void* javaContext) {
|
|
|
|
g_jvm = static_cast<JavaVM*> (javaVM);
|
|
g_javaContext = static_cast<jobject> (javaContext);
|
|
|
|
if (javaVM) {
|
|
JNIEnv* env = NULL;
|
|
if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
|
|
"%s: could not get Java environment", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
// get java capture class type (note path to class packet)
|
|
jclass javaCmClassLocal = env->FindClass(AndroidJavaCaptureClass);
|
|
if (!javaCmClassLocal) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
|
|
"%s: could not find java class", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
// create a global reference to the class
|
|
// (to tell JNI that we are referencing it
|
|
// after this function has returned)
|
|
g_javaCmClass = static_cast<jclass>
|
|
(env->NewGlobalRef(javaCmClassLocal));
|
|
if (!g_javaCmClass) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
|
|
"%s: InitVideoEngineJava(): could not create"
|
|
" Java Camera class reference",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
// Delete local class ref, we only use the global ref
|
|
env->DeleteLocalRef(javaCmClassLocal);
|
|
JNINativeMethod nativeFunctions =
|
|
{ "ProvideCameraFrame", "([BIJ)V",
|
|
(void*) &VideoCaptureAndroid::ProvideCameraFrame };
|
|
if (env->RegisterNatives(g_javaCmClass, &nativeFunctions, 1) == 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
|
|
"%s: Registered native functions", __FUNCTION__);
|
|
}
|
|
else {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
|
|
"%s: Failed to register native functions",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
|
|
// get java capture class type (note path to class packet)
|
|
jclass javaCmDevInfoClassLocal = env->FindClass(
|
|
AndroidJavaCaptureDeviceInfoClass);
|
|
if (!javaCmDevInfoClassLocal) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
|
|
"%s: could not find java class", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
|
|
// create a global reference to the class
|
|
// (to tell JNI that we are referencing it
|
|
// after this function has returned)
|
|
g_javaCmDevInfoClass = static_cast<jclass>
|
|
(env->NewGlobalRef(javaCmDevInfoClassLocal));
|
|
if (!g_javaCmDevInfoClass) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
|
|
"%s: InitVideoEngineJava(): could not create Java "
|
|
"Camera Device info class reference",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
// Delete local class ref, we only use the global ref
|
|
env->DeleteLocalRef(javaCmDevInfoClassLocal);
|
|
|
|
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
|
|
"VideoCaptureDeviceInfoAndroid get method id");
|
|
|
|
// get the method ID for the Android Java CaptureClass static
|
|
//CreateVideoCaptureAndroid factory method.
|
|
jmethodID cid = env->GetStaticMethodID(
|
|
g_javaCmDevInfoClass,
|
|
"CreateVideoCaptureDeviceInfoAndroid",
|
|
"(ILandroid/content/Context;)"
|
|
"Lorg/webrtc/videoengine/VideoCaptureDeviceInfoAndroid;");
|
|
if (cid == NULL) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
|
|
"%s: could not get java"
|
|
"VideoCaptureDeviceInfoAndroid constructor ID",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
|
|
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
|
|
"%s: construct static java device object", __FUNCTION__);
|
|
|
|
// construct the object by calling the static constructor object
|
|
jobject javaCameraDeviceInfoObjLocal =
|
|
env->CallStaticObjectMethod(g_javaCmDevInfoClass,
|
|
cid, (int) -1,
|
|
g_javaContext);
|
|
if (!javaCameraDeviceInfoObjLocal) {
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, -1,
|
|
"%s: could not create Java Capture Device info object",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
// create a reference to the object (to tell JNI that
|
|
// we are referencing it after this function has returned)
|
|
g_javaCmDevInfoObject = env->NewGlobalRef(javaCameraDeviceInfoObjLocal);
|
|
if (!g_javaCmDevInfoObject) {
|
|
WEBRTC_TRACE(webrtc::kTraceError,
|
|
webrtc::kTraceAudioDevice,
|
|
-1,
|
|
"%s: could not create Java"
|
|
"cameradevinceinfo object reference",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
// Delete local object ref, we only use the global ref
|
|
env->DeleteLocalRef(javaCameraDeviceInfoObjLocal);
|
|
return 0;
|
|
}
|
|
else {
|
|
WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
|
|
"%s: JVM is NULL, assuming deinit", __FUNCTION__);
|
|
if (!g_jvm) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
|
|
"%s: SetAndroidObjects not called with a valid JVM.",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
JNIEnv* env = NULL;
|
|
bool 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;
|
|
}
|
|
env->DeleteGlobalRef(g_javaCmDevInfoObject);
|
|
env->DeleteGlobalRef(g_javaCmDevInfoClass);
|
|
env->DeleteGlobalRef(g_javaCmClass);
|
|
if (attached && g_jvm->DetachCurrentThread() < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, -1,
|
|
"%s: Could not detach thread from JVM", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
env = (JNIEnv *) NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
WebRtc_Word32 VideoCaptureAndroid::AttachAndUseAndroidDeviceInfoObjects(
|
|
JNIEnv*& env,
|
|
jclass& javaCmDevInfoClass,
|
|
jobject& javaCmDevInfoObject,
|
|
bool& attached) {
|
|
// 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;
|
|
}
|
|
javaCmDevInfoClass = g_javaCmDevInfoClass;
|
|
javaCmDevInfoObject = g_javaCmDevInfoObject;
|
|
return 0;
|
|
|
|
}
|
|
|
|
WebRtc_Word32 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;
|
|
}
|
|
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,
|
|
jobject,
|
|
jbyteArray javaCameraFrame,
|
|
jint length,
|
|
jlong context) {
|
|
VideoCaptureAndroid* captureModule =
|
|
reinterpret_cast<VideoCaptureAndroid*>(context);
|
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture,
|
|
-1, "%s: IncomingFrame %d", __FUNCTION__,length);
|
|
jbyte* cameraFrame= env->GetByteArrayElements(javaCameraFrame,NULL);
|
|
captureModule->IncomingFrame((WebRtc_UWord8*) cameraFrame,
|
|
length,captureModule->_frameInfo,0);
|
|
env->ReleaseByteArrayElements(javaCameraFrame,cameraFrame,JNI_ABORT);
|
|
}
|
|
|
|
|
|
|
|
VideoCaptureAndroid::VideoCaptureAndroid(const WebRtc_Word32 id)
|
|
: VideoCaptureImpl(id), _capInfo(id), _javaCaptureObj(NULL),
|
|
_captureStarted(false) {
|
|
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
|
|
"%s: context %x", __FUNCTION__, (int) this);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Init
|
|
//
|
|
// Initializes needed Java resources like the JNI interface to
|
|
// VideoCaptureAndroid.java
|
|
// ----------------------------------------------------------------------------
|
|
WebRtc_Word32 VideoCaptureAndroid::Init(const WebRtc_Word32 id,
|
|
const char* deviceUniqueIdUTF8) {
|
|
const int nameLength = strlen(deviceUniqueIdUTF8);
|
|
if (nameLength >= kVideoCaptureUniqueNameLength) {
|
|
return -1;
|
|
}
|
|
|
|
// Store the device name
|
|
_deviceUniqueId = new char[nameLength + 1];
|
|
memcpy(_deviceUniqueId, deviceUniqueIdUTF8, nameLength + 1);
|
|
|
|
if (_capInfo.Init() != 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError,
|
|
webrtc::kTraceVideoCapture,
|
|
_id,
|
|
"%s: Failed to initialize CaptureDeviceInfo",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
|
|
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;
|
|
|
|
// 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);
|
|
return -1;
|
|
}
|
|
isAttached = true;
|
|
}
|
|
|
|
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",
|
|
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,
|
|
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;
|
|
}
|
|
|
|
// create a reference to the object (to tell JNI that we are referencing it
|
|
// after this function has returned)
|
|
_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;
|
|
}
|
|
}
|
|
|
|
// 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 {
|
|
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__);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
WebRtc_Word32 VideoCaptureAndroid::StartCapture(
|
|
const VideoCaptureCapability& capability) {
|
|
CriticalSectionScoped cs(&_apiCs);
|
|
WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
|
|
"%s: ", __FUNCTION__);
|
|
|
|
bool isAttached = false;
|
|
WebRtc_Word32 result = 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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// Store the new expected capture delay
|
|
_captureDelay = _frameInfo.expectedCaptureDelay;
|
|
|
|
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
|
|
"%s: _frameInfo w%d h%d", __FUNCTION__, _frameInfo.width,
|
|
_frameInfo.height);
|
|
|
|
// get the method ID for the Android Java
|
|
// CaptureClass static StartCapture method.
|
|
jmethodID cid = env->GetMethodID(g_javaCmClass, "StartCapture", "(III)I");
|
|
if (cid != NULL) {
|
|
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
|
|
"%s: Call StartCapture", __FUNCTION__);
|
|
// Close the camera by calling the static destruct function.
|
|
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;
|
|
}
|
|
|
|
WebRtc_Word32 VideoCaptureAndroid::StopCapture() {
|
|
CriticalSectionScoped cs(&_apiCs);
|
|
WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
|
|
"%s: ", __FUNCTION__);
|
|
|
|
bool isAttached = false;
|
|
WebRtc_Word32 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;
|
|
}
|
|
}
|
|
|
|
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,
|
|
"%s: Call StopCapture", __FUNCTION__);
|
|
// 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() {
|
|
CriticalSectionScoped cs(&_apiCs);
|
|
WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
|
|
"%s: ", __FUNCTION__);
|
|
return _captureStarted;
|
|
}
|
|
|
|
WebRtc_Word32 VideoCaptureAndroid::CaptureSettings(
|
|
VideoCaptureCapability& settings) {
|
|
CriticalSectionScoped cs(&_apiCs);
|
|
WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
|
|
"%s: ", __FUNCTION__);
|
|
settings = _requestedCapability;
|
|
return 0;
|
|
}
|
|
|
|
WebRtc_Word32 VideoCaptureAndroid::SetCaptureRotation(
|
|
VideoCaptureRotation rotation) {
|
|
CriticalSectionScoped cs(&_apiCs);
|
|
if (VideoCaptureImpl::SetCaptureRotation(rotation) == 0) {
|
|
if (!g_jvm)
|
|
return -1;
|
|
|
|
// get the JNI env for this thread
|
|
JNIEnv *env;
|
|
bool isAttached = false;
|
|
|
|
// 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);
|
|
return -1;
|
|
}
|
|
isAttached = true;
|
|
}
|
|
|
|
jmethodID cid = env->GetMethodID(g_javaCmClass, "SetPreviewRotation",
|
|
"(I)V");
|
|
if (cid == NULL) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
|
|
"%s: could not get java SetPreviewRotation ID",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
jint rotateFrame = 0;
|
|
switch (rotation) {
|
|
case kCameraRotate0:
|
|
rotateFrame = 0;
|
|
break;
|
|
case kCameraRotate90:
|
|
rotateFrame = 90;
|
|
break;
|
|
case kCameraRotate180:
|
|
rotateFrame = 180;
|
|
break;
|
|
case kCameraRotate270:
|
|
rotateFrame = 270;
|
|
break;
|
|
}
|
|
env->CallVoidMethod(_javaCaptureObj, cid, rotateFrame);
|
|
|
|
// 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;
|
|
}
|
|
|
|
} // namespace videocapturemodule
|
|
} // namespace webrtc
|