2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/video_capture/android/video_capture_android.h"
13 #include "webrtc/modules/utility/interface/helpers_android.h"
14 #include "webrtc/modules/video_capture/android/device_info_android.h"
15 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
16 #include "webrtc/system_wrappers/interface/logcat_trace_context.h"
17 #include "webrtc/system_wrappers/interface/ref_count.h"
18 #include "webrtc/system_wrappers/interface/trace.h"
20 static JavaVM* g_jvm = NULL;
21 static jclass g_java_capturer_class = NULL; // VideoCaptureAndroid.class.
25 // Called by Java when the camera has a new frame to deliver.
26 void JNICALL ProvideCameraFrame(
29 jbyteArray javaCameraFrame,
32 webrtc::videocapturemodule::VideoCaptureAndroid* captureModule =
33 reinterpret_cast<webrtc::videocapturemodule::VideoCaptureAndroid*>(
35 jbyte* cameraFrame = env->GetByteArrayElements(javaCameraFrame, NULL);
36 captureModule->OnIncomingFrame(
37 reinterpret_cast<uint8_t*>(cameraFrame), length, 0);
38 env->ReleaseByteArrayElements(javaCameraFrame, cameraFrame, JNI_ABORT);
41 int32_t SetCaptureAndroidVM(JavaVM* javaVM) {
44 AttachThreadScoped ats(g_jvm);
46 videocapturemodule::DeviceInfoAndroid::Initialize(ats.env());
48 jclass j_capture_class =
49 ats.env()->FindClass("org/webrtc/videoengine/VideoCaptureAndroid");
50 assert(j_capture_class);
51 g_java_capturer_class =
52 reinterpret_cast<jclass>(ats.env()->NewGlobalRef(j_capture_class));
53 assert(g_java_capturer_class);
55 JNINativeMethod native_method = {
56 "ProvideCameraFrame", "([BIJ)V",
57 reinterpret_cast<void*>(&ProvideCameraFrame)
59 if (ats.env()->RegisterNatives(g_java_capturer_class, &native_method, 1) != 0)
65 namespace videocapturemodule {
67 VideoCaptureModule* VideoCaptureImpl::Create(
69 const char* deviceUniqueIdUTF8) {
70 RefCountImpl<videocapturemodule::VideoCaptureAndroid>* implementation =
71 new RefCountImpl<videocapturemodule::VideoCaptureAndroid>(id);
72 if (implementation->Init(id, deviceUniqueIdUTF8) != 0) {
73 delete implementation;
74 implementation = NULL;
76 return implementation;
79 int32_t VideoCaptureAndroid::OnIncomingFrame(uint8_t* videoFrame,
80 int32_t videoFrameLength,
81 int64_t captureTime) {
83 videoFrame, videoFrameLength, _captureCapability, captureTime);
86 VideoCaptureAndroid::VideoCaptureAndroid(const int32_t id)
87 : VideoCaptureImpl(id),
90 _captureStarted(false) {
93 int32_t VideoCaptureAndroid::Init(const int32_t id,
94 const char* deviceUniqueIdUTF8) {
95 const int nameLength = strlen(deviceUniqueIdUTF8);
96 if (nameLength >= kVideoCaptureUniqueNameLength)
99 // Store the device name
100 _deviceUniqueId = new char[nameLength + 1];
101 memcpy(_deviceUniqueId, deviceUniqueIdUTF8, nameLength + 1);
103 AttachThreadScoped ats(g_jvm);
104 JNIEnv* env = ats.env();
106 jmethodID ctor = env->GetMethodID(g_java_capturer_class, "<init>", "(IJ)V");
108 jlong j_this = reinterpret_cast<intptr_t>(this);
109 size_t camera_id = 0;
110 if (!_deviceInfo.FindCameraIndex(deviceUniqueIdUTF8, &camera_id))
112 _jCapturer = env->NewGlobalRef(
113 env->NewObject(g_java_capturer_class, ctor, camera_id, j_this));
118 VideoCaptureAndroid::~VideoCaptureAndroid() {
119 // Ensure Java camera is released even if our caller didn't explicitly Stop.
122 AttachThreadScoped ats(g_jvm);
123 ats.env()->DeleteGlobalRef(_jCapturer);
126 int32_t VideoCaptureAndroid::StartCapture(
127 const VideoCaptureCapability& capability) {
128 CriticalSectionScoped cs(&_apiCs);
129 AttachThreadScoped ats(g_jvm);
130 JNIEnv* env = ats.env();
132 if (_deviceInfo.GetBestMatchedCapability(
133 _deviceUniqueId, capability, _captureCapability) < 0) {
134 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
135 "%s: GetBestMatchedCapability failed: %dx%d",
136 __FUNCTION__, capability.width, capability.height);
140 _captureDelay = _captureCapability.expectedCaptureDelay;
143 env->GetMethodID(g_java_capturer_class, "startCapture", "(IIII)Z");
147 _deviceInfo.GetMFpsRange(_deviceUniqueId, _captureCapability.maxFPS,
148 &min_mfps, &max_mfps);
149 bool started = env->CallBooleanMethod(_jCapturer, j_start,
150 _captureCapability.width,
151 _captureCapability.height,
154 _requestedCapability = capability;
155 _captureStarted = true;
157 return started ? 0 : -1;
160 int32_t VideoCaptureAndroid::StopCapture() {
161 CriticalSectionScoped cs(&_apiCs);
162 AttachThreadScoped ats(g_jvm);
163 JNIEnv* env = ats.env();
165 memset(&_requestedCapability, 0, sizeof(_requestedCapability));
166 memset(&_captureCapability, 0, sizeof(_captureCapability));
167 _captureStarted = false;
170 env->GetMethodID(g_java_capturer_class, "stopCapture", "()Z");
171 return env->CallBooleanMethod(_jCapturer, j_stop) ? 0 : -1;
174 bool VideoCaptureAndroid::CaptureStarted() {
175 CriticalSectionScoped cs(&_apiCs);
176 return _captureStarted;
179 int32_t VideoCaptureAndroid::CaptureSettings(
180 VideoCaptureCapability& settings) {
181 CriticalSectionScoped cs(&_apiCs);
182 settings = _requestedCapability;
186 int32_t VideoCaptureAndroid::SetCaptureRotation(
187 VideoCaptureRotation rotation) {
188 CriticalSectionScoped cs(&_apiCs);
189 if (VideoCaptureImpl::SetCaptureRotation(rotation) != 0)
192 AttachThreadScoped ats(g_jvm);
193 JNIEnv* env = ats.env();
196 env->GetMethodID(g_java_capturer_class, "setPreviewRotation", "(I)V");
198 int rotation_degrees;
199 if (RotationInDegrees(rotation, &rotation_degrees) != 0) {
202 env->CallVoidMethod(_jCapturer, j_spr, rotation_degrees);
206 } // namespace videocapturemodule
207 } // namespace webrtc