/*
 *  Copyright 2016 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 android.os.Environment;
import android.support.test.filters.SmallTest;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(BaseJUnit4ClassRunner.class)
public class FileVideoCapturerTest {
  public class MockCapturerObserver implements VideoCapturer.CapturerObserver {
    private final ArrayList<VideoFrame> frames = new ArrayList<VideoFrame>();

    @Override
    public void onCapturerStarted(boolean success) {
      assertTrue(success);
    }

    @Override
    public void onCapturerStopped() {
      // Empty on purpose.
    }

    @Override
    public synchronized void onByteBufferFrameCaptured(
        byte[] data, int width, int height, int rotation, long timeStamp) {
      // Empty on purpose.
    }

    @Override
    public void onTextureFrameCaptured(int width, int height, int oesTextureId,
        float[] transformMatrix, int rotation, long timestamp) {
      // Empty on purpose.
    }

    @Override
    public synchronized void onFrameCaptured(VideoFrame frame) {
      frames.add(frame);
      notify();
    }

    public synchronized ArrayList<VideoFrame> getMinimumFramesBlocking(int minFrames)
        throws InterruptedException {
      while (frames.size() < minFrames) {
        wait();
      }
      return new ArrayList<VideoFrame>(frames);
    }
  }

  @Test
  @SmallTest
  public void testVideoCaptureFromFile() throws InterruptedException, IOException {
    final int FRAME_WIDTH = 4;
    final int FRAME_HEIGHT = 4;
    final int FRAME_CHROMA_WIDTH = (FRAME_WIDTH + 1) / 2;
    final int FRAME_CHROMA_HEIGHT = (FRAME_HEIGHT + 1) / 2;
    final int FRAME_SIZE_Y = FRAME_WIDTH * FRAME_HEIGHT;
    final int FRAME_SIZE_CHROMA = FRAME_CHROMA_WIDTH * FRAME_CHROMA_HEIGHT;

    final FileVideoCapturer fileVideoCapturer =
        new FileVideoCapturer(Environment.getExternalStorageDirectory().getPath()
            + "/chromium_tests_root/sdk/android/instrumentationtests/src/org/webrtc/"
            + "capturetestvideo.y4m");
    final MockCapturerObserver capturerObserver = new MockCapturerObserver();
    fileVideoCapturer.initialize(
        null /* surfaceTextureHelper */, null /* applicationContext */, capturerObserver);
    fileVideoCapturer.startCapture(FRAME_WIDTH, FRAME_HEIGHT, 33 /* fps */);

    final String[] expectedFrames = {
        "THIS IS JUST SOME TEXT x", "THE SECOND FRAME qwerty.", "HERE IS THE THRID FRAME!"};

    final ArrayList<VideoFrame> frames =
        capturerObserver.getMinimumFramesBlocking(expectedFrames.length);
    assertEquals(expectedFrames.length, frames.size());

    fileVideoCapturer.stopCapture();
    fileVideoCapturer.dispose();

    // Check the content of the frames.
    for (int i = 0; i < expectedFrames.length; ++i) {
      final VideoFrame frame = frames.get(i);
      final VideoFrame.Buffer buffer = frame.getBuffer();
      assertTrue(buffer instanceof VideoFrame.I420Buffer);
      final VideoFrame.I420Buffer i420Buffer = (VideoFrame.I420Buffer) buffer;

      assertEquals(FRAME_WIDTH, i420Buffer.getWidth());
      assertEquals(FRAME_HEIGHT, i420Buffer.getHeight());

      final ByteBuffer dataY = i420Buffer.getDataY();
      final ByteBuffer dataU = i420Buffer.getDataU();
      final ByteBuffer dataV = i420Buffer.getDataV();

      assertEquals(FRAME_SIZE_Y, dataY.remaining());
      assertEquals(FRAME_SIZE_CHROMA, dataU.remaining());
      assertEquals(FRAME_SIZE_CHROMA, dataV.remaining());

      ByteBuffer frameContents = ByteBuffer.allocate(FRAME_SIZE_Y + 2 * FRAME_SIZE_CHROMA);
      frameContents.put(dataY);
      frameContents.put(dataU);
      frameContents.put(dataV);
      frameContents.rewind(); // Move back to the beginning.

      assertByteBufferContents(
          expectedFrames[i].getBytes(Charset.forName("US-ASCII")), frameContents);
    }
  }

  private static void assertByteBufferContents(byte[] expected, ByteBuffer actual) {
    assertEquals("Unexpected ByteBuffer size.", expected.length, actual.remaining());
    for (int i = 0; i < expected.length; i++) {
      assertEquals("Unexpected byte at index: " + i, expected[i], actual.get());
    }
  }
}
