/*
 *  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/video/video_receive_stream.h"

#include <assert.h>
#include <stdlib.h>

#include <string>

#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/video/receive_statistics_proxy.h"
#include "webrtc/video_engine/include/vie_base.h"
#include "webrtc/video_engine/include/vie_capture.h"
#include "webrtc/video_engine/include/vie_codec.h"
#include "webrtc/video_engine/include/vie_external_codec.h"
#include "webrtc/video_engine/include/vie_image_process.h"
#include "webrtc/video_engine/include/vie_network.h"
#include "webrtc/video_engine/include/vie_render.h"
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
#include "webrtc/video_receive_stream.h"

namespace webrtc {
namespace internal {

VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
                                       const VideoReceiveStream::Config& config,
                                       newapi::Transport* transport,
                                       webrtc::VoiceEngine* voice_engine,
                                       int base_channel)
    : transport_adapter_(transport),
      encoded_frame_proxy_(config.pre_decode_callback),
      config_(config),
      clock_(Clock::GetRealTimeClock()),
      channel_(-1) {
  video_engine_base_ = ViEBase::GetInterface(video_engine);
  video_engine_base_->CreateReceiveChannel(channel_, base_channel);
  assert(channel_ != -1);

  rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine);
  assert(rtp_rtcp_ != NULL);

  // TODO(pbos): This is not fine grained enough...
  rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
  rtp_rtcp_->SetKeyFrameRequestMethod(channel_, kViEKeyFrameRequestPliRtcp);
  switch (config_.rtp.rtcp_mode) {
    case newapi::kRtcpCompound:
      rtp_rtcp_->SetRTCPStatus(channel_, kRtcpCompound_RFC4585);
      break;
    case newapi::kRtcpReducedSize:
      rtp_rtcp_->SetRTCPStatus(channel_, kRtcpNonCompound_RFC5506);
      break;
  }

  assert(config_.rtp.remote_ssrc != 0);
  // TODO(pbos): What's an appropriate local_ssrc for receive-only streams?
  assert(config_.rtp.local_ssrc != 0);
  assert(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);

  rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.local_ssrc);
  // TODO(pbos): Support multiple RTX, per video payload.
  Config::Rtp::RtxMap::const_iterator it = config_.rtp.rtx.begin();
  if (it != config_.rtp.rtx.end()) {
    assert(it->second.ssrc != 0);
    assert(it->second.payload_type != 0);

    rtp_rtcp_->SetRemoteSSRCType(channel_, kViEStreamTypeRtx, it->second.ssrc);
    rtp_rtcp_->SetRtxReceivePayloadType(channel_, it->second.payload_type);
  }

  rtp_rtcp_->SetRembStatus(channel_, false, config_.rtp.remb);

  for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
    const std::string& extension = config_.rtp.extensions[i].name;
    int id = config_.rtp.extensions[i].id;
    if (extension == RtpExtension::kTOffset) {
      if (rtp_rtcp_->SetReceiveTimestampOffsetStatus(channel_, true, id) != 0)
        abort();
    } else if (extension == RtpExtension::kAbsSendTime) {
      if (rtp_rtcp_->SetReceiveAbsoluteSendTimeStatus(channel_, true, id) != 0)
        abort();
    } else {
      abort();  // Unsupported extension.
    }
  }

  network_ = ViENetwork::GetInterface(video_engine);
  assert(network_ != NULL);

  network_->RegisterSendTransport(channel_, transport_adapter_);

  codec_ = ViECodec::GetInterface(video_engine);

  if (config_.rtp.fec.ulpfec_payload_type != -1) {
    // ULPFEC without RED doesn't make sense.
    assert(config_.rtp.fec.red_payload_type != -1);
    VideoCodec codec;
    memset(&codec, 0, sizeof(codec));
    codec.codecType = kVideoCodecULPFEC;
    strcpy(codec.plName, "ulpfec");
    codec.plType = config_.rtp.fec.ulpfec_payload_type;
    if (codec_->SetReceiveCodec(channel_, codec) != 0) {
      LOG(LS_ERROR) << "Could not set ULPFEC codec. This shouldn't happen.";
      abort();
    }
  }
  if (config_.rtp.fec.red_payload_type != -1) {
    VideoCodec codec;
    memset(&codec, 0, sizeof(codec));
    codec.codecType = kVideoCodecRED;
    strcpy(codec.plName, "red");
    codec.plType = config_.rtp.fec.red_payload_type;
    if (codec_->SetReceiveCodec(channel_, codec) != 0) {
      LOG(LS_ERROR) << "Could not set RED codec. This shouldn't happen.";
      abort();
    }
  }

  assert(!config_.codecs.empty());
  for (size_t i = 0; i < config_.codecs.size(); ++i) {
    if (codec_->SetReceiveCodec(channel_, config_.codecs[i]) != 0) {
      // TODO(pbos): Abort gracefully, this can be a runtime error.
      //             Factor out to an Init() method.
      abort();
    }
  }

  stats_proxy_.reset(new ReceiveStatisticsProxy(
      config_.rtp.local_ssrc, clock_, rtp_rtcp_, codec_, channel_));

  if (rtp_rtcp_->RegisterReceiveChannelRtcpStatisticsCallback(
          channel_, stats_proxy_.get()) != 0)
    abort();

  if (rtp_rtcp_->RegisterReceiveChannelRtpStatisticsCallback(
          channel_, stats_proxy_.get()) != 0)
    abort();

  if (codec_->RegisterDecoderObserver(channel_, *stats_proxy_) != 0)
    abort();

  external_codec_ = ViEExternalCodec::GetInterface(video_engine);
  for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
    const ExternalVideoDecoder& decoder = config_.external_decoders[i];
    if (external_codec_->RegisterExternalReceiveCodec(
            channel_,
            decoder.payload_type,
            decoder.decoder,
            decoder.renderer,
            decoder.expected_delay_ms) != 0) {
      // TODO(pbos): Abort gracefully? Can this be a runtime error?
      abort();
    }
  }

  render_ = ViERender::GetInterface(video_engine);
  assert(render_ != NULL);

  render_->AddRenderCallback(channel_, this);

  if (voice_engine) {
    video_engine_base_->SetVoiceEngine(voice_engine);
    video_engine_base_->ConnectAudioChannel(channel_, config_.audio_channel_id);
  }

  image_process_ = ViEImageProcess::GetInterface(video_engine);
  if (config.pre_decode_callback) {
    image_process_->RegisterPreDecodeImageCallback(channel_,
                                                   &encoded_frame_proxy_);
  }
  image_process_->RegisterPreRenderCallback(channel_, this);

  if (config.rtp.rtcp_xr.receiver_reference_time_report) {
    rtp_rtcp_->SetRtcpXrRrtrStatus(channel_, true);
  }
}

VideoReceiveStream::~VideoReceiveStream() {
  image_process_->DeRegisterPreRenderCallback(channel_);
  image_process_->DeRegisterPreDecodeCallback(channel_);

  render_->RemoveRenderer(channel_);

  for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
    external_codec_->DeRegisterExternalReceiveCodec(
        channel_, config_.external_decoders[i].payload_type);
  }

  network_->DeregisterSendTransport(channel_);

  video_engine_base_->SetVoiceEngine(NULL);
  image_process_->Release();
  video_engine_base_->Release();
  external_codec_->Release();
  codec_->DeregisterDecoderObserver(channel_);
  rtp_rtcp_->DeregisterReceiveChannelRtpStatisticsCallback(channel_,
                                                           stats_proxy_.get());
  rtp_rtcp_->DeregisterReceiveChannelRtcpStatisticsCallback(channel_,
                                                            stats_proxy_.get());
  codec_->Release();
  network_->Release();
  render_->Release();
  rtp_rtcp_->Release();
}

void VideoReceiveStream::Start() {
  transport_adapter_.Enable();
  if (render_->StartRender(channel_) != 0)
    abort();
  if (video_engine_base_->StartReceive(channel_) != 0)
    abort();
}

void VideoReceiveStream::Stop() {
  if (render_->StopRender(channel_) != 0)
    abort();
  if (video_engine_base_->StopReceive(channel_) != 0)
    abort();
  transport_adapter_.Disable();
}

VideoReceiveStream::Stats VideoReceiveStream::GetStats() const {
  return stats_proxy_->GetStats();
}

void VideoReceiveStream::GetCurrentReceiveCodec(VideoCodec* receive_codec) {
  // TODO(pbos): Implement
}

bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
  return network_->ReceivedRTCPPacket(
             channel_, packet, static_cast<int>(length)) == 0;
}

bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) {
  return network_->ReceivedRTPPacket(
             channel_, packet, static_cast<int>(length), PacketTime()) == 0;
}

void VideoReceiveStream::FrameCallback(I420VideoFrame* video_frame) {
  stats_proxy_->OnDecodedFrame();

  if (config_.pre_render_callback)
    config_.pre_render_callback->FrameCallback(video_frame);
}

int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id,
                                        I420VideoFrame& video_frame) {
  if (config_.renderer != NULL)
    config_.renderer->RenderFrame(
        video_frame,
        video_frame.render_time_ms() - clock_->TimeInMilliseconds());

  stats_proxy_->OnRenderedFrame();

  return 0;
}
}  // namespace internal
}  // namespace webrtc
