OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/sdk/android/src/jni/native_handle_impl.h" | 11 #include "webrtc/sdk/android/src/jni/native_handle_impl.h" |
12 | 12 |
13 #include <memory> | 13 #include <memory> |
14 | 14 |
15 #include "webrtc/common_video/include/video_frame_buffer.h" | 15 #include "webrtc/common_video/include/video_frame_buffer.h" |
16 #include "webrtc/rtc_base/bind.h" | 16 #include "webrtc/rtc_base/bind.h" |
17 #include "webrtc/rtc_base/checks.h" | 17 #include "webrtc/rtc_base/checks.h" |
18 #include "webrtc/rtc_base/keep_ref_until_done.h" | 18 #include "webrtc/rtc_base/keep_ref_until_done.h" |
19 #include "webrtc/rtc_base/logging.h" | 19 #include "webrtc/rtc_base/logging.h" |
20 #include "webrtc/rtc_base/scoped_ref_ptr.h" | 20 #include "webrtc/rtc_base/scoped_ref_ptr.h" |
21 #include "webrtc/rtc_base/timeutils.h" | 21 #include "webrtc/rtc_base/timeutils.h" |
22 #include "webrtc/sdk/android/src/jni/classreferenceholder.h" | 22 #include "webrtc/sdk/android/src/jni/classreferenceholder.h" |
23 #include "webrtc/sdk/android/src/jni/jni_helpers.h" | 23 #include "webrtc/sdk/android/src/jni/jni_helpers.h" |
24 #include "webrtc/system_wrappers/include/aligned_malloc.h" | 24 #include "webrtc/system_wrappers/include/aligned_malloc.h" |
25 | 25 |
26 namespace webrtc_jni { | 26 namespace webrtc_jni { |
27 | 27 |
28 namespace { | |
29 | |
30 class AndroidVideoI420Buffer : public AndroidVideoBuffer, | |
magjed_webrtc
2017/07/27 14:45:01
Don't inherit from AndroidVideoBuffer, because you
sakal
2017/07/28 09:01:10
Done.
| |
31 public webrtc::I420BufferInterface { | |
32 public: | |
33 AndroidVideoI420Buffer(JNIEnv* jni, | |
34 jmethodID j_release_id, | |
35 jmethodID j_get_width_id, | |
36 jmethodID j_get_height_id, | |
37 jmethodID j_get_data_y_id, | |
38 jmethodID j_get_data_u_id, | |
39 jmethodID j_get_data_v_id, | |
40 jmethodID j_get_stride_y_id, | |
41 jmethodID j_get_stride_u_id, | |
42 jmethodID j_get_stride_v_id, | |
43 jobject j_video_frame_buffer); | |
44 | |
45 private: | |
46 const uint8_t* DataY() const override; | |
47 const uint8_t* DataU() const override; | |
48 const uint8_t* DataV() const override; | |
49 | |
50 int StrideY() const override; | |
51 int StrideU() const override; | |
52 int StrideV() const override; | |
53 | |
54 using webrtc::I420BufferInterface::type; | |
55 int width() const override { return AndroidVideoBuffer::width(); } | |
56 int height() const override { return AndroidVideoBuffer::height(); } | |
57 | |
58 const jmethodID j_get_data_y_id_; | |
59 const jmethodID j_get_data_u_id_; | |
60 const jmethodID j_get_data_v_id_; | |
61 const jmethodID j_get_stride_y_id_; | |
62 const jmethodID j_get_stride_u_id_; | |
63 const jmethodID j_get_stride_v_id_; | |
64 }; | |
65 | |
66 AndroidVideoI420Buffer::AndroidVideoI420Buffer(JNIEnv* jni, | |
67 jmethodID j_release_id, | |
68 jmethodID j_get_width_id, | |
69 jmethodID j_get_height_id, | |
70 jmethodID j_get_data_y_id, | |
71 jmethodID j_get_data_u_id, | |
72 jmethodID j_get_data_v_id, | |
73 jmethodID j_get_stride_y_id, | |
74 jmethodID j_get_stride_u_id, | |
75 jmethodID j_get_stride_v_id, | |
76 jobject j_video_frame_buffer) | |
77 : AndroidVideoBuffer(jni, | |
78 j_release_id, | |
79 j_get_width_id, | |
80 j_get_height_id, | |
81 j_video_frame_buffer), | |
82 j_get_data_y_id_(j_get_data_y_id), | |
83 j_get_data_u_id_(j_get_data_u_id), | |
84 j_get_data_v_id_(j_get_data_v_id), | |
85 j_get_stride_y_id_(j_get_stride_y_id), | |
86 j_get_stride_u_id_(j_get_stride_u_id), | |
87 j_get_stride_v_id_(j_get_stride_v_id) {} | |
88 | |
89 const uint8_t* AndroidVideoI420Buffer::DataY() const { | |
90 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | |
91 ScopedLocalRefFrame local_ref_frame(jni); | |
92 jobject j_data_y = | |
93 jni->CallObjectMethod(*j_video_frame_buffer_, j_get_data_y_id_); | |
94 return static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_y)); | |
95 } | |
96 | |
97 const uint8_t* AndroidVideoI420Buffer::DataU() const { | |
98 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | |
99 ScopedLocalRefFrame local_ref_frame(jni); | |
100 jobject j_data_u = | |
101 jni->CallObjectMethod(*j_video_frame_buffer_, j_get_data_u_id_); | |
102 return static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_u)); | |
103 } | |
104 | |
105 const uint8_t* AndroidVideoI420Buffer::DataV() const { | |
106 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | |
107 ScopedLocalRefFrame local_ref_frame(jni); | |
108 jobject j_data_v = | |
109 jni->CallObjectMethod(*j_video_frame_buffer_, j_get_data_v_id_); | |
110 return static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_v)); | |
111 } | |
112 | |
113 int AndroidVideoI420Buffer::StrideY() const { | |
114 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | |
115 return jni->CallIntMethod(*j_video_frame_buffer_, j_get_stride_y_id_); | |
116 } | |
117 | |
118 int AndroidVideoI420Buffer::StrideU() const { | |
119 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | |
120 return jni->CallIntMethod(*j_video_frame_buffer_, j_get_stride_u_id_); | |
121 } | |
122 | |
123 int AndroidVideoI420Buffer::StrideV() const { | |
124 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | |
125 return jni->CallIntMethod(*j_video_frame_buffer_, j_get_stride_v_id_); | |
126 } | |
127 | |
128 } // namespace | |
129 | |
28 Matrix::Matrix(JNIEnv* jni, jfloatArray a) { | 130 Matrix::Matrix(JNIEnv* jni, jfloatArray a) { |
29 RTC_CHECK_EQ(16, jni->GetArrayLength(a)); | 131 RTC_CHECK_EQ(16, jni->GetArrayLength(a)); |
30 jfloat* ptr = jni->GetFloatArrayElements(a, nullptr); | 132 jfloat* ptr = jni->GetFloatArrayElements(a, nullptr); |
31 for (int i = 0; i < 16; ++i) { | 133 for (int i = 0; i < 16; ++i) { |
32 elem_[i] = ptr[i]; | 134 elem_[i] = ptr[i]; |
33 } | 135 } |
34 jni->ReleaseFloatArrayElements(a, ptr, 0); | 136 jni->ReleaseFloatArrayElements(a, ptr, 0); |
35 } | 137 } |
36 | 138 |
37 jfloatArray Matrix::ToJava(JNIEnv* jni) const { | 139 jfloatArray Matrix::ToJava(JNIEnv* jni) const { |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
190 jni->CallVoidMethod(surface_texture_helper_, | 292 jni->CallVoidMethod(surface_texture_helper_, |
191 transform_mid, | 293 transform_mid, |
192 byte_buffer, width(), height(), stride, | 294 byte_buffer, width(), height(), stride, |
193 native_handle_.oes_texture_id, sampling_matrix); | 295 native_handle_.oes_texture_id, sampling_matrix); |
194 CHECK_EXCEPTION(jni) << "textureToYUV throwed an exception"; | 296 CHECK_EXCEPTION(jni) << "textureToYUV throwed an exception"; |
195 | 297 |
196 return copy; | 298 return copy; |
197 } | 299 } |
198 | 300 |
199 AndroidVideoBuffer::AndroidVideoBuffer(JNIEnv* jni, | 301 AndroidVideoBuffer::AndroidVideoBuffer(JNIEnv* jni, |
200 jmethodID j_retain_id, | |
201 jmethodID j_release_id, | 302 jmethodID j_release_id, |
202 jmethodID j_get_width_id, | 303 jmethodID j_get_width_id, |
203 jmethodID j_get_height_id, | 304 jmethodID j_get_height_id, |
204 jobject j_video_frame_buffer) | 305 jobject j_video_frame_buffer) |
205 : j_release_id_(j_release_id), | 306 : j_video_frame_buffer_(jni, j_video_frame_buffer), |
307 j_release_id_(j_release_id), | |
206 j_get_width_id_(j_get_width_id), | 308 j_get_width_id_(j_get_width_id), |
207 j_get_height_id_(j_get_height_id), | 309 j_get_height_id_(j_get_height_id) {} |
208 j_video_frame_buffer_(jni, j_video_frame_buffer) { | |
209 jni->CallVoidMethod(j_video_frame_buffer, j_retain_id); | |
210 } | |
211 | 310 |
212 AndroidVideoBuffer::~AndroidVideoBuffer() { | 311 AndroidVideoBuffer::~AndroidVideoBuffer() { |
213 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 312 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
214 jni->CallVoidMethod(*j_video_frame_buffer_, j_release_id_); | 313 jni->CallVoidMethod(*j_video_frame_buffer_, j_release_id_); |
215 } | 314 } |
216 | 315 |
217 jobject AndroidVideoBuffer::video_frame_buffer() const { | 316 jobject AndroidVideoBuffer::video_frame_buffer() const { |
218 return *j_video_frame_buffer_; | 317 return *j_video_frame_buffer_; |
219 } | 318 } |
220 | 319 |
221 webrtc::VideoFrameBuffer::Type AndroidVideoBuffer::type() const { | 320 webrtc::VideoFrameBuffer::Type AndroidVideoBuffer::type() const { |
222 return Type::kNative; | 321 return Type::kNative; |
223 } | 322 } |
224 | 323 |
225 int AndroidVideoBuffer::width() const { | 324 int AndroidVideoBuffer::width() const { |
226 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 325 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
227 return jni->CallIntMethod(*j_video_frame_buffer_, j_get_width_id_); | 326 return jni->CallIntMethod(*j_video_frame_buffer_, j_get_width_id_); |
228 } | 327 } |
229 | 328 |
230 int AndroidVideoBuffer::height() const { | 329 int AndroidVideoBuffer::height() const { |
231 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 330 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
232 return jni->CallIntMethod(*j_video_frame_buffer_, j_get_height_id_); | 331 return jni->CallIntMethod(*j_video_frame_buffer_, j_get_height_id_); |
233 } | 332 } |
234 | 333 |
235 rtc::scoped_refptr<webrtc::I420BufferInterface> AndroidVideoBuffer::ToI420() { | 334 rtc::scoped_refptr<webrtc::I420BufferInterface> AndroidVideoBuffer::ToI420() { |
236 // TODO(magjed): Implement using Java ToI420. | 335 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
237 return nullptr; | 336 ScopedLocalRefFrame local_ref_frame(jni); |
337 | |
338 jclass j_video_frame_buffer_class = | |
339 FindClass(jni, "org/webrtc/VideoFrame$Buffer"); | |
340 jmethodID j_to_i420_id = | |
341 jni->GetMethodID(j_video_frame_buffer_class, "toI420", | |
342 "()Lorg/webrtc/VideoFrame$I420Buffer;"); | |
343 | |
344 jclass j_video_frame_i420_buffer_class = | |
345 FindClass(jni, "org/webrtc/VideoFrame$I420Buffer"); | |
346 jmethodID j_get_data_y_id = jni->GetMethodID( | |
347 j_video_frame_i420_buffer_class, "getDataY", "()Ljava/nio/ByteBuffer;"); | |
348 jmethodID j_get_data_u_id = jni->GetMethodID( | |
349 j_video_frame_i420_buffer_class, "getDataU", "()Ljava/nio/ByteBuffer;"); | |
350 jmethodID j_get_data_v_id = jni->GetMethodID( | |
351 j_video_frame_i420_buffer_class, "getDataV", "()Ljava/nio/ByteBuffer;"); | |
352 jmethodID j_get_stride_y_id = | |
353 jni->GetMethodID(j_video_frame_i420_buffer_class, "getStrideY", "()I"); | |
354 jmethodID j_get_stride_u_id = | |
355 jni->GetMethodID(j_video_frame_i420_buffer_class, "getStrideU", "()I"); | |
356 jmethodID j_get_stride_v_id = | |
357 jni->GetMethodID(j_video_frame_i420_buffer_class, "getStrideV", "()I"); | |
358 | |
359 jobject j_i420_buffer = | |
360 jni->CallObjectMethod(*j_video_frame_buffer_, j_to_i420_id); | |
361 | |
362 return new rtc::RefCountedObject<AndroidVideoI420Buffer>( | |
363 jni, j_release_id_, j_get_width_id_, j_get_height_id_, j_get_data_y_id, | |
364 j_get_data_u_id, j_get_data_v_id, j_get_stride_y_id, j_get_stride_u_id, | |
365 j_get_stride_v_id, j_i420_buffer); | |
238 } | 366 } |
239 | 367 |
240 jobject AndroidVideoBuffer::ToJavaI420Frame(JNIEnv* jni, | 368 jobject AndroidVideoBuffer::ToJavaI420Frame(JNIEnv* jni, |
241 int rotation) { | 369 int rotation) { |
242 jclass j_byte_buffer_class = jni->FindClass("java/nio/ByteBuffer"); | 370 jclass j_byte_buffer_class = jni->FindClass("java/nio/ByteBuffer"); |
243 jclass j_i420_frame_class = | 371 jclass j_i420_frame_class = |
244 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame"); | 372 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame"); |
245 jmethodID j_i420_frame_ctor_id = GetMethodID( | 373 jmethodID j_i420_frame_ctor_id = GetMethodID( |
246 jni, j_i420_frame_class, "<init>", "(ILorg/webrtc/VideoFrame$Buffer;J)V"); | 374 jni, j_i420_frame_class, "<init>", "(ILorg/webrtc/VideoFrame$Buffer;J)V"); |
247 // Java code just uses the native frame to hold a reference to the buffer so | 375 // Java code just uses the native frame to hold a reference to the buffer so |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
287 rtc::scoped_refptr<AndroidVideoBuffer> buffer = | 415 rtc::scoped_refptr<AndroidVideoBuffer> buffer = |
288 CreateBuffer(j_video_frame_buffer); | 416 CreateBuffer(j_video_frame_buffer); |
289 return webrtc::VideoFrame(buffer, timestamp_rtp, | 417 return webrtc::VideoFrame(buffer, timestamp_rtp, |
290 timestamp_ns / rtc::kNumNanosecsPerMillisec, | 418 timestamp_ns / rtc::kNumNanosecsPerMillisec, |
291 static_cast<webrtc::VideoRotation>(rotation)); | 419 static_cast<webrtc::VideoRotation>(rotation)); |
292 } | 420 } |
293 | 421 |
294 rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBufferFactory::CreateBuffer( | 422 rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBufferFactory::CreateBuffer( |
295 jobject j_video_frame_buffer) const { | 423 jobject j_video_frame_buffer) const { |
296 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 424 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
425 jni->CallVoidMethod(j_video_frame_buffer, j_retain_id_); | |
297 return new rtc::RefCountedObject<AndroidVideoBuffer>( | 426 return new rtc::RefCountedObject<AndroidVideoBuffer>( |
298 jni, j_retain_id_, j_release_id_, j_get_width_id_, j_get_height_id_, | 427 jni, j_release_id_, j_get_width_id_, j_get_height_id_, |
299 j_video_frame_buffer); | 428 j_video_frame_buffer); |
300 } | 429 } |
301 | 430 |
302 } // namespace webrtc_jni | 431 } // namespace webrtc_jni |
OLD | NEW |