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 |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 Matrix::Matrix(JNIEnv* jni, jfloatArray a) { | 28 Matrix::Matrix(JNIEnv* jni, jfloatArray a) { |
29 RTC_CHECK_EQ(16, jni->GetArrayLength(a)); | 29 RTC_CHECK_EQ(16, jni->GetArrayLength(a)); |
30 jfloat* ptr = jni->GetFloatArrayElements(a, nullptr); | 30 jfloat* ptr = jni->GetFloatArrayElements(a, nullptr); |
31 for (int i = 0; i < 16; ++i) { | 31 for (int i = 0; i < 16; ++i) { |
32 elem_[i] = ptr[i]; | 32 elem_[i] = ptr[i]; |
33 } | 33 } |
34 jni->ReleaseFloatArrayElements(a, ptr, 0); | 34 jni->ReleaseFloatArrayElements(a, ptr, 0); |
35 } | 35 } |
36 | 36 |
37 Matrix Matrix::fromAndroidGraphicsMatrix(JNIEnv* jni, jobject j_matrix) { | |
38 jfloatArray array_3x3 = jni->NewFloatArray(9); | |
39 jclass j_matrix_class = jni->FindClass("android/graphics/Matrix"); | |
40 jni->CallVoidMethod(j_matrix, | |
41 GetMethodID(jni, j_matrix_class, "getValues", "([F)V"), | |
42 array_3x3); | |
43 jfloat* array_3x3_ptr = jni->GetFloatArrayElements(array_3x3, nullptr); | |
44 Matrix matrix; | |
45 memset(matrix.elem_, 0, sizeof(matrix.elem_)); | |
46 // The android.graphics.Matrix looks like this: | |
47 // [x1 y1 w1] | |
48 // [x2 y2 w2] | |
49 // [x3 y3 w3] | |
50 // We want to contruct a matrix that looks like this: | |
51 // [x1 y1 0 w1] | |
52 // [x2 y2 0 w2] | |
53 // [ 0 0 1 0] | |
54 // [x3 y3 0 w3] | |
55 // Since it is stored in column-major order, it looks like this: | |
56 // [x1 x2 0 x3 | |
57 // y1 y2 0 y3 | |
58 // 0 0 1 0 | |
59 // w1 w2 0 w3] | |
60 matrix.elem_[0 * 4 + 0] = array_3x3_ptr[0 * 3 + 0]; | |
61 matrix.elem_[0 * 4 + 1] = array_3x3_ptr[1 * 3 + 0]; | |
62 matrix.elem_[0 * 4 + 3] = array_3x3_ptr[2 * 3 + 0]; | |
63 matrix.elem_[1 * 4 + 0] = array_3x3_ptr[0 * 3 + 1]; | |
64 matrix.elem_[1 * 4 + 1] = array_3x3_ptr[1 * 3 + 1]; | |
65 matrix.elem_[1 * 4 + 3] = array_3x3_ptr[2 * 3 + 1]; | |
66 matrix.elem_[2 * 4 + 2] = 1; // Z-scale should be 1. | |
67 matrix.elem_[3 * 4 + 0] = array_3x3_ptr[0 * 3 + 2]; | |
68 matrix.elem_[3 * 4 + 1] = array_3x3_ptr[1 * 3 + 2]; | |
69 matrix.elem_[3 * 4 + 3] = array_3x3_ptr[2 * 3 + 2]; | |
70 return matrix; | |
71 } | |
72 | |
73 jfloatArray Matrix::ToJava(JNIEnv* jni) const { | 37 jfloatArray Matrix::ToJava(JNIEnv* jni) const { |
74 jfloatArray matrix = jni->NewFloatArray(16); | 38 jfloatArray matrix = jni->NewFloatArray(16); |
75 jni->SetFloatArrayRegion(matrix, 0, 16, elem_); | 39 jni->SetFloatArrayRegion(matrix, 0, 16, elem_); |
76 return matrix; | 40 return matrix; |
77 } | 41 } |
78 | 42 |
79 void Matrix::Rotate(webrtc::VideoRotation rotation) { | 43 void Matrix::Rotate(webrtc::VideoRotation rotation) { |
80 // Texture coordinates are in the range 0 to 1. The transformation of the last | 44 // Texture coordinates are in the range 0 to 1. The transformation of the last |
81 // row in each rotation matrix is needed for proper translation, e.g, to | 45 // row in each rotation matrix is needed for proper translation, e.g, to |
82 // mirror x, we don't replace x by -x, but by 1-x. | 46 // mirror x, we don't replace x by -x, but by 1-x. |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 CHECK_EXCEPTION(jni) << "textureToYUV throwed an exception"; | 194 CHECK_EXCEPTION(jni) << "textureToYUV throwed an exception"; |
231 | 195 |
232 return copy; | 196 return copy; |
233 } | 197 } |
234 | 198 |
235 AndroidVideoBuffer::AndroidVideoBuffer(JNIEnv* jni, | 199 AndroidVideoBuffer::AndroidVideoBuffer(JNIEnv* jni, |
236 jmethodID j_retain_id, | 200 jmethodID j_retain_id, |
237 jmethodID j_release_id, | 201 jmethodID j_release_id, |
238 int width, | 202 int width, |
239 int height, | 203 int height, |
240 const Matrix& matrix, | |
241 jobject j_video_frame_buffer) | 204 jobject j_video_frame_buffer) |
242 : j_release_id_(j_release_id), | 205 : j_release_id_(j_release_id), |
243 width_(width), | 206 width_(width), |
244 height_(height), | 207 height_(height), |
245 matrix_(matrix), | |
246 j_video_frame_buffer_(jni, j_video_frame_buffer) { | 208 j_video_frame_buffer_(jni, j_video_frame_buffer) { |
247 jni->CallVoidMethod(j_video_frame_buffer, j_retain_id); | 209 jni->CallVoidMethod(j_video_frame_buffer, j_retain_id); |
248 } | 210 } |
249 | 211 |
250 AndroidVideoBuffer::~AndroidVideoBuffer() { | 212 AndroidVideoBuffer::~AndroidVideoBuffer() { |
251 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 213 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
252 jni->CallVoidMethod(*j_video_frame_buffer_, j_release_id_); | 214 jni->CallVoidMethod(*j_video_frame_buffer_, j_release_id_); |
253 } | 215 } |
254 | 216 |
255 jobject AndroidVideoBuffer::video_frame_buffer() const { | 217 jobject AndroidVideoBuffer::video_frame_buffer() const { |
(...skipping 11 matching lines...) Expand all Loading... |
267 int AndroidVideoBuffer::height() const { | 229 int AndroidVideoBuffer::height() const { |
268 return height_; | 230 return height_; |
269 } | 231 } |
270 | 232 |
271 rtc::scoped_refptr<webrtc::I420BufferInterface> AndroidVideoBuffer::ToI420() { | 233 rtc::scoped_refptr<webrtc::I420BufferInterface> AndroidVideoBuffer::ToI420() { |
272 // TODO(magjed): Implement using Java ToI420. | 234 // TODO(magjed): Implement using Java ToI420. |
273 return nullptr; | 235 return nullptr; |
274 } | 236 } |
275 | 237 |
276 jobject AndroidVideoBuffer::ToJavaI420Frame(JNIEnv* jni, | 238 jobject AndroidVideoBuffer::ToJavaI420Frame(JNIEnv* jni, |
277 int width, | |
278 int height, | |
279 int rotation) { | 239 int rotation) { |
280 jclass j_byte_buffer_class = jni->FindClass("java/nio/ByteBuffer"); | 240 jclass j_byte_buffer_class = jni->FindClass("java/nio/ByteBuffer"); |
281 jclass j_i420_frame_class = | 241 jclass j_i420_frame_class = |
282 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame"); | 242 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame"); |
283 jmethodID j_i420_frame_ctor_id = | 243 jmethodID j_i420_frame_ctor_id = GetMethodID( |
284 GetMethodID(jni, j_i420_frame_class, "<init>", | 244 jni, j_i420_frame_class, "<init>", "(ILorg/webrtc/VideoFrame$Buffer;J)V"); |
285 "(III[FLorg/webrtc/VideoFrame$Buffer;J)V"); | |
286 // Java code just uses the native frame to hold a reference to the buffer so | 245 // Java code just uses the native frame to hold a reference to the buffer so |
287 // this is okay. | 246 // this is okay. |
288 webrtc::VideoFrame* native_frame = new webrtc::VideoFrame( | 247 webrtc::VideoFrame* native_frame = new webrtc::VideoFrame( |
289 this, 0 /* timestamp */, 0 /* render_time_ms */, | 248 this, 0 /* timestamp */, 0 /* render_time_ms */, |
290 webrtc::VideoRotation::kVideoRotation_0 /* rotation */); | 249 webrtc::VideoRotation::kVideoRotation_0 /* rotation */); |
291 return jni->NewObject(j_i420_frame_class, j_i420_frame_ctor_id, width, height, | 250 return jni->NewObject(j_i420_frame_class, j_i420_frame_ctor_id, rotation, |
292 rotation, matrix_.ToJava(jni), *j_video_frame_buffer_, | 251 *j_video_frame_buffer_, jlongFromPointer(native_frame)); |
293 jlongFromPointer(native_frame)); | |
294 } | 252 } |
295 | 253 |
296 AndroidVideoBufferFactory::AndroidVideoBufferFactory(JNIEnv* jni) | 254 AndroidVideoBufferFactory::AndroidVideoBufferFactory(JNIEnv* jni) |
297 : j_video_frame_class_(jni, FindClass(jni, "org/webrtc/VideoFrame")), | 255 : j_video_frame_class_(jni, FindClass(jni, "org/webrtc/VideoFrame")), |
298 j_get_buffer_id_(GetMethodID(jni, | 256 j_get_buffer_id_(GetMethodID(jni, |
299 *j_video_frame_class_, | 257 *j_video_frame_class_, |
300 "getBuffer", | 258 "getBuffer", |
301 "()Lorg/webrtc/VideoFrame$Buffer;")), | 259 "()Lorg/webrtc/VideoFrame$Buffer;")), |
302 j_get_width_id_( | |
303 GetMethodID(jni, *j_video_frame_class_, "getWidth", "()I")), | |
304 j_get_height_id_( | |
305 GetMethodID(jni, *j_video_frame_class_, "getHeight", "()I")), | |
306 j_get_rotation_id_( | 260 j_get_rotation_id_( |
307 GetMethodID(jni, *j_video_frame_class_, "getRotation", "()I")), | 261 GetMethodID(jni, *j_video_frame_class_, "getRotation", "()I")), |
308 j_get_transform_matrix_id_(GetMethodID(jni, | |
309 *j_video_frame_class_, | |
310 "getTransformMatrix", | |
311 "()Landroid/graphics/Matrix;")), | |
312 j_get_timestamp_ns_id_( | 262 j_get_timestamp_ns_id_( |
313 GetMethodID(jni, *j_video_frame_class_, "getTimestampNs", "()J")), | 263 GetMethodID(jni, *j_video_frame_class_, "getTimestampNs", "()J")), |
314 j_video_frame_buffer_class_( | 264 j_video_frame_buffer_class_( |
315 jni, | 265 jni, |
316 FindClass(jni, "org/webrtc/VideoFrame$Buffer")), | 266 FindClass(jni, "org/webrtc/VideoFrame$Buffer")), |
317 j_retain_id_( | 267 j_retain_id_( |
318 GetMethodID(jni, *j_video_frame_buffer_class_, "retain", "()V")), | 268 GetMethodID(jni, *j_video_frame_buffer_class_, "retain", "()V")), |
319 j_release_id_( | 269 j_release_id_( |
320 GetMethodID(jni, *j_video_frame_buffer_class_, "release", "()V")) {} | 270 GetMethodID(jni, *j_video_frame_buffer_class_, "release", "()V")), |
| 271 j_get_width_id_( |
| 272 GetMethodID(jni, *j_video_frame_buffer_class_, "getWidth", "()I")), |
| 273 j_get_height_id_( |
| 274 GetMethodID(jni, *j_video_frame_buffer_class_, "getHeight", "()I")) {} |
321 | 275 |
322 webrtc::VideoFrame AndroidVideoBufferFactory::CreateFrame( | 276 webrtc::VideoFrame AndroidVideoBufferFactory::CreateFrame( |
323 JNIEnv* jni, | 277 JNIEnv* jni, |
324 jobject j_video_frame, | 278 jobject j_video_frame, |
325 uint32_t timestamp_rtp) const { | 279 uint32_t timestamp_rtp) const { |
326 jobject j_video_frame_buffer = | 280 jobject j_video_frame_buffer = |
327 jni->CallObjectMethod(j_video_frame, j_get_buffer_id_); | 281 jni->CallObjectMethod(j_video_frame, j_get_buffer_id_); |
328 int width = jni->CallIntMethod(j_video_frame, j_get_width_id_); | |
329 int height = jni->CallIntMethod(j_video_frame, j_get_height_id_); | |
330 int rotation = jni->CallIntMethod(j_video_frame, j_get_rotation_id_); | 282 int rotation = jni->CallIntMethod(j_video_frame, j_get_rotation_id_); |
331 jobject j_matrix = | |
332 jni->CallObjectMethod(j_video_frame, j_get_transform_matrix_id_); | |
333 Matrix matrix = Matrix::fromAndroidGraphicsMatrix(jni, j_matrix); | |
334 uint32_t timestamp_ns = | 283 uint32_t timestamp_ns = |
335 jni->CallLongMethod(j_video_frame, j_get_timestamp_ns_id_); | 284 jni->CallLongMethod(j_video_frame, j_get_timestamp_ns_id_); |
336 rtc::scoped_refptr<AndroidVideoBuffer> buffer = | 285 rtc::scoped_refptr<AndroidVideoBuffer> buffer = |
337 CreateBuffer(width, height, matrix, j_video_frame_buffer); | 286 CreateBuffer(j_video_frame_buffer); |
338 return webrtc::VideoFrame(buffer, timestamp_rtp, | 287 return webrtc::VideoFrame(buffer, timestamp_rtp, |
339 timestamp_ns / rtc::kNumNanosecsPerMillisec, | 288 timestamp_ns / rtc::kNumNanosecsPerMillisec, |
340 static_cast<webrtc::VideoRotation>(rotation)); | 289 static_cast<webrtc::VideoRotation>(rotation)); |
341 } | 290 } |
342 | 291 |
343 rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBufferFactory::CreateBuffer( | 292 rtc::scoped_refptr<AndroidVideoBuffer> AndroidVideoBufferFactory::CreateBuffer( |
344 int width, | |
345 int height, | |
346 const Matrix& matrix, | |
347 jobject j_video_frame_buffer) const { | 293 jobject j_video_frame_buffer) const { |
348 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 294 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
| 295 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_); |
349 return new rtc::RefCountedObject<AndroidVideoBuffer>( | 297 return new rtc::RefCountedObject<AndroidVideoBuffer>( |
350 jni, j_retain_id_, j_release_id_, width, height, matrix, | 298 jni, j_retain_id_, j_release_id_, width, height, j_video_frame_buffer); |
351 j_video_frame_buffer); | |
352 } | 299 } |
353 | 300 |
354 } // namespace webrtc_jni | 301 } // namespace webrtc_jni |
OLD | NEW |