| Index: webrtc/sdk/android/src/jni/native_handle_impl.cc
|
| diff --git a/webrtc/sdk/android/src/jni/native_handle_impl.cc b/webrtc/sdk/android/src/jni/native_handle_impl.cc
|
| index f04a0b82b31565f589d81ceea69b92166a0973eb..f0070b9ee9e2edce474a74fa128f411a6b12726b 100644
|
| --- a/webrtc/sdk/android/src/jni/native_handle_impl.cc
|
| +++ b/webrtc/sdk/android/src/jni/native_handle_impl.cc
|
| @@ -25,6 +25,132 @@
|
|
|
| namespace webrtc_jni {
|
|
|
| +namespace {
|
| +
|
| +class AndroidVideoI420Buffer : public webrtc::I420BufferInterface {
|
| + public:
|
| + // Wraps an existing reference to a Java VideoBuffer. Retain will not be
|
| + // called but release will be called when the C++ object is destroyed.
|
| + static rtc::scoped_refptr<AndroidVideoI420Buffer> WrapReference(
|
| + JNIEnv* jni,
|
| + jmethodID j_release_id,
|
| + int width,
|
| + int height,
|
| + jobject j_video_frame_buffer);
|
| +
|
| + protected:
|
| + AndroidVideoI420Buffer(JNIEnv* jni,
|
| + jmethodID j_retain_id,
|
| + jmethodID j_release_id,
|
| + int width,
|
| + int height,
|
| + jobject j_video_frame_buffer);
|
| + // Should not be called directly. Wraps a reference. Use
|
| + // AndroidVideoI420Buffer::WrapReference instead for clarity.
|
| + AndroidVideoI420Buffer(JNIEnv* jni,
|
| + jmethodID j_release_id,
|
| + int width,
|
| + int height,
|
| + jobject j_video_frame_buffer);
|
| + ~AndroidVideoI420Buffer();
|
| +
|
| + private:
|
| + const uint8_t* DataY() const override { return data_y_; }
|
| + const uint8_t* DataU() const override { return data_u_; }
|
| + const uint8_t* DataV() const override { return data_v_; }
|
| +
|
| + int StrideY() const override { return stride_y_; }
|
| + int StrideU() const override { return stride_u_; }
|
| + int StrideV() const override { return stride_v_; }
|
| +
|
| + int width() const override { return width_; }
|
| + int height() const override { return height_; }
|
| +
|
| + const jmethodID j_release_id_;
|
| + const int width_;
|
| + const int height_;
|
| + // Holds a VideoFrame.I420Buffer.
|
| + const ScopedGlobalRef<jobject> j_video_frame_buffer_;
|
| +
|
| + const uint8_t* data_y_;
|
| + const uint8_t* data_u_;
|
| + const uint8_t* data_v_;
|
| + int stride_y_;
|
| + int stride_u_;
|
| + int stride_v_;
|
| +};
|
| +
|
| +rtc::scoped_refptr<AndroidVideoI420Buffer>
|
| +AndroidVideoI420Buffer::WrapReference(JNIEnv* jni,
|
| + jmethodID j_release_id,
|
| + int width,
|
| + int height,
|
| + jobject j_video_frame_buffer) {
|
| + return new rtc::RefCountedObject<AndroidVideoI420Buffer>(
|
| + jni, j_release_id, width, height, j_video_frame_buffer);
|
| +}
|
| +
|
| +AndroidVideoI420Buffer::AndroidVideoI420Buffer(JNIEnv* jni,
|
| + jmethodID j_retain_id,
|
| + jmethodID j_release_id,
|
| + int width,
|
| + int height,
|
| + jobject j_video_frame_buffer)
|
| + : AndroidVideoI420Buffer(jni,
|
| + j_release_id,
|
| + width,
|
| + height,
|
| + j_video_frame_buffer) {
|
| + jni->CallVoidMethod(j_video_frame_buffer, j_retain_id);
|
| +}
|
| +
|
| +AndroidVideoI420Buffer::AndroidVideoI420Buffer(JNIEnv* jni,
|
| + jmethodID j_release_id,
|
| + int width,
|
| + int height,
|
| + jobject j_video_frame_buffer)
|
| + : j_release_id_(j_release_id),
|
| + width_(width),
|
| + height_(height),
|
| + j_video_frame_buffer_(jni, j_video_frame_buffer) {
|
| + jclass j_video_frame_i420_buffer_class =
|
| + FindClass(jni, "org/webrtc/VideoFrame$I420Buffer");
|
| + jmethodID j_get_data_y_id = jni->GetMethodID(
|
| + j_video_frame_i420_buffer_class, "getDataY", "()Ljava/nio/ByteBuffer;");
|
| + jmethodID j_get_data_u_id = jni->GetMethodID(
|
| + j_video_frame_i420_buffer_class, "getDataU", "()Ljava/nio/ByteBuffer;");
|
| + jmethodID j_get_data_v_id = jni->GetMethodID(
|
| + j_video_frame_i420_buffer_class, "getDataV", "()Ljava/nio/ByteBuffer;");
|
| + jmethodID j_get_stride_y_id =
|
| + jni->GetMethodID(j_video_frame_i420_buffer_class, "getStrideY", "()I");
|
| + jmethodID j_get_stride_u_id =
|
| + jni->GetMethodID(j_video_frame_i420_buffer_class, "getStrideU", "()I");
|
| + jmethodID j_get_stride_v_id =
|
| + jni->GetMethodID(j_video_frame_i420_buffer_class, "getStrideV", "()I");
|
| +
|
| + jobject j_data_y =
|
| + jni->CallObjectMethod(j_video_frame_buffer, j_get_data_y_id);
|
| + jobject j_data_u =
|
| + jni->CallObjectMethod(j_video_frame_buffer, j_get_data_u_id);
|
| + jobject j_data_v =
|
| + jni->CallObjectMethod(j_video_frame_buffer, j_get_data_v_id);
|
| +
|
| + data_y_ = static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_y));
|
| + data_u_ = static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_u));
|
| + data_v_ = static_cast<const uint8_t*>(jni->GetDirectBufferAddress(j_data_v));
|
| +
|
| + stride_y_ = jni->CallIntMethod(j_video_frame_buffer, j_get_stride_y_id);
|
| + stride_u_ = jni->CallIntMethod(j_video_frame_buffer, j_get_stride_u_id);
|
| + stride_v_ = jni->CallIntMethod(j_video_frame_buffer, j_get_stride_v_id);
|
| +}
|
| +
|
| +AndroidVideoI420Buffer::~AndroidVideoI420Buffer() {
|
| + JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
| + jni->CallVoidMethod(*j_video_frame_buffer_, j_release_id_);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| Matrix::Matrix(JNIEnv* jni, jfloatArray a) {
|
| RTC_CHECK_EQ(16, jni->GetArrayLength(a));
|
| jfloat* ptr = jni->GetFloatArrayElements(a, nullptr);
|
| @@ -231,8 +357,22 @@ int AndroidVideoBuffer::height() const {
|
| }
|
|
|
| rtc::scoped_refptr<webrtc::I420BufferInterface> AndroidVideoBuffer::ToI420() {
|
| - // TODO(magjed): Implement using Java ToI420.
|
| - return nullptr;
|
| + JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
| + ScopedLocalRefFrame local_ref_frame(jni);
|
| +
|
| + jclass j_video_frame_buffer_class =
|
| + FindClass(jni, "org/webrtc/VideoFrame$Buffer");
|
| + jmethodID j_to_i420_id =
|
| + jni->GetMethodID(j_video_frame_buffer_class, "toI420",
|
| + "()Lorg/webrtc/VideoFrame$I420Buffer;");
|
| +
|
| + jobject j_i420_buffer =
|
| + jni->CallObjectMethod(*j_video_frame_buffer_, j_to_i420_id);
|
| +
|
| + // We don't need to retain the buffer because toI420 returns a new object that
|
| + // we are assumed to take the ownership of.
|
| + return AndroidVideoI420Buffer::WrapReference(jni, j_release_id_, width_,
|
| + height_, j_i420_buffer);
|
| }
|
|
|
| jobject AndroidVideoBuffer::ToJavaI420Frame(JNIEnv* jni,
|
|
|