/*
 *  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 uint16_t payload_size,
      const WebRtcRTPHeader* rtp_header) OVERRIDE {
    return vcm_->IncomingPacket(payload_data, payload_size, *rtp_header);
  }

  virtual bool OnRecoveredPacket(const uint8_t* packet,
                                 int 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;
      }
    }
    while (decode_dual_frame && vcm_->DecodeDualFrame(0) == 1) {
    }
    return Process() ? 0 : -1;
  }

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

  bool Decode() {
    vcm_->Decode(10000);
    while (vcm_->DecodeDualFrame(0) == 1) {
    }
    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,
    uint32_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
