OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 11 matching lines...) Expand all Loading... |
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 * | 26 * |
27 */ | 27 */ |
28 | 28 |
29 #include "talk/app/webrtc/java/jni/androidvideocapturer_jni.h" | 29 #include "talk/app/webrtc/java/jni/androidvideocapturer_jni.h" |
30 #include "talk/app/webrtc/java/jni/classreferenceholder.h" | 30 #include "talk/app/webrtc/java/jni/classreferenceholder.h" |
31 #include "talk/app/webrtc/java/jni/native_handle_impl.h" | 31 #include "talk/app/webrtc/java/jni/native_handle_impl.h" |
| 32 #include "talk/app/webrtc/java/jni/surfacetexturehelper_jni.h" |
| 33 #include "third_party/libyuv/include/libyuv/convert.h" |
32 #include "webrtc/base/bind.h" | 34 #include "webrtc/base/bind.h" |
33 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | |
34 | 35 |
35 namespace webrtc_jni { | 36 namespace webrtc_jni { |
36 | 37 |
37 jobject AndroidVideoCapturerJni::application_context_ = nullptr; | 38 jobject AndroidVideoCapturerJni::application_context_ = nullptr; |
38 | 39 |
39 // static | 40 // static |
40 int AndroidVideoCapturerJni::SetAndroidObjects(JNIEnv* jni, | 41 int AndroidVideoCapturerJni::SetAndroidObjects(JNIEnv* jni, |
41 jobject appliction_context) { | 42 jobject appliction_context) { |
42 if (application_context_) { | 43 if (application_context_) { |
43 jni->DeleteGlobalRef(application_context_); | 44 jni->DeleteGlobalRef(application_context_); |
44 } | 45 } |
45 application_context_ = NewGlobalRef(jni, appliction_context); | 46 application_context_ = NewGlobalRef(jni, appliction_context); |
46 | 47 |
47 return 0; | 48 return 0; |
48 } | 49 } |
49 | 50 |
50 AndroidVideoCapturerJni::AndroidVideoCapturerJni( | 51 AndroidVideoCapturerJni::AndroidVideoCapturerJni( |
51 JNIEnv* jni, | 52 JNIEnv* jni, |
52 jobject j_video_capturer, | 53 jobject j_video_capturer, |
53 jobject j_surface_texture_helper) | 54 jobject j_surface_texture_helper) |
54 : j_video_capturer_(jni, j_video_capturer), | 55 : j_video_capturer_(jni, j_video_capturer), |
55 j_surface_texture_helper_(jni, j_surface_texture_helper), | |
56 j_video_capturer_class_( | 56 j_video_capturer_class_( |
57 jni, FindClass(jni, "org/webrtc/VideoCapturerAndroid")), | 57 jni, FindClass(jni, "org/webrtc/VideoCapturerAndroid")), |
58 j_observer_class_( | 58 j_observer_class_( |
59 jni, | 59 jni, |
60 FindClass(jni, | 60 FindClass(jni, |
61 "org/webrtc/VideoCapturerAndroid$NativeObserver")), | 61 "org/webrtc/VideoCapturerAndroid$NativeObserver")), |
| 62 surface_texture_helper_(new rtc::RefCountedObject<SurfaceTextureHelper>( |
| 63 jni, j_surface_texture_helper)), |
62 capturer_(nullptr) { | 64 capturer_(nullptr) { |
63 LOG(LS_INFO) << "AndroidVideoCapturerJni ctor"; | 65 LOG(LS_INFO) << "AndroidVideoCapturerJni ctor"; |
64 thread_checker_.DetachFromThread(); | 66 thread_checker_.DetachFromThread(); |
65 } | 67 } |
66 | 68 |
67 AndroidVideoCapturerJni::~AndroidVideoCapturerJni() { | 69 AndroidVideoCapturerJni::~AndroidVideoCapturerJni() { |
68 LOG(LS_INFO) << "AndroidVideoCapturerJni dtor"; | 70 LOG(LS_INFO) << "AndroidVideoCapturerJni dtor"; |
69 jni()->CallVoidMethod( | 71 jni()->CallVoidMethod( |
70 *j_video_capturer_, | 72 *j_video_capturer_, |
71 GetMethodID(jni(), *j_video_capturer_class_, "release", "()V")); | 73 GetMethodID(jni(), *j_video_capturer_class_, "release", "()V")); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 void (webrtc::AndroidVideoCapturer::*method)(Args...), | 125 void (webrtc::AndroidVideoCapturer::*method)(Args...), |
124 typename Identity<Args>::type... args) { | 126 typename Identity<Args>::type... args) { |
125 rtc::CritScope cs(&capturer_lock_); | 127 rtc::CritScope cs(&capturer_lock_); |
126 if (!invoker_) { | 128 if (!invoker_) { |
127 LOG(LS_WARNING) << method_name << "() called for closed capturer."; | 129 LOG(LS_WARNING) << method_name << "() called for closed capturer."; |
128 return; | 130 return; |
129 } | 131 } |
130 invoker_->AsyncInvoke<void>(rtc::Bind(method, capturer_, args...)); | 132 invoker_->AsyncInvoke<void>(rtc::Bind(method, capturer_, args...)); |
131 } | 133 } |
132 | 134 |
133 void AndroidVideoCapturerJni::ReturnBuffer(int64_t time_stamp) { | |
134 jmethodID m = GetMethodID(jni(), *j_video_capturer_class_, | |
135 "returnBuffer", "(J)V"); | |
136 jni()->CallVoidMethod(*j_video_capturer_, m, time_stamp); | |
137 CHECK_EXCEPTION(jni()) << "error during VideoCapturerAndroid.returnBuffer"; | |
138 } | |
139 | |
140 std::string AndroidVideoCapturerJni::GetSupportedFormats() { | 135 std::string AndroidVideoCapturerJni::GetSupportedFormats() { |
141 jmethodID m = | 136 jmethodID m = |
142 GetMethodID(jni(), *j_video_capturer_class_, | 137 GetMethodID(jni(), *j_video_capturer_class_, |
143 "getSupportedFormatsAsJson", "()Ljava/lang/String;"); | 138 "getSupportedFormatsAsJson", "()Ljava/lang/String;"); |
144 jstring j_json_caps = | 139 jstring j_json_caps = |
145 (jstring) jni()->CallObjectMethod(*j_video_capturer_, m); | 140 (jstring) jni()->CallObjectMethod(*j_video_capturer_, m); |
146 CHECK_EXCEPTION(jni()) << "error during supportedFormatsAsJson"; | 141 CHECK_EXCEPTION(jni()) << "error during supportedFormatsAsJson"; |
147 return JavaToStdString(jni(), j_json_caps); | 142 return JavaToStdString(jni(), j_json_caps); |
148 } | 143 } |
149 | 144 |
150 void AndroidVideoCapturerJni::OnCapturerStarted(bool success) { | 145 void AndroidVideoCapturerJni::OnCapturerStarted(bool success) { |
151 LOG(LS_INFO) << "AndroidVideoCapturerJni capture started: " << success; | 146 LOG(LS_INFO) << "AndroidVideoCapturerJni capture started: " << success; |
152 AsyncCapturerInvoke("OnCapturerStarted", | 147 AsyncCapturerInvoke("OnCapturerStarted", |
153 &webrtc::AndroidVideoCapturer::OnCapturerStarted, | 148 &webrtc::AndroidVideoCapturer::OnCapturerStarted, |
154 success); | 149 success); |
155 } | 150 } |
156 | 151 |
157 void AndroidVideoCapturerJni::OnMemoryBufferFrame(void* video_frame, | 152 void AndroidVideoCapturerJni::OnMemoryBufferFrame(void* video_frame, |
158 int length, | 153 int length, |
159 int width, | 154 int width, |
160 int height, | 155 int height, |
161 int rotation, | 156 int rotation, |
162 int64_t timestamp_ns) { | 157 int64_t timestamp_ns) { |
163 const uint8_t* y_plane = static_cast<uint8_t*>(video_frame); | 158 const uint8_t* y_plane = static_cast<uint8_t*>(video_frame); |
164 // Android guarantees that the stride is a multiple of 16. | 159 const uint8_t* vu_plane = y_plane + width * height; |
165 // http://developer.android.com/reference/android/hardware/Camera.Parameters.h
tml#setPreviewFormat%28int%29 | |
166 int y_stride; | |
167 int uv_stride; | |
168 webrtc::Calc16ByteAlignedStride(width, &y_stride, &uv_stride); | |
169 const uint8_t* v_plane = y_plane + y_stride * height; | |
170 const uint8_t* u_plane = | |
171 v_plane + uv_stride * webrtc::AlignInt(height, 2) / 2; | |
172 | 160 |
173 // Wrap the Java buffer, and call ReturnBuffer() in the wrapped | 161 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer = |
174 // VideoFrameBuffer destructor. | 162 buffer_pool_.CreateBuffer(width, height); |
175 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer( | 163 libyuv::NV21ToI420( |
176 new rtc::RefCountedObject<webrtc::WrappedI420Buffer>( | 164 y_plane, width, |
177 width, height, y_plane, y_stride, u_plane, uv_stride, v_plane, | 165 vu_plane, width, |
178 uv_stride, | 166 buffer->MutableData(webrtc::kYPlane), buffer->stride(webrtc::kYPlane), |
179 rtc::Bind(&AndroidVideoCapturerJni::ReturnBuffer, this, | 167 buffer->MutableData(webrtc::kUPlane), buffer->stride(webrtc::kUPlane), |
180 timestamp_ns))); | 168 buffer->MutableData(webrtc::kVPlane), buffer->stride(webrtc::kVPlane), |
| 169 width, height); |
181 AsyncCapturerInvoke("OnIncomingFrame", | 170 AsyncCapturerInvoke("OnIncomingFrame", |
182 &webrtc::AndroidVideoCapturer::OnIncomingFrame, | 171 &webrtc::AndroidVideoCapturer::OnIncomingFrame, |
183 buffer, rotation, timestamp_ns); | 172 buffer, rotation, timestamp_ns); |
184 } | 173 } |
185 | 174 |
186 void AndroidVideoCapturerJni::OnTextureFrame(int width, | 175 void AndroidVideoCapturerJni::OnTextureFrame(int width, |
187 int height, | 176 int height, |
188 int rotation, | 177 int rotation, |
189 int64_t timestamp_ns, | 178 int64_t timestamp_ns, |
190 const NativeHandleImpl& handle) { | 179 const NativeHandleImpl& handle) { |
191 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer( | 180 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer( |
192 new rtc::RefCountedObject<AndroidTextureBuffer>( | 181 surface_texture_helper_->CreateTextureFrame(width, height, handle)); |
193 width, height, handle, *j_surface_texture_helper_, | 182 |
194 rtc::Bind(&AndroidVideoCapturerJni::ReturnBuffer, this, | |
195 timestamp_ns))); | |
196 AsyncCapturerInvoke("OnIncomingFrame", | 183 AsyncCapturerInvoke("OnIncomingFrame", |
197 &webrtc::AndroidVideoCapturer::OnIncomingFrame, | 184 &webrtc::AndroidVideoCapturer::OnIncomingFrame, |
198 buffer, rotation, timestamp_ns); | 185 buffer, rotation, timestamp_ns); |
199 } | 186 } |
200 | 187 |
201 void AndroidVideoCapturerJni::OnOutputFormatRequest(int width, | 188 void AndroidVideoCapturerJni::OnOutputFormatRequest(int width, |
202 int height, | 189 int height, |
203 int fps) { | 190 int fps) { |
204 AsyncCapturerInvoke("OnOutputFormatRequest", | 191 AsyncCapturerInvoke("OnOutputFormatRequest", |
205 &webrtc::AndroidVideoCapturer::OnOutputFormatRequest, | 192 &webrtc::AndroidVideoCapturer::OnOutputFormatRequest, |
206 width, height, fps); | 193 width, height, fps); |
207 } | 194 } |
208 | 195 |
209 JNIEnv* AndroidVideoCapturerJni::jni() { return AttachCurrentThreadIfNeeded(); } | 196 JNIEnv* AndroidVideoCapturerJni::jni() { return AttachCurrentThreadIfNeeded(); } |
210 | 197 |
211 JOW(void, | 198 JOW(void, |
212 VideoCapturerAndroid_00024NativeObserver_nativeOnByteBufferFrameCaptured) | 199 VideoCapturerAndroid_00024NativeObserver_nativeOnByteBufferFrameCaptured) |
213 (JNIEnv* jni, jclass, jlong j_capturer, jbyteArray j_frame, jint length, | 200 (JNIEnv* jni, jclass, jlong j_capturer, jbyteArray j_frame, jint length, |
214 jint width, jint height, jint rotation, jlong timestamp) { | 201 jint width, jint height, jint rotation, jlong timestamp) { |
215 jboolean is_copy = true; | 202 jboolean is_copy = true; |
216 jbyte* bytes = jni->GetByteArrayElements(j_frame, &is_copy); | 203 jbyte* bytes = jni->GetByteArrayElements(j_frame, &is_copy); |
217 // If this is a copy of the original frame, it means that the memory | |
218 // is not direct memory and thus VideoCapturerAndroid does not guarantee | |
219 // that the memory is valid when we have released |j_frame|. | |
220 // TODO(magjed): Move ReleaseByteArrayElements() into ReturnBuffer() and | |
221 // remove this check. | |
222 RTC_CHECK(!is_copy) | |
223 << "NativeObserver_nativeOnFrameCaptured: frame is a copy"; | |
224 reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer) | 204 reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer) |
225 ->OnMemoryBufferFrame(bytes, length, width, height, rotation, timestamp); | 205 ->OnMemoryBufferFrame(bytes, length, width, height, rotation, timestamp); |
226 jni->ReleaseByteArrayElements(j_frame, bytes, JNI_ABORT); | 206 jni->ReleaseByteArrayElements(j_frame, bytes, JNI_ABORT); |
227 } | 207 } |
228 | 208 |
229 JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeOnTextureFrameCaptured) | 209 JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeOnTextureFrameCaptured) |
230 (JNIEnv* jni, jclass, jlong j_capturer, jint j_width, jint j_height, | 210 (JNIEnv* jni, jclass, jlong j_capturer, jint j_width, jint j_height, |
231 jint j_oes_texture_id, jfloatArray j_transform_matrix, | 211 jint j_oes_texture_id, jfloatArray j_transform_matrix, |
232 jint j_rotation, jlong j_timestamp) { | 212 jint j_rotation, jlong j_timestamp) { |
233 reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer) | 213 reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer) |
(...skipping 23 matching lines...) Expand all Loading... |
257 rtc::scoped_refptr<webrtc::AndroidVideoCapturerDelegate> delegate = | 237 rtc::scoped_refptr<webrtc::AndroidVideoCapturerDelegate> delegate = |
258 new rtc::RefCountedObject<AndroidVideoCapturerJni>( | 238 new rtc::RefCountedObject<AndroidVideoCapturerJni>( |
259 jni, j_video_capturer, j_surface_texture_helper); | 239 jni, j_video_capturer, j_surface_texture_helper); |
260 rtc::scoped_ptr<cricket::VideoCapturer> capturer( | 240 rtc::scoped_ptr<cricket::VideoCapturer> capturer( |
261 new webrtc::AndroidVideoCapturer(delegate)); | 241 new webrtc::AndroidVideoCapturer(delegate)); |
262 // Caller takes ownership of the cricket::VideoCapturer* pointer. | 242 // Caller takes ownership of the cricket::VideoCapturer* pointer. |
263 return jlongFromPointer(capturer.release()); | 243 return jlongFromPointer(capturer.release()); |
264 } | 244 } |
265 | 245 |
266 } // namespace webrtc_jni | 246 } // namespace webrtc_jni |
OLD | NEW |