/*
 *  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 "webrtc/common_types.h"
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
#include "webrtc/modules/video_coding/main/source/jitter_buffer.h"
#include "webrtc/modules/video_coding/main/source/packet.h"
#include "webrtc/modules/video_coding/main/source/video_coding_impl.h"
#include "webrtc/system_wrappers/interface/clock.h"

namespace webrtc {
namespace vcm {

int64_t
VCMProcessTimer::Period() const {
    return _periodMs;
}

int64_t
VCMProcessTimer::TimeUntilProcess() const {
    const int64_t time_since_process = _clock->TimeInMilliseconds() - _latestMs;
    const int64_t time_until_process = _periodMs - time_since_process;
    return std::max<int64_t>(time_until_process, 0);
}

void
VCMProcessTimer::Processed() {
    _latestMs = _clock->TimeInMilliseconds();
}
}  // namespace vcm

namespace {
// This wrapper provides a way to modify the callback without the need to expose
// a register method all the way down to the function calling it.
class EncodedImageCallbackWrapper : public EncodedImageCallback {
 public:
  EncodedImageCallbackWrapper()
      : cs_(CriticalSectionWrapper::CreateCriticalSection()), callback_(NULL) {}

  virtual ~EncodedImageCallbackWrapper() {}

  void Register(EncodedImageCallback* callback) {
    CriticalSectionScoped cs(cs_.get());
    callback_ = callback;
  }

  // TODO(andresp): Change to void as return value is ignored.
  virtual int32_t Encoded(const EncodedImage& encoded_image,
                          const CodecSpecificInfo* codec_specific_info,
                          const RTPFragmentationHeader* fragmentation) {
    CriticalSectionScoped cs(cs_.get());
    if (callback_)
      return callback_->Encoded(
          encoded_image, codec_specific_info, fragmentation);
    return 0;
  }

 private:
  rtc::scoped_ptr<CriticalSectionWrapper> cs_;
  EncodedImageCallback* callback_ GUARDED_BY(cs_);
};

class VideoCodingModuleImpl : public VideoCodingModule {
 public:
  VideoCodingModuleImpl(Clock* clock,
                        EventFactory* event_factory,
                        bool owns_event_factory,
                        VideoEncoderRateObserver* encoder_rate_observer,
                        VCMQMSettingsCallback* qm_settings_callback)
      : VideoCodingModule(),
        sender_(new vcm::VideoSender(clock,
                                     &post_encode_callback_,
                                     encoder_rate_observer,
                                     qm_settings_callback)),
        receiver_(new vcm::VideoReceiver(clock, event_factory)),
        own_event_factory_(owns_event_factory ? event_factory : NULL) {}

  virtual ~VideoCodingModuleImpl() {
    sender_.reset();
    receiver_.reset();
    own_event_factory_.reset();
  }

  int64_t TimeUntilNextProcess() override {
    int64_t sender_time = sender_->TimeUntilNextProcess();
    int64_t receiver_time = receiver_->TimeUntilNextProcess();
    assert(sender_time >= 0);
    assert(receiver_time >= 0);
    return VCM_MIN(sender_time, receiver_time);
  }

  int32_t Process() override {
    int32_t sender_return = sender_->Process();
    int32_t receiver_return = receiver_->Process();
    if (sender_return != VCM_OK)
      return sender_return;
    return receiver_return;
  }

  int32_t RegisterSendCodec(const VideoCodec* sendCodec,
                            uint32_t numberOfCores,
                            uint32_t maxPayloadSize) override {
    return sender_->RegisterSendCodec(sendCodec, numberOfCores, maxPayloadSize);
  }

  const VideoCodec& GetSendCodec() const override {
    return sender_->GetSendCodec();
  }

  // DEPRECATED.
  int32_t SendCodec(VideoCodec* currentSendCodec) const override {
    return sender_->SendCodecBlocking(currentSendCodec);
  }

  // DEPRECATED.
  VideoCodecType SendCodec() const override {
    return sender_->SendCodecBlocking();
  }

  int32_t RegisterExternalEncoder(VideoEncoder* externalEncoder,
                                  uint8_t payloadType,
                                  bool internalSource) override {
    return sender_->RegisterExternalEncoder(
        externalEncoder, payloadType, internalSource);
  }

  int32_t CodecConfigParameters(uint8_t* buffer, int32_t size) override {
    return sender_->CodecConfigParameters(buffer, size);
  }

  int Bitrate(unsigned int* bitrate) const override {
    return sender_->Bitrate(bitrate);
  }

  int FrameRate(unsigned int* framerate) const override {
    return sender_->FrameRate(framerate);
  }

  int32_t SetChannelParameters(uint32_t target_bitrate,  // bits/s.
                               uint8_t lossRate,
                               int64_t rtt) override {
    return sender_->SetChannelParameters(target_bitrate, lossRate, rtt);
  }

  int32_t RegisterTransportCallback(
      VCMPacketizationCallback* transport) override {
    return sender_->RegisterTransportCallback(transport);
  }

  int32_t RegisterSendStatisticsCallback(
      VCMSendStatisticsCallback* sendStats) override {
    return sender_->RegisterSendStatisticsCallback(sendStats);
  }

  int32_t RegisterProtectionCallback(
      VCMProtectionCallback* protection) override {
    return sender_->RegisterProtectionCallback(protection);
  }

  int32_t SetVideoProtection(VCMVideoProtection videoProtection,
                             bool enable) override {
    // TODO(pbos): Remove enable from receive-side protection modes as well.
    if (enable)
      sender_->SetVideoProtection(videoProtection);
    return receiver_->SetVideoProtection(videoProtection, enable);
  }

  int32_t AddVideoFrame(const VideoFrame& videoFrame,
                        const VideoContentMetrics* contentMetrics,
                        const CodecSpecificInfo* codecSpecificInfo) override {
    return sender_->AddVideoFrame(
        videoFrame, contentMetrics, codecSpecificInfo);
  }

  int32_t IntraFrameRequest(int stream_index) override {
    return sender_->IntraFrameRequest(stream_index);
  }

  int32_t EnableFrameDropper(bool enable) override {
    return sender_->EnableFrameDropper(enable);
  }

  void SuspendBelowMinBitrate() override {
    return sender_->SuspendBelowMinBitrate();
  }

  bool VideoSuspended() const override { return sender_->VideoSuspended(); }

  int32_t RegisterReceiveCodec(const VideoCodec* receiveCodec,
                               int32_t numberOfCores,
                               bool requireKeyFrame) override {
    return receiver_->RegisterReceiveCodec(
        receiveCodec, numberOfCores, requireKeyFrame);
  }

  int32_t RegisterExternalDecoder(VideoDecoder* externalDecoder,
                                  uint8_t payloadType,
                                  bool internalRenderTiming) override {
    return receiver_->RegisterExternalDecoder(
        externalDecoder, payloadType, internalRenderTiming);
  }

  int32_t RegisterReceiveCallback(
      VCMReceiveCallback* receiveCallback) override {
    return receiver_->RegisterReceiveCallback(receiveCallback);
  }

  int32_t RegisterReceiveStatisticsCallback(
      VCMReceiveStatisticsCallback* receiveStats) override {
    return receiver_->RegisterReceiveStatisticsCallback(receiveStats);
  }

  int32_t RegisterDecoderTimingCallback(
      VCMDecoderTimingCallback* decoderTiming) override {
    return receiver_->RegisterDecoderTimingCallback(decoderTiming);
  }

  int32_t RegisterFrameTypeCallback(
      VCMFrameTypeCallback* frameTypeCallback) override {
    return receiver_->RegisterFrameTypeCallback(frameTypeCallback);
  }

  int32_t RegisterPacketRequestCallback(
      VCMPacketRequestCallback* callback) override {
    return receiver_->RegisterPacketRequestCallback(callback);
  }

  int RegisterRenderBufferSizeCallback(
      VCMRenderBufferSizeCallback* callback) override {
    return receiver_->RegisterRenderBufferSizeCallback(callback);
  }

  int32_t Decode(uint16_t maxWaitTimeMs) override {
    return receiver_->Decode(maxWaitTimeMs);
  }

  int32_t ResetDecoder() override { return receiver_->ResetDecoder(); }

  int32_t ReceiveCodec(VideoCodec* currentReceiveCodec) const override {
    return receiver_->ReceiveCodec(currentReceiveCodec);
  }

  VideoCodecType ReceiveCodec() const override {
    return receiver_->ReceiveCodec();
  }

  int32_t IncomingPacket(const uint8_t* incomingPayload,
                         size_t payloadLength,
                         const WebRtcRTPHeader& rtpInfo) override {
    return receiver_->IncomingPacket(incomingPayload, payloadLength, rtpInfo);
  }

  int32_t SetMinimumPlayoutDelay(uint32_t minPlayoutDelayMs) override {
    return receiver_->SetMinimumPlayoutDelay(minPlayoutDelayMs);
  }

  int32_t SetRenderDelay(uint32_t timeMS) override {
    return receiver_->SetRenderDelay(timeMS);
  }

  int32_t Delay() const override { return receiver_->Delay(); }

  uint32_t DiscardedPackets() const override {
    return receiver_->DiscardedPackets();
  }

  int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode,
                                VCMDecodeErrorMode errorMode) override {
    return receiver_->SetReceiverRobustnessMode(robustnessMode, errorMode);
  }

  void SetNackSettings(size_t max_nack_list_size,
                       int max_packet_age_to_nack,
                       int max_incomplete_time_ms) override {
    return receiver_->SetNackSettings(
        max_nack_list_size, max_packet_age_to_nack, max_incomplete_time_ms);
  }

  void SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) override {
    return receiver_->SetDecodeErrorMode(decode_error_mode);
  }

  int SetMinReceiverDelay(int desired_delay_ms) override {
    return receiver_->SetMinReceiverDelay(desired_delay_ms);
  }

  int32_t SetReceiveChannelParameters(int64_t rtt) override {
    return receiver_->SetReceiveChannelParameters(rtt);
  }

  void RegisterPreDecodeImageCallback(EncodedImageCallback* observer) override {
    receiver_->RegisterPreDecodeImageCallback(observer);
  }

  void RegisterPostEncodeImageCallback(
      EncodedImageCallback* observer) override {
    post_encode_callback_.Register(observer);
  }

  void TriggerDecoderShutdown() override {
    receiver_->TriggerDecoderShutdown();
  }

 private:
  EncodedImageCallbackWrapper post_encode_callback_;
  // TODO(tommi): Change sender_ and receiver_ to be non pointers
  // (construction is 1 alloc instead of 3).
  rtc::scoped_ptr<vcm::VideoSender> sender_;
  rtc::scoped_ptr<vcm::VideoReceiver> receiver_;
  rtc::scoped_ptr<EventFactory> own_event_factory_;
};
}  // namespace

uint8_t VideoCodingModule::NumberOfCodecs() {
  return VCMCodecDataBase::NumberOfCodecs();
}

int32_t VideoCodingModule::Codec(uint8_t listId, VideoCodec* codec) {
  if (codec == NULL) {
    return VCM_PARAMETER_ERROR;
  }
  return VCMCodecDataBase::Codec(listId, codec) ? 0 : -1;
}

int32_t VideoCodingModule::Codec(VideoCodecType codecType, VideoCodec* codec) {
  if (codec == NULL) {
    return VCM_PARAMETER_ERROR;
  }
  return VCMCodecDataBase::Codec(codecType, codec) ? 0 : -1;
}

VideoCodingModule* VideoCodingModule::Create(
    Clock* clock,
    VideoEncoderRateObserver* encoder_rate_observer,
    VCMQMSettingsCallback* qm_settings_callback) {
  return new VideoCodingModuleImpl(clock, new EventFactoryImpl, true,
                                   encoder_rate_observer, qm_settings_callback);
}

VideoCodingModule* VideoCodingModule::Create(
    Clock* clock,
    EventFactory* event_factory) {
  assert(clock);
  assert(event_factory);
  return new VideoCodingModuleImpl(clock, event_factory, false, nullptr,
                                   nullptr);
}

void VideoCodingModule::Destroy(VideoCodingModule* module) {
  if (module != NULL) {
    delete static_cast<VideoCodingModuleImpl*>(module);
  }
}
}  // namespace webrtc
