/*
 *  Copyright 2018 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 static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

import android.graphics.Matrix;
import android.opengl.GLES20;
import android.os.Handler;
import android.os.HandlerThread;
import androidx.test.filters.SmallTest;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.chromium.base.test.params.BaseJUnit4RunnerDelegate;
import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.webrtc.VideoFrame;

/**
 * Test VideoFrame buffers of different kind of formats: I420, RGB, OES, NV12, NV21, and verify
 * toI420() and cropAndScale() behavior. Creating RGB/OES textures involves VideoFrameDrawer and
 * GlRectDrawer and we are testing the full chain I420 -> OES/RGB texture -> I420, with and without
 * cropping in the middle. Reading textures back to I420 also exercises the YuvConverter code.
 */
@RunWith(ParameterizedRunner.class)
@UseRunnerDelegate(BaseJUnit4RunnerDelegate.class)
public class VideoFrameBufferTest {
  /**
   * These tests are parameterized on this enum which represents the different VideoFrame.Buffers.
   */
  private static enum BufferType { I420_JAVA, I420_NATIVE, RGB_TEXTURE, OES_TEXTURE, NV21, NV12 }

  @ClassParameter private static List<ParameterSet> CLASS_PARAMS = new ArrayList<>();

  static {
    for (BufferType bufferType : BufferType.values()) {
      // The parameterization framework can not send Enums, so we pass it as a string instead.
      CLASS_PARAMS.add(new ParameterSet().value(bufferType.name()).name(bufferType.name()));
    }
  }

  @BeforeClass
  public static void setUp() {
    // Needed for JniCommon.nativeAllocateByteBuffer() to work, which is used from JavaI420Buffer.
    System.loadLibrary(TestConstants.NATIVE_LIBRARY);
  }

  private final BufferType bufferType;

  public VideoFrameBufferTest(String bufferTypeName) {
    // Parse the string back to an enum.
    bufferType = BufferType.valueOf(bufferTypeName);
  }

  /**
   * Create a VideoFrame.Buffer of the given type with the same pixel content as the given I420
   * buffer.
   */
  private static VideoFrame.Buffer createBufferWithType(
      BufferType bufferType, VideoFrame.I420Buffer i420Buffer) {
    VideoFrame.Buffer buffer;
    switch (bufferType) {
      case I420_JAVA:
        buffer = i420Buffer;
        buffer.retain();
        assertEquals(VideoFrameBufferType.I420, buffer.getBufferType());
        assertEquals(VideoFrameBufferType.I420, nativeGetBufferType(buffer));
        return buffer;
      case I420_NATIVE:
        buffer = nativeGetNativeI420Buffer(i420Buffer);
        assertEquals(VideoFrameBufferType.I420, buffer.getBufferType());
        assertEquals(VideoFrameBufferType.I420, nativeGetBufferType(buffer));
        return buffer;
      case RGB_TEXTURE:
        buffer = createRgbTextureBuffer(/* eglContext= */ null, i420Buffer);
        assertEquals(VideoFrameBufferType.NATIVE, buffer.getBufferType());
        assertEquals(VideoFrameBufferType.NATIVE, nativeGetBufferType(buffer));
        return buffer;
      case OES_TEXTURE:
        buffer = createOesTextureBuffer(/* eglContext= */ null, i420Buffer);
        assertEquals(VideoFrameBufferType.NATIVE, buffer.getBufferType());
        assertEquals(VideoFrameBufferType.NATIVE, nativeGetBufferType(buffer));
        return buffer;
      case NV21:
        buffer = createNV21Buffer(i420Buffer);
        assertEquals(VideoFrameBufferType.NATIVE, buffer.getBufferType());
        assertEquals(VideoFrameBufferType.NATIVE, nativeGetBufferType(buffer));
        return buffer;
      case NV12:
        buffer = createNV12Buffer(i420Buffer);
        assertEquals(VideoFrameBufferType.NATIVE, buffer.getBufferType());
        assertEquals(VideoFrameBufferType.NATIVE, nativeGetBufferType(buffer));
        return buffer;
      default:
        throw new IllegalArgumentException("Unknown buffer type: " + bufferType);
    }
  }

  private VideoFrame.Buffer createBufferToTest(VideoFrame.I420Buffer i420Buffer) {
    return createBufferWithType(this.bufferType, i420Buffer);
  }

  /**
   * Creates a 16x16 I420 buffer that varies smoothly and spans all RGB values.
   */
  public static VideoFrame.I420Buffer createTestI420Buffer() {
    final int width = 16;
    final int height = 16;
    final int[] yData = new int[] {156, 162, 167, 172, 177, 182, 187, 193, 199, 203, 209, 214, 219,
        224, 229, 235, 147, 152, 157, 162, 168, 173, 178, 183, 188, 193, 199, 205, 210, 215, 220,
        225, 138, 143, 148, 153, 158, 163, 168, 174, 180, 184, 190, 195, 200, 205, 211, 216, 128,
        133, 138, 144, 149, 154, 159, 165, 170, 175, 181, 186, 191, 196, 201, 206, 119, 124, 129,
        134, 140, 145, 150, 156, 161, 166, 171, 176, 181, 187, 192, 197, 109, 114, 119, 126, 130,
        136, 141, 146, 151, 156, 162, 167, 172, 177, 182, 187, 101, 105, 111, 116, 121, 126, 132,
        137, 142, 147, 152, 157, 162, 168, 173, 178, 90, 96, 101, 107, 112, 117, 122, 127, 132, 138,
        143, 148, 153, 158, 163, 168, 82, 87, 92, 97, 102, 107, 113, 118, 123, 128, 133, 138, 144,
        149, 154, 159, 72, 77, 83, 88, 93, 98, 103, 108, 113, 119, 124, 129, 134, 139, 144, 150, 63,
        68, 73, 78, 83, 89, 94, 99, 104, 109, 114, 119, 125, 130, 135, 140, 53, 58, 64, 69, 74, 79,
        84, 89, 95, 100, 105, 110, 115, 120, 126, 131, 44, 49, 54, 59, 64, 70, 75, 80, 85, 90, 95,
        101, 106, 111, 116, 121, 34, 40, 45, 50, 55, 60, 65, 71, 76, 81, 86, 91, 96, 101, 107, 113,
        25, 30, 35, 40, 46, 51, 56, 61, 66, 71, 77, 82, 87, 92, 98, 103, 16, 21, 26, 31, 36, 41, 46,
        52, 57, 62, 67, 72, 77, 83, 89, 94};
    final int[] uData = new int[] {110, 113, 116, 118, 120, 123, 125, 128, 113, 116, 118, 120, 123,
        125, 128, 130, 116, 118, 120, 123, 125, 128, 130, 132, 118, 120, 123, 125, 128, 130, 132,
        135, 120, 123, 125, 128, 130, 132, 135, 138, 123, 125, 128, 130, 132, 135, 138, 139, 125,
        128, 130, 132, 135, 138, 139, 142, 128, 130, 132, 135, 138, 139, 142, 145};
    final int[] vData = new int[] {31, 45, 59, 73, 87, 100, 114, 127, 45, 59, 73, 87, 100, 114, 128,
        141, 59, 73, 87, 100, 114, 127, 141, 155, 73, 87, 100, 114, 127, 141, 155, 168, 87, 100,
        114, 128, 141, 155, 168, 182, 100, 114, 128, 141, 155, 168, 182, 197, 114, 127, 141, 155,
        168, 182, 196, 210, 127, 141, 155, 168, 182, 196, 210, 224};
    return JavaI420Buffer.wrap(width, height, toByteBuffer(yData),
        /* strideY= */ width, toByteBuffer(uData), /* strideU= */ width / 2, toByteBuffer(vData),
        /* strideV= */ width / 2,
        /* releaseCallback= */ null);
  }

  /**
   * Create an RGB texture buffer available in `eglContext` with the same pixel content as the given
   * I420 buffer.
   */
  public static VideoFrame.TextureBuffer createRgbTextureBuffer(
      EglBase.Context eglContext, VideoFrame.I420Buffer i420Buffer) {
    final int width = i420Buffer.getWidth();
    final int height = i420Buffer.getHeight();

    final HandlerThread renderThread = new HandlerThread("RGB texture thread");
    renderThread.start();
    final Handler renderThreadHandler = new Handler(renderThread.getLooper());
    return ThreadUtils.invokeAtFrontUninterruptibly(renderThreadHandler, () -> {
      // Create EGL base with a pixel buffer as display output.
      final EglBase eglBase = EglBase.create(eglContext, EglBase.CONFIG_PIXEL_BUFFER);
      eglBase.createDummyPbufferSurface();
      eglBase.makeCurrent();

      final GlTextureFrameBuffer textureFrameBuffer = new GlTextureFrameBuffer(GLES20.GL_RGBA);
      textureFrameBuffer.setSize(width, height);

      GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, textureFrameBuffer.getFrameBufferId());
      drawI420Buffer(i420Buffer);
      GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

      final YuvConverter yuvConverter = new YuvConverter();
      return new TextureBufferImpl(width, height, VideoFrame.TextureBuffer.Type.RGB,
          textureFrameBuffer.getTextureId(),
          /* transformMatrix= */ new Matrix(), renderThreadHandler, yuvConverter,
          /* releaseCallback= */ () -> renderThreadHandler.post(() -> {
            textureFrameBuffer.release();
            yuvConverter.release();
            eglBase.release();
            renderThread.quit();
          }));
    });
  }

  /**
   * Create an OES texture buffer available in `eglContext` with the same pixel content as the given
   * I420 buffer.
   */
  public static VideoFrame.TextureBuffer createOesTextureBuffer(
      EglBase.Context eglContext, VideoFrame.I420Buffer i420Buffer) {
    final int width = i420Buffer.getWidth();
    final int height = i420Buffer.getHeight();

    // Create resources for generating OES textures.
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create("SurfaceTextureHelper test", eglContext);
    surfaceTextureHelper.setTextureSize(width, height);

    final HandlerThread renderThread = new HandlerThread("OES texture thread");
    renderThread.start();
    final Handler renderThreadHandler = new Handler(renderThread.getLooper());
    final VideoFrame.TextureBuffer oesBuffer =
        ThreadUtils.invokeAtFrontUninterruptibly(renderThreadHandler, () -> {
          // Create EGL base with the SurfaceTexture as display output.
          final EglBase eglBase = EglBase.create(eglContext, EglBase.CONFIG_PLAIN);
          eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
          eglBase.makeCurrent();
          assertEquals(width, eglBase.surfaceWidth());
          assertEquals(height, eglBase.surfaceHeight());

          final SurfaceTextureHelperTest.MockTextureListener listener =
              new SurfaceTextureHelperTest.MockTextureListener();
          surfaceTextureHelper.startListening(listener);

          // Draw the frame and block until an OES texture is delivered.
          drawI420Buffer(i420Buffer);
          eglBase.swapBuffers();
          final VideoFrame.TextureBuffer textureBuffer = listener.waitForTextureBuffer();
          surfaceTextureHelper.stopListening();
          surfaceTextureHelper.dispose();

          return textureBuffer;
        });
    renderThread.quit();

    return oesBuffer;
  }

  /** Create an NV21Buffer with the same pixel content as the given I420 buffer. */
  public static NV21Buffer createNV21Buffer(VideoFrame.I420Buffer i420Buffer) {
    final int width = i420Buffer.getWidth();
    final int height = i420Buffer.getHeight();
    final int chromaStride = width;
    final int chromaWidth = (width + 1) / 2;
    final int chromaHeight = (height + 1) / 2;
    final int ySize = width * height;

    final ByteBuffer nv21Buffer = ByteBuffer.allocateDirect(ySize + chromaStride * chromaHeight);
    // We don't care what the array offset is since we only want an array that is direct.
    @SuppressWarnings("ByteBufferBackingArray") final byte[] nv21Data = nv21Buffer.array();

    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        final byte yValue = i420Buffer.getDataY().get(y * i420Buffer.getStrideY() + x);
        nv21Data[y * width + x] = yValue;
      }
    }
    for (int y = 0; y < chromaHeight; ++y) {
      for (int x = 0; x < chromaWidth; ++x) {
        final byte uValue = i420Buffer.getDataU().get(y * i420Buffer.getStrideU() + x);
        final byte vValue = i420Buffer.getDataV().get(y * i420Buffer.getStrideV() + x);
        nv21Data[ySize + y * chromaStride + 2 * x + 0] = vValue;
        nv21Data[ySize + y * chromaStride + 2 * x + 1] = uValue;
      }
    }
    return new NV21Buffer(nv21Data, width, height, /* releaseCallback= */ null);
  }

  /** Create an NV12Buffer with the same pixel content as the given I420 buffer. */
  public static NV12Buffer createNV12Buffer(VideoFrame.I420Buffer i420Buffer) {
    final int width = i420Buffer.getWidth();
    final int height = i420Buffer.getHeight();
    final int chromaStride = width;
    final int chromaWidth = (width + 1) / 2;
    final int chromaHeight = (height + 1) / 2;
    final int ySize = width * height;

    final ByteBuffer nv12Buffer = ByteBuffer.allocateDirect(ySize + chromaStride * chromaHeight);

    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        final byte yValue = i420Buffer.getDataY().get(y * i420Buffer.getStrideY() + x);
        nv12Buffer.put(y * width + x, yValue);
      }
    }
    for (int y = 0; y < chromaHeight; ++y) {
      for (int x = 0; x < chromaWidth; ++x) {
        final byte uValue = i420Buffer.getDataU().get(y * i420Buffer.getStrideU() + x);
        final byte vValue = i420Buffer.getDataV().get(y * i420Buffer.getStrideV() + x);
        nv12Buffer.put(ySize + y * chromaStride + 2 * x + 0, uValue);
        nv12Buffer.put(ySize + y * chromaStride + 2 * x + 1, vValue);
      }
    }
    return new NV12Buffer(width, height, /* stride= */ width, /* sliceHeight= */ height, nv12Buffer,
        /* releaseCallback */ null);
  }

  /** Print the ByteBuffer plane to the StringBuilder. */
  private static void printPlane(
      StringBuilder stringBuilder, int width, int height, ByteBuffer plane, int stride) {
    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        final int value = plane.get(y * stride + x) & 0xFF;
        if (x != 0) {
          stringBuilder.append(", ");
        }
        stringBuilder.append(value);
      }
      stringBuilder.append("\n");
    }
  }

  /** Convert the pixel content of an I420 buffer to a string representation. */
  private static String i420BufferToString(VideoFrame.I420Buffer buffer) {
    final StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(
        "I420 buffer with size: " + buffer.getWidth() + "x" + buffer.getHeight() + ".\n");
    stringBuilder.append("Y-plane:\n");
    printPlane(stringBuilder, buffer.getWidth(), buffer.getHeight(), buffer.getDataY(),
        buffer.getStrideY());
    final int chromaWidth = (buffer.getWidth() + 1) / 2;
    final int chromaHeight = (buffer.getHeight() + 1) / 2;
    stringBuilder.append("U-plane:\n");
    printPlane(stringBuilder, chromaWidth, chromaHeight, buffer.getDataU(), buffer.getStrideU());
    stringBuilder.append("V-plane:\n");
    printPlane(stringBuilder, chromaWidth, chromaHeight, buffer.getDataV(), buffer.getStrideV());
    return stringBuilder.toString();
  }

  /**
   * Assert that the given I420 buffers are almost identical, allowing for some difference due to
   * numerical errors. It has limits for both overall PSNR and maximum individual pixel difference.
   */
  public static void assertAlmostEqualI420Buffers(
      VideoFrame.I420Buffer bufferA, VideoFrame.I420Buffer bufferB) {
    final int diff = maxDiff(bufferA, bufferB);
    assertThat("Pixel difference too high: " + diff + "."
            + "\nBuffer A: " + i420BufferToString(bufferA)
            + "Buffer B: " + i420BufferToString(bufferB),
        diff, lessThanOrEqualTo(4));
    final double psnr = calculatePsnr(bufferA, bufferB);
    assertThat("PSNR too low: " + psnr + "."
            + "\nBuffer A: " + i420BufferToString(bufferA)
            + "Buffer B: " + i420BufferToString(bufferB),
        psnr, greaterThanOrEqualTo(50.0));
  }

  /** Returns a flattened list of pixel differences for two ByteBuffer planes. */
  private static List<Integer> getPixelDiffs(
      int width, int height, ByteBuffer planeA, int strideA, ByteBuffer planeB, int strideB) {
    List<Integer> res = new ArrayList<>();
    for (int y = 0; y < height; ++y) {
      for (int x = 0; x < width; ++x) {
        final int valueA = planeA.get(y * strideA + x) & 0xFF;
        final int valueB = planeB.get(y * strideB + x) & 0xFF;
        res.add(Math.abs(valueA - valueB));
      }
    }
    return res;
  }

  /** Returns a flattened list of pixel differences for two I420 buffers. */
  private static List<Integer> getPixelDiffs(
      VideoFrame.I420Buffer bufferA, VideoFrame.I420Buffer bufferB) {
    assertEquals(bufferA.getWidth(), bufferB.getWidth());
    assertEquals(bufferA.getHeight(), bufferB.getHeight());
    final int width = bufferA.getWidth();
    final int height = bufferA.getHeight();
    final int chromaWidth = (width + 1) / 2;
    final int chromaHeight = (height + 1) / 2;
    final List<Integer> diffs = getPixelDiffs(width, height, bufferA.getDataY(),
        bufferA.getStrideY(), bufferB.getDataY(), bufferB.getStrideY());
    diffs.addAll(getPixelDiffs(chromaWidth, chromaHeight, bufferA.getDataU(), bufferA.getStrideU(),
        bufferB.getDataU(), bufferB.getStrideU()));
    diffs.addAll(getPixelDiffs(chromaWidth, chromaHeight, bufferA.getDataV(), bufferA.getStrideV(),
        bufferB.getDataV(), bufferB.getStrideV()));
    return diffs;
  }

  /** Returns the maximum pixel difference from any of the Y/U/V planes in the given buffers. */
  private static int maxDiff(VideoFrame.I420Buffer bufferA, VideoFrame.I420Buffer bufferB) {
    return Collections.max(getPixelDiffs(bufferA, bufferB));
  }

  /**
   * Returns the PSNR given a sum of squared error and the number of measurements that were added.
   */
  private static double sseToPsnr(long sse, int count) {
    if (sse == 0) {
      return Double.POSITIVE_INFINITY;
    }
    final double meanSquaredError = (double) sse / (double) count;
    final double maxPixelValue = 255.0;
    return 10.0 * Math.log10(maxPixelValue * maxPixelValue / meanSquaredError);
  }

  /** Returns the PSNR of the given I420 buffers. */
  private static double calculatePsnr(
      VideoFrame.I420Buffer bufferA, VideoFrame.I420Buffer bufferB) {
    final List<Integer> pixelDiffs = getPixelDiffs(bufferA, bufferB);
    long sse = 0;
    for (int pixelDiff : pixelDiffs) {
      sse += pixelDiff * pixelDiff;
    }
    return sseToPsnr(sse, pixelDiffs.size());
  }

  /**
   * Convert an int array to a byte array and make sure the values are within the range [0, 255].
   */
  private static byte[] toByteArray(int[] array) {
    final byte[] res = new byte[array.length];
    for (int i = 0; i < array.length; ++i) {
      final int value = array[i];
      assertThat(value, greaterThanOrEqualTo(0));
      assertThat(value, lessThanOrEqualTo(255));
      res[i] = (byte) value;
    }
    return res;
  }

  /** Convert a byte array to a direct ByteBuffer. */
  private static ByteBuffer toByteBuffer(int[] array) {
    final ByteBuffer buffer = ByteBuffer.allocateDirect(array.length);
    buffer.put(toByteArray(array));
    buffer.rewind();
    return buffer;
  }

  /**
   * Draw an I420 buffer on the currently bound frame buffer, allocating and releasing any
   * resources necessary.
   */
  private static void drawI420Buffer(VideoFrame.I420Buffer i420Buffer) {
    final GlRectDrawer drawer = new GlRectDrawer();
    final VideoFrameDrawer videoFrameDrawer = new VideoFrameDrawer();
    videoFrameDrawer.drawFrame(
        new VideoFrame(i420Buffer, /* rotation= */ 0, /* timestampNs= */ 0), drawer);
    videoFrameDrawer.release();
    drawer.release();
  }

  /**
   * Helper function that tests cropAndScale() with the given cropping and scaling parameters, and
   * compares the pixel content against a reference I420 buffer.
   */
  private void testCropAndScale(
      int cropX, int cropY, int cropWidth, int cropHeight, int scaleWidth, int scaleHeight) {
    final VideoFrame.I420Buffer referenceI420Buffer = createTestI420Buffer();
    final VideoFrame.Buffer bufferToTest = createBufferToTest(referenceI420Buffer);

    final VideoFrame.Buffer croppedReferenceBuffer = referenceI420Buffer.cropAndScale(
        cropX, cropY, cropWidth, cropHeight, scaleWidth, scaleHeight);
    referenceI420Buffer.release();
    final VideoFrame.I420Buffer croppedReferenceI420Buffer = croppedReferenceBuffer.toI420();
    croppedReferenceBuffer.release();

    final VideoFrame.Buffer croppedBufferToTest =
        bufferToTest.cropAndScale(cropX, cropY, cropWidth, cropHeight, scaleWidth, scaleHeight);
    bufferToTest.release();

    final VideoFrame.I420Buffer croppedOutputI420Buffer = croppedBufferToTest.toI420();
    croppedBufferToTest.release();

    assertAlmostEqualI420Buffers(croppedReferenceI420Buffer, croppedOutputI420Buffer);
    croppedReferenceI420Buffer.release();
    croppedOutputI420Buffer.release();
  }

  @Test
  @SmallTest
  /** Test calling toI420() and comparing pixel content against I420 reference. */
  public void testToI420() {
    final VideoFrame.I420Buffer referenceI420Buffer = createTestI420Buffer();
    final VideoFrame.Buffer bufferToTest = createBufferToTest(referenceI420Buffer);

    final VideoFrame.I420Buffer outputI420Buffer = bufferToTest.toI420();
    bufferToTest.release();

    assertEquals(VideoFrameBufferType.I420, nativeGetBufferType(outputI420Buffer));
    assertAlmostEqualI420Buffers(referenceI420Buffer, outputI420Buffer);
    referenceI420Buffer.release();
    outputI420Buffer.release();
  }

  @Test
  @SmallTest
  /** Pure 2x scaling with no cropping. */
  public void testScale2x() {
    testCropAndScale(0 /* cropX= */, 0 /* cropY= */, /* cropWidth= */ 16, /* cropHeight= */ 16,
        /* scaleWidth= */ 8, /* scaleHeight= */ 8);
  }

  @Test
  @SmallTest
  /** Test cropping only X direction, with no scaling. */
  public void testCropX() {
    testCropAndScale(8 /* cropX= */, 0 /* cropY= */, /* cropWidth= */ 8, /* cropHeight= */ 16,
        /* scaleWidth= */ 8, /* scaleHeight= */ 16);
  }

  @Test
  @SmallTest
  /** Test cropping only Y direction, with no scaling. */
  public void testCropY() {
    testCropAndScale(0 /* cropX= */, 8 /* cropY= */, /* cropWidth= */ 16, /* cropHeight= */ 8,
        /* scaleWidth= */ 16, /* scaleHeight= */ 8);
  }

  @Test
  @SmallTest
  /** Test center crop, with no scaling. */
  public void testCenterCrop() {
    testCropAndScale(4 /* cropX= */, 4 /* cropY= */, /* cropWidth= */ 8, /* cropHeight= */ 8,
        /* scaleWidth= */ 8, /* scaleHeight= */ 8);
  }

  @Test
  @SmallTest
  /** Test non-center crop for right bottom corner, with no scaling. */
  public void testRightBottomCornerCrop() {
    testCropAndScale(8 /* cropX= */, 8 /* cropY= */, /* cropWidth= */ 8, /* cropHeight= */ 8,
        /* scaleWidth= */ 8, /* scaleHeight= */ 8);
  }

  @Test
  @SmallTest
  /** Test combined cropping and scaling. */
  public void testCropAndScale() {
    testCropAndScale(4 /* cropX= */, 4 /* cropY= */, /* cropWidth= */ 12, /* cropHeight= */ 12,
        /* scaleWidth= */ 8, /* scaleHeight= */ 8);
  }

  @VideoFrameBufferType private static native int nativeGetBufferType(VideoFrame.Buffer buffer);

  /** Returns the copy of I420Buffer using WrappedNativeI420Buffer. */
  private static native VideoFrame.Buffer nativeGetNativeI420Buffer(
      VideoFrame.I420Buffer i420Buffer);
}
