/*
 *  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 org.webrtc.MediaCodecVideoEncoder.OutputBufferInfo;

import android.annotation.TargetApi;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.os.Build;
import android.test.ActivityTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;

import java.nio.ByteBuffer;

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
public final class MediaCodecVideoEncoderTest extends ActivityTestCase {
  final static String TAG = "MediaCodecVideoEncoderTest";

  @SmallTest
  public static void testInitializeUsingByteBuffer() {
    if (!MediaCodecVideoEncoder.isVp8HwSupported()) {
      Log.i(TAG,
            "Hardware does not support VP8 encoding, skipping testInitReleaseUsingByteBuffer");
      return;
    }
    MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
    assertTrue(encoder.initEncode(
        MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, 640, 480, 300, 30, null));
    encoder.release();
  }

  @SmallTest
  public static void testInitilizeUsingTextures() {
    if (!MediaCodecVideoEncoder.isVp8HwSupportedUsingTextures()) {
      Log.i(TAG, "hardware does not support VP8 encoding, skipping testEncoderUsingTextures");
      return;
    }
    EglBase14 eglBase = new EglBase14(null, EglBase.CONFIG_PLAIN);
    MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
    assertTrue(encoder.initEncode(
        MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, 640, 480, 300, 30,
        eglBase.getEglBaseContext()));
    encoder.release();
    eglBase.release();
  }

  @SmallTest
  public static void testInitializeUsingByteBufferReInitilizeUsingTextures() {
    if (!MediaCodecVideoEncoder.isVp8HwSupportedUsingTextures()) {
      Log.i(TAG, "hardware does not support VP8 encoding, skipping testEncoderUsingTextures");
      return;
    }
    MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();
    assertTrue(encoder.initEncode(
        MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, 640, 480, 300, 30,
        null));
    encoder.release();
    EglBase14 eglBase = new EglBase14(null, EglBase.CONFIG_PLAIN);
    assertTrue(encoder.initEncode(
        MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, 640, 480, 300, 30,
        eglBase.getEglBaseContext()));
    encoder.release();
    eglBase.release();
  }

  @SmallTest
  public static void testEncoderUsingByteBuffer() throws InterruptedException {
    if (!MediaCodecVideoEncoder.isVp8HwSupported()) {
      Log.i(TAG, "Hardware does not support VP8 encoding, skipping testEncoderUsingByteBuffer");
      return;
    }

    final int width = 640;
    final int height = 480;
    final int min_size = width * height * 3 / 2;
    final long presentationTimestampUs = 2;

    MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();

    assertTrue(encoder.initEncode(
        MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, width, height, 300, 30, null));
    ByteBuffer[] inputBuffers = encoder.getInputBuffers();
    assertNotNull(inputBuffers);
    assertTrue(min_size <= inputBuffers[0].capacity());

    int bufferIndex;
    do {
      Thread.sleep(10);
      bufferIndex = encoder.dequeueInputBuffer();
    } while (bufferIndex == -1); // |-1| is returned when there is no buffer available yet.

    assertTrue(bufferIndex >= 0);
    assertTrue(bufferIndex < inputBuffers.length);
    assertTrue(encoder.encodeBuffer(true, bufferIndex, min_size, presentationTimestampUs));

    OutputBufferInfo info;
    do {
      info = encoder.dequeueOutputBuffer();
      Thread.sleep(10);
    } while (info == null);
    assertTrue(info.index >= 0);
    assertEquals(presentationTimestampUs, info.presentationTimestampUs);
    assertTrue(info.buffer.capacity() > 0);
    encoder.releaseOutputBuffer(info.index);

    encoder.release();
  }

  @SmallTest
  public static void testEncoderUsingTextures() throws InterruptedException {
    if (!MediaCodecVideoEncoder.isVp8HwSupportedUsingTextures()) {
      Log.i(TAG, "Hardware does not support VP8 encoding, skipping testEncoderUsingTextures");
      return;
    }

    final int width = 640;
    final int height = 480;
    final long presentationTs = 2;

    final EglBase14 eglOesBase = new EglBase14(null, EglBase.CONFIG_PIXEL_BUFFER);
    eglOesBase.createDummyPbufferSurface();
    eglOesBase.makeCurrent();
    int oesTextureId = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);

    // TODO(perkj): This test is week since we don't fill the texture with valid data with correct
    // width and height and verify the encoded data. Fill the OES texture and figure out a way to
    // verify that the output make sense.

    MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder();

    assertTrue(encoder.initEncode(
        MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, width, height, 300, 30,
        eglOesBase.getEglBaseContext()));
    assertTrue(encoder.encodeTexture(true, oesTextureId, RendererCommon.identityMatrix(),
        presentationTs));
    GlUtil.checkNoGLES2Error("encodeTexture");

    // It should be Ok to delete the texture after calling encodeTexture.
    GLES20.glDeleteTextures(1, new int[] {oesTextureId}, 0);

    OutputBufferInfo info = encoder.dequeueOutputBuffer();
    while (info == null) {
      info = encoder.dequeueOutputBuffer();
      Thread.sleep(20);
    }
    assertTrue(info.index != -1);
    assertTrue(info.buffer.capacity() > 0);
    assertEquals(presentationTs, info.presentationTimestampUs);
    encoder.releaseOutputBuffer(info.index);

    encoder.release();
    eglOesBase.release();
  }
}
