/*
 *  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 "webrtc/modules/video_coding/main/test/vcm_payload_sink_factory.h"

#include <assert.h>

#include <algorithm>

#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/video_coding/main/test/test_util.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"

namespace webrtc {
namespace rtpplayer {

class VcmPayloadSinkFactory::VcmPayloadSink
    : public PayloadSinkInterface,
      public VCMPacketRequestCallback {
 public:
  VcmPayloadSink(VcmPayloadSinkFactory* factory,
                 RtpStreamInterface* stream,
                 rtc::scoped_ptr<VideoCodingModule>* vcm,
                 rtc::scoped_ptr<FileOutputFrameReceiver>* frame_receiver)
      : factory_(factory), stream_(stream), vcm_(), frame_receiver_() {
    assert(factory);
    assert(stream);
    assert(vcm);
    assert(vcm->get());
    assert(frame_receiver);
    assert(frame_receiver->get());
    vcm_.swap(*vcm);
    frame_receiver_.swap(*frame_receiver);
    vcm_->RegisterPacketRequestCallback(this);
    vcm_->RegisterReceiveCallback(frame_receiver_.get());
  }

  virtual ~VcmPayloadSink() {
    factory_->Remove(this);
  }

  // PayloadSinkInterface
  virtual int32_t OnReceivedPayloadData(
      const uint8_t* payload_data,
      const size_t payload_size,
      const WebRtcRTPHeader* rtp_header) OVERRIDE {
    return vcm_->IncomingPacket(payload_data, payload_size, *rtp_header);
  }

  virtual bool OnRecoveredPacket(const uint8_t* packet,
                                 size_t packet_length) OVERRIDE {
    // We currently don't handle FEC.
    return true;
  }

  // VCMPacketRequestCallback
  virtual int32_t ResendPackets(const uint16_t* sequence_numbers,
                                uint16_t length) OVERRIDE {
    stream_->ResendPackets(sequence_numbers, length);
    return 0;
  }

  int DecodeAndProcess(bool should_decode, bool decode_dual_frame) {
    if (should_decode) {
      if (vcm_->Decode() < 0) {
        return -1;
      }
    }
    return Process() ? 0 : -1;
  }

  bool Process() {
    if (vcm_->TimeUntilNextProcess() <= 0) {
      if (vcm_->Process() < 0) {
        return false;
      }
    }
    return true;
  }

  bool Decode() {
    vcm_->Decode(10000);
    return true;
  }

 private:
  VcmPayloadSinkFactory* factory_;
  RtpStreamInterface* stream_;
  rtc::scoped_ptr<VideoCodingModule> vcm_;
  rtc::scoped_ptr<FileOutputFrameReceiver> frame_receiver_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(VcmPayloadSink);
};

VcmPayloadSinkFactory::VcmPayloadSinkFactory(
    const std::string& base_out_filename,
    Clock* clock,
    bool protection_enabled,
    VCMVideoProtection protection_method,
    int64_t rtt_ms,
    uint32_t render_delay_ms,
    uint32_t min_playout_delay_ms)
    : base_out_filename_(base_out_filename),
      clock_(clock),
      protection_enabled_(protection_enabled),
      protection_method_(protection_method),
      rtt_ms_(rtt_ms),
      render_delay_ms_(render_delay_ms),
      min_playout_delay_ms_(min_playout_delay_ms),
      null_event_factory_(new NullEventFactory()),
      crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
      sinks_() {
  assert(clock);
  assert(crit_sect_.get());
}

VcmPayloadSinkFactory::~VcmPayloadSinkFactory() {
  assert(sinks_.empty());
}

PayloadSinkInterface* VcmPayloadSinkFactory::Create(
    RtpStreamInterface* stream) {
  assert(stream);
  CriticalSectionScoped cs(crit_sect_.get());

  rtc::scoped_ptr<VideoCodingModule> vcm(
      VideoCodingModule::Create(clock_, null_event_factory_.get()));
  if (vcm.get() == NULL) {
    return NULL;
  }
  if (vcm->InitializeReceiver() < 0) {
    return NULL;
  }

  const PayloadTypes& plt = stream->payload_types();
  for (PayloadTypesIterator it = plt.begin(); it != plt.end();
      ++it) {
    if (it->codec_type() != kVideoCodecULPFEC &&
        it->codec_type() != kVideoCodecRED) {
      VideoCodec codec;
      if (VideoCodingModule::Codec(it->codec_type(), &codec) < 0) {
        return NULL;
      }
      codec.plType = it->payload_type();
      if (vcm->RegisterReceiveCodec(&codec, 1) < 0) {
        return NULL;
      }
    }
  }

  vcm->SetChannelParameters(0, 0, rtt_ms_);
  vcm->SetVideoProtection(protection_method_, protection_enabled_);
  vcm->SetRenderDelay(render_delay_ms_);
  vcm->SetMinimumPlayoutDelay(min_playout_delay_ms_);
  vcm->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);

  rtc::scoped_ptr<FileOutputFrameReceiver> frame_receiver(
      new FileOutputFrameReceiver(base_out_filename_, stream->ssrc()));
  rtc::scoped_ptr<VcmPayloadSink> sink(
      new VcmPayloadSink(this, stream, &vcm, &frame_receiver));

  sinks_.push_back(sink.get());
  return sink.release();
}

int VcmPayloadSinkFactory::DecodeAndProcessAll(bool decode_dual_frame) {
  CriticalSectionScoped cs(crit_sect_.get());
  assert(clock_);
  bool should_decode = (clock_->TimeInMilliseconds() % 5) == 0;
  for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) {
    if ((*it)->DecodeAndProcess(should_decode, decode_dual_frame) < 0) {
      return -1;
    }
  }
  return 0;
}

bool VcmPayloadSinkFactory::ProcessAll() {
  CriticalSectionScoped cs(crit_sect_.get());
  for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) {
    if (!(*it)->Process()) {
      return false;
    }
  }
  return true;
}

bool VcmPayloadSinkFactory::DecodeAll() {
  CriticalSectionScoped cs(crit_sect_.get());
  for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) {
    if (!(*it)->Decode()) {
      return false;
    }
  }
  return true;
}

void VcmPayloadSinkFactory::Remove(VcmPayloadSink* sink) {
  assert(sink);
  CriticalSectionScoped cs(crit_sect_.get());
  Sinks::iterator it = std::find(sinks_.begin(), sinks_.end(), sink);
  assert(it != sinks_.end());
  sinks_.erase(it);
}

}  // namespace rtpplayer
}  // namespace webrtc
