| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * libjingle | |
| 3 * Copyright 2015 Google Inc. | |
| 4 * | |
| 5 * Redistribution and use in source and binary forms, with or without | |
| 6 * modification, are permitted provided that the following conditions are met: | |
| 7 * | |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | |
| 9 * this list of conditions and the following disclaimer. | |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 11 * this list of conditions and the following disclaimer in the documentation | |
| 12 * and/or other materials provided with the distribution. | |
| 13 * 3. The name of the author may not be used to endorse or promote products | |
| 14 * derived from this software without specific prior written permission. | |
| 15 * | |
| 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
| 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
| 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |
| 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
| 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
| 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 | |
| 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 26 * | |
| 27 */ | |
| 28 | |
| 29 #include "talk/app/webrtc/java/jni/androidvideocapturer_jni.h" | |
| 30 #include "talk/app/webrtc/java/jni/classreferenceholder.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" | |
| 34 #include "webrtc/base/bind.h" | |
| 35 | |
| 36 namespace webrtc_jni { | |
| 37 | |
| 38 jobject AndroidVideoCapturerJni::application_context_ = nullptr; | |
| 39 | |
| 40 // static | |
| 41 int AndroidVideoCapturerJni::SetAndroidObjects(JNIEnv* jni, | |
| 42 jobject appliction_context) { | |
| 43 if (application_context_) { | |
| 44 jni->DeleteGlobalRef(application_context_); | |
| 45 } | |
| 46 application_context_ = NewGlobalRef(jni, appliction_context); | |
| 47 | |
| 48 return 0; | |
| 49 } | |
| 50 | |
| 51 AndroidVideoCapturerJni::AndroidVideoCapturerJni( | |
| 52 JNIEnv* jni, | |
| 53 jobject j_video_capturer, | |
| 54 jobject j_surface_texture_helper) | |
| 55 : j_video_capturer_(jni, j_video_capturer), | |
| 56 j_video_capturer_class_( | |
| 57 jni, FindClass(jni, "org/webrtc/VideoCapturerAndroid")), | |
| 58 j_observer_class_( | |
| 59 jni, | |
| 60 FindClass(jni, | |
| 61 "org/webrtc/VideoCapturerAndroid$NativeObserver")), | |
| 62 surface_texture_helper_(new rtc::RefCountedObject<SurfaceTextureHelper>( | |
| 63 jni, j_surface_texture_helper)), | |
| 64 capturer_(nullptr) { | |
| 65 LOG(LS_INFO) << "AndroidVideoCapturerJni ctor"; | |
| 66 thread_checker_.DetachFromThread(); | |
| 67 } | |
| 68 | |
| 69 AndroidVideoCapturerJni::~AndroidVideoCapturerJni() { | |
| 70 LOG(LS_INFO) << "AndroidVideoCapturerJni dtor"; | |
| 71 jni()->CallVoidMethod( | |
| 72 *j_video_capturer_, | |
| 73 GetMethodID(jni(), *j_video_capturer_class_, "release", "()V")); | |
| 74 CHECK_EXCEPTION(jni()) << "error during VideoCapturerAndroid.release()"; | |
| 75 } | |
| 76 | |
| 77 void AndroidVideoCapturerJni::Start(int width, int height, int framerate, | |
| 78 webrtc::AndroidVideoCapturer* capturer) { | |
| 79 LOG(LS_INFO) << "AndroidVideoCapturerJni start"; | |
| 80 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
| 81 { | |
| 82 rtc::CritScope cs(&capturer_lock_); | |
| 83 RTC_CHECK(capturer_ == nullptr); | |
| 84 RTC_CHECK(invoker_.get() == nullptr); | |
| 85 capturer_ = capturer; | |
| 86 invoker_.reset(new rtc::GuardedAsyncInvoker()); | |
| 87 } | |
| 88 jobject j_frame_observer = | |
| 89 jni()->NewObject(*j_observer_class_, | |
| 90 GetMethodID(jni(), *j_observer_class_, "<init>", "(J)V"), | |
| 91 jlongFromPointer(this)); | |
| 92 CHECK_EXCEPTION(jni()) << "error during NewObject"; | |
| 93 | |
| 94 jmethodID m = GetMethodID( | |
| 95 jni(), *j_video_capturer_class_, "startCapture", | |
| 96 "(IIILandroid/content/Context;" | |
| 97 "Lorg/webrtc/VideoCapturerAndroid$CapturerObserver;)V"); | |
| 98 jni()->CallVoidMethod(*j_video_capturer_, | |
| 99 m, width, height, | |
| 100 framerate, | |
| 101 application_context_, | |
| 102 j_frame_observer); | |
| 103 CHECK_EXCEPTION(jni()) << "error during VideoCapturerAndroid.startCapture"; | |
| 104 } | |
| 105 | |
| 106 void AndroidVideoCapturerJni::Stop() { | |
| 107 LOG(LS_INFO) << "AndroidVideoCapturerJni stop"; | |
| 108 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | |
| 109 { | |
| 110 rtc::CritScope cs(&capturer_lock_); | |
| 111 // Destroying |invoker_| will cancel all pending calls to |capturer_|. | |
| 112 invoker_ = nullptr; | |
| 113 capturer_ = nullptr; | |
| 114 } | |
| 115 jmethodID m = GetMethodID(jni(), *j_video_capturer_class_, | |
| 116 "stopCapture", "()V"); | |
| 117 jni()->CallVoidMethod(*j_video_capturer_, m); | |
| 118 CHECK_EXCEPTION(jni()) << "error during VideoCapturerAndroid.stopCapture"; | |
| 119 LOG(LS_INFO) << "AndroidVideoCapturerJni stop done"; | |
| 120 } | |
| 121 | |
| 122 template <typename... Args> | |
| 123 void AndroidVideoCapturerJni::AsyncCapturerInvoke( | |
| 124 const char* method_name, | |
| 125 void (webrtc::AndroidVideoCapturer::*method)(Args...), | |
| 126 typename Identity<Args>::type... args) { | |
| 127 rtc::CritScope cs(&capturer_lock_); | |
| 128 if (!invoker_) { | |
| 129 LOG(LS_WARNING) << method_name << "() called for closed capturer."; | |
| 130 return; | |
| 131 } | |
| 132 invoker_->AsyncInvoke<void>(rtc::Bind(method, capturer_, args...)); | |
| 133 } | |
| 134 | |
| 135 std::string AndroidVideoCapturerJni::GetSupportedFormats() { | |
| 136 jmethodID m = | |
| 137 GetMethodID(jni(), *j_video_capturer_class_, | |
| 138 "getSupportedFormatsAsJson", "()Ljava/lang/String;"); | |
| 139 jstring j_json_caps = | |
| 140 (jstring) jni()->CallObjectMethod(*j_video_capturer_, m); | |
| 141 CHECK_EXCEPTION(jni()) << "error during supportedFormatsAsJson"; | |
| 142 return JavaToStdString(jni(), j_json_caps); | |
| 143 } | |
| 144 | |
| 145 void AndroidVideoCapturerJni::OnCapturerStarted(bool success) { | |
| 146 LOG(LS_INFO) << "AndroidVideoCapturerJni capture started: " << success; | |
| 147 AsyncCapturerInvoke("OnCapturerStarted", | |
| 148 &webrtc::AndroidVideoCapturer::OnCapturerStarted, | |
| 149 success); | |
| 150 } | |
| 151 | |
| 152 void AndroidVideoCapturerJni::OnMemoryBufferFrame(void* video_frame, | |
| 153 int length, | |
| 154 int width, | |
| 155 int height, | |
| 156 int rotation, | |
| 157 int64_t timestamp_ns) { | |
| 158 const uint8_t* y_plane = static_cast<uint8_t*>(video_frame); | |
| 159 const uint8_t* vu_plane = y_plane + width * height; | |
| 160 | |
| 161 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer = | |
| 162 buffer_pool_.CreateBuffer(width, height); | |
| 163 libyuv::NV21ToI420( | |
| 164 y_plane, width, | |
| 165 vu_plane, width, | |
| 166 buffer->MutableData(webrtc::kYPlane), buffer->stride(webrtc::kYPlane), | |
| 167 buffer->MutableData(webrtc::kUPlane), buffer->stride(webrtc::kUPlane), | |
| 168 buffer->MutableData(webrtc::kVPlane), buffer->stride(webrtc::kVPlane), | |
| 169 width, height); | |
| 170 AsyncCapturerInvoke("OnIncomingFrame", | |
| 171 &webrtc::AndroidVideoCapturer::OnIncomingFrame, | |
| 172 buffer, rotation, timestamp_ns); | |
| 173 } | |
| 174 | |
| 175 void AndroidVideoCapturerJni::OnTextureFrame(int width, | |
| 176 int height, | |
| 177 int rotation, | |
| 178 int64_t timestamp_ns, | |
| 179 const NativeHandleImpl& handle) { | |
| 180 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer( | |
| 181 surface_texture_helper_->CreateTextureFrame(width, height, handle)); | |
| 182 | |
| 183 AsyncCapturerInvoke("OnIncomingFrame", | |
| 184 &webrtc::AndroidVideoCapturer::OnIncomingFrame, | |
| 185 buffer, rotation, timestamp_ns); | |
| 186 } | |
| 187 | |
| 188 void AndroidVideoCapturerJni::OnOutputFormatRequest(int width, | |
| 189 int height, | |
| 190 int fps) { | |
| 191 AsyncCapturerInvoke("OnOutputFormatRequest", | |
| 192 &webrtc::AndroidVideoCapturer::OnOutputFormatRequest, | |
| 193 width, height, fps); | |
| 194 } | |
| 195 | |
| 196 JNIEnv* AndroidVideoCapturerJni::jni() { return AttachCurrentThreadIfNeeded(); } | |
| 197 | |
| 198 JOW(void, | |
| 199 VideoCapturerAndroid_00024NativeObserver_nativeOnByteBufferFrameCaptured) | |
| 200 (JNIEnv* jni, jclass, jlong j_capturer, jbyteArray j_frame, jint length, | |
| 201 jint width, jint height, jint rotation, jlong timestamp) { | |
| 202 jboolean is_copy = true; | |
| 203 jbyte* bytes = jni->GetByteArrayElements(j_frame, &is_copy); | |
| 204 reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer) | |
| 205 ->OnMemoryBufferFrame(bytes, length, width, height, rotation, timestamp); | |
| 206 jni->ReleaseByteArrayElements(j_frame, bytes, JNI_ABORT); | |
| 207 } | |
| 208 | |
| 209 JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeOnTextureFrameCaptured) | |
| 210 (JNIEnv* jni, jclass, jlong j_capturer, jint j_width, jint j_height, | |
| 211 jint j_oes_texture_id, jfloatArray j_transform_matrix, | |
| 212 jint j_rotation, jlong j_timestamp) { | |
| 213 reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer) | |
| 214 ->OnTextureFrame(j_width, j_height, j_rotation, j_timestamp, | |
| 215 NativeHandleImpl(jni, j_oes_texture_id, | |
| 216 j_transform_matrix)); | |
| 217 } | |
| 218 | |
| 219 JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeCapturerStarted) | |
| 220 (JNIEnv* jni, jclass, jlong j_capturer, jboolean j_success) { | |
| 221 LOG(LS_INFO) << "NativeObserver_nativeCapturerStarted"; | |
| 222 reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer)->OnCapturerStarted( | |
| 223 j_success); | |
| 224 } | |
| 225 | |
| 226 JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeOnOutputFormatRequest) | |
| 227 (JNIEnv* jni, jclass, jlong j_capturer, jint j_width, jint j_height, | |
| 228 jint j_fps) { | |
| 229 LOG(LS_INFO) << "NativeObserver_nativeOnOutputFormatRequest"; | |
| 230 reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer)->OnOutputFormatRequest( | |
| 231 j_width, j_height, j_fps); | |
| 232 } | |
| 233 | |
| 234 JOW(jlong, VideoCapturerAndroid_nativeCreateVideoCapturer) | |
| 235 (JNIEnv* jni, jclass, | |
| 236 jobject j_video_capturer, jobject j_surface_texture_helper) { | |
| 237 rtc::scoped_refptr<webrtc::AndroidVideoCapturerDelegate> delegate = | |
| 238 new rtc::RefCountedObject<AndroidVideoCapturerJni>( | |
| 239 jni, j_video_capturer, j_surface_texture_helper); | |
| 240 rtc::scoped_ptr<cricket::VideoCapturer> capturer( | |
| 241 new webrtc::AndroidVideoCapturer(delegate)); | |
| 242 // Caller takes ownership of the cricket::VideoCapturer* pointer. | |
| 243 return jlongFromPointer(capturer.release()); | |
| 244 } | |
| 245 | |
| 246 } // namespace webrtc_jni | |
| OLD | NEW |