/*
 *  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 android.graphics.SurfaceTexture;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * Helper class to create and synchronize access to a SurfaceTexture. The caller will get notified
 * of new frames in onTextureFrameAvailable(), and should call returnTextureFrame() when done with
 * the frame. Only one texture frame can be in flight at once, so returnTextureFrame() must be
 * called in order to receive a new frame. Call stopListening() to stop receiveing new frames. Call
 * dispose to release all resources once the texture frame is returned.
 * Note that there is a C++ counter part of this class that optionally can be used. It is used for
 * wrapping texture frames into webrtc::VideoFrames and also handles calling returnTextureFrame()
 * when the webrtc::VideoFrame is no longer used.
 */
class SurfaceTextureHelper {
  private static final String TAG = "SurfaceTextureHelper";
  /**
   * Callback interface for being notified that a new texture frame is available. The calls will be
   * made on a dedicated thread with a bound EGLContext. The thread will be the same throughout the
   * lifetime of the SurfaceTextureHelper instance, but different from the thread calling the
   * SurfaceTextureHelper constructor. The callee is not allowed to make another EGLContext current
   * on the calling thread.
   */
  public interface OnTextureFrameAvailableListener {
    abstract void onTextureFrameAvailable(
        int oesTextureId, float[] transformMatrix, long timestampNs);
  }

  /**
   * Construct a new SurfaceTextureHelper sharing OpenGL resources with |sharedContext|. A dedicated
   * thread and handler is created for handling the SurfaceTexture. May return null if EGL fails to
   * initialize a pixel buffer surface and make it current.
   */
  public static SurfaceTextureHelper create(
      final String threadName, final EglBase.Context sharedContext) {
    final HandlerThread thread = new HandlerThread(threadName);
    thread.start();
    final Handler handler = new Handler(thread.getLooper());

    // The onFrameAvailable() callback will be executed on the SurfaceTexture ctor thread. See:
    // http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/graphics/SurfaceTexture.java#195.
    // Therefore, in order to control the callback thread on API lvl < 21, the SurfaceTextureHelper
    // is constructed on the |handler| thread.
    return ThreadUtils.invokeAtFrontUninterruptibly(handler, new Callable<SurfaceTextureHelper>() {
      @Override
      public SurfaceTextureHelper call() {
        try {
          return new SurfaceTextureHelper(sharedContext, handler);
        } catch (RuntimeException e) {
          Logging.e(TAG, threadName + " create failure", e);
          return null;
        }
      }
    });
  }

  // State for YUV conversion, instantiated on demand.
  static private class YuvConverter {
    private final EglBase eglBase;
    private final GlShader shader;
    private boolean released = false;

    // Vertex coordinates in Normalized Device Coordinates, i.e.
    // (-1, -1) is bottom-left and (1, 1) is top-right.
    private static final FloatBuffer DEVICE_RECTANGLE = GlUtil.createFloatBuffer(new float[] {
        -1.0f, -1.0f, // Bottom left.
        1.0f, -1.0f, // Bottom right.
        -1.0f, 1.0f, // Top left.
        1.0f, 1.0f, // Top right.
    });

    // Texture coordinates - (0, 0) is bottom-left and (1, 1) is top-right.
    private static final FloatBuffer TEXTURE_RECTANGLE = GlUtil.createFloatBuffer(new float[] {
        0.0f, 0.0f, // Bottom left.
        1.0f, 0.0f, // Bottom right.
        0.0f, 1.0f, // Top left.
        1.0f, 1.0f // Top right.
    });

    // clang-format off
    private static final String VERTEX_SHADER =
          "varying vec2 interp_tc;\n"
        + "attribute vec4 in_pos;\n"
        + "attribute vec4 in_tc;\n"
        + "\n"
        + "uniform mat4 texMatrix;\n"
        + "\n"
        + "void main() {\n"
        + "    gl_Position = in_pos;\n"
        + "    interp_tc = (texMatrix * in_tc).xy;\n"
        + "}\n";

    private static final String FRAGMENT_SHADER =
          "#extension GL_OES_EGL_image_external : require\n"
        + "precision mediump float;\n"
        + "varying vec2 interp_tc;\n"
        + "\n"
        + "uniform samplerExternalOES oesTex;\n"
        // Difference in texture coordinate corresponding to one
        // sub-pixel in the x direction.
        + "uniform vec2 xUnit;\n"
        // Color conversion coefficients, including constant term
        + "uniform vec4 coeffs;\n"
        + "\n"
        + "void main() {\n"
        // Since the alpha read from the texture is always 1, this could
        // be written as a mat4 x vec4 multiply. However, that seems to
        // give a worse framerate, possibly because the additional
        // multiplies by 1.0 consume resources. TODO(nisse): Could also
        // try to do it as a vec3 x mat3x4, followed by an add in of a
        // constant vector.
        + "  gl_FragColor.r = coeffs.a + dot(coeffs.rgb,\n"
        + "      texture2D(oesTex, interp_tc - 1.5 * xUnit).rgb);\n"
        + "  gl_FragColor.g = coeffs.a + dot(coeffs.rgb,\n"
        + "      texture2D(oesTex, interp_tc - 0.5 * xUnit).rgb);\n"
        + "  gl_FragColor.b = coeffs.a + dot(coeffs.rgb,\n"
        + "      texture2D(oesTex, interp_tc + 0.5 * xUnit).rgb);\n"
        + "  gl_FragColor.a = coeffs.a + dot(coeffs.rgb,\n"
        + "      texture2D(oesTex, interp_tc + 1.5 * xUnit).rgb);\n"
        + "}\n";
    // clang-format on

    private int texMatrixLoc;
    private int xUnitLoc;
    private int coeffsLoc;

    YuvConverter(EglBase.Context sharedContext) {
      eglBase = EglBase.create(sharedContext, EglBase.CONFIG_PIXEL_RGBA_BUFFER);
      eglBase.createDummyPbufferSurface();
      eglBase.makeCurrent();

      shader = new GlShader(VERTEX_SHADER, FRAGMENT_SHADER);
      shader.useProgram();
      texMatrixLoc = shader.getUniformLocation("texMatrix");
      xUnitLoc = shader.getUniformLocation("xUnit");
      coeffsLoc = shader.getUniformLocation("coeffs");
      GLES20.glUniform1i(shader.getUniformLocation("oesTex"), 0);
      GlUtil.checkNoGLES2Error("Initialize fragment shader uniform values.");
      // Initialize vertex shader attributes.
      shader.setVertexAttribArray("in_pos", 2, DEVICE_RECTANGLE);
      // If the width is not a multiple of 4 pixels, the texture
      // will be scaled up slightly and clipped at the right border.
      shader.setVertexAttribArray("in_tc", 2, TEXTURE_RECTANGLE);
      eglBase.detachCurrent();
    }

    synchronized void convert(
        ByteBuffer buf, int width, int height, int stride, int textureId, float[] transformMatrix) {
      if (released) {
        throw new IllegalStateException("YuvConverter.convert called on released object");
      }

      // We draw into a buffer laid out like
      //
      //    +---------+
      //    |         |
      //    |  Y      |
      //    |         |
      //    |         |
      //    +----+----+
      //    | U  | V  |
      //    |    |    |
      //    +----+----+
      //
      // In memory, we use the same stride for all of Y, U and V. The
      // U data starts at offset |height| * |stride| from the Y data,
      // and the V data starts at at offset |stride/2| from the U
      // data, with rows of U and V data alternating.
      //
      // Now, it would have made sense to allocate a pixel buffer with
      // a single byte per pixel (EGL10.EGL_COLOR_BUFFER_TYPE,
      // EGL10.EGL_LUMINANCE_BUFFER,), but that seems to be
      // unsupported by devices. So do the following hack: Allocate an
      // RGBA buffer, of width |stride|/4. To render each of these
      // large pixels, sample the texture at 4 different x coordinates
      // and store the results in the four components.
      //
      // Since the V data needs to start on a boundary of such a
      // larger pixel, it is not sufficient that |stride| is even, it
      // has to be a multiple of 8 pixels.

      if (stride % 8 != 0) {
        throw new IllegalArgumentException("Invalid stride, must be a multiple of 8");
      }
      if (stride < width) {
        throw new IllegalArgumentException("Invalid stride, must >= width");
      }

      int y_width = (width + 3) / 4;
      int uv_width = (width + 7) / 8;
      int uv_height = (height + 1) / 2;
      int total_height = height + uv_height;
      int size = stride * total_height;

      if (buf.capacity() < size) {
        throw new IllegalArgumentException("YuvConverter.convert called with too small buffer");
      }
      // Produce a frame buffer starting at top-left corner, not
      // bottom-left.
      transformMatrix =
          RendererCommon.multiplyMatrices(transformMatrix, RendererCommon.verticalFlipMatrix());

      // Create new pBuffferSurface with the correct size if needed.
      if (eglBase.hasSurface()) {
        if (eglBase.surfaceWidth() != stride / 4 || eglBase.surfaceHeight() != total_height) {
          eglBase.releaseSurface();
          eglBase.createPbufferSurface(stride / 4, total_height);
        }
      } else {
        eglBase.createPbufferSurface(stride / 4, total_height);
      }

      eglBase.makeCurrent();

      GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
      GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
      GLES20.glUniformMatrix4fv(texMatrixLoc, 1, false, transformMatrix, 0);

      // Draw Y
      GLES20.glViewport(0, 0, y_width, height);
      // Matrix * (1;0;0;0) / width. Note that opengl uses column major order.
      GLES20.glUniform2f(xUnitLoc, transformMatrix[0] / width, transformMatrix[1] / width);
      // Y'UV444 to RGB888, see
      // https://en.wikipedia.org/wiki/YUV#Y.27UV444_to_RGB888_conversion.
      // We use the ITU-R coefficients for U and V */
      GLES20.glUniform4f(coeffsLoc, 0.299f, 0.587f, 0.114f, 0.0f);
      GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

      // Draw U
      GLES20.glViewport(0, height, uv_width, uv_height);
      // Matrix * (1;0;0;0) / (width / 2). Note that opengl uses column major order.
      GLES20.glUniform2f(
          xUnitLoc, 2.0f * transformMatrix[0] / width, 2.0f * transformMatrix[1] / width);
      GLES20.glUniform4f(coeffsLoc, -0.169f, -0.331f, 0.499f, 0.5f);
      GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

      // Draw V
      GLES20.glViewport(stride / 8, height, uv_width, uv_height);
      GLES20.glUniform4f(coeffsLoc, 0.499f, -0.418f, -0.0813f, 0.5f);
      GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

      GLES20.glReadPixels(
          0, 0, stride / 4, total_height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);

      GlUtil.checkNoGLES2Error("YuvConverter.convert");

      // Unbind texture. Reportedly needed on some devices to get
      // the texture updated from the camera.
      GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
      eglBase.detachCurrent();
    }

    synchronized void release() {
      released = true;
      eglBase.makeCurrent();
      shader.release();
      eglBase.release();
    }
  }

  private final Handler handler;
  private final EglBase eglBase;
  private final SurfaceTexture surfaceTexture;
  private final int oesTextureId;
  private YuvConverter yuvConverter;

  // These variables are only accessed from the |handler| thread.
  private OnTextureFrameAvailableListener listener;
  // The possible states of this class.
  private boolean hasPendingTexture = false;
  private volatile boolean isTextureInUse = false;
  private boolean isQuitting = false;
  // |pendingListener| is set in setListener() and the runnable is posted to the handler thread.
  // setListener() is not allowed to be called again before stopListening(), so this is thread safe.
  private OnTextureFrameAvailableListener pendingListener;
  final Runnable setListenerRunnable = new Runnable() {
    @Override
    public void run() {
      Logging.d(TAG, "Setting listener to " + pendingListener);
      listener = pendingListener;
      pendingListener = null;
      // May have a pending frame from the previous capture session - drop it.
      if (hasPendingTexture) {
        // Calling updateTexImage() is neccessary in order to receive new frames.
        updateTexImage();
        hasPendingTexture = false;
      }
    }
  };

  private SurfaceTextureHelper(EglBase.Context sharedContext, Handler handler) {
    if (handler.getLooper().getThread() != Thread.currentThread()) {
      throw new IllegalStateException("SurfaceTextureHelper must be created on the handler thread");
    }
    this.handler = handler;

    eglBase = EglBase.create(sharedContext, EglBase.CONFIG_PIXEL_BUFFER);
    try {
      // Both these statements have been observed to fail on rare occasions, see BUG=webrtc:5682.
      eglBase.createDummyPbufferSurface();
      eglBase.makeCurrent();
    } catch (RuntimeException e) {
      // Clean up before rethrowing the exception.
      eglBase.release();
      handler.getLooper().quit();
      throw e;
    }

    oesTextureId = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
    surfaceTexture = new SurfaceTexture(oesTextureId);
    surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
      @Override
      public void onFrameAvailable(SurfaceTexture surfaceTexture) {
        hasPendingTexture = true;
        tryDeliverTextureFrame();
      }
    });
  }

  private YuvConverter getYuvConverter() {
    // yuvConverter is assigned once
    if (yuvConverter != null)
      return yuvConverter;

    synchronized (this) {
      if (yuvConverter == null)
        yuvConverter = new YuvConverter(eglBase.getEglBaseContext());
      return yuvConverter;
    }
  }

  /**
   * Start to stream textures to the given |listener|. If you need to change listener, you need to
   * call stopListening() first.
   */
  public void startListening(final OnTextureFrameAvailableListener listener) {
    if (this.listener != null || this.pendingListener != null) {
      throw new IllegalStateException("SurfaceTextureHelper listener has already been set.");
    }
    this.pendingListener = listener;
    handler.post(setListenerRunnable);
  }

  /**
   * Stop listening. The listener set in startListening() is guaranteded to not receive any more
   * onTextureFrameAvailable() callbacks after this function returns.
   */
  public void stopListening() {
    Logging.d(TAG, "stopListening()");
    handler.removeCallbacks(setListenerRunnable);
    ThreadUtils.invokeAtFrontUninterruptibly(handler, new Runnable() {
      @Override
      public void run() {
        listener = null;
        pendingListener = null;
      }
    });
  }

  /**
   * Retrieve the underlying SurfaceTexture. The SurfaceTexture should be passed in to a video
   * producer such as a camera or decoder.
   */
  public SurfaceTexture getSurfaceTexture() {
    return surfaceTexture;
  }

  /**
   * Retrieve the handler that calls onTextureFrameAvailable(). This handler is valid until
   * dispose() is called.
   */
  public Handler getHandler() {
    return handler;
  }

  /**
   * Call this function to signal that you are done with the frame received in
   * onTextureFrameAvailable(). Only one texture frame can be in flight at once, so you must call
   * this function in order to receive a new frame.
   */
  public void returnTextureFrame() {
    handler.post(new Runnable() {
      @Override
      public void run() {
        isTextureInUse = false;
        if (isQuitting) {
          release();
        } else {
          tryDeliverTextureFrame();
        }
      }
    });
  }

  public boolean isTextureInUse() {
    return isTextureInUse;
  }

  /**
   * Call disconnect() to stop receiving frames. OpenGL resources are released and the handler is
   * stopped when the texture frame has been returned by a call to returnTextureFrame(). You are
   * guaranteed to not receive any more onTextureFrameAvailable() after this function returns.
   */
  public void dispose() {
    Logging.d(TAG, "dispose()");
    ThreadUtils.invokeAtFrontUninterruptibly(handler, new Runnable() {
      @Override
      public void run() {
        isQuitting = true;
        if (!isTextureInUse) {
          release();
        }
      }
    });
  }

  public void textureToYUV(
      ByteBuffer buf, int width, int height, int stride, int textureId, float[] transformMatrix) {
    if (textureId != oesTextureId)
      throw new IllegalStateException("textureToByteBuffer called with unexpected textureId");

    getYuvConverter().convert(buf, width, height, stride, textureId, transformMatrix);
  }

  private void updateTexImage() {
    // SurfaceTexture.updateTexImage apparently can compete and deadlock with eglSwapBuffers,
    // as observed on Nexus 5. Therefore, synchronize it with the EGL functions.
    // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5702 for more info.
    synchronized (EglBase.lock) {
      surfaceTexture.updateTexImage();
    }
  }

  private void tryDeliverTextureFrame() {
    if (handler.getLooper().getThread() != Thread.currentThread()) {
      throw new IllegalStateException("Wrong thread.");
    }
    if (isQuitting || !hasPendingTexture || isTextureInUse || listener == null) {
      return;
    }
    isTextureInUse = true;
    hasPendingTexture = false;

    updateTexImage();

    final float[] transformMatrix = new float[16];
    surfaceTexture.getTransformMatrix(transformMatrix);
    final long timestampNs = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        ? surfaceTexture.getTimestamp()
        : TimeUnit.MILLISECONDS.toNanos(SystemClock.elapsedRealtime());
    listener.onTextureFrameAvailable(oesTextureId, transformMatrix, timestampNs);
  }

  private void release() {
    if (handler.getLooper().getThread() != Thread.currentThread()) {
      throw new IllegalStateException("Wrong thread.");
    }
    if (isTextureInUse || !isQuitting) {
      throw new IllegalStateException("Unexpected release.");
    }
    synchronized (this) {
      if (yuvConverter != null)
        yuvConverter.release();
    }
    GLES20.glDeleteTextures(1, new int[] {oesTextureId}, 0);
    surfaceTexture.release();
    eglBase.release();
    handler.getLooper().quit();
  }
}
