/*
 *  Copyright 2015 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.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.opengl.GLES20;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(BaseJUnit4ClassRunner.class)
public class SurfaceTextureHelperTest {
  /**
   * Mock texture listener with blocking wait functionality.
   */
  public static final class MockTextureListener implements VideoSink {
    private final Object lock = new Object();
    private @Nullable VideoFrame.TextureBuffer textureBuffer;
    // Thread where frames are expected to be received on.
    private final @Nullable Thread expectedThread;

    MockTextureListener() {
      this.expectedThread = null;
    }

    MockTextureListener(Thread expectedThread) {
      this.expectedThread = expectedThread;
    }

    @Override
    public void onFrame(VideoFrame frame) {
      if (expectedThread != null && Thread.currentThread() != expectedThread) {
        throw new IllegalStateException("onTextureFrameAvailable called on wrong thread.");
      }
      synchronized (lock) {
        this.textureBuffer = (VideoFrame.TextureBuffer) frame.getBuffer();
        textureBuffer.retain();
        lock.notifyAll();
      }
    }

    /** Wait indefinitely for a new textureBuffer. */
    public VideoFrame.TextureBuffer waitForTextureBuffer() throws InterruptedException {
      synchronized (lock) {
        while (true) {
          final VideoFrame.TextureBuffer textureBufferToReturn = textureBuffer;
          if (textureBufferToReturn != null) {
            textureBuffer = null;
            return textureBufferToReturn;
          }
          lock.wait();
        }
      }
    }

    /** Make sure we get no frame in the specified time period. */
    public void assertNoFrameIsDelivered(final long waitPeriodMs) throws InterruptedException {
      final long startTimeMs = SystemClock.elapsedRealtime();
      long timeRemainingMs = waitPeriodMs;
      synchronized (lock) {
        while (textureBuffer == null && timeRemainingMs > 0) {
          lock.wait(timeRemainingMs);
          final long elapsedTimeMs = SystemClock.elapsedRealtime() - startTimeMs;
          timeRemainingMs = waitPeriodMs - elapsedTimeMs;
        }
        assertTrue(textureBuffer == null);
      }
    }
  }

  /** Assert that two integers are close, with difference at most
   * {@code threshold}. */
  public static void assertClose(int threshold, int expected, int actual) {
    if (Math.abs(expected - actual) <= threshold)
      return;
    fail("Not close enough, threshold " + threshold + ". Expected: " + expected + " Actual: "
        + actual);
  }

  @Before
  public void setUp() {
    // Load the JNI library for textureToYuv.
    NativeLibrary.initialize(new NativeLibrary.DefaultLoader(), TestConstants.NATIVE_LIBRARY);
  }

  /**
   * Test normal use by receiving three uniform texture frames. Texture frames are returned as early
   * as possible. The texture pixel values are inspected by drawing the texture frame to a pixel
   * buffer and reading it back with glReadPixels().
   */
  @Test
  @MediumTest
  public void testThreeConstantColorFrames() throws InterruptedException {
    final int width = 16;
    final int height = 16;
    // Create EGL base with a pixel buffer as display output.
    final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PIXEL_BUFFER);
    eglBase.createPbufferSurface(width, height);
    final GlRectDrawer drawer = new GlRectDrawer();

    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create(
        "SurfaceTextureHelper test" /* threadName */, eglBase.getEglBaseContext());
    final MockTextureListener listener = new MockTextureListener();
    surfaceTextureHelper.startListening(listener);
    surfaceTextureHelper.setTextureSize(width, height);

    // Create resources for stubbing an OES texture producer. |eglOesBase| has the SurfaceTexture in
    // |surfaceTextureHelper| as the target EGLSurface.
    final EglBase eglOesBase = EglBase.create(eglBase.getEglBaseContext(), EglBase.CONFIG_PLAIN);
    eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    assertEquals(eglOesBase.surfaceWidth(), width);
    assertEquals(eglOesBase.surfaceHeight(), height);

    final int red[] = new int[] {79, 144, 185};
    final int green[] = new int[] {66, 210, 162};
    final int blue[] = new int[] {161, 117, 158};
    // Draw three frames.
    for (int i = 0; i < 3; ++i) {
      // Draw a constant color frame onto the SurfaceTexture.
      eglOesBase.makeCurrent();
      GLES20.glClearColor(red[i] / 255.0f, green[i] / 255.0f, blue[i] / 255.0f, 1.0f);
      GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
      // swapBuffers() will ultimately trigger onTextureFrameAvailable().
      eglOesBase.swapBuffers();

      // Wait for an OES texture to arrive and draw it onto the pixel buffer.
      final VideoFrame.TextureBuffer textureBuffer = listener.waitForTextureBuffer();
      eglBase.makeCurrent();
      drawer.drawOes(textureBuffer.getTextureId(),
          RendererCommon.convertMatrixFromAndroidGraphicsMatrix(textureBuffer.getTransformMatrix()),
          width, height, 0, 0, width, height);
      textureBuffer.release();

      // Download the pixels in the pixel buffer as RGBA. Not all platforms support RGB, e.g.
      // Nexus 9.
      final ByteBuffer rgbaData = ByteBuffer.allocateDirect(width * height * 4);
      GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, rgbaData);
      GlUtil.checkNoGLES2Error("glReadPixels");

      // Assert rendered image is expected constant color.
      while (rgbaData.hasRemaining()) {
        assertEquals(rgbaData.get() & 0xFF, red[i]);
        assertEquals(rgbaData.get() & 0xFF, green[i]);
        assertEquals(rgbaData.get() & 0xFF, blue[i]);
        assertEquals(rgbaData.get() & 0xFF, 255);
      }
    }

    drawer.release();
    surfaceTextureHelper.dispose();
    eglBase.release();
  }

  /**
   * Test disposing the SurfaceTextureHelper while holding a pending texture frame. The pending
   * texture frame should still be valid, and this is tested by drawing the texture frame to a pixel
   * buffer and reading it back with glReadPixels().
   */
  @Test
  @MediumTest
  public void testLateReturnFrame() throws InterruptedException {
    final int width = 16;
    final int height = 16;
    // Create EGL base with a pixel buffer as display output.
    final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PIXEL_BUFFER);
    eglBase.createPbufferSurface(width, height);

    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create(
        "SurfaceTextureHelper test" /* threadName */, eglBase.getEglBaseContext());
    final MockTextureListener listener = new MockTextureListener();
    surfaceTextureHelper.startListening(listener);
    surfaceTextureHelper.setTextureSize(width, height);

    // Create resources for stubbing an OES texture producer. |eglOesBase| has the SurfaceTexture in
    // |surfaceTextureHelper| as the target EGLSurface.
    final EglBase eglOesBase = EglBase.create(eglBase.getEglBaseContext(), EglBase.CONFIG_PLAIN);
    eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    assertEquals(eglOesBase.surfaceWidth(), width);
    assertEquals(eglOesBase.surfaceHeight(), height);

    final int red = 79;
    final int green = 66;
    final int blue = 161;
    // Draw a constant color frame onto the SurfaceTexture.
    eglOesBase.makeCurrent();
    GLES20.glClearColor(red / 255.0f, green / 255.0f, blue / 255.0f, 1.0f);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // swapBuffers() will ultimately trigger onTextureFrameAvailable().
    eglOesBase.swapBuffers();
    eglOesBase.release();

    // Wait for OES texture frame.
    final VideoFrame.TextureBuffer textureBuffer = listener.waitForTextureBuffer();
    // Diconnect while holding the frame.
    surfaceTextureHelper.dispose();

    // Draw the pending texture frame onto the pixel buffer.
    eglBase.makeCurrent();
    final GlRectDrawer drawer = new GlRectDrawer();
    drawer.drawOes(textureBuffer.getTextureId(),
        RendererCommon.convertMatrixFromAndroidGraphicsMatrix(textureBuffer.getTransformMatrix()),
        width, height, 0, 0, width, height);
    drawer.release();

    // Download the pixels in the pixel buffer as RGBA. Not all platforms support RGB, e.g. Nexus 9.
    final ByteBuffer rgbaData = ByteBuffer.allocateDirect(width * height * 4);
    GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, rgbaData);
    GlUtil.checkNoGLES2Error("glReadPixels");
    eglBase.release();

    // Assert rendered image is expected constant color.
    while (rgbaData.hasRemaining()) {
      assertEquals(rgbaData.get() & 0xFF, red);
      assertEquals(rgbaData.get() & 0xFF, green);
      assertEquals(rgbaData.get() & 0xFF, blue);
      assertEquals(rgbaData.get() & 0xFF, 255);
    }
    // Late frame return after everything has been disposed and released.
    textureBuffer.release();
  }

  /**
   * Test disposing the SurfaceTextureHelper, but keep trying to produce more texture frames. No
   * frames should be delivered to the listener.
   */
  @Test
  @MediumTest
  public void testDispose() throws InterruptedException {
    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
    final MockTextureListener listener = new MockTextureListener();
    surfaceTextureHelper.startListening(listener);
    // Create EglBase with the SurfaceTexture as target EGLSurface.
    final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
    surfaceTextureHelper.setTextureSize(/* textureWidth= */ 32, /* textureHeight= */ 32);
    eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    eglBase.makeCurrent();
    // Assert no frame has been received yet.
    listener.assertNoFrameIsDelivered(/* waitPeriodMs= */ 1);
    // Draw and wait for one frame.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // swapBuffers() will ultimately trigger onTextureFrameAvailable().
    eglBase.swapBuffers();
    listener.waitForTextureBuffer().release();

    // Dispose - we should not receive any textures after this.
    surfaceTextureHelper.dispose();

    // Draw one frame.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    eglBase.swapBuffers();
    // swapBuffers() should not trigger onTextureFrameAvailable() because disposed has been called.
    // Assert that no OES texture was delivered.
    listener.assertNoFrameIsDelivered(/* waitPeriodMs= */ 500);

    eglBase.release();
  }

  /**
   * Test disposing the SurfaceTextureHelper immediately after is has been setup to use a
   * shared context. No frames should be delivered to the listener.
   */
  @Test
  @SmallTest
  public void testDisposeImmediately() {
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
    surfaceTextureHelper.dispose();
  }

  /**
   * Call stopListening(), but keep trying to produce more texture frames. No frames should be
   * delivered to the listener.
   */
  @Test
  @MediumTest
  public void testStopListening() throws InterruptedException {
    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
    surfaceTextureHelper.setTextureSize(/* textureWidth= */ 32, /* textureHeight= */ 32);
    final MockTextureListener listener = new MockTextureListener();
    surfaceTextureHelper.startListening(listener);
    // Create EglBase with the SurfaceTexture as target EGLSurface.
    final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
    eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    eglBase.makeCurrent();
    // Assert no frame has been received yet.
    listener.assertNoFrameIsDelivered(/* waitPeriodMs= */ 1);
    // Draw and wait for one frame.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // swapBuffers() will ultimately trigger onTextureFrameAvailable().
    eglBase.swapBuffers();
    listener.waitForTextureBuffer().release();

    // Stop listening - we should not receive any textures after this.
    surfaceTextureHelper.stopListening();

    // Draw one frame.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    eglBase.swapBuffers();
    // swapBuffers() should not trigger onTextureFrameAvailable() because disposed has been called.
    // Assert that no OES texture was delivered.
    listener.assertNoFrameIsDelivered(/* waitPeriodMs= */ 500);

    surfaceTextureHelper.dispose();
    eglBase.release();
  }

  /**
   * Test stopListening() immediately after the SurfaceTextureHelper has been setup.
   */
  @Test
  @SmallTest
  public void testStopListeningImmediately() throws InterruptedException {
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
    final MockTextureListener listener = new MockTextureListener();
    surfaceTextureHelper.startListening(listener);
    surfaceTextureHelper.stopListening();
    surfaceTextureHelper.dispose();
  }

  /**
   * Test stopListening() immediately after the SurfaceTextureHelper has been setup on the handler
   * thread.
   */
  @Test
  @SmallTest
  public void testStopListeningImmediatelyOnHandlerThread() throws InterruptedException {
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
    final MockTextureListener listener = new MockTextureListener();

    final CountDownLatch stopListeningBarrier = new CountDownLatch(1);
    final CountDownLatch stopListeningBarrierDone = new CountDownLatch(1);
    // Start by posting to the handler thread to keep it occupied.
    surfaceTextureHelper.getHandler().post(new Runnable() {
      @Override
      public void run() {
        ThreadUtils.awaitUninterruptibly(stopListeningBarrier);
        surfaceTextureHelper.stopListening();
        stopListeningBarrierDone.countDown();
      }
    });

    // startListening() is asynchronous and will post to the occupied handler thread.
    surfaceTextureHelper.startListening(listener);
    // Wait for stopListening() to be called on the handler thread.
    stopListeningBarrier.countDown();
    stopListeningBarrierDone.await();
    // Wait until handler thread is idle to try to catch late startListening() call.
    final CountDownLatch barrier = new CountDownLatch(1);
    surfaceTextureHelper.getHandler().post(new Runnable() {
      @Override
      public void run() {
        barrier.countDown();
      }
    });
    ThreadUtils.awaitUninterruptibly(barrier);
    // Previous startListening() call should never have taken place and it should be ok to call it
    // again.
    surfaceTextureHelper.startListening(listener);

    surfaceTextureHelper.dispose();
  }

  /**
   * Test calling startListening() with a new listener after stopListening() has been called.
   */
  @Test
  @MediumTest
  public void testRestartListeningWithNewListener() throws InterruptedException {
    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper =
        SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
    surfaceTextureHelper.setTextureSize(/* textureWidth= */ 32, /* textureHeight= */ 32);
    final MockTextureListener listener1 = new MockTextureListener();
    surfaceTextureHelper.startListening(listener1);
    // Create EglBase with the SurfaceTexture as target EGLSurface.
    final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
    eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    eglBase.makeCurrent();
    // Assert no frame has been received yet.
    listener1.assertNoFrameIsDelivered(/* waitPeriodMs= */ 1);
    // Draw and wait for one frame.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // swapBuffers() will ultimately trigger onTextureFrameAvailable().
    eglBase.swapBuffers();
    listener1.waitForTextureBuffer().release();

    // Stop listening - |listener1| should not receive any textures after this.
    surfaceTextureHelper.stopListening();

    // Connect different listener.
    final MockTextureListener listener2 = new MockTextureListener();
    surfaceTextureHelper.startListening(listener2);
    // Assert no frame has been received yet.
    listener2.assertNoFrameIsDelivered(/* waitPeriodMs= */ 1);

    // Draw one frame.
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    eglBase.swapBuffers();

    // Check that |listener2| received the frame, and not |listener1|.
    listener2.waitForTextureBuffer().release();
    listener1.assertNoFrameIsDelivered(/* waitPeriodMs= */ 1);

    surfaceTextureHelper.dispose();
    eglBase.release();
  }

  @Test
  @MediumTest
  public void testTexturetoYuv() throws InterruptedException {
    final int width = 16;
    final int height = 16;

    final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);

    // Create SurfaceTextureHelper and listener.
    final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create(
        "SurfaceTextureHelper test" /* threadName */, eglBase.getEglBaseContext());
    final MockTextureListener listener = new MockTextureListener();
    surfaceTextureHelper.startListening(listener);
    surfaceTextureHelper.setTextureSize(width, height);

    // Create resources for stubbing an OES texture producer. |eglBase| has the SurfaceTexture in
    // |surfaceTextureHelper| as the target EGLSurface.

    eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
    assertEquals(eglBase.surfaceWidth(), width);
    assertEquals(eglBase.surfaceHeight(), height);

    final int red[] = new int[] {79, 144, 185};
    final int green[] = new int[] {66, 210, 162};
    final int blue[] = new int[] {161, 117, 158};

    final int ref_y[] = new int[] {85, 170, 161};
    final int ref_u[] = new int[] {168, 97, 123};
    final int ref_v[] = new int[] {127, 106, 138};

    // Draw three frames.
    for (int i = 0; i < 3; ++i) {
      // Draw a constant color frame onto the SurfaceTexture.
      eglBase.makeCurrent();
      GLES20.glClearColor(red[i] / 255.0f, green[i] / 255.0f, blue[i] / 255.0f, 1.0f);
      GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
      // swapBuffers() will ultimately trigger onTextureFrameAvailable().
      eglBase.swapBuffers();

      // Wait for an OES texture to arrive.
      final VideoFrame.TextureBuffer textureBuffer = listener.waitForTextureBuffer();
      final VideoFrame.I420Buffer i420 = textureBuffer.toI420();
      textureBuffer.release();

      // Memory layout: Lines are 16 bytes. First 16 lines are
      // the Y data. These are followed by 8 lines with 8 bytes of U
      // data on the left and 8 bytes of V data on the right.
      //
      // Offset
      //      0 YYYYYYYY YYYYYYYY
      //     16 YYYYYYYY YYYYYYYY
      //    ...
      //    240 YYYYYYYY YYYYYYYY
      //    256 UUUUUUUU VVVVVVVV
      //    272 UUUUUUUU VVVVVVVV
      //    ...
      //    368 UUUUUUUU VVVVVVVV
      //    384 buffer end

      // Allow off-by-one differences due to different rounding.
      final ByteBuffer dataY = i420.getDataY();
      final int strideY = i420.getStrideY();
      for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
          assertClose(1, ref_y[i], dataY.get(y * strideY + x) & 0xFF);
        }
      }

      final int chromaWidth = width / 2;
      final int chromaHeight = height / 2;

      final ByteBuffer dataU = i420.getDataU();
      final ByteBuffer dataV = i420.getDataV();
      final int strideU = i420.getStrideU();
      final int strideV = i420.getStrideV();
      for (int y = 0; y < chromaHeight; y++) {
        for (int x = 0; x < chromaWidth; x++) {
          assertClose(1, ref_u[i], dataU.get(y * strideU + x) & 0xFF);
          assertClose(1, ref_v[i], dataV.get(y * strideV + x) & 0xFF);
        }
      }
      i420.release();
    }

    surfaceTextureHelper.dispose();
    eglBase.release();
  }
}
