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

#include <vector>

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/video_coding/codecs/interface/mock/mock_video_codec_interface.h"
#include "webrtc/modules/video_coding/main/interface/mock/mock_vcm_callbacks.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/modules/video_coding/main/source/video_coding_impl.h"
#include "webrtc/modules/video_coding/main/test/test_util.h"
#include "webrtc/system_wrappers/interface/clock.h"

using ::testing::_;
using ::testing::NiceMock;

namespace webrtc {
namespace vcm {
namespace {

class TestVideoReceiver : public ::testing::Test {
 protected:
  static const int kUnusedPayloadType = 10;

  TestVideoReceiver() : clock_(0) {}

  virtual void SetUp() {
    receiver_.reset(new VideoReceiver(&clock_, &event_factory_));
    EXPECT_EQ(0, receiver_->RegisterExternalDecoder(&decoder_,
                                                    kUnusedPayloadType, true));
    const size_t kMaxNackListSize = 250;
    const int kMaxPacketAgeToNack = 450;
    receiver_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);

    memset(&settings_, 0, sizeof(settings_));
    EXPECT_EQ(0, VideoCodingModule::Codec(kVideoCodecVP8, &settings_));
    settings_.plType = kUnusedPayloadType;  // Use the mocked encoder.
    EXPECT_EQ(0, receiver_->RegisterReceiveCodec(&settings_, 1, true));
  }

  void InsertAndVerifyPaddingFrame(const uint8_t* payload,
                                   WebRtcRTPHeader* header) {
    ASSERT_TRUE(header != NULL);
    for (int j = 0; j < 5; ++j) {
      // Padding only packets are passed to the VCM with payload size 0.
      EXPECT_EQ(0, receiver_->IncomingPacket(payload, 0, *header));
      ++header->header.sequenceNumber;
    }
    EXPECT_EQ(0, receiver_->Process());
    EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(0);
    EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_->Decode(0));
  }

  void InsertAndVerifyDecodableFrame(const uint8_t* payload,
                                     size_t length,
                                     WebRtcRTPHeader* header) {
    ASSERT_TRUE(header != NULL);
    EXPECT_EQ(0, receiver_->IncomingPacket(payload, length, *header));
    ++header->header.sequenceNumber;
    EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
    EXPECT_EQ(0, receiver_->Process());
    EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(1);
    EXPECT_EQ(0, receiver_->Decode(0));
  }

  SimulatedClock clock_;
  NullEventFactory event_factory_;
  VideoCodec settings_;
  NiceMock<MockVideoDecoder> decoder_;
  NiceMock<MockPacketRequestCallback> packet_request_callback_;

  rtc::scoped_ptr<VideoReceiver> receiver_;
};

TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
  EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
  EXPECT_EQ(
      0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
  const size_t kPaddingSize = 220;
  const uint8_t payload[kPaddingSize] = {0};
  WebRtcRTPHeader header;
  memset(&header, 0, sizeof(header));
  header.frameType = kFrameEmpty;
  header.header.markerBit = false;
  header.header.paddingLength = kPaddingSize;
  header.header.payloadType = kUnusedPayloadType;
  header.header.ssrc = 1;
  header.header.headerLength = 12;
  header.type.Video.codec = kRtpVideoVp8;
  for (int i = 0; i < 10; ++i) {
    EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
    InsertAndVerifyPaddingFrame(payload, &header);
    clock_.AdvanceTimeMilliseconds(33);
    header.header.timestamp += 3000;
  }
}

TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
  EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
  EXPECT_EQ(
      0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
  const size_t kFrameSize = 1200;
  const size_t kPaddingSize = 220;
  const uint8_t payload[kFrameSize] = {0};
  WebRtcRTPHeader header;
  memset(&header, 0, sizeof(header));
  header.frameType = kFrameEmpty;
  header.header.markerBit = false;
  header.header.paddingLength = kPaddingSize;
  header.header.payloadType = kUnusedPayloadType;
  header.header.ssrc = 1;
  header.header.headerLength = 12;
  header.type.Video.codec = kRtpVideoVp8;
  // Insert one video frame to get one frame decoded.
  header.frameType = kVideoFrameKey;
  header.type.Video.isFirstPacket = true;
  header.header.markerBit = true;
  InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
  clock_.AdvanceTimeMilliseconds(33);
  header.header.timestamp += 3000;

  header.frameType = kFrameEmpty;
  header.type.Video.isFirstPacket = false;
  header.header.markerBit = false;
  // Insert padding frames.
  for (int i = 0; i < 10; ++i) {
    // Lose one packet from the 6th frame.
    if (i == 5) {
      ++header.header.sequenceNumber;
    }
    // Lose the 4th frame.
    if (i == 3) {
      header.header.sequenceNumber += 5;
    } else {
      if (i > 3 && i < 5) {
        EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
      } else if (i >= 5) {
        EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
      } else {
        EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
      }
      InsertAndVerifyPaddingFrame(payload, &header);
    }
    clock_.AdvanceTimeMilliseconds(33);
    header.header.timestamp += 3000;
  }
}

TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
  EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
  EXPECT_EQ(
      0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
  const size_t kFrameSize = 1200;
  const size_t kPaddingSize = 220;
  const uint8_t payload[kFrameSize] = {0};
  WebRtcRTPHeader header;
  memset(&header, 0, sizeof(header));
  header.frameType = kFrameEmpty;
  header.type.Video.isFirstPacket = false;
  header.header.markerBit = false;
  header.header.paddingLength = kPaddingSize;
  header.header.payloadType = kUnusedPayloadType;
  header.header.ssrc = 1;
  header.header.headerLength = 12;
  header.type.Video.codec = kRtpVideoVp8;
  header.type.Video.codecHeader.VP8.pictureId = -1;
  header.type.Video.codecHeader.VP8.tl0PicIdx = -1;
  for (int i = 0; i < 3; ++i) {
    // Insert 2 video frames.
    for (int j = 0; j < 2; ++j) {
      if (i == 0 && j == 0)  // First frame should be a key frame.
        header.frameType = kVideoFrameKey;
      else
        header.frameType = kVideoFrameDelta;
      header.type.Video.isFirstPacket = true;
      header.header.markerBit = true;
      InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
      clock_.AdvanceTimeMilliseconds(33);
      header.header.timestamp += 3000;
    }

    // Insert 2 padding only frames.
    header.frameType = kFrameEmpty;
    header.type.Video.isFirstPacket = false;
    header.header.markerBit = false;
    for (int j = 0; j < 2; ++j) {
      // InsertAndVerifyPaddingFrame(payload, &header);
      clock_.AdvanceTimeMilliseconds(33);
      header.header.timestamp += 3000;
    }
  }
}

TEST_F(TestVideoReceiver, ReceiverDelay) {
  EXPECT_EQ(0, receiver_->SetMinReceiverDelay(0));
  EXPECT_EQ(0, receiver_->SetMinReceiverDelay(5000));
  EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(-100));
  EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(10010));
}

}  // namespace
}  // namespace vcm
}  // namespace webrtc
