/*
 *  Copyright 2013 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.support.annotation.Nullable;

/**
 * Java wrapper of native AndroidVideoTrackSource.
 */
public class VideoSource extends MediaSource {
  /** Simple aspect ratio clas for use in constraining output format. */
  public static class AspectRatio {
    public static final AspectRatio UNDEFINED = new AspectRatio(/* width= */ 0, /* height= */ 0);

    public final int width;
    public final int height;

    public AspectRatio(int width, int height) {
      this.width = width;
      this.height = height;
    }
  }

  private final NativeAndroidVideoTrackSource nativeAndroidVideoTrackSource;
  private final Object videoProcessorLock = new Object();
  @Nullable private VideoProcessor videoProcessor;
  private boolean isCapturerRunning;

  private final CapturerObserver capturerObserver = new CapturerObserver() {
    @Override
    public void onCapturerStarted(boolean success) {
      nativeAndroidVideoTrackSource.setState(success);
      synchronized (videoProcessorLock) {
        isCapturerRunning = success;
        if (videoProcessor != null) {
          videoProcessor.onCapturerStarted(success);
        }
      }
    }

    @Override
    public void onCapturerStopped() {
      nativeAndroidVideoTrackSource.setState(/* isLive= */ false);
      synchronized (videoProcessorLock) {
        isCapturerRunning = false;
        if (videoProcessor != null) {
          videoProcessor.onCapturerStopped();
        }
      }
    }

    @Override
    public void onFrameCaptured(VideoFrame frame) {
      final VideoProcessor.FrameAdaptationParameters parameters =
          nativeAndroidVideoTrackSource.adaptFrame(frame);
      synchronized (videoProcessorLock) {
        if (videoProcessor != null) {
          videoProcessor.onFrameCaptured(frame, parameters);
          return;
        }
      }

      VideoFrame adaptedFrame = VideoProcessor.applyFrameAdaptationParameters(frame, parameters);
      if (adaptedFrame != null) {
        nativeAndroidVideoTrackSource.onFrameCaptured(adaptedFrame);
        adaptedFrame.release();
      }
    }
  };

  public VideoSource(long nativeSource) {
    super(nativeSource);
    this.nativeAndroidVideoTrackSource = new NativeAndroidVideoTrackSource(nativeSource);
  }

  /**
   * Calling this function will cause frames to be scaled down to the requested resolution. Also,
   * frames will be cropped to match the requested aspect ratio, and frames will be dropped to match
   * the requested fps. The requested aspect ratio is orientation agnostic and will be adjusted to
   * maintain the input orientation, so it doesn't matter if e.g. 1280x720 or 720x1280 is requested.
   */
  public void adaptOutputFormat(int width, int height, int fps) {
    final int maxSide = Math.max(width, height);
    final int minSide = Math.min(width, height);
    adaptOutputFormat(maxSide, minSide, minSide, maxSide, fps);
  }

  /**
   * Same as above, but allows setting two different target resolutions depending on incoming
   * frame orientation. This gives more fine-grained control and can e.g. be used to force landscape
   * video to be cropped to portrait video.
   */
  public void adaptOutputFormat(
      int landscapeWidth, int landscapeHeight, int portraitWidth, int portraitHeight, int fps) {
    adaptOutputFormat(new AspectRatio(landscapeWidth, landscapeHeight),
        /* maxLandscapePixelCount= */ landscapeWidth * landscapeHeight,
        new AspectRatio(portraitWidth, portraitHeight),
        /* maxPortraitPixelCount= */ portraitWidth * portraitHeight, fps);
  }

  /** Same as above, with even more control as each constraint is optional. */
  public void adaptOutputFormat(AspectRatio targetLandscapeAspectRatio,
      @Nullable Integer maxLandscapePixelCount, AspectRatio targetPortraitAspectRatio,
      @Nullable Integer maxPortraitPixelCount, @Nullable Integer maxFps) {
    nativeAndroidVideoTrackSource.adaptOutputFormat(targetLandscapeAspectRatio,
        maxLandscapePixelCount, targetPortraitAspectRatio, maxPortraitPixelCount, maxFps);
  }

  /**
   * Hook for injecting a custom video processor before frames are passed onto WebRTC. The frames
   * will be cropped and scaled depending on CPU and network conditions before they are passed to
   * the video processor. Frames will be delivered to the video processor on the same thread they
   * are passed to this object. The video processor is allowed to deliver the processed frames
   * back on any thread.
   */
  public void setVideoProcessor(@Nullable VideoProcessor newVideoProcessor) {
    synchronized (videoProcessorLock) {
      if (videoProcessor != null) {
        videoProcessor.setSink(/* sink= */ null);
        if (isCapturerRunning) {
          videoProcessor.onCapturerStopped();
        }
      }
      videoProcessor = newVideoProcessor;
      if (newVideoProcessor != null) {
        newVideoProcessor.setSink(nativeAndroidVideoTrackSource::onFrameCaptured);
        if (isCapturerRunning) {
          newVideoProcessor.onCapturerStarted(/* success= */ true);
        }
      }
    }
  }

  public CapturerObserver getCapturerObserver() {
    return capturerObserver;
  }

  /** Returns a pointer to webrtc::VideoTrackSourceInterface. */
  long getNativeVideoTrackSource() {
    return getNativeMediaSource();
  }

  @Override
  public void dispose() {
    setVideoProcessor(/* newVideoProcessor= */ null);
    super.dispose();
  }
}
