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 webrtc::I420BufferInterface { | |
31 public: | |
32 AndroidVideoI420Buffer(JNIEnv* jni, | |
33 jmethodID j_release_id, | |
34 const uint8_t* data_y, | |
35 const uint8_t* data_u, | |
36 const uint8_t* data_v, | |
37 int stride_y, | |
38 int stride_u, | |
39 int stride_v, | |
40 int width, | |
41 int height, | |
42 jobject j_video_frame_buffer); | |
43 | |
44 private: | |
45 const uint8_t* DataY() const override { return data_y_; } | |
46 const uint8_t* DataU() const override { return data_u_; } | |
47 const uint8_t* DataV() const override { return data_v_; } | |
48 | |
49 int StrideY() const override { return stride_y_; } | |
50 int StrideU() const override { return stride_u_; } | |
51 int StrideV() const override { return stride_v_; } | |
52 | |
53 int width() const override { return android_video_buffer->width(); } | |
54 int height() const override { return android_video_buffer->height(); } | |
55 | |
56 rtc::scoped_refptr<AndroidVideoBuffer> android_video_buffer; | |
57 const uint8_t* data_y_; | |
58 const uint8_t* data_u_; | |
59 const uint8_t* data_v_; | |
60 const int stride_y_; | |
61 const int stride_u_; | |
62 const int stride_v_; | |
63 }; | |
64 | |
65 AndroidVideoI420Buffer::AndroidVideoI420Buffer(JNIEnv* jni, | |
66 jmethodID j_release_id, | |
67 const uint8_t* data_y, | |
68 const uint8_t* data_u, | |
69 const uint8_t* data_v, | |
70 int stride_y, | |
71 int stride_u, | |
72 int stride_v, | |
73 int width, | |
74 int height, | |
75 jobject j_video_frame_buffer) | |
76 : android_video_buffer( | |
77 new rtc::RefCountedObject<AndroidVideoBuffer>(jni, | |
magjed_webrtc
2017/07/28 09:45:04
I think it's clearer to duplicate the code you nee
| |
78 j_release_id, | |
79 width, | |
80 height, | |
81 j_video_frame_buffer)), | |
82 data_y_(data_y), | |
83 data_u_(data_u), | |
84 data_v_(data_v), | |
85 stride_y_(stride_y), | |
86 stride_u_(stride_u), | |
87 stride_v_(stride_v) {} | |
88 | |
89 } // namespace | |
90 | |
28 Matrix::Matrix(JNIEnv* jni, jfloatArray a) { | 91 Matrix::Matrix(JNIEnv* jni, jfloatArray a) { |
29 RTC_CHECK_EQ(16, jni->GetArrayLength(a)); | 92 RTC_CHECK_EQ(16, jni->GetArrayLength(a)); |
30 jfloat* ptr = jni->GetFloatArrayElements(a, nullptr); | 93 jfloat* ptr = jni->GetFloatArrayElements(a, nullptr); |
31 for (int i = 0; i < 16; ++i) { | 94 for (int i = 0; i < 16; ++i) { |
32 elem_[i] = ptr[i]; | 95 elem_[i] = ptr[i]; |
33 } | 96 } |
34 jni->ReleaseFloatArrayElements(a, ptr, 0); | 97 jni->ReleaseFloatArrayElements(a, ptr, 0); |
35 } | 98 } |
36 | 99 |
37 jfloatArray Matrix::ToJava(JNIEnv* jni) const { | 100 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_, | 253 jni->CallVoidMethod(surface_texture_helper_, |
191 transform_mid, | 254 transform_mid, |
192 byte_buffer, width(), height(), stride, | 255 byte_buffer, width(), height(), stride, |
193 native_handle_.oes_texture_id, sampling_matrix); | 256 native_handle_.oes_texture_id, sampling_matrix); |
194 CHECK_EXCEPTION(jni) << "textureToYUV throwed an exception"; | 257 CHECK_EXCEPTION(jni) << "textureToYUV throwed an exception"; |
195 | 258 |
196 return copy; | 259 return copy; |
197 } | 260 } |
198 | 261 |
199 AndroidVideoBuffer::AndroidVideoBuffer(JNIEnv* jni, | 262 AndroidVideoBuffer::AndroidVideoBuffer(JNIEnv* jni, |
200 jmethodID j_retain_id, | |
magjed_webrtc
2017/07/28 09:45:05
Revert this change in this CL.
sakal
2017/07/28 11:08:49
Done.
| |
201 jmethodID j_release_id, | 263 jmethodID j_release_id, |
202 int width, | 264 int width, |
203 int height, | 265 int height, |
204 jobject j_video_frame_buffer) | 266 jobject j_video_frame_buffer) |
205 : j_release_id_(j_release_id), | 267 : j_release_id_(j_release_id), |
206 width_(width), | 268 width_(width), |
207 height_(height), | 269 height_(height), |
208 j_video_frame_buffer_(jni, j_video_frame_buffer) { | 270 j_video_frame_buffer_(jni, j_video_frame_buffer) {} |
209 jni->CallVoidMethod(j_video_frame_buffer, j_retain_id); | |
210 } | |
211 | 271 |
212 AndroidVideoBuffer::~AndroidVideoBuffer() { | 272 AndroidVideoBuffer::~AndroidVideoBuffer() { |
213 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 273 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
214 jni->CallVoidMethod(*j_video_frame_buffer_, j_release_id_); | 274 jni->CallVoidMethod(*j_video_frame_buffer_, j_release_id_); |
215 } | 275 } |
216 | 276 |
217 jobject AndroidVideoBuffer::video_frame_buffer() const { | 277 jobject AndroidVideoBuffer::video_frame_buffer() const { |
218 return *j_video_frame_buffer_; | 278 return *j_video_frame_buffer_; |
219 } | 279 } |
220 | 280 |
221 webrtc::VideoFrameBuffer::Type AndroidVideoBuffer::type() const { | 281 webrtc::VideoFrameBuffer::Type AndroidVideoBuffer::type() const { |
222 return Type::kNative; | 282 return Type::kNative; |
223 } | 283 } |
224 | 284 |
225 int AndroidVideoBuffer::width() const { | 285 int AndroidVideoBuffer::width() const { |
226 return width_; | 286 return width_; |
227 } | 287 } |
228 | 288 |
229 int AndroidVideoBuffer::height() const { | 289 int AndroidVideoBuffer::height() const { |
230 return height_; | 290 return height_; |
231 } | 291 } |
232 | 292 |
233 rtc::scoped_refptr<webrtc::I420BufferInterface> AndroidVideoBuffer::ToI420() { | 293 rtc::scoped_refptr<webrtc::I420BufferInterface> AndroidVideoBuffer::ToI420() { |
234 // TODO(magjed): Implement using Java ToI420. | 294 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
235 return nullptr; | 295 ScopedLocalRefFrame local_ref_frame(jni); |
296 | |
297 jclass j_video_frame_buffer_class = | |
298 FindClass(jni, "org/webrtc/VideoFrame$Buffer"); | |
299 jmethodID j_to_i420_id = | |
300 jni->GetMethodID(j_video_frame_buffer_class, "toI420", | |
301 "()Lorg/webrtc/VideoFrame$I420Buffer;"); | |
302 | |
303 jclass j_video_frame_i420_buffer_class = | |
304 FindClass(jni, "org/webrtc/VideoFrame$I420Buffer"); | |
305 jmethodID j_get_data_y_id = jni->GetMethodID( | |
306 j_video_frame_i420_buffer_class, "getDataY", "()Ljava/nio/ByteBuffer;"); | |
307 jmethodID j_get_data_u_id = jni->GetMethodID( | |
308 j_video_frame_i420_buffer_class, "getDataU", "()Ljava/nio/ByteBuffer;"); | |
309 jmethodID j_get_data_v_id = jni->GetMethodID( | |
310 j_video_frame_i420_buffer_class, "getDataV", "()Ljava/nio/ByteBuffer;"); | |
311 jmethodID j_get_stride_y_id = | |
312 jni->GetMethodID(j_video_frame_i420_buffer_class, "getStrideY", "()I"); | |
313 jmethodID j_get_stride_u_id = | |
314 jni->GetMethodID(j_video_frame_i420_buffer_class, "getStrideU", "()I"); | |
315 jmethodID j_get_stride_v_id = | |
316 jni->GetMethodID(j_video_frame_i420_buffer_class, "getStrideV", "()I"); | |
317 | |
318 jobject j_i420_buffer = | |
319 jni->CallObjectMethod(*j_video_frame_buffer_, j_to_i420_id); | |
magjed_webrtc
2017/07/28 09:45:05
How about extracting j_i420_buffer here and passin
sakal
2017/07/28 11:08:49
Done.
| |
320 | |
321 jobject j_data_y = jni->CallObjectMethod(j_i420_buffer, j_get_data_y_id); | |
322 jobject j_data_u = jni->CallObjectMethod(j_i420_buffer, j_get_data_u_id); | |
323 jobject j_data_v = jni->CallObjectMethod(j_i420_buffer, j_get_data_v_id); | |
324 | |
325 const uint8_t* data_y = | |
326 static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_y)); | |
327 const uint8_t* data_u = | |
328 static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_u)); | |
329 const uint8_t* data_v = | |
330 static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_v)); | |
331 | |
332 int stride_y = jni->CallIntMethod(j_i420_buffer, j_get_stride_y_id); | |
333 int stride_u = jni->CallIntMethod(j_i420_buffer, j_get_stride_u_id); | |
334 int stride_v = jni->CallIntMethod(j_i420_buffer, j_get_stride_v_id); | |
335 | |
336 return new rtc::RefCountedObject<AndroidVideoI420Buffer>( | |
337 jni, j_release_id_, data_y, data_u, data_v, stride_y, stride_u, stride_v, | |
338 width_, height_, j_i420_buffer); | |
236 } | 339 } |
237 | 340 |
238 jobject AndroidVideoBuffer::ToJavaI420Frame(JNIEnv* jni, | 341 jobject AndroidVideoBuffer::ToJavaI420Frame(JNIEnv* jni, |
239 int rotation) { | 342 int rotation) { |
240 jclass j_byte_buffer_class = jni->FindClass("java/nio/ByteBuffer"); | 343 jclass j_byte_buffer_class = jni->FindClass("java/nio/ByteBuffer"); |
241 jclass j_i420_frame_class = | 344 jclass j_i420_frame_class = |
242 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame"); | 345 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame"); |
243 jmethodID j_i420_frame_ctor_id = GetMethodID( | 346 jmethodID j_i420_frame_ctor_id = GetMethodID( |
244 jni, j_i420_frame_class, "<init>", "(ILorg/webrtc/VideoFrame$Buffer;J)V"); | 347 jni, j_i420_frame_class, "<init>", "(ILorg/webrtc/VideoFrame$Buffer;J)V"); |
245 // Java code just uses the native frame to hold a reference to the buffer so | 348 // 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... | |
285 rtc::scoped_refptr<AndroidVideoBuffer> buffer = | 388 rtc::scoped_refptr<AndroidVideoBuffer> buffer = |
286 CreateBuffer(j_video_frame_buffer); | 389 CreateBuffer(j_video_frame_buffer); |
287 return webrtc::VideoFrame(buffer, timestamp_rtp, | 390 return webrtc::VideoFrame(buffer, timestamp_rtp, |
288 timestamp_ns / rtc::kNumNanosecsPerMillisec, | 391 timestamp_ns / rtc::kNumNanosecsPerMillisec, |
289 static_cast<webrtc::VideoRotation>(rotation)); | 392 static_cast<webrtc::VideoRotation>(rotation)); |
290 } | 393 } |
291 | 394 |
292 rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBufferFactory::CreateBuffer( | 395 rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBufferFactory::CreateBuffer( |
293 jobject j_video_frame_buffer) const { | 396 jobject j_video_frame_buffer) const { |
294 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 397 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
398 jni->CallVoidMethod(j_video_frame_buffer, j_retain_id_); | |
295 int width = jni->CallIntMethod(j_video_frame_buffer, j_get_width_id_); | 399 int width = jni->CallIntMethod(j_video_frame_buffer, j_get_width_id_); |
296 int height = jni->CallIntMethod(j_video_frame_buffer, j_get_height_id_); | 400 int height = jni->CallIntMethod(j_video_frame_buffer, j_get_height_id_); |
297 return new rtc::RefCountedObject<AndroidVideoBuffer>( | 401 return new rtc::RefCountedObject<AndroidVideoBuffer>( |
298 jni, j_retain_id_, j_release_id_, width, height, j_video_frame_buffer); | 402 jni, j_release_id_, width, height, j_video_frame_buffer); |
299 } | 403 } |
300 | 404 |
301 } // namespace webrtc_jni | 405 } // namespace webrtc_jni |
OLD | NEW |