/*
 *  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,
                 scoped_ptr<VideoCodingModule>* vcm,
                 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_;
  scoped_ptr<VideoCodingModule> vcm_;
  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());

  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);

  scoped_ptr<FileOutputFrameReceiver> frame_receiver(
      new FileOutputFrameReceiver(base_out_filename_, stream->ssrc()));
  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
