Android: Generate JNI code for VideoDecoder

Bug: webrtc:8278
Change-Id: I985fa63b0c5a9cdd0fb1817730646bcd4b30288a
Reviewed-on: https://webrtc-review.googlesource.com/24221
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20803}
diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn
index 9daae54..98ba0da 100644
--- a/sdk/android/BUILD.gn
+++ b/sdk/android/BUILD.gn
@@ -105,11 +105,14 @@
 
 generate_jni("generated_video_jni") {
   sources = [
+    "api/org/webrtc/EncodedImage.java",
     "api/org/webrtc/SurfaceTextureHelper.java",
     "api/org/webrtc/VideoCodecStatus.java",
+    "api/org/webrtc/VideoDecoder.java",
     "api/org/webrtc/VideoEncoder.java",
     "api/org/webrtc/VideoFrame.java",
     "api/org/webrtc/VideoSink.java",
+    "src/java/org/webrtc/VideoDecoderWrapper.java",
     "src/java/org/webrtc/VideoEncoderWrapper.java",
     "src/java/org/webrtc/WrappedNativeVideoDecoder.java",
     "src/java/org/webrtc/WrappedNativeVideoEncoder.java",
@@ -128,6 +131,8 @@
     "src/jni/androidvideotracksource.cc",
     "src/jni/androidvideotracksource.h",
     "src/jni/androidvideotracksource_jni.cc",
+    "src/jni/encodedimage.cc",
+    "src/jni/encodedimage.h",
     "src/jni/hardwarevideoencoderfactory.cc",
     "src/jni/jni_generator_helper.h",
     "src/jni/nv12buffer_jni.cc",
@@ -138,6 +143,8 @@
     "src/jni/video_renderer_jni.cc",
     "src/jni/videocodecinfo.cc",
     "src/jni/videocodecinfo.h",
+    "src/jni/videocodecstatus.cc",
+    "src/jni/videocodecstatus.h",
     "src/jni/videodecoderfactorywrapper.cc",
     "src/jni/videodecoderfactorywrapper.h",
     "src/jni/videodecoderfallback.cc",
@@ -447,6 +454,7 @@
 
 rtc_android_library("libjingle_peerconnection_java") {
   java_files = [
+    "src/java/org/webrtc/VideoDecoderWrapper.java",
     "api/org/webrtc/AudioProcessingFactory.java",
     "api/org/webrtc/AudioSource.java",
     "api/org/webrtc/AudioTrack.java",
@@ -548,7 +556,6 @@
     "src/java/org/webrtc/NV21Buffer.java",
     "src/java/org/webrtc/TextureBufferImpl.java",
     "src/java/org/webrtc/VideoCodecType.java",
-    "src/java/org/webrtc/VideoDecoderWrapperCallback.java",
     "src/java/org/webrtc/VideoEncoderWrapper.java",
     "src/java/org/webrtc/WrappedNativeI420Buffer.java",
     "src/java/org/webrtc/WrappedNativeVideoEncoder.java",
diff --git a/sdk/android/api/org/webrtc/EncodedImage.java b/sdk/android/api/org/webrtc/EncodedImage.java
index c6c56ce..dc8eb62 100644
--- a/sdk/android/api/org/webrtc/EncodedImage.java
+++ b/sdk/android/api/org/webrtc/EncodedImage.java
@@ -12,6 +12,8 @@
 
 import java.nio.ByteBuffer;
 import java.util.concurrent.TimeUnit;
+// TODO(bugs.webrtc.org/8556): Remove unnecessary import.
+import org.webrtc.EncodedImage;
 
 /**
  * An encoded frame from a video stream. Used as an input for decoders and as an output for
@@ -33,6 +35,17 @@
     public int getNative() {
       return nativeIndex;
     }
+
+    // TODO(bugs.webrtc.org/8556): Remove unnecessary 'EncodedImage.'.
+    @CalledByNative("FrameType")
+    static EncodedImage.FrameType fromNativeIndex(int nativeIndex) {
+      for (FrameType type : FrameType.values()) {
+        if (type.getNative() == nativeIndex) {
+          return type;
+        }
+      }
+      throw new IllegalArgumentException("Unknown native frame type: " + nativeIndex);
+    }
   }
 
   public final ByteBuffer buffer;
@@ -125,4 +138,13 @@
           rotation, completeFrame, qp);
     }
   }
+
+  // TODO(bugs.webrtc.org/8551) Remove.
+  @CalledByNative
+  static EncodedImage create(ByteBuffer buffer, int encodedWidth, int encodedHeight,
+      long captureTimeNs, EncodedImage.FrameType frameType, int rotation, boolean completeFrame,
+      Integer qp) {
+    return new EncodedImage(
+        buffer, encodedWidth, encodedHeight, captureTimeNs, frameType, rotation, completeFrame, qp);
+  }
 }
diff --git a/sdk/android/api/org/webrtc/VideoDecoder.java b/sdk/android/api/org/webrtc/VideoDecoder.java
index 76b030c..f5acfad 100644
--- a/sdk/android/api/org/webrtc/VideoDecoder.java
+++ b/sdk/android/api/org/webrtc/VideoDecoder.java
@@ -54,23 +54,23 @@
    * Initializes the decoding process with specified settings. Will be called on the decoding thread
    * before any decode calls.
    */
-  VideoCodecStatus initDecode(Settings settings, Callback decodeCallback);
+  @CalledByNative VideoCodecStatus initDecode(Settings settings, Callback decodeCallback);
   /**
    * Called when the decoder is no longer needed. Any more calls to decode will not be made.
    */
-  VideoCodecStatus release();
+  @CalledByNative VideoCodecStatus release();
   /**
    * Request the decoder to decode a frame.
    */
-  VideoCodecStatus decode(EncodedImage frame, DecodeInfo info);
+  @CalledByNative VideoCodecStatus decode(EncodedImage frame, DecodeInfo info);
   /**
    * The decoder should return true if it prefers late decoding. That is, it can not decode
    * infinite number of frames before the decoded frame is consumed.
    */
-  boolean getPrefersLateDecoding();
+  @CalledByNative boolean getPrefersLateDecoding();
   /**
    * Should return a descriptive name for the implementation. Gets called once and cached. May be
    * called from arbitrary thread.
    */
-  String getImplementationName();
+  @CalledByNative String getImplementationName();
 }
diff --git a/sdk/android/src/java/org/webrtc/VideoDecoderWrapper.java b/sdk/android/src/java/org/webrtc/VideoDecoderWrapper.java
new file mode 100644
index 0000000..97134c5
--- /dev/null
+++ b/sdk/android/src/java/org/webrtc/VideoDecoderWrapper.java
@@ -0,0 +1,34 @@
+/*
+ *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+package org.webrtc;
+
+import org.webrtc.VideoDecoder;
+
+/**
+ * This class contains the Java glue code for JNI generation of VideoDecoder.
+ */
+class VideoDecoderWrapper {
+  // TODO(bugs.webrtc.org/8551) Remove.
+  @CalledByNative
+  static VideoDecoder.Settings createSettings(int numberOfCores, int width, int height) {
+    return new VideoDecoder.Settings(numberOfCores, width, height);
+  }
+
+  @CalledByNative
+  static VideoDecoder.Callback createDecoderCallback(final long nativeDecoder) {
+    return (VideoFrame frame, Integer decodeTimeMs,
+               Integer qp) -> nativeOnDecodedFrame(nativeDecoder, frame, decodeTimeMs, qp);
+  }
+
+  @NativeClassQualifiedName("webrtc::jni::VideoDecoderWrapper")
+  private static native void nativeOnDecodedFrame(
+      long nativeDecoder, VideoFrame frame, Integer decodeTimeMs, Integer qp);
+}
diff --git a/sdk/android/src/java/org/webrtc/VideoDecoderWrapperCallback.java b/sdk/android/src/java/org/webrtc/VideoDecoderWrapperCallback.java
deleted file mode 100644
index 232466d..0000000
--- a/sdk/android/src/java/org/webrtc/VideoDecoderWrapperCallback.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-package org.webrtc;
-
-/**
- * VideoDecoder callback that calls VideoDecoderWrapper.OnDecodedFrame for the decoded frames.
- */
-class VideoDecoderWrapperCallback implements VideoDecoder.Callback {
-  private final long nativeDecoder;
-
-  public VideoDecoderWrapperCallback(long nativeDecoder) {
-    this.nativeDecoder = nativeDecoder;
-  }
-
-  @Override
-  public void onDecodedFrame(VideoFrame frame, Integer decodeTimeMs, Integer qp) {
-    nativeOnDecodedFrame(nativeDecoder, frame, decodeTimeMs, qp);
-  }
-
-  private native static void nativeOnDecodedFrame(
-      long nativeDecoder, VideoFrame frame, Integer decodeTimeMs, Integer qp);
-}
diff --git a/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java b/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java
index b2bc081..5acfe67 100644
--- a/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java
+++ b/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java
@@ -37,16 +37,6 @@
   }
 
   @CalledByNative
-  static EncodedImage.FrameType createFrameType(int nativeIndex) {
-    for (EncodedImage.FrameType type : EncodedImage.FrameType.values()) {
-      if (type.getNative() == nativeIndex) {
-        return type;
-      }
-    }
-    throw new IllegalArgumentException("Unknown native frame type: " + nativeIndex);
-  }
-
-  @CalledByNative
   static boolean getScalingSettingsOn(VideoEncoder.ScalingSettings scalingSettings) {
     return scalingSettings.on;
   }
diff --git a/sdk/android/src/jni/classreferenceholder.cc b/sdk/android/src/jni/classreferenceholder.cc
index 25cb38c..910aa56 100644
--- a/sdk/android/src/jni/classreferenceholder.cc
+++ b/sdk/android/src/jni/classreferenceholder.cc
@@ -113,8 +113,6 @@
   LoadClass(jni, "org/webrtc/VideoCapturer");
   LoadClass(jni, "org/webrtc/VideoCodecInfo");
   LoadClass(jni, "org/webrtc/VideoCodecStatus");
-  LoadClass(jni, "org/webrtc/VideoDecoder$Settings");
-  LoadClass(jni, "org/webrtc/VideoDecoderWrapperCallback");
   LoadClass(jni, "org/webrtc/VideoFrame");
   LoadClass(jni, "org/webrtc/VideoFrame$Buffer");
   LoadClass(jni, "org/webrtc/VideoFrame$I420Buffer");
diff --git a/sdk/android/src/jni/encodedimage.cc b/sdk/android/src/jni/encodedimage.cc
new file mode 100644
index 0000000..f540b77
--- /dev/null
+++ b/sdk/android/src/jni/encodedimage.cc
@@ -0,0 +1,35 @@
+/*
+ *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "sdk/android/src/jni/encodedimage.h"
+
+#include "common_video/include/video_frame.h"
+#include "rtc_base/timeutils.h"
+#include "sdk/android/generated_video_jni/jni/EncodedImage_jni.h"
+
+namespace webrtc {
+namespace jni {
+
+jobject NativeToJavaFrameType(JNIEnv* env, FrameType frame_type) {
+  return Java_FrameType_fromNativeIndex(env, frame_type);
+}
+
+jobject NativeToJavaEncodedImage(JNIEnv* jni, const EncodedImage& image) {
+  jobject buffer = jni->NewDirectByteBuffer(image._buffer, image._length);
+  jobject frame_type = NativeToJavaFrameType(jni, image._frameType);
+  jobject qp = (image.qp_ == -1) ? nullptr : JavaIntegerFromInt(jni, image.qp_);
+  return Java_EncodedImage_create(
+      jni, buffer, image._encodedWidth, image._encodedHeight,
+      image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec, frame_type,
+      static_cast<jint>(image.rotation_), image._completeFrame, qp);
+}
+
+}  // namespace jni
+}  // namespace webrtc
diff --git a/sdk/android/src/jni/encodedimage.h b/sdk/android/src/jni/encodedimage.h
new file mode 100644
index 0000000..a84b91e
--- /dev/null
+++ b/sdk/android/src/jni/encodedimage.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef SDK_ANDROID_SRC_JNI_ENCODEDIMAGE_H_
+#define SDK_ANDROID_SRC_JNI_ENCODEDIMAGE_H_
+
+#include <jni.h>
+
+#include "api/video/video_rotation.h"
+#include "common_types.h"  // NOLINT(build/include)
+
+namespace webrtc {
+
+class EncodedImage;
+
+namespace jni {
+
+jobject NativeToJavaFrameType(JNIEnv* env, FrameType frame_type);
+jobject NativeToJavaEncodedImage(JNIEnv* jni, const EncodedImage& image);
+
+}  // namespace jni
+}  // namespace webrtc
+
+#endif  // SDK_ANDROID_SRC_JNI_ENCODEDIMAGE_H_
diff --git a/sdk/android/src/jni/videocodecstatus.cc b/sdk/android/src/jni/videocodecstatus.cc
new file mode 100644
index 0000000..6641f30
--- /dev/null
+++ b/sdk/android/src/jni/videocodecstatus.cc
@@ -0,0 +1,24 @@
+/*
+ *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "sdk/android/src/jni/videocodecstatus.h"
+
+#include "sdk/android/generated_video_jni/jni/VideoCodecStatus_jni.h"
+
+namespace webrtc {
+namespace jni {
+
+int32_t JavaToNativeVideoCodecStatus(JNIEnv* env,
+                                     jobject j_video_codec_status) {
+  return Java_VideoCodecStatus_getNumber(env, j_video_codec_status);
+}
+
+}  // namespace jni
+}  // namespace webrtc
diff --git a/sdk/android/src/jni/videocodecstatus.h b/sdk/android/src/jni/videocodecstatus.h
new file mode 100644
index 0000000..a2ad39e
--- /dev/null
+++ b/sdk/android/src/jni/videocodecstatus.h
@@ -0,0 +1,23 @@
+/*
+ *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef SDK_ANDROID_SRC_JNI_VIDEOCODECSTATUS_H_
+#define SDK_ANDROID_SRC_JNI_VIDEOCODECSTATUS_H_
+
+#include <jni.h>
+#include <stdint.h>
+
+namespace webrtc {
+namespace jni {
+int32_t JavaToNativeVideoCodecStatus(JNIEnv* env, jobject j_video_codec_status);
+}  // namespace jni
+}  // namespace webrtc
+
+#endif  // SDK_ANDROID_SRC_JNI_VIDEOCODECSTATUS_H_
diff --git a/sdk/android/src/jni/videodecoderwrapper.cc b/sdk/android/src/jni/videodecoderwrapper.cc
index 1bc75b0..3dd398e 100644
--- a/sdk/android/src/jni/videodecoderwrapper.cc
+++ b/sdk/android/src/jni/videodecoderwrapper.cc
@@ -15,9 +15,12 @@
 #include "modules/video_coding/utility/vp8_header_parser.h"
 #include "modules/video_coding/utility/vp9_uncompressed_header_parser.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/safe_conversions.h"
-#include "rtc_base/timeutils.h"
+#include "sdk/android/generated_video_jni/jni/VideoDecoderWrapper_jni.h"
+#include "sdk/android/generated_video_jni/jni/VideoDecoder_jni.h"
 #include "sdk/android/src/jni/classreferenceholder.h"
+#include "sdk/android/src/jni/encodedimage.h"
+#include "sdk/android/src/jni/videocodecstatus.h"
+#include "sdk/android/src/jni/videoframe.h"
 
 namespace webrtc {
 namespace jni {
@@ -31,58 +34,13 @@
 }  // namespace
 
 VideoDecoderWrapper::VideoDecoderWrapper(JNIEnv* jni, jobject decoder)
-    : decoder_(jni, decoder),
-      encoded_image_class_(jni, FindClass(jni, "org/webrtc/EncodedImage")),
-      frame_type_class_(jni,
-                        FindClass(jni, "org/webrtc/EncodedImage$FrameType")),
-      settings_class_(jni, FindClass(jni, "org/webrtc/VideoDecoder$Settings")),
-      video_frame_class_(jni, FindClass(jni, "org/webrtc/VideoFrame")),
-      video_codec_status_class_(jni,
-                                FindClass(jni, "org/webrtc/VideoCodecStatus")),
-      integer_class_(jni, jni->FindClass("java/lang/Integer")) {
-  encoded_image_constructor_ =
-      jni->GetMethodID(*encoded_image_class_, "<init>",
-                       "(Ljava/nio/ByteBuffer;IIJLorg/webrtc/"
-                       "EncodedImage$FrameType;IZLjava/lang/Integer;)V");
-  settings_constructor_ =
-      jni->GetMethodID(*settings_class_, "<init>", "(III)V");
-
-  empty_frame_field_ = jni->GetStaticFieldID(
-      *frame_type_class_, "EmptyFrame", "Lorg/webrtc/EncodedImage$FrameType;");
-  video_frame_key_field_ =
-      jni->GetStaticFieldID(*frame_type_class_, "VideoFrameKey",
-                            "Lorg/webrtc/EncodedImage$FrameType;");
-  video_frame_delta_field_ =
-      jni->GetStaticFieldID(*frame_type_class_, "VideoFrameDelta",
-                            "Lorg/webrtc/EncodedImage$FrameType;");
-
-  video_frame_get_timestamp_ns_method_ =
-      jni->GetMethodID(*video_frame_class_, "getTimestampNs", "()J");
-
-  jclass decoder_class = jni->GetObjectClass(decoder);
-  init_decode_method_ =
-      jni->GetMethodID(decoder_class, "initDecode",
-                       "(Lorg/webrtc/VideoDecoder$Settings;Lorg/webrtc/"
-                       "VideoDecoder$Callback;)Lorg/webrtc/VideoCodecStatus;");
-  release_method_ = jni->GetMethodID(decoder_class, "release",
-                                     "()Lorg/webrtc/VideoCodecStatus;");
-  decode_method_ = jni->GetMethodID(decoder_class, "decode",
-                                    "(Lorg/webrtc/EncodedImage;Lorg/webrtc/"
-                                    "VideoDecoder$DecodeInfo;)Lorg/webrtc/"
-                                    "VideoCodecStatus;");
-  get_prefers_late_decoding_method_ =
-      jni->GetMethodID(decoder_class, "getPrefersLateDecoding", "()Z");
-  get_implementation_name_method_ = jni->GetMethodID(
-      decoder_class, "getImplementationName", "()Ljava/lang/String;");
-
-  get_number_method_ =
-      jni->GetMethodID(*video_codec_status_class_, "getNumber", "()I");
-
+    : decoder_(jni, decoder) {
   initialized_ = false;
   // QP parsing starts enabled and we disable it if the decoder provides frames.
   qp_parsing_enabled_ = true;
 
-  implementation_name_ = GetImplementationName(jni);
+  implementation_name_ = JavaToStdString(
+      jni, Java_VideoDecoder_getImplementationName(jni, decoder));
 }
 
 int32_t VideoDecoderWrapper::InitDecode(const VideoCodec* codec_settings,
@@ -96,20 +54,15 @@
 }
 
 int32_t VideoDecoderWrapper::InitDecodeInternal(JNIEnv* jni) {
-  jobject settings =
-      jni->NewObject(*settings_class_, settings_constructor_, number_of_cores_,
-                     codec_settings_.width, codec_settings_.height);
+  jobject settings = Java_VideoDecoderWrapper_createSettings(
+      jni, number_of_cores_, codec_settings_.width, codec_settings_.height);
 
-  jclass callback_class =
-      FindClass(jni, "org/webrtc/VideoDecoderWrapperCallback");
-  jmethodID callback_constructor =
-      jni->GetMethodID(callback_class, "<init>", "(J)V");
-  jobject callback = jni->NewObject(callback_class, callback_constructor,
-                                    jlongFromPointer(this));
+  jobject callback = Java_VideoDecoderWrapper_createDecoderCallback(
+      jni, jlongFromPointer(this));
 
   jobject ret =
-      jni->CallObjectMethod(*decoder_, init_decode_method_, settings, callback);
-  if (jni->CallIntMethod(ret, get_number_method_) == WEBRTC_VIDEO_CODEC_OK) {
+      Java_VideoDecoder_initDecode(jni, *decoder_, settings, callback);
+  if (JavaToNativeVideoCodecStatus(jni, ret) == WEBRTC_VIDEO_CODEC_OK) {
     initialized_ = true;
   }
 
@@ -142,10 +95,8 @@
       qp_parsing_enabled_ ? ParseQP(input_image) : rtc::nullopt;
   frame_extra_infos_.push_back(frame_extra_info);
 
-  jobject jinput_image =
-      ConvertEncodedImageToJavaEncodedImage(jni, input_image);
-  jobject ret =
-      jni->CallObjectMethod(*decoder_, decode_method_, jinput_image, nullptr);
+  jobject jinput_image = NativeToJavaEncodedImage(jni, input_image);
+  jobject ret = Java_VideoDecoder_decode(jni, *decoder_, jinput_image, nullptr);
   return HandleReturnCode(jni, ret);
 }
 
@@ -158,7 +109,7 @@
 int32_t VideoDecoderWrapper::Release() {
   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   ScopedLocalRefFrame local_ref_frame(jni);
-  jobject ret = jni->CallObjectMethod(*decoder_, release_method_);
+  jobject ret = Java_VideoDecoder_release(jni, *decoder_);
   frame_extra_infos_.clear();
   initialized_ = false;
   return HandleReturnCode(jni, ret);
@@ -166,19 +117,20 @@
 
 bool VideoDecoderWrapper::PrefersLateDecoding() const {
   JNIEnv* jni = AttachCurrentThreadIfNeeded();
-  return jni->CallBooleanMethod(*decoder_, get_prefers_late_decoding_method_);
+  return Java_VideoDecoder_getPrefersLateDecoding(jni, *decoder_);
 }
 
 const char* VideoDecoderWrapper::ImplementationName() const {
   return implementation_name_.c_str();
 }
 
-void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* jni,
-                                         jobject jframe,
-                                         jobject jdecode_time_ms,
-                                         jobject jqp) {
-  const jlong capture_time_ns =
-      jni->CallLongMethod(jframe, video_frame_get_timestamp_ns_method_);
+void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* env,
+                                         jobject j_caller,
+                                         jobject j_frame,
+                                         jobject j_decode_time_ms,
+                                         jobject j_qp) {
+  const uint64_t capture_time_ns = GetJavaVideoFrameTimestampNs(env, j_frame);
+
   FrameExtraInfo frame_extra_info;
   do {
     if (frame_extra_infos_.empty()) {
@@ -193,13 +145,13 @@
   } while (frame_extra_info.capture_time_ns != capture_time_ns);
 
   VideoFrame frame =
-      JavaToNativeFrame(jni, jframe, frame_extra_info.timestamp_rtp);
+      JavaToNativeFrame(env, j_frame, frame_extra_info.timestamp_rtp);
 
   rtc::Optional<int32_t> decoding_time_ms =
-      JavaIntegerToOptionalInt(jni, jdecode_time_ms);
+      JavaIntegerToOptionalInt(env, j_decode_time_ms);
 
   rtc::Optional<uint8_t> decoder_qp =
-      cast_optional<uint8_t, int32_t>(JavaIntegerToOptionalInt(jni, jqp));
+      cast_optional<uint8_t, int32_t>(JavaIntegerToOptionalInt(env, j_qp));
   // If the decoder provides QP values itself, no need to parse the bitstream.
   // Enable QP parsing if decoder does not provide QP values itself.
   qp_parsing_enabled_ = !decoder_qp.has_value();
@@ -207,41 +159,8 @@
                      decoder_qp ? decoder_qp : frame_extra_info.qp);
 }
 
-jobject VideoDecoderWrapper::ConvertEncodedImageToJavaEncodedImage(
-    JNIEnv* jni,
-    const EncodedImage& image) {
-  jobject buffer = jni->NewDirectByteBuffer(image._buffer, image._length);
-  jfieldID frame_type_field;
-  switch (image._frameType) {
-    case kEmptyFrame:
-      frame_type_field = empty_frame_field_;
-      break;
-    case kVideoFrameKey:
-      frame_type_field = video_frame_key_field_;
-      break;
-    case kVideoFrameDelta:
-      frame_type_field = video_frame_delta_field_;
-      break;
-    default:
-      RTC_NOTREACHED();
-      return nullptr;
-  }
-  jobject frame_type =
-      jni->GetStaticObjectField(*frame_type_class_, frame_type_field);
-  jobject qp = nullptr;
-  if (image.qp_ != -1) {
-    qp = JavaIntegerFromInt(jni, image.qp_);
-  }
-  return jni->NewObject(
-      *encoded_image_class_, encoded_image_constructor_, buffer,
-      static_cast<jint>(image._encodedWidth),
-      static_cast<jint>(image._encodedHeight),
-      static_cast<jlong>(image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec),
-      frame_type, static_cast<jint>(image.rotation_), image._completeFrame, qp);
-}
-
 int32_t VideoDecoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) {
-  int32_t value = jni->CallIntMethod(code, get_number_method_);
+  int32_t value = JavaToNativeVideoCodecStatus(jni, code);
   if (value < 0) {  // Any errors are represented by negative values.
     // Reset the codec.
     if (Release() == WEBRTC_VIDEO_CODEC_OK) {
@@ -292,24 +211,5 @@
   return qp;
 }
 
-std::string VideoDecoderWrapper::GetImplementationName(JNIEnv* jni) const {
-  jstring jname = reinterpret_cast<jstring>(
-      jni->CallObjectMethod(*decoder_, get_implementation_name_method_));
-  return JavaToStdString(jni, jname);
-}
-
-JNI_FUNCTION_DECLARATION(void,
-                         VideoDecoderWrapperCallback_nativeOnDecodedFrame,
-                         JNIEnv* jni,
-                         jclass,
-                         jlong jnative_decoder,
-                         jobject jframe,
-                         jobject jdecode_time_ms,
-                         jobject jqp) {
-  VideoDecoderWrapper* native_decoder =
-      reinterpret_cast<VideoDecoderWrapper*>(jnative_decoder);
-  native_decoder->OnDecodedFrame(jni, jframe, jdecode_time_ms, jqp);
-}
-
 }  // namespace jni
 }  // namespace webrtc
diff --git a/sdk/android/src/jni/videodecoderwrapper.h b/sdk/android/src/jni/videodecoderwrapper.h
index 0e4e96e..48517c7 100644
--- a/sdk/android/src/jni/videodecoderwrapper.h
+++ b/sdk/android/src/jni/videodecoderwrapper.h
@@ -17,14 +17,11 @@
 #include "api/video_codecs/video_decoder.h"
 #include "common_video/h264/h264_bitstream_parser.h"
 #include "sdk/android/src/jni/jni_helpers.h"
-#include "sdk/android/src/jni/videoframe.h"
 
 namespace webrtc {
 namespace jni {
 
-// Wraps a Java decoder and delegates all calls to it. Passes
-// VideoDecoderWrapperCallback to the decoder on InitDecode. Wraps the received
-// frames to AndroidVideoBuffer.
+// Wraps a Java decoder and delegates all calls to it.
 class VideoDecoderWrapper : public VideoDecoder {
  public:
   VideoDecoderWrapper(JNIEnv* jni, jobject decoder);
@@ -51,10 +48,11 @@
   const char* ImplementationName() const override;
 
   // Wraps the frame to a AndroidVideoBuffer and passes it to the callback.
-  void OnDecodedFrame(JNIEnv* jni,
-                      jobject jframe,
-                      jobject jdecode_time_ms,
-                      jobject jqp);
+  void OnDecodedFrame(JNIEnv* env,
+                      jobject j_caller,
+                      jobject j_frame,
+                      jobject j_decode_time_ms,
+                      jobject j_qp);
 
  private:
   struct FrameExtraInfo {
@@ -72,8 +70,6 @@
 
   rtc::Optional<uint8_t> ParseQP(const EncodedImage& input_image);
 
-  std::string GetImplementationName(JNIEnv* jni) const;
-
   VideoCodec codec_settings_;
   int32_t number_of_cores_;
 
@@ -86,32 +82,6 @@
   DecodedImageCallback* callback_;
 
   const ScopedGlobalRef<jobject> decoder_;
-  const ScopedGlobalRef<jclass> encoded_image_class_;
-  const ScopedGlobalRef<jclass> frame_type_class_;
-  const ScopedGlobalRef<jclass> settings_class_;
-  const ScopedGlobalRef<jclass> video_frame_class_;
-  const ScopedGlobalRef<jclass> video_codec_status_class_;
-  const ScopedGlobalRef<jclass> integer_class_;
-
-  jmethodID encoded_image_constructor_;
-  jmethodID settings_constructor_;
-
-  jfieldID empty_frame_field_;
-  jfieldID video_frame_key_field_;
-  jfieldID video_frame_delta_field_;
-
-  jmethodID video_frame_get_timestamp_ns_method_;
-
-  jmethodID init_decode_method_;
-  jmethodID release_method_;
-  jmethodID decode_method_;
-  jmethodID get_prefers_late_decoding_method_;
-  jmethodID get_implementation_name_method_;
-
-  jmethodID get_number_method_;
-
-  jobject ConvertEncodedImageToJavaEncodedImage(JNIEnv* jni,
-                                                const EncodedImage& image);
 };
 
 }  // namespace jni
diff --git a/sdk/android/src/jni/videoencoderwrapper.cc b/sdk/android/src/jni/videoencoderwrapper.cc
index 360a5c6..66b54f9 100644
--- a/sdk/android/src/jni/videoencoderwrapper.cc
+++ b/sdk/android/src/jni/videoencoderwrapper.cc
@@ -21,10 +21,11 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/random.h"
 #include "rtc_base/timeutils.h"
-#include "sdk/android/generated_video_jni/jni/VideoCodecStatus_jni.h"
 #include "sdk/android/generated_video_jni/jni/VideoEncoderWrapper_jni.h"
 #include "sdk/android/generated_video_jni/jni/VideoEncoder_jni.h"
 #include "sdk/android/src/jni/class_loader.h"
+#include "sdk/android/src/jni/encodedimage.h"
+#include "sdk/android/src/jni/videocodecstatus.h"
 
 namespace webrtc {
 namespace jni {
@@ -84,7 +85,7 @@
   jobject ret =
       Java_VideoEncoder_initEncode(jni, *encoder_, settings, callback);
 
-  if (Java_VideoCodecStatus_getNumber(jni, ret) == WEBRTC_VIDEO_CODEC_OK) {
+  if (JavaToNativeVideoCodecStatus(jni, ret) == WEBRTC_VIDEO_CODEC_OK) {
     initialized_ = true;
   }
 
@@ -123,8 +124,7 @@
   jobjectArray j_frame_types =
       jni->NewObjectArray(frame_types->size(), *frame_type_class_, nullptr);
   for (size_t i = 0; i < frame_types->size(); ++i) {
-    jobject j_frame_type = Java_VideoEncoderWrapper_createFrameType(
-        jni, static_cast<jint>((*frame_types)[i]));
+    jobject j_frame_type = NativeToJavaFrameType(jni, (*frame_types)[i]);
     jni->SetObjectArrayElement(j_frame_types, i, j_frame_type);
   }
   jobject encode_info =
@@ -245,7 +245,7 @@
 }
 
 int32_t VideoEncoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) {
-  int32_t value = Java_VideoCodecStatus_getNumber(jni, code);
+  int32_t value = JavaToNativeVideoCodecStatus(jni, code);
   if (value < 0) {  // Any errors are represented by negative values.
     // Try resetting the codec.
     if (++num_resets_ <= kMaxJavaEncoderResets &&
diff --git a/sdk/android/src/jni/videoframe.cc b/sdk/android/src/jni/videoframe.cc
index c914727..be07c75 100644
--- a/sdk/android/src/jni/videoframe.cc
+++ b/sdk/android/src/jni/videoframe.cc
@@ -109,6 +109,10 @@
 
 }  // namespace
 
+int64_t GetJavaVideoFrameTimestampNs(JNIEnv* jni, jobject j_video_frame) {
+  return Java_VideoFrame_getTimestampNs(jni, j_video_frame);
+}
+
 Matrix::Matrix(JNIEnv* jni, jfloatArray a) {
   RTC_CHECK_EQ(16, jni->GetArrayLength(a));
   jfloat* ptr = jni->GetFloatArrayElements(a, nullptr);
@@ -366,7 +370,7 @@
                              uint32_t timestamp_rtp) {
   jobject j_video_frame_buffer = Java_VideoFrame_getBuffer(jni, j_video_frame);
   int rotation = Java_VideoFrame_getRotation(jni, j_video_frame);
-  uint32_t timestamp_ns = Java_VideoFrame_getTimestampNs(jni, j_video_frame);
+  int64_t timestamp_ns = Java_VideoFrame_getTimestampNs(jni, j_video_frame);
   rtc::scoped_refptr<AndroidVideoBuffer> buffer =
       AndroidVideoBuffer::Create(jni, j_video_frame_buffer);
   return VideoFrame(buffer, timestamp_rtp,
diff --git a/sdk/android/src/jni/videoframe.h b/sdk/android/src/jni/videoframe.h
index 1f10eb4..26206b8 100644
--- a/sdk/android/src/jni/videoframe.h
+++ b/sdk/android/src/jni/videoframe.h
@@ -159,6 +159,8 @@
 
 jobject NativeToJavaFrame(JNIEnv* jni, const VideoFrame& frame);
 
+int64_t GetJavaVideoFrameTimestampNs(JNIEnv* jni, jobject j_video_frame);
+
 }  // namespace jni
 }  // namespace webrtc