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

import android.annotation.TargetApi;
import android.content.Context;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Environment;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.junit.runner.RunWith;
import org.webrtc.CameraEnumerationAndroid.CaptureFormat;
import org.webrtc.VideoRenderer.I420Frame;

class CameraVideoCapturerTestFixtures {
  static final String TAG = "CameraVideoCapturerTestFixtures";
  // Default values used for starting capturing
  static final int DEFAULT_WIDTH = 640;
  static final int DEFAULT_HEIGHT = 480;
  static final int DEFAULT_FPS = 15;

  static private class RendererCallbacks implements VideoRenderer.Callbacks {
    private final Object frameLock = new Object();
    private int framesRendered = 0;
    private int width = 0;
    private int height = 0;

    @Override
    public void renderFrame(I420Frame frame) {
      synchronized (frameLock) {
        ++framesRendered;
        width = frame.rotatedWidth();
        height = frame.rotatedHeight();
        frameLock.notify();
      }
      VideoRenderer.renderFrameDone(frame);
    }

    public int frameWidth() {
      synchronized (frameLock) {
        return width;
      }
    }

    public int frameHeight() {
      synchronized (frameLock) {
        return height;
      }
    }

    public int waitForNextFrameToRender() throws InterruptedException {
      Logging.d(TAG, "Waiting for the next frame to render");
      synchronized (frameLock) {
        final int framesRenderedStart = framesRendered;
        while (framesRendered == framesRenderedStart) {
          frameLock.wait();
        }
        return framesRendered;
      }
    }
  }

  static private class FakeAsyncRenderer implements VideoRenderer.Callbacks {
    private final List<I420Frame> pendingFrames = new ArrayList<I420Frame>();

    @Override
    public void renderFrame(I420Frame frame) {
      synchronized (pendingFrames) {
        pendingFrames.add(frame);
        pendingFrames.notifyAll();
      }
    }

    // Wait until at least one frame have been received, before returning them.
    public List<I420Frame> waitForPendingFrames() throws InterruptedException {
      Logging.d(TAG, "Waiting for pending frames");
      synchronized (pendingFrames) {
        while (pendingFrames.isEmpty()) {
          pendingFrames.wait();
        }
        return new ArrayList<I420Frame>(pendingFrames);
      }
    }
  }

  static private class FakeCapturerObserver implements CameraVideoCapturer.CapturerObserver {
    private int framesCaptured = 0;
    private VideoFrame videoFrame;
    final private Object frameLock = new Object();
    final private Object capturerStartLock = new Object();
    private Boolean capturerStartResult;
    final private List<Long> timestamps = new ArrayList<Long>();

    @Override
    public void onCapturerStarted(boolean success) {
      Logging.d(TAG, "onCapturerStarted: " + success);

      synchronized (capturerStartLock) {
        capturerStartResult = success;
        capturerStartLock.notifyAll();
      }
    }

    @Override
    public void onCapturerStopped() {
      Logging.d(TAG, "onCapturerStopped");
    }

    @Override
    public void onByteBufferFrameCaptured(
        byte[] frame, int width, int height, int rotation, long timeStamp) {
      throw new RuntimeException("onByteBufferFrameCaptured called");
    }

    @Override
    public void onTextureFrameCaptured(int width, int height, int oesTextureId,
        float[] transformMatrix, int rotation, long timeStamp) {
      throw new RuntimeException("onTextureFrameCaptured called");
    }

    @Override
    public void onFrameCaptured(VideoFrame frame) {
      synchronized (frameLock) {
        ++framesCaptured;
        if (videoFrame != null) {
          videoFrame.release();
        }
        videoFrame = frame;
        videoFrame.retain();
        timestamps.add(videoFrame.getTimestampNs());
        frameLock.notify();
      }
    }

    public boolean waitForCapturerToStart() throws InterruptedException {
      Logging.d(TAG, "Waiting for the capturer to start");
      synchronized (capturerStartLock) {
        while (capturerStartResult == null) {
          capturerStartLock.wait();
        }
        return capturerStartResult;
      }
    }

    public int waitForNextCapturedFrame() throws InterruptedException {
      Logging.d(TAG, "Waiting for the next captured frame");
      synchronized (frameLock) {
        final int framesCapturedStart = framesCaptured;
        while (framesCaptured == framesCapturedStart) {
          frameLock.wait();
        }
        return framesCaptured;
      }
    }

    int frameWidth() {
      synchronized (frameLock) {
        return videoFrame.getBuffer().getWidth();
      }
    }

    int frameHeight() {
      synchronized (frameLock) {
        return videoFrame.getBuffer().getHeight();
      }
    }

    void releaseFrame() {
      synchronized (frameLock) {
        if (videoFrame != null) {
          videoFrame.release();
          videoFrame = null;
        }
      }
    }

    List<Long> getCopyAndResetListOftimeStamps() {
      synchronized (frameLock) {
        ArrayList<Long> list = new ArrayList<Long>(timestamps);
        timestamps.clear();
        return list;
      }
    }
  }

  static class CameraEvents implements CameraVideoCapturer.CameraEventsHandler {
    public boolean onCameraOpeningCalled;
    public boolean onFirstFrameAvailableCalled;
    private final Object onCameraFreezedLock = new Object();
    private String onCameraFreezedDescription;
    private final Object cameraClosedLock = new Object();
    private boolean cameraClosed = true;

    @Override
    public void onCameraError(String errorDescription) {
      Logging.w(TAG, "Camera error: " + errorDescription);
      cameraClosed = true;
    }

    @Override
    public void onCameraDisconnected() {}

    @Override
    public void onCameraFreezed(String errorDescription) {
      synchronized (onCameraFreezedLock) {
        onCameraFreezedDescription = errorDescription;
        onCameraFreezedLock.notifyAll();
      }
    }

    @Override
    public void onCameraOpening(String cameraName) {
      onCameraOpeningCalled = true;
      synchronized (cameraClosedLock) {
        cameraClosed = false;
      }
    }

    @Override
    public void onFirstFrameAvailable() {
      onFirstFrameAvailableCalled = true;
    }

    @Override
    public void onCameraClosed() {
      synchronized (cameraClosedLock) {
        cameraClosed = true;
        cameraClosedLock.notifyAll();
      }
    }

    public String waitForCameraFreezed() throws InterruptedException {
      Logging.d(TAG, "Waiting for the camera to freeze");
      synchronized (onCameraFreezedLock) {
        while (onCameraFreezedDescription == null) {
          onCameraFreezedLock.wait();
        }
        return onCameraFreezedDescription;
      }
    }

    public void waitForCameraClosed() throws InterruptedException {
      synchronized (cameraClosedLock) {
        while (!cameraClosed) {
          Logging.d(TAG, "Waiting for the camera to close.");
          cameraClosedLock.wait();
        }
      }
    }
  }

  /**
   * Class to collect all classes related to single capturer instance.
   */
  static private class CapturerInstance {
    public CameraVideoCapturer capturer;
    public CameraEvents cameraEvents;
    public SurfaceTextureHelper surfaceTextureHelper;
    public FakeCapturerObserver observer;
    public List<CaptureFormat> supportedFormats;
    public CaptureFormat format;
  }

  /**
   * Class used for collecting a VideoSource, a VideoTrack and a renderer. The class
   * is used for testing local rendering from a capturer.
   */
  static private class VideoTrackWithRenderer {
    public VideoSource source;
    public VideoTrack track;
    public RendererCallbacks rendererCallbacks;
    public FakeAsyncRenderer fakeAsyncRenderer;
  }

  public abstract static class TestObjectFactory {
    final CameraEnumerator cameraEnumerator;

    TestObjectFactory() {
      cameraEnumerator = getCameraEnumerator();
    }

    public CameraVideoCapturer createCapturer(
        String name, CameraVideoCapturer.CameraEventsHandler eventsHandler) {
      return cameraEnumerator.createCapturer(name, eventsHandler);
    }

    public String getNameOfFrontFacingDevice() {
      for (String deviceName : cameraEnumerator.getDeviceNames()) {
        if (cameraEnumerator.isFrontFacing(deviceName)) {
          return deviceName;
        }
      }

      return null;
    }

    public String getNameOfBackFacingDevice() {
      for (String deviceName : cameraEnumerator.getDeviceNames()) {
        if (cameraEnumerator.isBackFacing(deviceName)) {
          return deviceName;
        }
      }

      return null;
    }

    public boolean haveTwoCameras() {
      return cameraEnumerator.getDeviceNames().length >= 2;
    }

    public boolean isCapturingToTexture() {
      // In the future, we plan to only support capturing to texture, so default to true
      return true;
    }

    abstract public CameraEnumerator getCameraEnumerator();
    abstract public Context getAppContext();

    // CameraVideoCapturer API is too slow for some of our tests where we need to open a competing
    // camera. These methods are used instead.
    abstract public Object rawOpenCamera(String cameraName);
    abstract public void rawCloseCamera(Object camera);
  }

  private PeerConnectionFactory peerConnectionFactory;
  private TestObjectFactory testObjectFactory;

  CameraVideoCapturerTestFixtures(TestObjectFactory testObjectFactory) {
    PeerConnectionFactory.initialize(
        PeerConnectionFactory.InitializationOptions.builder(testObjectFactory.getAppContext())
            .setFieldTrials(PeerConnectionFactory.VIDEO_FRAME_EMIT_TRIAL + "/"
                + PeerConnectionFactory.TRIAL_ENABLED + "/")
            .createInitializationOptions());

    this.peerConnectionFactory = new PeerConnectionFactory(null /* options */);
    this.testObjectFactory = testObjectFactory;
  }

  public void dispose() {
    this.peerConnectionFactory.dispose();
  }

  // Internal helper methods
  private CapturerInstance createCapturer(String name, boolean initialize) {
    CapturerInstance instance = new CapturerInstance();
    instance.cameraEvents = new CameraEvents();
    instance.capturer = testObjectFactory.createCapturer(name, instance.cameraEvents);
    instance.surfaceTextureHelper = SurfaceTextureHelper.create(
        "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */);
    instance.observer = new FakeCapturerObserver();
    if (initialize) {
      instance.capturer.initialize(
          instance.surfaceTextureHelper, testObjectFactory.getAppContext(), instance.observer);
    }
    instance.supportedFormats = testObjectFactory.cameraEnumerator.getSupportedFormats(name);
    return instance;
  }

  private CapturerInstance createCapturer(boolean initialize) {
    String name = testObjectFactory.cameraEnumerator.getDeviceNames()[0];
    return createCapturer(name, initialize);
  }

  private void startCapture(CapturerInstance instance) {
    startCapture(instance, 0);
  }

  private void startCapture(CapturerInstance instance, int formatIndex) {
    final CameraEnumerationAndroid.CaptureFormat format =
        instance.supportedFormats.get(formatIndex);

    instance.capturer.startCapture(format.width, format.height, format.framerate.max);
    instance.format = format;
  }

  private void disposeCapturer(CapturerInstance instance) throws InterruptedException {
    instance.capturer.stopCapture();
    instance.cameraEvents.waitForCameraClosed();
    instance.capturer.dispose();
    instance.observer.releaseFrame();
    instance.surfaceTextureHelper.dispose();
  }

  private VideoTrackWithRenderer createVideoTrackWithRenderer(
      CameraVideoCapturer capturer, VideoRenderer.Callbacks rendererCallbacks) {
    VideoTrackWithRenderer videoTrackWithRenderer = new VideoTrackWithRenderer();
    videoTrackWithRenderer.source = peerConnectionFactory.createVideoSource(capturer);
    capturer.startCapture(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FPS);
    videoTrackWithRenderer.track =
        peerConnectionFactory.createVideoTrack("dummy", videoTrackWithRenderer.source);
    videoTrackWithRenderer.track.addRenderer(new VideoRenderer(rendererCallbacks));
    return videoTrackWithRenderer;
  }

  private VideoTrackWithRenderer createVideoTrackWithRenderer(CameraVideoCapturer capturer) {
    RendererCallbacks rendererCallbacks = new RendererCallbacks();
    VideoTrackWithRenderer videoTrackWithRenderer =
        createVideoTrackWithRenderer(capturer, rendererCallbacks);
    videoTrackWithRenderer.rendererCallbacks = rendererCallbacks;
    return videoTrackWithRenderer;
  }

  private VideoTrackWithRenderer createVideoTrackWithFakeAsyncRenderer(
      CameraVideoCapturer capturer) {
    FakeAsyncRenderer fakeAsyncRenderer = new FakeAsyncRenderer();
    VideoTrackWithRenderer videoTrackWithRenderer =
        createVideoTrackWithRenderer(capturer, fakeAsyncRenderer);
    videoTrackWithRenderer.fakeAsyncRenderer = fakeAsyncRenderer;
    return videoTrackWithRenderer;
  }

  private void disposeVideoTrackWithRenderer(VideoTrackWithRenderer videoTrackWithRenderer) {
    videoTrackWithRenderer.track.dispose();
    videoTrackWithRenderer.source.dispose();
  }

  private void waitUntilIdle(CapturerInstance capturerInstance) throws InterruptedException {
    final CountDownLatch barrier = new CountDownLatch(1);
    capturerInstance.surfaceTextureHelper.getHandler().post(new Runnable() {
      @Override
      public void run() {
        barrier.countDown();
      }
    });
    barrier.await();
  }

  private void createCapturerAndRender(String name) throws InterruptedException {
    if (name == null) {
      Logging.w(TAG, "Skipping video capturer test because device name is null.");
      return;
    }

    final CapturerInstance capturerInstance = createCapturer(name, false /* initialize */);
    final VideoTrackWithRenderer videoTrackWithRenderer =
        createVideoTrackWithRenderer(capturerInstance.capturer);
    assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);
    disposeCapturer(capturerInstance);
    disposeVideoTrackWithRenderer(videoTrackWithRenderer);
  }

  // Test methods
  public void createCapturerAndDispose() throws InterruptedException {
    disposeCapturer(createCapturer(true /* initialize */));
  }

  public void createNonExistingCamera() throws InterruptedException {
    try {
      disposeCapturer(createCapturer("non-existing camera", false /* initialize */));
    } catch (IllegalArgumentException e) {
      return;
    }

    fail("Expected illegal argument exception when creating non-existing camera.");
  }

  public void createCapturerAndRender() throws InterruptedException {
    String name = testObjectFactory.cameraEnumerator.getDeviceNames()[0];
    createCapturerAndRender(name);
  }

  public void createFrontFacingCapturerAndRender() throws InterruptedException {
    createCapturerAndRender(testObjectFactory.getNameOfFrontFacingDevice());
  }

  public void createBackFacingCapturerAndRender() throws InterruptedException {
    createCapturerAndRender(testObjectFactory.getNameOfBackFacingDevice());
  }

  public void switchCamera() throws InterruptedException {
    if (!testObjectFactory.haveTwoCameras()) {
      Logging.w(
          TAG, "Skipping test switch video capturer because the device doesn't have two cameras.");
      return;
    }

    final CapturerInstance capturerInstance = createCapturer(false /* initialize */);
    final VideoTrackWithRenderer videoTrackWithRenderer =
        createVideoTrackWithRenderer(capturerInstance.capturer);
    // Wait for the camera to start so we can switch it
    assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);

    // Array with one element to avoid final problem in nested classes.
    final boolean[] cameraSwitchSuccessful = new boolean[1];
    final CountDownLatch barrier = new CountDownLatch(1);
    capturerInstance.capturer.switchCamera(new CameraVideoCapturer.CameraSwitchHandler() {
      @Override
      public void onCameraSwitchDone(boolean isFrontCamera) {
        cameraSwitchSuccessful[0] = true;
        barrier.countDown();
      }
      @Override
      public void onCameraSwitchError(String errorDescription) {
        cameraSwitchSuccessful[0] = false;
        barrier.countDown();
      }
    });
    // Wait until the camera has been switched.
    barrier.await();

    // Check result.
    assertTrue(cameraSwitchSuccessful[0]);
    // Ensure that frames are received.
    assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);
    disposeCapturer(capturerInstance);
    disposeVideoTrackWithRenderer(videoTrackWithRenderer);
  }

  @TargetApi(21)
  private static void prepareMediaRecorderForTests(
      MediaRecorder mediaRecorder, File outputFile, boolean useSurfaceCapture) throws IOException {
    mediaRecorder.setVideoSource(
        useSurfaceCapture ? MediaRecorder.VideoSource.SURFACE : MediaRecorder.VideoSource.CAMERA);
    CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
    profile.videoCodec = MediaRecorder.VideoEncoder.H264;
    profile.videoBitRate = 2500000;
    profile.videoFrameWidth = 640;
    profile.videoFrameHeight = 480;
    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mediaRecorder.setVideoFrameRate(profile.videoFrameRate);
    mediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
    mediaRecorder.setVideoEncodingBitRate(profile.videoBitRate);
    mediaRecorder.setVideoEncoder(profile.videoCodec);
    mediaRecorder.setOutputFile(outputFile.getPath());
    mediaRecorder.prepare();
  }

  @TargetApi(21)
  public void updateMediaRecorder(boolean useSurfaceCapture)
      throws InterruptedException, IOException {
    final CapturerInstance capturerInstance = createCapturer(false /* initialize */);
    final VideoTrackWithRenderer videoTrackWithRenderer =
        createVideoTrackWithRenderer(capturerInstance.capturer);
    // Wait for the camera to start so we can add and remove MediaRecorder.
    assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);

    final String videoOutPath = Environment.getExternalStorageDirectory().getPath()
        + "/chromium_tests_root/testmediarecorder.mp4";
    File outputFile = new File(videoOutPath);

    // Create MediaRecorder object
    MediaRecorder mediaRecorder = new MediaRecorder();
    if (useSurfaceCapture) {
      // When using using surface capture, media recorder has to be prepared before adding it to the
      // camera.
      prepareMediaRecorderForTests(mediaRecorder, outputFile, useSurfaceCapture);
    }

    // Add MediaRecorder to camera pipeline.
    final boolean[] addMediaRecorderSuccessful = new boolean[1];
    final CountDownLatch addBarrier = new CountDownLatch(1);
    CameraVideoCapturer.MediaRecorderHandler addMediaRecorderHandler =
        new CameraVideoCapturer.MediaRecorderHandler() {
          @Override
          public void onMediaRecorderSuccess() {
            addMediaRecorderSuccessful[0] = true;
            addBarrier.countDown();
          }
          @Override
          public void onMediaRecorderError(String errorDescription) {
            Logging.e(TAG, errorDescription);
            addMediaRecorderSuccessful[0] = false;
            addBarrier.countDown();
          }
        };
    capturerInstance.capturer.addMediaRecorderToCamera(mediaRecorder, addMediaRecorderHandler);
    // Wait until MediaRecoder has been added.
    addBarrier.await();
    // Check result.
    assertTrue(addMediaRecorderSuccessful[0]);

    // Start MediaRecorder and wait for a few frames to capture.
    if (!useSurfaceCapture) {
      // When using using camera capture, media recorder has to be prepared after adding it to the
      // camera.
      prepareMediaRecorderForTests(mediaRecorder, outputFile, useSurfaceCapture);
    }
    mediaRecorder.start();
    for (int i = 0; i < 5; i++) {
      assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);
    }
    mediaRecorder.stop();

    // Remove MediaRecorder from camera pipeline.
    final boolean[] removeMediaRecorderSuccessful = new boolean[1];
    final CountDownLatch removeBarrier = new CountDownLatch(1);
    CameraVideoCapturer.MediaRecorderHandler removeMediaRecorderHandler =
        new CameraVideoCapturer.MediaRecorderHandler() {
          @Override
          public void onMediaRecorderSuccess() {
            removeMediaRecorderSuccessful[0] = true;
            removeBarrier.countDown();
          }
          @Override
          public void onMediaRecorderError(String errorDescription) {
            removeMediaRecorderSuccessful[0] = false;
            removeBarrier.countDown();
          }
        };
    capturerInstance.capturer.removeMediaRecorderFromCamera(removeMediaRecorderHandler);
    // Wait until MediaRecoder has been removed.
    removeBarrier.await();
    // Check result.
    assertTrue(removeMediaRecorderSuccessful[0]);
    // Ensure that frames are received after removing MediaRecorder.
    assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);
    // Check that recorded file contains some data.
    assertTrue(outputFile.length() > 0);

    disposeCapturer(capturerInstance);
    disposeVideoTrackWithRenderer(videoTrackWithRenderer);
  }

  public void cameraEventsInvoked() throws InterruptedException {
    final CapturerInstance capturerInstance = createCapturer(true /* initialize */);
    startCapture(capturerInstance);
    // Make sure camera is started and first frame is received and then stop it.
    assertTrue(capturerInstance.observer.waitForCapturerToStart());
    capturerInstance.observer.waitForNextCapturedFrame();
    disposeCapturer(capturerInstance);

    assertTrue(capturerInstance.cameraEvents.onCameraOpeningCalled);
    assertTrue(capturerInstance.cameraEvents.onFirstFrameAvailableCalled);
  }

  public void cameraCallsAfterStop() throws InterruptedException {
    final CapturerInstance capturerInstance = createCapturer(true /* initialize */);
    startCapture(capturerInstance);
    // Make sure camera is started and then stop it.
    assertTrue(capturerInstance.observer.waitForCapturerToStart());
    capturerInstance.capturer.stopCapture();
    capturerInstance.observer.releaseFrame();

    // We can't change |capturer| at this point, but we should not crash.
    capturerInstance.capturer.switchCamera(null /* switchEventsHandler */);
    capturerInstance.capturer.changeCaptureFormat(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FPS);

    disposeCapturer(capturerInstance);
  }

  public void stopRestartVideoSource() throws InterruptedException {
    final CapturerInstance capturerInstance = createCapturer(false /* initialize */);
    final VideoTrackWithRenderer videoTrackWithRenderer =
        createVideoTrackWithRenderer(capturerInstance.capturer);

    assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);
    assertEquals(MediaSource.State.LIVE, videoTrackWithRenderer.source.state());

    capturerInstance.capturer.stopCapture();
    assertEquals(MediaSource.State.ENDED, videoTrackWithRenderer.source.state());

    startCapture(capturerInstance);
    assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);
    assertEquals(MediaSource.State.LIVE, videoTrackWithRenderer.source.state());

    disposeCapturer(capturerInstance);
    disposeVideoTrackWithRenderer(videoTrackWithRenderer);
  }

  public void startStopWithDifferentResolutions() throws InterruptedException {
    final CapturerInstance capturerInstance = createCapturer(true /* initialize */);

    for (int i = 0; i < 3; ++i) {
      startCapture(capturerInstance, i);
      assertTrue(capturerInstance.observer.waitForCapturerToStart());
      capturerInstance.observer.waitForNextCapturedFrame();

      // Check the frame size. The actual width and height depend on how the capturer is mounted.
      final boolean identicalResolution =
          (capturerInstance.observer.frameWidth() == capturerInstance.format.width
              && capturerInstance.observer.frameHeight() == capturerInstance.format.height);
      final boolean flippedResolution =
          (capturerInstance.observer.frameWidth() == capturerInstance.format.height
              && capturerInstance.observer.frameHeight() == capturerInstance.format.width);
      if (!identicalResolution && !flippedResolution) {
        fail("Wrong resolution, got: " + capturerInstance.observer.frameWidth() + "x"
            + capturerInstance.observer.frameHeight() + " expected: "
            + capturerInstance.format.width + "x" + capturerInstance.format.height + " or "
            + capturerInstance.format.height + "x" + capturerInstance.format.width);
      }

      capturerInstance.capturer.stopCapture();
      capturerInstance.observer.releaseFrame();
    }
    disposeCapturer(capturerInstance);
  }

  public void returnBufferLate() throws InterruptedException {
    final CapturerInstance capturerInstance = createCapturer(true /* initialize */);
    startCapture(capturerInstance);
    assertTrue(capturerInstance.observer.waitForCapturerToStart());

    capturerInstance.observer.waitForNextCapturedFrame();
    capturerInstance.capturer.stopCapture();
    List<Long> listOftimestamps = capturerInstance.observer.getCopyAndResetListOftimeStamps();
    assertTrue(listOftimestamps.size() >= 1);

    startCapture(capturerInstance, 1);
    capturerInstance.observer.waitForCapturerToStart();
    capturerInstance.observer.releaseFrame();

    capturerInstance.observer.waitForNextCapturedFrame();
    capturerInstance.capturer.stopCapture();

    listOftimestamps = capturerInstance.observer.getCopyAndResetListOftimeStamps();
    assertTrue(listOftimestamps.size() >= 1);

    disposeCapturer(capturerInstance);
  }

  public void returnBufferLateEndToEnd() throws InterruptedException {
    final CapturerInstance capturerInstance = createCapturer(false /* initialize */);
    final VideoTrackWithRenderer videoTrackWithRenderer =
        createVideoTrackWithFakeAsyncRenderer(capturerInstance.capturer);
    // Wait for at least one frame that has not been returned.
    assertFalse(videoTrackWithRenderer.fakeAsyncRenderer.waitForPendingFrames().isEmpty());

    capturerInstance.capturer.stopCapture();

    // Dispose everything.
    disposeCapturer(capturerInstance);
    disposeVideoTrackWithRenderer(videoTrackWithRenderer);

    // Return the frame(s), on a different thread out of spite.
    final List<I420Frame> pendingFrames =
        videoTrackWithRenderer.fakeAsyncRenderer.waitForPendingFrames();
    final Thread returnThread = new Thread(new Runnable() {
      @Override
      public void run() {
        for (I420Frame frame : pendingFrames) {
          VideoRenderer.renderFrameDone(frame);
        }
      }
    });
    returnThread.start();
    returnThread.join();
  }

  public void cameraFreezedEventOnBufferStarvation() throws InterruptedException {
    final CapturerInstance capturerInstance = createCapturer(true /* initialize */);
    startCapture(capturerInstance);
    // Make sure camera is started.
    assertTrue(capturerInstance.observer.waitForCapturerToStart());
    // Since we don't return the buffer, we should get a starvation message if we are
    // capturing to a texture.
    assertEquals("Camera failure. Client must return video buffers.",
        capturerInstance.cameraEvents.waitForCameraFreezed());

    capturerInstance.capturer.stopCapture();
    disposeCapturer(capturerInstance);
  }

  public void scaleCameraOutput() throws InterruptedException {
    final CapturerInstance capturerInstance = createCapturer(false /* initialize */);
    final VideoTrackWithRenderer videoTrackWithRenderer =
        createVideoTrackWithRenderer(capturerInstance.capturer);
    assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0);

    final int startWidth = videoTrackWithRenderer.rendererCallbacks.frameWidth();
    final int startHeight = videoTrackWithRenderer.rendererCallbacks.frameHeight();
    final int frameRate = 30;
    final int scaledWidth = startWidth / 2;
    final int scaledHeight = startHeight / 2;

    // Request the captured frames to be scaled.
    videoTrackWithRenderer.source.adaptOutputFormat(scaledWidth, scaledHeight, frameRate);

    boolean gotExpectedResolution = false;
    int numberOfInspectedFrames = 0;

    do {
      videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender();
      ++numberOfInspectedFrames;

      gotExpectedResolution = (videoTrackWithRenderer.rendererCallbacks.frameWidth() == scaledWidth
          && videoTrackWithRenderer.rendererCallbacks.frameHeight() == scaledHeight);
    } while (!gotExpectedResolution && numberOfInspectedFrames < 30);

    disposeCapturer(capturerInstance);
    disposeVideoTrackWithRenderer(videoTrackWithRenderer);

    assertTrue(gotExpectedResolution);
  }

  public void startWhileCameraIsAlreadyOpen() throws InterruptedException {
    final String cameraName = testObjectFactory.getNameOfBackFacingDevice();
    // At this point camera is not actually opened.
    final CapturerInstance capturerInstance = createCapturer(cameraName, true /* initialize */);

    final Object competingCamera = testObjectFactory.rawOpenCamera(cameraName);

    startCapture(capturerInstance);

    if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
      // The first opened camera client will be evicted.
      assertTrue(capturerInstance.observer.waitForCapturerToStart());
    } else {
      assertFalse(capturerInstance.observer.waitForCapturerToStart());
    }

    testObjectFactory.rawCloseCamera(competingCamera);
    disposeCapturer(capturerInstance);
  }

  public void startWhileCameraIsAlreadyOpenAndCloseCamera() throws InterruptedException {
    final String cameraName = testObjectFactory.getNameOfBackFacingDevice();
    // At this point camera is not actually opened.
    final CapturerInstance capturerInstance = createCapturer(cameraName, false /* initialize */);

    Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Opening competing camera.");
    final Object competingCamera = testObjectFactory.rawOpenCamera(cameraName);

    Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Opening camera.");
    final VideoTrackWithRenderer videoTrackWithRenderer =
        createVideoTrackWithRenderer(capturerInstance.capturer);
    waitUntilIdle(capturerInstance);

    Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Closing competing camera.");
    testObjectFactory.rawCloseCamera(competingCamera);

    // Make sure camera is started and first frame is received and then stop it.
    Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Waiting for capture to start.");
    videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender();
    Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Stopping capture.");
    disposeCapturer(capturerInstance);
  }

  public void startWhileCameraIsAlreadyOpenAndStop() throws InterruptedException {
    final String cameraName = testObjectFactory.getNameOfBackFacingDevice();
    // At this point camera is not actually opened.
    final CapturerInstance capturerInstance = createCapturer(cameraName, true /* initialize */);

    final Object competingCamera = testObjectFactory.rawOpenCamera(cameraName);

    startCapture(capturerInstance);
    disposeCapturer(capturerInstance);

    testObjectFactory.rawCloseCamera(competingCamera);
  }
}
