1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1187c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/android/video_capture_android.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13d3d2598c721994a90907527bfda9a119fbc27db3fischman@webrtc.org#include "webrtc/base/common.h"
1481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org#include "webrtc/modules/utility/interface/helpers_android.h"
1581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org#include "webrtc/modules/video_capture/android/device_info_android.h"
1687c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
1781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org#include "webrtc/system_wrappers/interface/logcat_trace_context.h"
18ab52e9a726313a44423fe7a5988f4d1eff75a208glaznev@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
1987c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/ref_count.h"
2087c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace.h"
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgstatic JavaVM* g_jvm = NULL;
2381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgstatic jclass g_java_capturer_class = NULL;  // VideoCaptureAndroid.class.
245101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.orgstatic jobject g_context = NULL;  // Owned android.content.Context.
2581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
2681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgnamespace webrtc {
2781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
285101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org// Called by Java to get the global application context.
295101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.orgjobject JNICALL GetContext(JNIEnv* env, jclass) {
305101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  assert(g_context);
315101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  return g_context;
325101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org}
335101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org
3481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// Called by Java when the camera has a new frame to deliver.
3581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgvoid JNICALL ProvideCameraFrame(
3681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    JNIEnv* env,
3781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    jobject,
3881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    jbyteArray javaCameraFrame,
3981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    jint length,
40ab52e9a726313a44423fe7a5988f4d1eff75a208glaznev@webrtc.org    jlong timeStamp,
4181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    jlong context) {
4281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  webrtc::videocapturemodule::VideoCaptureAndroid* captureModule =
4381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      reinterpret_cast<webrtc::videocapturemodule::VideoCaptureAndroid*>(
4481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org          context);
4581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jbyte* cameraFrame = env->GetByteArrayElements(javaCameraFrame, NULL);
4681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  captureModule->OnIncomingFrame(
4781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      reinterpret_cast<uint8_t*>(cameraFrame), length, 0);
4881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  env->ReleaseByteArrayElements(javaCameraFrame, cameraFrame, JNI_ABORT);
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
515101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org// Called by Java when the device orientation has changed.
525101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.orgvoid JNICALL OnOrientationChanged(
535101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org    JNIEnv* env, jobject, jlong context, jint degrees) {
545101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  webrtc::videocapturemodule::VideoCaptureAndroid* captureModule =
555101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org      reinterpret_cast<webrtc::videocapturemodule::VideoCaptureAndroid*>(
565101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org          context);
575101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  degrees = (360 + degrees) % 360;
585101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  assert(degrees >= 0 && degrees < 360);
595101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  VideoCaptureRotation rotation =
605101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org      (degrees <= 45 || degrees > 315) ? kCameraRotate0 :
615101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org      (degrees > 45 && degrees <= 135) ? kCameraRotate90 :
625101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org      (degrees > 135 && degrees <= 225) ? kCameraRotate180 :
635101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org      (degrees > 225 && degrees <= 315) ? kCameraRotate270 :
645101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org      kCameraRotate0;  // Impossible.
655101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  int32_t status =
665101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org      captureModule->VideoCaptureImpl::SetCaptureRotation(rotation);
67d3d2598c721994a90907527bfda9a119fbc27db3fischman@webrtc.org  RTC_UNUSED(status);
685101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  assert(status == 0);
695101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org}
705101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org
715101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.orgint32_t SetCaptureAndroidVM(JavaVM* javaVM, jobject context) {
72ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org  if (javaVM) {
73ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    assert(!g_jvm);
74ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    g_jvm = javaVM;
75ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    AttachThreadScoped ats(g_jvm);
765101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org    g_context = ats.env()->NewGlobalRef(context);
7781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
78ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    videocapturemodule::DeviceInfoAndroid::Initialize(ats.env());
7981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
80ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    jclass j_capture_class =
81ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org        ats.env()->FindClass("org/webrtc/videoengine/VideoCaptureAndroid");
82ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    assert(j_capture_class);
83ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    g_java_capturer_class =
84ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org        reinterpret_cast<jclass>(ats.env()->NewGlobalRef(j_capture_class));
85ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    assert(g_java_capturer_class);
8681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
875101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org    JNINativeMethod native_methods[] = {
885101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org        {"GetContext",
895101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org         "()Landroid/content/Context;",
905101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org         reinterpret_cast<void*>(&GetContext)},
915101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org        {"OnOrientationChanged",
925101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org         "(JI)V",
935101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org         reinterpret_cast<void*>(&OnOrientationChanged)},
945101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org        {"ProvideCameraFrame",
95ab52e9a726313a44423fe7a5988f4d1eff75a208glaznev@webrtc.org         "([BIJJ)V",
965101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org         reinterpret_cast<void*>(&ProvideCameraFrame)}};
97ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    if (ats.env()->RegisterNatives(g_java_capturer_class,
985101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org                                   native_methods, 3) != 0)
99ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org      assert(false);
100ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org  } else {
101ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    if (g_jvm) {
102ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org      AttachThreadScoped ats(g_jvm);
103ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org      ats.env()->UnregisterNatives(g_java_capturer_class);
104ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org      ats.env()->DeleteGlobalRef(g_java_capturer_class);
105ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org      g_java_capturer_class = NULL;
1065101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org      ats.env()->DeleteGlobalRef(g_context);
1075101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org      g_context = NULL;
108ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org      videocapturemodule::DeviceInfoAndroid::DeInitialize();
109ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org      g_jvm = NULL;
110ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    }
111ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org  }
11281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
11381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return 0;
11481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org}
11581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
11681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgnamespace videocapturemodule {
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVideoCaptureModule* VideoCaptureImpl::Create(
119f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org    const int32_t id,
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const char* deviceUniqueIdUTF8) {
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  RefCountImpl<videocapturemodule::VideoCaptureAndroid>* implementation =
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      new RefCountImpl<videocapturemodule::VideoCaptureAndroid>(id);
12381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (implementation->Init(id, deviceUniqueIdUTF8) != 0) {
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete implementation;
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    implementation = NULL;
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return implementation;
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgint32_t VideoCaptureAndroid::OnIncomingFrame(uint8_t* videoFrame,
13181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org                                             int32_t videoFrameLength,
13281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org                                             int64_t captureTime) {
13382383d9b14ff8e5fedf5a70229eb0ac6b512909aglaznev@webrtc.org  if (!_captureStarted)
13482383d9b14ff8e5fedf5a70229eb0ac6b512909aglaznev@webrtc.org    return 0;
13581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return IncomingFrame(
13681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      videoFrame, videoFrameLength, _captureCapability, captureTime);
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
139f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgVideoCaptureAndroid::VideoCaptureAndroid(const int32_t id)
14081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    : VideoCaptureImpl(id),
14181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      _deviceInfo(id),
14281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      _jCapturer(NULL),
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      _captureStarted(false) {
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
146f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureAndroid::Init(const int32_t id,
147f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org                                  const char* deviceUniqueIdUTF8) {
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const int nameLength = strlen(deviceUniqueIdUTF8);
14981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (nameLength >= kVideoCaptureUniqueNameLength)
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Store the device name
153ab52e9a726313a44423fe7a5988f4d1eff75a208glaznev@webrtc.org  LOG(LS_INFO) << "VideoCaptureAndroid::Init: " << deviceUniqueIdUTF8;
154ab52e9a726313a44423fe7a5988f4d1eff75a208glaznev@webrtc.org  size_t camera_id = 0;
155ab52e9a726313a44423fe7a5988f4d1eff75a208glaznev@webrtc.org  if (!_deviceInfo.FindCameraIndex(deviceUniqueIdUTF8, &camera_id))
156ab52e9a726313a44423fe7a5988f4d1eff75a208glaznev@webrtc.org    return -1;
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  _deviceUniqueId = new char[nameLength + 1];
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(_deviceUniqueId, deviceUniqueIdUTF8, nameLength + 1);
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
16081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  AttachThreadScoped ats(g_jvm);
16181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  JNIEnv* env = ats.env();
16281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jmethodID ctor = env->GetMethodID(g_java_capturer_class, "<init>", "(IJ)V");
16381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  assert(ctor);
16481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jlong j_this = reinterpret_cast<intptr_t>(this);
16581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  _jCapturer = env->NewGlobalRef(
16681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      env->NewObject(g_java_capturer_class, ctor, camera_id, j_this));
16781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  assert(_jCapturer);
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVideoCaptureAndroid::~VideoCaptureAndroid() {
17281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  // Ensure Java camera is released even if our caller didn't explicitly Stop.
17381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (_captureStarted)
17481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    StopCapture();
17581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  AttachThreadScoped ats(g_jvm);
17681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  ats.env()->DeleteGlobalRef(_jCapturer);
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
179f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureAndroid::StartCapture(
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const VideoCaptureCapability& capability) {
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(&_apiCs);
18281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  AttachThreadScoped ats(g_jvm);
18381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  JNIEnv* env = ats.env();
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
18581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (_deviceInfo.GetBestMatchedCapability(
18681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org          _deviceUniqueId, capability, _captureCapability) < 0) {
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
18881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org                 "%s: GetBestMatchedCapability failed: %dx%d",
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 __FUNCTION__, capability.width, capability.height);
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  _captureDelay = _captureCapability.expectedCaptureDelay;
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jmethodID j_start =
19681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      env->GetMethodID(g_java_capturer_class, "startCapture", "(IIII)Z");
19781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  assert(j_start);
19881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  int min_mfps = 0;
19981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  int max_mfps = 0;
200b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org  _deviceInfo.GetMFpsRange(_deviceUniqueId, _captureCapability.maxFPS,
201b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org                           &min_mfps, &max_mfps);
20281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  bool started = env->CallBooleanMethod(_jCapturer, j_start,
20381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org                                        _captureCapability.width,
20481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org                                        _captureCapability.height,
20581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org                                        min_mfps, max_mfps);
20681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (started) {
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _requestedCapability = capability;
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _captureStarted = true;
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
21081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return started ? 0 : -1;
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
213f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureAndroid::StopCapture() {
21482383d9b14ff8e5fedf5a70229eb0ac6b512909aglaznev@webrtc.org  _apiCs.Enter();
21581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  AttachThreadScoped ats(g_jvm);
21681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  JNIEnv* env = ats.env();
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memset(&_requestedCapability, 0, sizeof(_requestedCapability));
21981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  memset(&_captureCapability, 0, sizeof(_captureCapability));
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  _captureStarted = false;
22182383d9b14ff8e5fedf5a70229eb0ac6b512909aglaznev@webrtc.org  // Exit critical section to avoid blocking camera thread inside
22282383d9b14ff8e5fedf5a70229eb0ac6b512909aglaznev@webrtc.org  // onIncomingFrame() call.
22382383d9b14ff8e5fedf5a70229eb0ac6b512909aglaznev@webrtc.org  _apiCs.Leave();
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
22581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jmethodID j_stop =
22681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      env->GetMethodID(g_java_capturer_class, "stopCapture", "()Z");
22781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return env->CallBooleanMethod(_jCapturer, j_stop) ? 0 : -1;
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VideoCaptureAndroid::CaptureStarted() {
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(&_apiCs);
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return _captureStarted;
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
235f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureAndroid::CaptureSettings(
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    VideoCaptureCapability& settings) {
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(&_apiCs);
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  settings = _requestedCapability;
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
242f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureAndroid::SetCaptureRotation(
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    VideoCaptureRotation rotation) {
2445101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  int32_t status = VideoCaptureImpl::SetCaptureRotation(rotation);
2455101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org  if (status != 0)
2465101f8464568c3233d0b95195247e2f63d9064cffischman@webrtc.org    return status;
24781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
24881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  AttachThreadScoped ats(g_jvm);
24981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  JNIEnv* env = ats.env();
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
25181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jmethodID j_spr =
25281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      env->GetMethodID(g_java_capturer_class, "setPreviewRotation", "(I)V");
25381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  assert(j_spr);
25481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  int rotation_degrees;
25581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (RotationInDegrees(rotation, &rotation_degrees) != 0) {
25681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    assert(false);
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
25881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  env->CallVoidMethod(_jCapturer, j_spr, rotation_degrees);
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace videocapturemodule
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
264