/*
 *  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 static 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());
    }
  }
}
