Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_capture / android / video_capture_android.cc
1 /*
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 "webrtc/modules/video_capture/android/video_capture_android.h"
12
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"
19
20 static JavaVM* g_jvm = NULL;
21 static jclass g_java_capturer_class = NULL;  // VideoCaptureAndroid.class.
22
23 namespace webrtc {
24
25 // Called by Java when the camera has a new frame to deliver.
26 void JNICALL ProvideCameraFrame(
27     JNIEnv* env,
28     jobject,
29     jbyteArray javaCameraFrame,
30     jint length,
31     jlong context) {
32   webrtc::videocapturemodule::VideoCaptureAndroid* captureModule =
33       reinterpret_cast<webrtc::videocapturemodule::VideoCaptureAndroid*>(
34           context);
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);
39 }
40
41 int32_t SetCaptureAndroidVM(JavaVM* javaVM) {
42   assert(!g_jvm);
43   g_jvm = javaVM;
44   AttachThreadScoped ats(g_jvm);
45
46   videocapturemodule::DeviceInfoAndroid::Initialize(ats.env());
47
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);
54
55   JNINativeMethod native_method = {
56     "ProvideCameraFrame", "([BIJ)V",
57     reinterpret_cast<void*>(&ProvideCameraFrame)
58   };
59   if (ats.env()->RegisterNatives(g_java_capturer_class, &native_method, 1) != 0)
60     assert(false);
61
62   return 0;
63 }
64
65 namespace videocapturemodule {
66
67 VideoCaptureModule* VideoCaptureImpl::Create(
68     const int32_t id,
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;
75   }
76   return implementation;
77 }
78
79 int32_t VideoCaptureAndroid::OnIncomingFrame(uint8_t* videoFrame,
80                                              int32_t videoFrameLength,
81                                              int64_t captureTime) {
82   return IncomingFrame(
83       videoFrame, videoFrameLength, _captureCapability, captureTime);
84 }
85
86 VideoCaptureAndroid::VideoCaptureAndroid(const int32_t id)
87     : VideoCaptureImpl(id),
88       _deviceInfo(id),
89       _jCapturer(NULL),
90       _captureStarted(false) {
91 }
92
93 int32_t VideoCaptureAndroid::Init(const int32_t id,
94                                   const char* deviceUniqueIdUTF8) {
95   const int nameLength = strlen(deviceUniqueIdUTF8);
96   if (nameLength >= kVideoCaptureUniqueNameLength)
97     return -1;
98
99   // Store the device name
100   _deviceUniqueId = new char[nameLength + 1];
101   memcpy(_deviceUniqueId, deviceUniqueIdUTF8, nameLength + 1);
102
103   AttachThreadScoped ats(g_jvm);
104   JNIEnv* env = ats.env();
105
106   jmethodID ctor = env->GetMethodID(g_java_capturer_class, "<init>", "(IJ)V");
107   assert(ctor);
108   jlong j_this = reinterpret_cast<intptr_t>(this);
109   size_t camera_id = 0;
110   if (!_deviceInfo.FindCameraIndex(deviceUniqueIdUTF8, &camera_id))
111     return -1;
112   _jCapturer = env->NewGlobalRef(
113       env->NewObject(g_java_capturer_class, ctor, camera_id, j_this));
114   assert(_jCapturer);
115   return 0;
116 }
117
118 VideoCaptureAndroid::~VideoCaptureAndroid() {
119   // Ensure Java camera is released even if our caller didn't explicitly Stop.
120   if (_captureStarted)
121     StopCapture();
122   AttachThreadScoped ats(g_jvm);
123   ats.env()->DeleteGlobalRef(_jCapturer);
124 }
125
126 int32_t VideoCaptureAndroid::StartCapture(
127     const VideoCaptureCapability& capability) {
128   CriticalSectionScoped cs(&_apiCs);
129   AttachThreadScoped ats(g_jvm);
130   JNIEnv* env = ats.env();
131
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);
137     return -1;
138   }
139
140   _captureDelay = _captureCapability.expectedCaptureDelay;
141
142   jmethodID j_start =
143       env->GetMethodID(g_java_capturer_class, "startCapture", "(IIII)Z");
144   assert(j_start);
145   int min_mfps = 0;
146   int max_mfps = 0;
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,
152                                         min_mfps, max_mfps);
153   if (started) {
154     _requestedCapability = capability;
155     _captureStarted = true;
156   }
157   return started ? 0 : -1;
158 }
159
160 int32_t VideoCaptureAndroid::StopCapture() {
161   CriticalSectionScoped cs(&_apiCs);
162   AttachThreadScoped ats(g_jvm);
163   JNIEnv* env = ats.env();
164
165   memset(&_requestedCapability, 0, sizeof(_requestedCapability));
166   memset(&_captureCapability, 0, sizeof(_captureCapability));
167   _captureStarted = false;
168
169   jmethodID j_stop =
170       env->GetMethodID(g_java_capturer_class, "stopCapture", "()Z");
171   return env->CallBooleanMethod(_jCapturer, j_stop) ? 0 : -1;
172 }
173
174 bool VideoCaptureAndroid::CaptureStarted() {
175   CriticalSectionScoped cs(&_apiCs);
176   return _captureStarted;
177 }
178
179 int32_t VideoCaptureAndroid::CaptureSettings(
180     VideoCaptureCapability& settings) {
181   CriticalSectionScoped cs(&_apiCs);
182   settings = _requestedCapability;
183   return 0;
184 }
185
186 int32_t VideoCaptureAndroid::SetCaptureRotation(
187     VideoCaptureRotation rotation) {
188   CriticalSectionScoped cs(&_apiCs);
189   if (VideoCaptureImpl::SetCaptureRotation(rotation) != 0)
190     return 0;
191
192   AttachThreadScoped ats(g_jvm);
193   JNIEnv* env = ats.env();
194
195   jmethodID j_spr =
196       env->GetMethodID(g_java_capturer_class, "setPreviewRotation", "(I)V");
197   assert(j_spr);
198   int rotation_degrees;
199   if (RotationInDegrees(rotation, &rotation_degrees) != 0) {
200     assert(false);
201   }
202   env->CallVoidMethod(_jCapturer, j_spr, rotation_degrees);
203   return 0;
204 }
205
206 }  // namespace videocapturemodule
207 }  // namespace webrtc