Make toVideoFrame in I420Frame return the original frame.

Bug: webrtc:7749
Change-Id: Ib9a2812e0b3b9b7c9f77ceb284f46c6cf2122467
Reviewed-on: https://webrtc-review.googlesource.com/1187
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Original-Commit-Position: refs/heads/master@{#19832}
Cr-Mirrored-From: https://webrtc.googlesource.com/src
Cr-Mirrored-Commit: 7d1f493a8b042b9ccf6993bb078c83bb0d992094
diff --git a/sdk/android/api/org/webrtc/VideoRenderer.java b/sdk/android/api/org/webrtc/VideoRenderer.java
index ec732be..e44578c 100644
--- a/sdk/android/api/org/webrtc/VideoRenderer.java
+++ b/sdk/android/api/org/webrtc/VideoRenderer.java
@@ -42,6 +42,10 @@
     // to be rendered correctly.
     public int rotationDegree;
 
+    // If this I420Frame was constructed from VideoFrame.Buffer, this points to
+    // the backing buffer.
+    private final VideoFrame.Buffer backingBuffer;
+
     /**
      * Construct a frame of the given dimensions with the specified planar data.
      */
@@ -54,6 +58,7 @@
       this.yuvFrame = true;
       this.rotationDegree = rotationDegree;
       this.nativeFramePointer = nativeFramePointer;
+      backingBuffer = null;
       if (rotationDegree % 90 != 0) {
         throw new IllegalArgumentException("Rotation degree not multiple of 90: " + rotationDegree);
       }
@@ -78,6 +83,7 @@
       this.yuvFrame = false;
       this.rotationDegree = rotationDegree;
       this.nativeFramePointer = nativeFramePointer;
+      backingBuffer = null;
       if (rotationDegree % 90 != 0) {
         throw new IllegalArgumentException("Rotation degree not multiple of 90: " + rotationDegree);
       }
@@ -103,9 +109,8 @@
 
         this.yuvStrides = null;
         this.yuvPlanes = null;
-      } else {
-        VideoFrame.I420Buffer i420Buffer = buffer.toI420();
-        buffer.release();
+      } else if (buffer instanceof VideoFrame.I420Buffer) {
+        VideoFrame.I420Buffer i420Buffer = (VideoFrame.I420Buffer) buffer;
         this.yuvFrame = true;
         this.yuvStrides =
             new int[] {i420Buffer.getStrideY(), i420Buffer.getStrideU(), i420Buffer.getStrideV()};
@@ -118,8 +123,15 @@
         this.samplingMatrix = RendererCommon.verticalFlipMatrix();
 
         this.textureId = 0;
+      } else {
+        this.yuvFrame = false;
+        this.textureId = 0;
+        this.samplingMatrix = null;
+        this.yuvStrides = null;
+        this.yuvPlanes = null;
       }
       this.nativeFramePointer = nativeFramePointer;
+      backingBuffer = buffer;
     }
 
     public int rotatedWidth() {
@@ -138,9 +150,19 @@
       return width + "x" + height + ", " + type;
     }
 
+    /**
+     * Convert the frame to VideoFrame. It is no longer safe to use the I420Frame after calling
+     * this.
+     */
     VideoFrame toVideoFrame() {
       final VideoFrame.Buffer buffer;
-      if (yuvFrame) {
+      if (backingBuffer != null) {
+        // We were construted from a VideoFrame.Buffer, just return it.
+        // Make sure webrtc::VideoFrame object is released.
+        backingBuffer.retain();
+        VideoRenderer.renderFrameDone(this);
+        buffer = backingBuffer;
+      } else if (yuvFrame) {
         buffer = new I420BufferImpl(width, height, yuvPlanes[0], yuvStrides[0], yuvPlanes[1],
             yuvStrides[1], yuvPlanes[2], yuvStrides[2],
             () -> { VideoRenderer.renderFrameDone(this); });