blob: f5abbc91cbf05fc9a1ecb09d7947acd0406ae911 [file] [log] [blame]
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "video_capture_android.h"
12
13#include <stdio.h>
14
15#include "critical_section_wrapper.h"
16#include "ref_count.h"
17#include "trace.h"
18
19namespace webrtc
20{
21#if defined(WEBRTC_ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
22// TODO(leozwang) These SetAndroidVM apis will be refactored, thus we only
23// keep and reference java vm.
24WebRtc_Word32 SetCaptureAndroidVM(void* javaVM, void* javaContext) {
25 return videocapturemodule::VideoCaptureAndroid::SetAndroidObjects(
26 javaVM,
27 javaContext);
28}
29#endif
30
31namespace videocapturemodule
32{
33
34VideoCaptureModule* VideoCaptureImpl::Create(
35 const WebRtc_Word32 id,
36 const char* deviceUniqueIdUTF8) {
37
38 RefCountImpl<videocapturemodule::VideoCaptureAndroid>* implementation =
39 new RefCountImpl<videocapturemodule::VideoCaptureAndroid>(id);
40
41 if (!implementation || implementation->Init(id, deviceUniqueIdUTF8) != 0) {
42 delete implementation;
43 implementation = NULL;
44 }
45 return implementation;
46}
47
48// Android logging, uncomment to print trace to
49// logcat instead of trace file/callback
50// #include <android/log.h>
51// #undef WEBRTC_TRACE
52// #define WEBRTC_TRACE(a,b,c,...)
53// __android_log_print(ANDROID_LOG_DEBUG, "*WEBRTCN*", __VA_ARGS__)
54
55JavaVM* VideoCaptureAndroid::g_jvm = NULL;
56//VideoCaptureAndroid.java
57jclass VideoCaptureAndroid::g_javaCmClass = NULL;
58//VideoCaptureDeviceInfoAndroid.java
59jclass VideoCaptureAndroid::g_javaCmDevInfoClass = NULL;
60//static instance of VideoCaptureDeviceInfoAndroid.java
61jobject VideoCaptureAndroid::g_javaCmDevInfoObject = NULL;
62jobject VideoCaptureAndroid::g_javaContext = NULL;
63
64/*
65 * Register references to Java Capture class.
66 */
67WebRtc_Word32 VideoCaptureAndroid::SetAndroidObjects(void* javaVM,
68 void* javaContext) {
69
70 g_jvm = static_cast<JavaVM*> (javaVM);
71 g_javaContext = static_cast<jobject> (javaContext);
72
73 if (javaVM) {
74 JNIEnv* env = NULL;
75 if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
76 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
77 "%s: could not get Java environment", __FUNCTION__);
78 return -1;
79 }
80 // get java capture class type (note path to class packet)
81 jclass javaCmClassLocal = env->FindClass(AndroidJavaCaptureClass);
82 if (!javaCmClassLocal) {
83 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
84 "%s: could not find java class", __FUNCTION__);
85 return -1;
86 }
87 // create a global reference to the class
88 // (to tell JNI that we are referencing it
89 // after this function has returned)
90 g_javaCmClass = static_cast<jclass>
91 (env->NewGlobalRef(javaCmClassLocal));
92 if (!g_javaCmClass) {
93 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
94 "%s: InitVideoEngineJava(): could not create"
95 " Java Camera class reference",
96 __FUNCTION__);
97 return -1;
98 }
99 // Delete local class ref, we only use the global ref
100 env->DeleteLocalRef(javaCmClassLocal);
101 JNINativeMethod nativeFunctions =
102 { "ProvideCameraFrame", "([BIJ)V",
103 (void*) &VideoCaptureAndroid::ProvideCameraFrame };
104 if (env->RegisterNatives(g_javaCmClass, &nativeFunctions, 1) == 0) {
105 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
106 "%s: Registered native functions", __FUNCTION__);
107 }
108 else {
109 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
110 "%s: Failed to register native functions",
111 __FUNCTION__);
112 return -1;
113 }
114
115 // get java capture class type (note path to class packet)
116 jclass javaCmDevInfoClassLocal = env->FindClass(
117 AndroidJavaCaptureDeviceInfoClass);
118 if (!javaCmDevInfoClassLocal) {
119 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
120 "%s: could not find java class", __FUNCTION__);
121 return -1;
122 }
123
124 // create a global reference to the class
125 // (to tell JNI that we are referencing it
126 // after this function has returned)
127 g_javaCmDevInfoClass = static_cast<jclass>
128 (env->NewGlobalRef(javaCmDevInfoClassLocal));
129 if (!g_javaCmDevInfoClass) {
130 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
131 "%s: InitVideoEngineJava(): could not create Java "
132 "Camera Device info class reference",
133 __FUNCTION__);
134 return -1;
135 }
136 // Delete local class ref, we only use the global ref
137 env->DeleteLocalRef(javaCmDevInfoClassLocal);
138
139 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
140 "VideoCaptureDeviceInfoAndroid get method id");
141
142 // get the method ID for the Android Java CaptureClass static
143 //CreateVideoCaptureAndroid factory method.
144 jmethodID cid = env->GetStaticMethodID(
145 g_javaCmDevInfoClass,
146 "CreateVideoCaptureDeviceInfoAndroid",
147 "(ILandroid/content/Context;)"
148 "Lorg/webrtc/videoengine/VideoCaptureDeviceInfoAndroid;");
149 if (cid == NULL) {
150 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
151 "%s: could not get java"
152 "VideoCaptureDeviceInfoAndroid constructor ID",
153 __FUNCTION__);
154 return -1;
155 }
156
157 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
158 "%s: construct static java device object", __FUNCTION__);
159
160 // construct the object by calling the static constructor object
161 jobject javaCameraDeviceInfoObjLocal =
162 env->CallStaticObjectMethod(g_javaCmDevInfoClass,
163 cid, (int) -1,
164 g_javaContext);
165 if (!javaCameraDeviceInfoObjLocal) {
166 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, -1,
167 "%s: could not create Java Capture Device info object",
168 __FUNCTION__);
169 return -1;
170 }
171 // create a reference to the object (to tell JNI that
172 // we are referencing it after this function has returned)
173 g_javaCmDevInfoObject = env->NewGlobalRef(javaCameraDeviceInfoObjLocal);
174 if (!g_javaCmDevInfoObject) {
175 WEBRTC_TRACE(webrtc::kTraceError,
176 webrtc::kTraceAudioDevice,
177 -1,
178 "%s: could not create Java"
179 "cameradevinceinfo object reference",
180 __FUNCTION__);
181 return -1;
182 }
183 // Delete local object ref, we only use the global ref
184 env->DeleteLocalRef(javaCameraDeviceInfoObjLocal);
185 return 0;
186 }
187 else {
188 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
189 "%s: JVM is NULL, assuming deinit", __FUNCTION__);
190 if (!g_jvm) {
191 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
192 "%s: SetAndroidObjects not called with a valid JVM.",
193 __FUNCTION__);
194 return -1;
195 }
196 JNIEnv* env = NULL;
197 bool attached = false;
198 if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
199 // try to attach the thread and get the env
200 // Attach this thread to JVM
201 jint res = g_jvm->AttachCurrentThread(&env, NULL);
202 if ((res < 0) || !env) {
203 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture,
204 -1, "%s: Could not attach thread to JVM (%d, %p)",
205 __FUNCTION__, res, env);
206 return -1;
207 }
208 attached = true;
209 }
210 env->DeleteGlobalRef(g_javaCmDevInfoObject);
211 env->DeleteGlobalRef(g_javaCmDevInfoClass);
212 env->DeleteGlobalRef(g_javaCmClass);
213 if (attached && g_jvm->DetachCurrentThread() < 0) {
214 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, -1,
215 "%s: Could not detach thread from JVM", __FUNCTION__);
216 return -1;
217 }
218 return 0;
219 env = (JNIEnv *) NULL;
220 }
221 return 0;
222}
223
224WebRtc_Word32 VideoCaptureAndroid::AttachAndUseAndroidDeviceInfoObjects(
225 JNIEnv*& env,
226 jclass& javaCmDevInfoClass,
227 jobject& javaCmDevInfoObject,
228 bool& attached) {
229 // get the JNI env for this thread
230 if (!g_jvm) {
231 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
232 "%s: SetAndroidObjects not called with a valid JVM.",
233 __FUNCTION__);
234 return -1;
235 }
236 attached = false;
237 if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
238 // try to attach the thread and get the env
239 // Attach this thread to JVM
240 jint res = g_jvm->AttachCurrentThread(&env, NULL);
241 if ((res < 0) || !env) {
242 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
243 "%s: Could not attach thread to JVM (%d, %p)",
244 __FUNCTION__, res, env);
245 return -1;
246 }
247 attached = true;
248 }
249 javaCmDevInfoClass = g_javaCmDevInfoClass;
250 javaCmDevInfoObject = g_javaCmDevInfoObject;
251 return 0;
252
253}
254
255WebRtc_Word32 VideoCaptureAndroid::ReleaseAndroidDeviceInfoObjects(
256 bool attached) {
257 if (attached && g_jvm->DetachCurrentThread() < 0) {
258 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, -1,
259 "%s: Could not detach thread from JVM", __FUNCTION__);
260 return -1;
261 }
262 return 0;
263}
264
265/*
266 * JNI callback from Java class. Called
267 * when the camera has a new frame to deliver
268 * Class: org_webrtc_capturemodule_VideoCaptureAndroid
269 * Method: ProvideCameraFrame
270 * Signature: ([BIJ)V
271 */
272void JNICALL VideoCaptureAndroid::ProvideCameraFrame(JNIEnv * env,
273 jobject,
274 jbyteArray javaCameraFrame,
275 jint length,
276 jlong context) {
277 VideoCaptureAndroid* captureModule =
278 reinterpret_cast<VideoCaptureAndroid*>(context);
279 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture,
280 -1, "%s: IncomingFrame %d", __FUNCTION__,length);
281 jbyte* cameraFrame= env->GetByteArrayElements(javaCameraFrame,NULL);
282 captureModule->IncomingFrame((WebRtc_UWord8*) cameraFrame,
283 length,captureModule->_frameInfo,0);
284 env->ReleaseByteArrayElements(javaCameraFrame,cameraFrame,JNI_ABORT);
285}
286
287
288
289VideoCaptureAndroid::VideoCaptureAndroid(const WebRtc_Word32 id)
290 : VideoCaptureImpl(id), _capInfo(id), _javaCaptureObj(NULL),
291 _captureStarted(false) {
292 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
293 "%s: context %x", __FUNCTION__, (int) this);
294}
295
296// ----------------------------------------------------------------------------
297// Init
298//
299// Initializes needed Java resources like the JNI interface to
300// VideoCaptureAndroid.java
301// ----------------------------------------------------------------------------
302WebRtc_Word32 VideoCaptureAndroid::Init(const WebRtc_Word32 id,
303 const char* deviceUniqueIdUTF8) {
304 const int nameLength = strlen(deviceUniqueIdUTF8);
305 if (nameLength >= kVideoCaptureUniqueNameLength) {
306 return -1;
307 }
308
309 // Store the device name
310 _deviceUniqueId = new char[nameLength + 1];
311 memcpy(_deviceUniqueId, deviceUniqueIdUTF8, nameLength + 1);
312
313 if (_capInfo.Init() != 0) {
314 WEBRTC_TRACE(webrtc::kTraceError,
315 webrtc::kTraceVideoCapture,
316 _id,
317 "%s: Failed to initialize CaptureDeviceInfo",
318 __FUNCTION__);
319 return -1;
320 }
321
322 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1, "%s:",
323 __FUNCTION__);
324 // use the jvm that has been set
325 if (!g_jvm) {
326 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
327 "%s: Not a valid Java VM pointer", __FUNCTION__);
328 return -1;
329 }
330 // get the JNI env for this thread
331 JNIEnv *env;
332 bool isAttached = false;
333
334 // get the JNI env for this thread
335 if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
336 // try to attach the thread and get the env
337 // Attach this thread to JVM
338 jint res = g_jvm->AttachCurrentThread(&env, NULL);
339 if ((res < 0) || !env) {
340 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
341 "%s: Could not attach thread to JVM (%d, %p)",
342 __FUNCTION__, res, env);
343 return -1;
344 }
345 isAttached = true;
346 }
347
348 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, _id,
349 "get method id");
350
351 // get the method ID for the Android Java
352 // CaptureDeviceInfoClass AllocateCamera factory method.
353 char signature[256];
354 sprintf(signature, "(IJLjava/lang/String;)L%s;", AndroidJavaCaptureClass);
355
356 jmethodID cid = env->GetMethodID(g_javaCmDevInfoClass, "AllocateCamera",
357 signature);
358 if (cid == NULL) {
359 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
360 "%s: could not get constructor ID", __FUNCTION__);
361 return -1; /* exception thrown */
362 }
363
364 jstring capureIdString = env->NewStringUTF((char*) deviceUniqueIdUTF8);
365 // construct the object by calling the static constructor object
366 jobject javaCameraObjLocal = env->CallObjectMethod(g_javaCmDevInfoObject,
367 cid, (jint) id,
368 (jlong) this,
369 capureIdString);
370 if (!javaCameraObjLocal) {
371 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
372 "%s: could not create Java Capture object", __FUNCTION__);
373 return -1;
374 }
375
376 // create a reference to the object (to tell JNI that we are referencing it
377 // after this function has returned)
378 _javaCaptureObj = env->NewGlobalRef(javaCameraObjLocal);
379 if (!_javaCaptureObj) {
380 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioDevice, _id,
381 "%s: could not create Java camera object reference",
382 __FUNCTION__);
383 return -1;
384 }
385
386 // Delete local object ref, we only use the global ref
387 env->DeleteLocalRef(javaCameraObjLocal);
388
389 // Detach this thread if it was attached
390 if (isAttached) {
391 if (g_jvm->DetachCurrentThread() < 0) {
392 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice, _id,
393 "%s: Could not detach thread from JVM", __FUNCTION__);
394 }
395 }
396
397 return 0;
398}
399
400VideoCaptureAndroid::~VideoCaptureAndroid() {
401 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1, "%s:",
402 __FUNCTION__);
403 if (_javaCaptureObj == NULL || g_jvm == NULL) {
404 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
405 "%s: Nothing to clean", __FUNCTION__);
406 }
407 else {
408 bool isAttached = false;
409 // get the JNI env for this thread
410 JNIEnv *env;
411 if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
412 // try to attach the thread and get the env
413 // Attach this thread to JVM
414 jint res = g_jvm->AttachCurrentThread(&env, NULL);
415 if ((res < 0) || !env) {
416 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture,
417 _id,
418 "%s: Could not attach thread to JVM (%d, %p)",
419 __FUNCTION__, res, env);
420 }
421 else {
422 isAttached = true;
423 }
424 }
425
426 // get the method ID for the Android Java CaptureClass static
427 // DeleteVideoCaptureAndroid method. Call this to release the camera so
428 // another application can use it.
429 jmethodID cid = env->GetStaticMethodID(
430 g_javaCmClass,
431 "DeleteVideoCaptureAndroid",
432 "(Lorg/webrtc/videoengine/VideoCaptureAndroid;)V");
433 if (cid != NULL) {
434 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
435 "%s: Call DeleteVideoCaptureAndroid", __FUNCTION__);
436 // Close the camera by calling the static destruct function.
437 env->CallStaticVoidMethod(g_javaCmClass, cid, _javaCaptureObj);
438
439 // Delete global object ref to the camera.
440 env->DeleteGlobalRef(_javaCaptureObj);
441 _javaCaptureObj = NULL;
442 }
443 else {
444 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
445 "%s: Failed to find DeleteVideoCaptureAndroid id",
446 __FUNCTION__);
447 }
448
449 // Detach this thread if it was attached
450 if (isAttached) {
451 if (g_jvm->DetachCurrentThread() < 0) {
452 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice,
453 _id, "%s: Could not detach thread from JVM",
454 __FUNCTION__);
455 }
456 }
457 }
458}
459
460WebRtc_Word32 VideoCaptureAndroid::StartCapture(
461 const VideoCaptureCapability& capability) {
462 CriticalSectionScoped cs(&_apiCs);
463 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
464 "%s: ", __FUNCTION__);
465
466 bool isAttached = false;
467 WebRtc_Word32 result = 0;
468 // get the JNI env for this thread
469 JNIEnv *env;
470 if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
471 // try to attach the thread and get the env
472 // Attach this thread to JVM
473 jint res = g_jvm->AttachCurrentThread(&env, NULL);
474 if ((res < 0) || !env) {
475 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
476 "%s: Could not attach thread to JVM (%d, %p)",
477 __FUNCTION__, res, env);
478 }
479 else {
480 isAttached = true;
481 }
482 }
483
484 if (_capInfo.GetBestMatchedCapability(_deviceUniqueId, capability,
485 _frameInfo) < 0) {
486 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
487 "%s: GetBestMatchedCapability failed. Req cap w%d h%d",
488 __FUNCTION__, capability.width, capability.height);
489 return -1;
490 }
491
492 // Store the new expected capture delay
493 _captureDelay = _frameInfo.expectedCaptureDelay;
494
495 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
496 "%s: _frameInfo w%d h%d", __FUNCTION__, _frameInfo.width,
497 _frameInfo.height);
498
499 // get the method ID for the Android Java
500 // CaptureClass static StartCapture method.
501 jmethodID cid = env->GetMethodID(g_javaCmClass, "StartCapture", "(III)I");
502 if (cid != NULL) {
503 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
504 "%s: Call StartCapture", __FUNCTION__);
505 // Close the camera by calling the static destruct function.
506 result = env->CallIntMethod(_javaCaptureObj, cid, _frameInfo.width,
507 _frameInfo.height, _frameInfo.maxFPS);
508 }
509 else {
510 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
511 "%s: Failed to find StartCapture id", __FUNCTION__);
512 }
513
514 // Detach this thread if it was attached
515 if (isAttached) {
516 if (g_jvm->DetachCurrentThread() < 0) {
517 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice, _id,
518 "%s: Could not detach thread from JVM", __FUNCTION__);
519 }
520 }
521 if (result == 0) {
522 _requestedCapability = capability;
523 _captureStarted = true;
524 }
525 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
526 "%s: result %d", __FUNCTION__, result);
527 return result;
528}
529
530WebRtc_Word32 VideoCaptureAndroid::StopCapture() {
531 CriticalSectionScoped cs(&_apiCs);
532 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
533 "%s: ", __FUNCTION__);
534
535 bool isAttached = false;
536 WebRtc_Word32 result = 0;
537 // get the JNI env for this thread
538 JNIEnv *env = NULL;
539 if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
540 // try to attach the thread and get the env
541 // Attach this thread to JVM
542 jint res = g_jvm->AttachCurrentThread(&env, NULL);
543 if ((res < 0) || !env) {
544 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
545 "%s: Could not attach thread to JVM (%d, %p)",
546 __FUNCTION__, res, env);
547 }
548 else {
549 isAttached = true;
550 }
551 }
552
553 memset(&_requestedCapability, 0, sizeof(_requestedCapability));
554 memset(&_frameInfo, 0, sizeof(_frameInfo));
555
556 // get the method ID for the Android Java CaptureClass StopCapture method.
557 jmethodID cid = env->GetMethodID(g_javaCmClass, "StopCapture", "()I");
558 if (cid != NULL) {
559 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
560 "%s: Call StopCapture", __FUNCTION__);
561 // Close the camera by calling the static destruct function.
562 result = env->CallIntMethod(_javaCaptureObj, cid);
563 }
564 else {
565 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
566 "%s: Failed to find StopCapture id", __FUNCTION__);
567 }
568
569 // Detach this thread if it was attached
570 if (isAttached) {
571 if (g_jvm->DetachCurrentThread() < 0) {
572 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice, _id,
573 "%s: Could not detach thread from JVM", __FUNCTION__);
574 }
575 }
576 _captureStarted = false;
577
578 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
579 "%s: result %d", __FUNCTION__, result);
580 return result;
581}
582
583bool VideoCaptureAndroid::CaptureStarted() {
584 CriticalSectionScoped cs(&_apiCs);
585 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
586 "%s: ", __FUNCTION__);
587 return _captureStarted;
588}
589
590WebRtc_Word32 VideoCaptureAndroid::CaptureSettings(
591 VideoCaptureCapability& settings) {
592 CriticalSectionScoped cs(&_apiCs);
593 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, -1,
594 "%s: ", __FUNCTION__);
595 settings = _requestedCapability;
596 return 0;
597}
598
599WebRtc_Word32 VideoCaptureAndroid::SetCaptureRotation(
600 VideoCaptureRotation rotation) {
601 CriticalSectionScoped cs(&_apiCs);
602 if (VideoCaptureImpl::SetCaptureRotation(rotation) == 0) {
603 if (!g_jvm)
604 return -1;
605
606 // get the JNI env for this thread
607 JNIEnv *env;
608 bool isAttached = false;
609
610 // get the JNI env for this thread
611 if (g_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
612 // try to attach the thread and get the env
613 // Attach this thread to JVM
614 jint res = g_jvm->AttachCurrentThread(&env, NULL);
615 if ((res < 0) || !env) {
616 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture,
617 _id,
618 "%s: Could not attach thread to JVM (%d, %p)",
619 __FUNCTION__, res, env);
620 return -1;
621 }
622 isAttached = true;
623 }
624
625 jmethodID cid = env->GetMethodID(g_javaCmClass, "SetPreviewRotation",
626 "(I)V");
627 if (cid == NULL) {
628 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
629 "%s: could not get java SetPreviewRotation ID",
630 __FUNCTION__);
631 return -1;
632 }
633 jint rotateFrame = 0;
634 switch (rotation) {
635 case kCameraRotate0:
636 rotateFrame = 0;
637 break;
638 case kCameraRotate90:
639 rotateFrame = 90;
640 break;
641 case kCameraRotate180:
642 rotateFrame = 180;
643 break;
644 case kCameraRotate270:
645 rotateFrame = 270;
646 break;
647 }
648 env->CallVoidMethod(_javaCaptureObj, cid, rotateFrame);
649
650 // Detach this thread if it was attached
651 if (isAttached) {
652 if (g_jvm->DetachCurrentThread() < 0) {
653 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice,
654 _id, "%s: Could not detach thread from JVM",
655 __FUNCTION__);
656 }
657 }
658
659 }
660 return 0;
661}
662
663} // namespace videocapturemodule
664} // namespace webrtc