| 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 |