OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 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 <jni.h> | 11 #include <jni.h> |
12 | 12 |
13 #include "webrtc/api/video/video_frame.h" | 13 #include "webrtc/api/video/video_frame.h" |
14 #include "webrtc/media/base/videosinkinterface.h" | 14 #include "webrtc/media/base/videosinkinterface.h" |
15 #include "webrtc/sdk/android/src/jni/classreferenceholder.h" | 15 #include "webrtc/sdk/android/src/jni/classreferenceholder.h" |
16 #include "webrtc/sdk/android/src/jni/jni_helpers.h" | 16 #include "webrtc/sdk/android/src/jni/jni_helpers.h" |
17 #include "webrtc/sdk/android/src/jni/native_handle_impl.h" | 17 #include "webrtc/sdk/android/src/jni/native_handle_impl.h" |
18 | 18 |
19 namespace webrtc_jni { | 19 namespace webrtc { |
| 20 namespace jni { |
20 | 21 |
21 // Wrapper dispatching rtc::VideoSinkInterface to a Java VideoRenderer | 22 // Wrapper dispatching rtc::VideoSinkInterface to a Java VideoRenderer |
22 // instance. | 23 // instance. |
23 class JavaVideoRendererWrapper | 24 class JavaVideoRendererWrapper : public rtc::VideoSinkInterface<VideoFrame> { |
24 : public rtc::VideoSinkInterface<webrtc::VideoFrame> { | |
25 public: | 25 public: |
26 JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks) | 26 JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks) |
27 : j_callbacks_(jni, j_callbacks), | 27 : j_callbacks_(jni, j_callbacks), |
28 j_render_frame_id_( | 28 j_render_frame_id_( |
29 GetMethodID(jni, | 29 GetMethodID(jni, |
30 GetObjectClass(jni, j_callbacks), | 30 GetObjectClass(jni, j_callbacks), |
31 "renderFrame", | 31 "renderFrame", |
32 "(Lorg/webrtc/VideoRenderer$I420Frame;)V")), | 32 "(Lorg/webrtc/VideoRenderer$I420Frame;)V")), |
33 j_frame_class_(jni, | 33 j_frame_class_(jni, |
34 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")), | 34 FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")), |
35 j_i420_frame_ctor_id_(GetMethodID(jni, | 35 j_i420_frame_ctor_id_(GetMethodID(jni, |
36 *j_frame_class_, | 36 *j_frame_class_, |
37 "<init>", | 37 "<init>", |
38 "(III[I[Ljava/nio/ByteBuffer;J)V")), | 38 "(III[I[Ljava/nio/ByteBuffer;J)V")), |
39 j_texture_frame_ctor_id_( | 39 j_texture_frame_ctor_id_( |
40 GetMethodID(jni, *j_frame_class_, "<init>", "(IIII[FJ)V")), | 40 GetMethodID(jni, *j_frame_class_, "<init>", "(IIII[FJ)V")), |
41 j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")) { | 41 j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")) { |
42 CHECK_EXCEPTION(jni); | 42 CHECK_EXCEPTION(jni); |
43 } | 43 } |
44 | 44 |
45 virtual ~JavaVideoRendererWrapper() {} | 45 virtual ~JavaVideoRendererWrapper() {} |
46 | 46 |
47 void OnFrame(const webrtc::VideoFrame& video_frame) override { | 47 void OnFrame(const VideoFrame& video_frame) override { |
48 ScopedLocalRefFrame local_ref_frame(jni()); | 48 ScopedLocalRefFrame local_ref_frame(jni()); |
49 | 49 |
50 jobject j_frame; | 50 jobject j_frame; |
51 if (video_frame.video_frame_buffer()->type() == | 51 if (video_frame.video_frame_buffer()->type() == |
52 webrtc::VideoFrameBuffer::Type::kNative) { | 52 VideoFrameBuffer::Type::kNative) { |
53 AndroidVideoFrameBuffer* android_buffer = | 53 AndroidVideoFrameBuffer* android_buffer = |
54 static_cast<AndroidVideoFrameBuffer*>( | 54 static_cast<AndroidVideoFrameBuffer*>( |
55 video_frame.video_frame_buffer().get()); | 55 video_frame.video_frame_buffer().get()); |
56 switch (android_buffer->android_type()) { | 56 switch (android_buffer->android_type()) { |
57 case AndroidVideoFrameBuffer::AndroidType::kTextureBuffer: | 57 case AndroidVideoFrameBuffer::AndroidType::kTextureBuffer: |
58 j_frame = ToJavaTextureFrame(&video_frame); | 58 j_frame = ToJavaTextureFrame(&video_frame); |
59 break; | 59 break; |
60 case AndroidVideoFrameBuffer::AndroidType::kJavaBuffer: | 60 case AndroidVideoFrameBuffer::AndroidType::kJavaBuffer: |
61 j_frame = static_cast<AndroidVideoBuffer*>(android_buffer) | 61 j_frame = static_cast<AndroidVideoBuffer*>(android_buffer) |
62 ->ToJavaI420Frame(jni(), video_frame.rotation()); | 62 ->ToJavaI420Frame(jni(), video_frame.rotation()); |
63 break; | 63 break; |
64 default: | 64 default: |
65 RTC_NOTREACHED(); | 65 RTC_NOTREACHED(); |
66 } | 66 } |
67 } else { | 67 } else { |
68 j_frame = ToJavaI420Frame(&video_frame); | 68 j_frame = ToJavaI420Frame(&video_frame); |
69 } | 69 } |
70 // |j_callbacks_| is responsible for releasing |j_frame| with | 70 // |j_callbacks_| is responsible for releasing |j_frame| with |
71 // VideoRenderer.renderFrameDone(). | 71 // VideoRenderer.renderFrameDone(). |
72 jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame); | 72 jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame); |
73 CHECK_EXCEPTION(jni()); | 73 CHECK_EXCEPTION(jni()); |
74 } | 74 } |
75 | 75 |
76 private: | 76 private: |
77 // Make a shallow copy of |frame| to be used with Java. The callee has | 77 // Make a shallow copy of |frame| to be used with Java. The callee has |
78 // ownership of the frame, and the frame should be released with | 78 // ownership of the frame, and the frame should be released with |
79 // VideoRenderer.releaseNativeFrame(). | 79 // VideoRenderer.releaseNativeFrame(). |
80 static jlong javaShallowCopy(const webrtc::VideoFrame* frame) { | 80 static jlong javaShallowCopy(const VideoFrame* frame) { |
81 return jlongFromPointer(new webrtc::VideoFrame(*frame)); | 81 return jlongFromPointer(new VideoFrame(*frame)); |
82 } | 82 } |
83 | 83 |
84 // Return a VideoRenderer.I420Frame referring to the data in |frame|. | 84 // Return a VideoRenderer.I420Frame referring to the data in |frame|. |
85 jobject ToJavaI420Frame(const webrtc::VideoFrame* frame) { | 85 jobject ToJavaI420Frame(const VideoFrame* frame) { |
86 jintArray strides = jni()->NewIntArray(3); | 86 jintArray strides = jni()->NewIntArray(3); |
87 jint* strides_array = jni()->GetIntArrayElements(strides, NULL); | 87 jint* strides_array = jni()->GetIntArrayElements(strides, NULL); |
88 rtc::scoped_refptr<webrtc::I420BufferInterface> i420_buffer = | 88 rtc::scoped_refptr<I420BufferInterface> i420_buffer = |
89 frame->video_frame_buffer()->ToI420(); | 89 frame->video_frame_buffer()->ToI420(); |
90 strides_array[0] = i420_buffer->StrideY(); | 90 strides_array[0] = i420_buffer->StrideY(); |
91 strides_array[1] = i420_buffer->StrideU(); | 91 strides_array[1] = i420_buffer->StrideU(); |
92 strides_array[2] = i420_buffer->StrideV(); | 92 strides_array[2] = i420_buffer->StrideV(); |
93 jni()->ReleaseIntArrayElements(strides, strides_array, 0); | 93 jni()->ReleaseIntArrayElements(strides, strides_array, 0); |
94 jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL); | 94 jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL); |
95 jobject y_buffer = jni()->NewDirectByteBuffer( | 95 jobject y_buffer = jni()->NewDirectByteBuffer( |
96 const_cast<uint8_t*>(i420_buffer->DataY()), | 96 const_cast<uint8_t*>(i420_buffer->DataY()), |
97 i420_buffer->StrideY() * i420_buffer->height()); | 97 i420_buffer->StrideY() * i420_buffer->height()); |
98 size_t chroma_height = i420_buffer->ChromaHeight(); | 98 size_t chroma_height = i420_buffer->ChromaHeight(); |
99 jobject u_buffer = | 99 jobject u_buffer = |
100 jni()->NewDirectByteBuffer(const_cast<uint8_t*>(i420_buffer->DataU()), | 100 jni()->NewDirectByteBuffer(const_cast<uint8_t*>(i420_buffer->DataU()), |
101 i420_buffer->StrideU() * chroma_height); | 101 i420_buffer->StrideU() * chroma_height); |
102 jobject v_buffer = | 102 jobject v_buffer = |
103 jni()->NewDirectByteBuffer(const_cast<uint8_t*>(i420_buffer->DataV()), | 103 jni()->NewDirectByteBuffer(const_cast<uint8_t*>(i420_buffer->DataV()), |
104 i420_buffer->StrideV() * chroma_height); | 104 i420_buffer->StrideV() * chroma_height); |
105 | 105 |
106 jni()->SetObjectArrayElement(planes, 0, y_buffer); | 106 jni()->SetObjectArrayElement(planes, 0, y_buffer); |
107 jni()->SetObjectArrayElement(planes, 1, u_buffer); | 107 jni()->SetObjectArrayElement(planes, 1, u_buffer); |
108 jni()->SetObjectArrayElement(planes, 2, v_buffer); | 108 jni()->SetObjectArrayElement(planes, 2, v_buffer); |
109 return jni()->NewObject(*j_frame_class_, j_i420_frame_ctor_id_, | 109 return jni()->NewObject(*j_frame_class_, j_i420_frame_ctor_id_, |
110 frame->width(), frame->height(), | 110 frame->width(), frame->height(), |
111 static_cast<int>(frame->rotation()), strides, | 111 static_cast<int>(frame->rotation()), strides, |
112 planes, javaShallowCopy(frame)); | 112 planes, javaShallowCopy(frame)); |
113 } | 113 } |
114 | 114 |
115 // Return a VideoRenderer.I420Frame referring texture object in |frame|. | 115 // Return a VideoRenderer.I420Frame referring texture object in |frame|. |
116 jobject ToJavaTextureFrame(const webrtc::VideoFrame* frame) { | 116 jobject ToJavaTextureFrame(const VideoFrame* frame) { |
117 NativeHandleImpl handle = | 117 NativeHandleImpl handle = |
118 static_cast<AndroidTextureBuffer*>(frame->video_frame_buffer().get()) | 118 static_cast<AndroidTextureBuffer*>(frame->video_frame_buffer().get()) |
119 ->native_handle_impl(); | 119 ->native_handle_impl(); |
120 jfloatArray sampling_matrix = handle.sampling_matrix.ToJava(jni()); | 120 jfloatArray sampling_matrix = handle.sampling_matrix.ToJava(jni()); |
121 | 121 |
122 return jni()->NewObject( | 122 return jni()->NewObject( |
123 *j_frame_class_, j_texture_frame_ctor_id_, frame->width(), | 123 *j_frame_class_, j_texture_frame_ctor_id_, frame->width(), |
124 frame->height(), static_cast<int>(frame->rotation()), | 124 frame->height(), static_cast<int>(frame->rotation()), |
125 handle.oes_texture_id, sampling_matrix, javaShallowCopy(frame)); | 125 handle.oes_texture_id, sampling_matrix, javaShallowCopy(frame)); |
126 } | 126 } |
(...skipping 14 matching lines...) Expand all Loading... |
141 jclass, | 141 jclass, |
142 jlong j_p) { | 142 jlong j_p) { |
143 delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p); | 143 delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p); |
144 } | 144 } |
145 | 145 |
146 JNI_FUNCTION_DECLARATION(void, | 146 JNI_FUNCTION_DECLARATION(void, |
147 VideoRenderer_releaseNativeFrame, | 147 VideoRenderer_releaseNativeFrame, |
148 JNIEnv* jni, | 148 JNIEnv* jni, |
149 jclass, | 149 jclass, |
150 jlong j_frame_ptr) { | 150 jlong j_frame_ptr) { |
151 delete reinterpret_cast<const webrtc::VideoFrame*>(j_frame_ptr); | 151 delete reinterpret_cast<const VideoFrame*>(j_frame_ptr); |
152 } | 152 } |
153 | 153 |
154 JNI_FUNCTION_DECLARATION(jlong, | 154 JNI_FUNCTION_DECLARATION(jlong, |
155 VideoRenderer_nativeWrapVideoRenderer, | 155 VideoRenderer_nativeWrapVideoRenderer, |
156 JNIEnv* jni, | 156 JNIEnv* jni, |
157 jclass, | 157 jclass, |
158 jobject j_callbacks) { | 158 jobject j_callbacks) { |
159 std::unique_ptr<JavaVideoRendererWrapper> renderer( | 159 std::unique_ptr<JavaVideoRendererWrapper> renderer( |
160 new JavaVideoRendererWrapper(jni, j_callbacks)); | 160 new JavaVideoRendererWrapper(jni, j_callbacks)); |
161 return (jlong)renderer.release(); | 161 return (jlong)renderer.release(); |
(...skipping 25 matching lines...) Expand all Loading... |
187 memcpy(dst, src, src_stride * height); | 187 memcpy(dst, src, src_stride * height); |
188 } else { | 188 } else { |
189 for (int i = 0; i < height; i++) { | 189 for (int i = 0; i < height; i++) { |
190 memcpy(dst, src, width); | 190 memcpy(dst, src, width); |
191 src += src_stride; | 191 src += src_stride; |
192 dst += dst_stride; | 192 dst += dst_stride; |
193 } | 193 } |
194 } | 194 } |
195 } | 195 } |
196 | 196 |
197 } // namespace webrtc_jni | 197 } // namespace jni |
| 198 } // namespace webrtc |
OLD | NEW |