Pass java EncodedImage over jni to VideoEncoderWrapper::OnEncodedFrame

Preparation for adding a release() method on java's EncodedImage, and
call that from C++.

Bug: webrtc:9378
Change-Id: I301f64b16684c535f45a3fc9cd9ae1543df59d92
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/141861
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28268}
diff --git a/sdk/android/api/org/webrtc/EncodedImage.java b/sdk/android/api/org/webrtc/EncodedImage.java
index 84c72b1..f8de3d2 100644
--- a/sdk/android/api/org/webrtc/EncodedImage.java
+++ b/sdk/android/api/org/webrtc/EncodedImage.java
@@ -10,6 +10,7 @@
 
 package org.webrtc;
 
+import android.support.annotation.Nullable;
 import java.nio.ByteBuffer;
 import java.util.concurrent.TimeUnit;
 
@@ -53,11 +54,11 @@
   public final FrameType frameType;
   public final int rotation;
   public final boolean completeFrame;
-  public final Integer qp;
+  public final @Nullable Integer qp;
 
   @CalledByNative
   private EncodedImage(ByteBuffer buffer, int encodedWidth, int encodedHeight, long captureTimeNs,
-      FrameType frameType, int rotation, boolean completeFrame, Integer qp) {
+      FrameType frameType, int rotation, boolean completeFrame, @Nullable Integer qp) {
     this.buffer = buffer;
     this.encodedWidth = encodedWidth;
     this.encodedHeight = encodedHeight;
@@ -69,6 +70,46 @@
     this.qp = qp;
   }
 
+  @CalledByNative
+  private ByteBuffer getBuffer() {
+    return buffer;
+  }
+
+  @CalledByNative
+  private int getEncodedWidth() {
+    return encodedWidth;
+  }
+
+  @CalledByNative
+  private int getEncodedHeight() {
+    return encodedHeight;
+  }
+
+  @CalledByNative
+  private long getCaptureTimeNs() {
+    return captureTimeNs;
+  }
+
+  @CalledByNative
+  private int getFrameType() {
+    return frameType.getNative();
+  }
+
+  @CalledByNative
+  private int getRotation() {
+    return rotation;
+  }
+
+  @CalledByNative
+  private boolean getCompleteFrame() {
+    return completeFrame;
+  }
+
+  @CalledByNative
+  private @Nullable Integer getQp() {
+    return qp;
+  }
+
   public static Builder builder() {
     return new Builder();
   }
@@ -81,7 +122,7 @@
     private EncodedImage.FrameType frameType;
     private int rotation;
     private boolean completeFrame;
-    private Integer qp;
+    private @Nullable Integer qp;
 
     private Builder() {}
 
@@ -126,7 +167,7 @@
       return this;
     }
 
-    public Builder setQp(Integer qp) {
+    public Builder setQp(@Nullable Integer qp) {
       this.qp = qp;
       return this;
     }
diff --git a/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java b/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java
index e167b89..03676b1 100644
--- a/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java
+++ b/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java
@@ -38,13 +38,10 @@
 
   @CalledByNative
   static VideoEncoder.Callback createEncoderCallback(final long nativeEncoder) {
-    return (EncodedImage frame, VideoEncoder.CodecSpecificInfo info)
-               -> nativeOnEncodedFrame(nativeEncoder, frame.buffer, frame.encodedWidth,
-                   frame.encodedHeight, frame.captureTimeNs, frame.frameType.getNative(),
-                   frame.rotation, frame.completeFrame, frame.qp);
+    return (EncodedImage frame,
+               VideoEncoder.CodecSpecificInfo info) -> nativeOnEncodedFrame(nativeEncoder, frame);
   }
 
-  private static native void nativeOnEncodedFrame(long nativeVideoEncoderWrapper, ByteBuffer buffer,
-      int encodedWidth, int encodedHeight, long captureTimeNs, int frameType, int rotation,
-      boolean completeFrame, Integer qp);
+  private static native void nativeOnEncodedFrame(
+      long nativeVideoEncoderWrapper, EncodedImage frame);
 }
diff --git a/sdk/android/src/jni/encoded_image.cc b/sdk/android/src/jni/encoded_image.cc
index b288d36..328aa7c 100644
--- a/sdk/android/src/jni/encoded_image.cc
+++ b/sdk/android/src/jni/encoded_image.cc
@@ -49,5 +49,40 @@
       &NativeToJavaFrameType);
 }
 
+EncodedImage JavaToNativeEncodedImage(JNIEnv* env,
+                                      const JavaRef<jobject>& j_encoded_image) {
+  const JavaRef<jobject>& j_buffer =
+      Java_EncodedImage_getBuffer(env, j_encoded_image);
+  const uint8_t* buffer =
+      static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj()));
+  const size_t buffer_size = env->GetDirectBufferCapacity(j_buffer.obj());
+
+  EncodedImage frame;
+  frame.Allocate(buffer_size);
+  frame.set_size(buffer_size);
+  memcpy(frame.data(), buffer, buffer_size);
+  frame._encodedWidth = Java_EncodedImage_getEncodedWidth(env, j_encoded_image);
+  frame._encodedHeight =
+      Java_EncodedImage_getEncodedHeight(env, j_encoded_image);
+  frame.rotation_ =
+      (VideoRotation)Java_EncodedImage_getRotation(env, j_encoded_image);
+  frame._completeFrame =
+      Java_EncodedImage_getCompleteFrame(env, j_encoded_image);
+
+  frame.qp_ = JavaToNativeOptionalInt(
+                  env, Java_EncodedImage_getQp(env, j_encoded_image))
+                  .value_or(-1);
+
+  frame._frameType =
+      (VideoFrameType)Java_EncodedImage_getFrameType(env, j_encoded_image);
+  return frame;
+}
+
+int64_t GetJavaEncodedImageCaptureTimeNs(
+    JNIEnv* env,
+    const JavaRef<jobject>& j_encoded_image) {
+  return Java_EncodedImage_getCaptureTimeNs(env, j_encoded_image);
+}
+
 }  // namespace jni
 }  // namespace webrtc
diff --git a/sdk/android/src/jni/encoded_image.h b/sdk/android/src/jni/encoded_image.h
index 2078830..fc6d062 100644
--- a/sdk/android/src/jni/encoded_image.h
+++ b/sdk/android/src/jni/encoded_image.h
@@ -32,6 +32,13 @@
     JNIEnv* env,
     const std::vector<VideoFrameType>& frame_types);
 
+EncodedImage JavaToNativeEncodedImage(JNIEnv* env,
+                                      const JavaRef<jobject>& j_encoded_image);
+
+int64_t GetJavaEncodedImageCaptureTimeNs(
+    JNIEnv* jni,
+    const JavaRef<jobject>& j_encoded_image);
+
 }  // namespace jni
 }  // namespace webrtc
 
diff --git a/sdk/android/src/jni/video_encoder_wrapper.cc b/sdk/android/src/jni/video_encoder_wrapper.cc
index e051b77..ebf6aad 100644
--- a/sdk/android/src/jni/video_encoder_wrapper.cc
+++ b/sdk/android/src/jni/video_encoder_wrapper.cc
@@ -214,38 +214,18 @@
   }
 }
 
-void VideoEncoderWrapper::OnEncodedFrame(JNIEnv* jni,
-                                         const JavaRef<jobject>& j_caller,
-                                         const JavaRef<jobject>& j_buffer,
-                                         jint encoded_width,
-                                         jint encoded_height,
-                                         jlong capture_time_ns,
-                                         jint frame_type,
-                                         jint rotation,
-                                         jboolean complete_frame,
-                                         const JavaRef<jobject>& j_qp) {
-  const uint8_t* buffer =
-      static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer.obj()));
-  const size_t buffer_size = jni->GetDirectBufferCapacity(j_buffer.obj());
-
-  EncodedImage frame;
-  frame.Allocate(buffer_size);
-  frame.set_size(buffer_size);
-  memcpy(frame.data(), buffer, buffer_size);
-  frame._encodedWidth = encoded_width;
-  frame._encodedHeight = encoded_height;
-  frame.rotation_ = (VideoRotation)rotation;
-  frame._completeFrame = complete_frame;
-
-  const absl::optional<int> qp = JavaToNativeOptionalInt(jni, j_qp);
-
-  frame._frameType = (VideoFrameType)frame_type;
+void VideoEncoderWrapper::OnEncodedFrame(
+    JNIEnv* jni,
+    const JavaRef<jobject>& j_caller,
+    const JavaRef<jobject>& j_encoded_image) {
+  EncodedImage frame = JavaToNativeEncodedImage(jni, j_encoded_image);
+  int64_t capture_time_ns =
+      GetJavaEncodedImageCaptureTimeNs(jni, j_encoded_image);
 
   {
     rtc::CritScope lock(&encoder_queue_crit_);
     if (encoder_queue_ != nullptr) {
-      encoder_queue_->PostTask(ToQueuedTask([this, frame, qp,
-                                             capture_time_ns]() {
+      encoder_queue_->PostTask(ToQueuedTask([this, frame, capture_time_ns]() {
         // Encoded frames are delivered in the order received, but some of them
         // may be dropped, so remove records of frames older than the current
         // one.
@@ -284,7 +264,9 @@
             capture_time_ns / rtc::kNumNanosecsPerMillisec;
 
         RTPFragmentationHeader header = ParseFragmentationHeader(frame);
-        frame_copy.qp_ = qp ? *qp : ParseQp(frame);
+        if (frame_copy.qp_ < 0)
+          frame_copy.qp_ = ParseQp(frame);
+
         CodecSpecificInfo info(ParseCodecSpecificInfo(frame));
 
         callback_->OnEncodedImage(frame_copy, &info, &header);
diff --git a/sdk/android/src/jni/video_encoder_wrapper.h b/sdk/android/src/jni/video_encoder_wrapper.h
index 43d1f6f..685c6da 100644
--- a/sdk/android/src/jni/video_encoder_wrapper.h
+++ b/sdk/android/src/jni/video_encoder_wrapper.h
@@ -51,14 +51,7 @@
   // Should only be called by JNI.
   void OnEncodedFrame(JNIEnv* jni,
                       const JavaRef<jobject>& j_caller,
-                      const JavaRef<jobject>& j_buffer,
-                      jint encoded_width,
-                      jint encoded_height,
-                      jlong capture_time_ms,
-                      jint frame_type,
-                      jint rotation,
-                      jboolean complete_frame,
-                      const JavaRef<jobject>& j_qp);
+                      const JavaRef<jobject>& j_encoded_image);
 
  private:
   struct FrameExtraInfo {