/*
 *  Copyright (c) 2018 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.
 */

#include "rtc_tools/frame_analyzer/video_geometry_aligner.h"

#include <cstddef>
#include <cstdint>
#include <map>

#include "api/make_ref_counted.h"
#include "api/scoped_refptr.h"
#include "api/video/i420_buffer.h"
#include "api/video/video_frame_buffer.h"
#include "rtc_base/checks.h"
#include "rtc_tools/frame_analyzer/video_quality_analysis.h"
#include "rtc_tools/video_file_reader.h"
#include "third_party/libyuv/include/libyuv/scale.h"

namespace webrtc {
namespace test {

namespace {

bool IsValidRegion(const CropRegion& region,
                   const scoped_refptr<I420BufferInterface>& frame) {
  return region.left >= 0 && region.right >= 0 && region.top >= 0 &&
         region.bottom >= 0 && region.left + region.right < frame->width() &&
         region.top + region.bottom < frame->height();
}

}  // namespace

scoped_refptr<I420BufferInterface> CropAndZoom(
    const CropRegion& crop_region,
    const scoped_refptr<I420BufferInterface>& frame) {
  RTC_CHECK(IsValidRegion(crop_region, frame));

  const int uv_crop_left = crop_region.left / 2;
  const int uv_crop_top = crop_region.top / 2;

  const int cropped_width =
      frame->width() - crop_region.left - crop_region.right;
  const int cropped_height =
      frame->height() - crop_region.top - crop_region.bottom;

  // Crop by only adjusting pointers.
  const uint8_t* y_plane =
      frame->DataY() + frame->StrideY() * crop_region.top + crop_region.left;
  const uint8_t* u_plane =
      frame->DataU() + frame->StrideU() * uv_crop_top + uv_crop_left;
  const uint8_t* v_plane =
      frame->DataV() + frame->StrideV() * uv_crop_top + uv_crop_left;

  // Stretch the cropped frame to the original size using libyuv.
  scoped_refptr<I420Buffer> adjusted_frame =
      I420Buffer::Create(frame->width(), frame->height());
  libyuv::I420Scale(y_plane, frame->StrideY(), u_plane, frame->StrideU(),
                    v_plane, frame->StrideV(), cropped_width, cropped_height,
                    adjusted_frame->MutableDataY(), adjusted_frame->StrideY(),
                    adjusted_frame->MutableDataU(), adjusted_frame->StrideU(),
                    adjusted_frame->MutableDataV(), adjusted_frame->StrideV(),
                    frame->width(), frame->height(), libyuv::kFilterBox);

  return adjusted_frame;
}

CropRegion CalculateCropRegion(
    const scoped_refptr<I420BufferInterface>& reference_frame,
    const scoped_refptr<I420BufferInterface>& test_frame) {
  RTC_CHECK_EQ(reference_frame->width(), test_frame->width());
  RTC_CHECK_EQ(reference_frame->height(), test_frame->height());

  CropRegion best_region;
  double best_ssim = Ssim(reference_frame, test_frame);

  typedef int CropRegion::*CropParameter;
  CropParameter crop_parameters[4] = {&CropRegion::left, &CropRegion::top,
                                      &CropRegion::right, &CropRegion::bottom};

  while (true) {
    // Find the parameter in which direction SSIM improves the most.
    CropParameter best_parameter = nullptr;
    const CropRegion prev_best_region = best_region;

    for (CropParameter crop_parameter : crop_parameters) {
      CropRegion test_region = prev_best_region;
      ++(test_region.*crop_parameter);

      if (!IsValidRegion(test_region, reference_frame))
        continue;

      const double ssim =
          Ssim(CropAndZoom(test_region, reference_frame), test_frame);

      if (ssim > best_ssim) {
        best_ssim = ssim;
        best_parameter = crop_parameter;
        best_region = test_region;
      }
    }

    // No improvement among any direction, stop iteration.
    if (best_parameter == nullptr)
      break;

    // Iterate in the best direction as long as it improves SSIM.
    for (CropRegion test_region = best_region;
         IsValidRegion(test_region, reference_frame);
         ++(test_region.*best_parameter)) {
      const double ssim =
          Ssim(CropAndZoom(test_region, reference_frame), test_frame);
      if (ssim <= best_ssim)
        break;

      best_ssim = ssim;
      best_region = test_region;
    }
  }

  return best_region;
}

scoped_refptr<I420BufferInterface> AdjustCropping(
    const scoped_refptr<I420BufferInterface>& reference_frame,
    const scoped_refptr<I420BufferInterface>& test_frame) {
  return CropAndZoom(CalculateCropRegion(reference_frame, test_frame),
                     reference_frame);
}

scoped_refptr<Video> AdjustCropping(const scoped_refptr<Video>& reference_video,
                                    const scoped_refptr<Video>& test_video) {
  class CroppedVideo : public Video {
   public:
    CroppedVideo(const scoped_refptr<Video>& reference_video,
                 const scoped_refptr<Video>& test_video)
        : reference_video_(reference_video), test_video_(test_video) {
      RTC_CHECK_EQ(reference_video->number_of_frames(),
                   test_video->number_of_frames());
      RTC_CHECK_EQ(reference_video->width(), test_video->width());
      RTC_CHECK_EQ(reference_video->height(), test_video->height());
    }

    int width() const override { return test_video_->width(); }
    int height() const override { return test_video_->height(); }
    size_t number_of_frames() const override {
      return test_video_->number_of_frames();
    }

    scoped_refptr<I420BufferInterface> GetFrame(size_t index) const override {
      const scoped_refptr<I420BufferInterface> reference_frame =
          reference_video_->GetFrame(index);

      // Only calculate cropping region once per frame since it's expensive.
      if (!crop_regions_.count(index)) {
        crop_regions_[index] =
            CalculateCropRegion(reference_frame, test_video_->GetFrame(index));
      }

      return CropAndZoom(crop_regions_[index], reference_frame);
    }

   private:
    const scoped_refptr<Video> reference_video_;
    const scoped_refptr<Video> test_video_;
    // Mutable since this is a cache that affects performance and not logical
    // behavior.
    mutable std::map<size_t, CropRegion> crop_regions_;
  };

  return make_ref_counted<CroppedVideo>(reference_video, test_video);
}

}  // namespace test
}  // namespace webrtc
