/*
 *  Copyright (c) 2012 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 <memory>

#include "webrtc/api/video/i420_buffer.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/video_coding/codecs/test/mock/mock_packet_manipulator.h"
#include "webrtc/modules/video_coding/codecs/test/videoprocessor.h"
#include "webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h"
#include "webrtc/modules/video_coding/include/video_coding.h"
#include "webrtc/rtc_base/ptr_util.h"
#include "webrtc/test/gmock.h"
#include "webrtc/test/gtest.h"
#include "webrtc/test/testsupport/mock/mock_frame_reader.h"
#include "webrtc/test/testsupport/mock/mock_frame_writer.h"
#include "webrtc/test/testsupport/packet_reader.h"
#include "webrtc/test/testsupport/unittest_utils.h"
#include "webrtc/test/video_codec_settings.h"
#include "webrtc/typedefs.h"

using ::testing::_;
using ::testing::AtLeast;
using ::testing::ElementsAre;
using ::testing::Property;
using ::testing::Return;

namespace webrtc {
namespace test {

namespace {

const int kWidth = 352;
const int kHeight = 288;
const int kFrameSize = kWidth * kHeight * 3 / 2;  // I420.
const int kNumFrames = 2;

}  // namespace

class VideoProcessorTest : public testing::Test {
 protected:
  VideoProcessorTest() {
    // Get a codec configuration struct and configure it.
    webrtc::test::CodecSettings(kVideoCodecVP8, &config_.codec_settings);
    config_.codec_settings.width = kWidth;
    config_.codec_settings.height = kHeight;

    EXPECT_CALL(frame_reader_mock_, NumberOfFrames())
        .WillRepeatedly(Return(kNumFrames));
    EXPECT_CALL(frame_reader_mock_, FrameLength())
        .WillRepeatedly(Return(kFrameSize));
    video_processor_ = rtc::MakeUnique<VideoProcessor>(
        &encoder_mock_, &decoder_mock_, &frame_reader_mock_,
        &frame_writer_mock_, &packet_manipulator_mock_, config_, &stats_,
        nullptr /* encoded_frame_writer */, nullptr /* decoded_frame_writer */);
  }

  void ExpectInit() {
    EXPECT_CALL(encoder_mock_, InitEncode(_, _, _)).Times(1);
    EXPECT_CALL(encoder_mock_, RegisterEncodeCompleteCallback(_)).Times(1);
    EXPECT_CALL(decoder_mock_, InitDecode(_, _)).Times(1);
    EXPECT_CALL(decoder_mock_, RegisterDecodeCompleteCallback(_)).Times(1);
  }

  void ExpectRelease() {
    EXPECT_CALL(encoder_mock_, Release()).Times(1);
    EXPECT_CALL(encoder_mock_, RegisterEncodeCompleteCallback(_)).Times(1);
    EXPECT_CALL(decoder_mock_, Release()).Times(1);
    EXPECT_CALL(decoder_mock_, RegisterDecodeCompleteCallback(_)).Times(1);
  }

  TestConfig config_;

  MockVideoEncoder encoder_mock_;
  MockVideoDecoder decoder_mock_;
  MockFrameReader frame_reader_mock_;
  MockFrameWriter frame_writer_mock_;
  MockPacketManipulator packet_manipulator_mock_;
  Stats stats_;
  std::unique_ptr<VideoProcessor> video_processor_;
};

TEST_F(VideoProcessorTest, InitRelease) {
  ExpectInit();
  video_processor_->Init();

  ExpectRelease();
  video_processor_->Release();
}

TEST_F(VideoProcessorTest, ProcessFrames_FixedFramerate) {
  ExpectInit();
  video_processor_->Init();

  const int kBitrateKbps = 456;
  const int kFramerateFps = 31;
  video_processor_->SetRates(kBitrateKbps, kFramerateFps);

  EXPECT_CALL(frame_reader_mock_, ReadFrame())
      .WillRepeatedly(Return(I420Buffer::Create(kWidth, kHeight)));
  EXPECT_CALL(
      encoder_mock_,
      Encode(Property(&VideoFrame::timestamp, 1 * 90000 / kFramerateFps), _, _))
      .Times(1);
  video_processor_->ProcessFrame();

  EXPECT_CALL(
      encoder_mock_,
      Encode(Property(&VideoFrame::timestamp, 2 * 90000 / kFramerateFps), _, _))
      .Times(1);
  video_processor_->ProcessFrame();

  ExpectRelease();
  video_processor_->Release();
}

TEST_F(VideoProcessorTest, ProcessFrames_VariableFramerate) {
  ExpectInit();
  video_processor_->Init();

  const int kBitrateKbps = 456;
  const int kStartFramerateFps = 27;
  video_processor_->SetRates(kBitrateKbps, kStartFramerateFps);

  EXPECT_CALL(frame_reader_mock_, ReadFrame())
      .WillRepeatedly(Return(I420Buffer::Create(kWidth, kHeight)));
  EXPECT_CALL(encoder_mock_, Encode(Property(&VideoFrame::timestamp,
                                             1 * 90000 / kStartFramerateFps),
                                    _, _))
      .Times(1);
  video_processor_->ProcessFrame();

  const int kNewFramerateFps = 13;
  video_processor_->SetRates(kBitrateKbps, kNewFramerateFps);

  EXPECT_CALL(encoder_mock_, Encode(Property(&VideoFrame::timestamp,
                                             2 * 90000 / kNewFramerateFps),
                                    _, _))
      .Times(1);
  video_processor_->ProcessFrame();

  ExpectRelease();
  video_processor_->Release();
}

TEST_F(VideoProcessorTest, SetRates) {
  ExpectInit();
  video_processor_->Init();

  const int kBitrateKbps = 123;
  const int kFramerateFps = 17;
  EXPECT_CALL(encoder_mock_,
              SetRateAllocation(
                  Property(&BitrateAllocation::get_sum_kbps, kBitrateKbps),
                  kFramerateFps))
      .Times(1);
  video_processor_->SetRates(kBitrateKbps, kFramerateFps);
  EXPECT_THAT(video_processor_->NumberDroppedFramesPerRateUpdate(),
              ElementsAre(0));
  EXPECT_THAT(video_processor_->NumberSpatialResizesPerRateUpdate(),
              ElementsAre(0));

  const int kNewBitrateKbps = 456;
  const int kNewFramerateFps = 34;
  EXPECT_CALL(encoder_mock_,
              SetRateAllocation(
                  Property(&BitrateAllocation::get_sum_kbps, kNewBitrateKbps),
                  kNewFramerateFps))
      .Times(1);
  video_processor_->SetRates(kNewBitrateKbps, kNewFramerateFps);
  EXPECT_THAT(video_processor_->NumberDroppedFramesPerRateUpdate(),
              ElementsAre(0, 0));
  EXPECT_THAT(video_processor_->NumberSpatialResizesPerRateUpdate(),
              ElementsAre(0, 0));

  ExpectRelease();
  video_processor_->Release();
}

}  // namespace test
}  // namespace webrtc
