/*
 *  Copyright 2015 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/pc/rtpreceiver.h"

#include "webrtc/api/mediastreamtrackproxy.h"
#include "webrtc/api/videosourceproxy.h"
#include "webrtc/pc/audiotrack.h"
#include "webrtc/pc/videotrack.h"
#include "webrtc/rtc_base/trace_event.h"

namespace webrtc {

AudioRtpReceiver::AudioRtpReceiver(const std::string& track_id,
                                   uint32_t ssrc,
                                   cricket::VoiceChannel* channel)
    : id_(track_id),
      ssrc_(ssrc),
      channel_(channel),
      track_(AudioTrackProxy::Create(
          rtc::Thread::Current(),
          AudioTrack::Create(track_id,
                             RemoteAudioSource::Create(ssrc, channel)))),
      cached_track_enabled_(track_->enabled()) {
  RTC_DCHECK(track_->GetSource()->remote());
  track_->RegisterObserver(this);
  track_->GetSource()->RegisterAudioObserver(this);
  Reconfigure();
  if (channel_) {
    channel_->SignalFirstPacketReceived.connect(
        this, &AudioRtpReceiver::OnFirstPacketReceived);
  }
}

AudioRtpReceiver::~AudioRtpReceiver() {
  track_->GetSource()->UnregisterAudioObserver(this);
  track_->UnregisterObserver(this);
  Stop();
}

void AudioRtpReceiver::OnChanged() {
  if (cached_track_enabled_ != track_->enabled()) {
    cached_track_enabled_ = track_->enabled();
    Reconfigure();
  }
}

void AudioRtpReceiver::OnSetVolume(double volume) {
  RTC_DCHECK_GE(volume, 0);
  RTC_DCHECK_LE(volume, 10);
  cached_volume_ = volume;
  if (!channel_) {
    LOG(LS_ERROR) << "AudioRtpReceiver::OnSetVolume: No audio channel exists.";
    return;
  }
  // When the track is disabled, the volume of the source, which is the
  // corresponding WebRtc Voice Engine channel will be 0. So we do not allow
  // setting the volume to the source when the track is disabled.
  if (!stopped_ && track_->enabled()) {
    if (!channel_->SetOutputVolume(ssrc_, cached_volume_)) {
      RTC_NOTREACHED();
    }
  }
}

RtpParameters AudioRtpReceiver::GetParameters() const {
  if (!channel_ || stopped_) {
    return RtpParameters();
  }
  return channel_->GetRtpReceiveParameters(ssrc_);
}

bool AudioRtpReceiver::SetParameters(const RtpParameters& parameters) {
  TRACE_EVENT0("webrtc", "AudioRtpReceiver::SetParameters");
  if (!channel_ || stopped_) {
    return false;
  }
  return channel_->SetRtpReceiveParameters(ssrc_, parameters);
}

void AudioRtpReceiver::Stop() {
  // TODO(deadbeef): Need to do more here to fully stop receiving packets.
  if (stopped_) {
    return;
  }
  if (channel_) {
    // Allow that SetOutputVolume fail. This is the normal case when the
    // underlying media channel has already been deleted.
    channel_->SetOutputVolume(ssrc_, 0);
  }
  stopped_ = true;
}

std::vector<RtpSource> AudioRtpReceiver::GetSources() const {
  return channel_->GetSources(ssrc_);
}

void AudioRtpReceiver::Reconfigure() {
  RTC_DCHECK(!stopped_);
  if (!channel_) {
    LOG(LS_ERROR) << "AudioRtpReceiver::Reconfigure: No audio channel exists.";
    return;
  }
  if (!channel_->SetOutputVolume(ssrc_,
                                 track_->enabled() ? cached_volume_ : 0)) {
    RTC_NOTREACHED();
  }
}

void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
  observer_ = observer;
  // Deliver any notifications the observer may have missed by being set late.
  if (received_first_packet_ && observer_) {
    observer_->OnFirstPacketReceived(media_type());
  }
}

void AudioRtpReceiver::SetChannel(cricket::VoiceChannel* channel) {
  if (channel_) {
    channel_->SignalFirstPacketReceived.disconnect(this);
  }
  channel_ = channel;
  if (channel_) {
    channel_->SignalFirstPacketReceived.connect(
        this, &AudioRtpReceiver::OnFirstPacketReceived);
  }
}

void AudioRtpReceiver::OnFirstPacketReceived(cricket::BaseChannel* channel) {
  if (observer_) {
    observer_->OnFirstPacketReceived(media_type());
  }
  received_first_packet_ = true;
}

VideoRtpReceiver::VideoRtpReceiver(const std::string& track_id,
                                   rtc::Thread* worker_thread,
                                   uint32_t ssrc,
                                   cricket::VideoChannel* channel)
    : id_(track_id),
      ssrc_(ssrc),
      channel_(channel),
      source_(new RefCountedObject<VideoTrackSource>(&broadcaster_,
                                                     true /* remote */)),
      track_(VideoTrackProxy::Create(
          rtc::Thread::Current(),
          worker_thread,
          VideoTrack::Create(
              track_id,
              VideoTrackSourceProxy::Create(rtc::Thread::Current(),
                                            worker_thread,
                                            source_),
              worker_thread))) {
  source_->SetState(MediaSourceInterface::kLive);
  if (!channel_) {
    LOG(LS_ERROR)
        << "VideoRtpReceiver::VideoRtpReceiver: No video channel exists.";
  } else {
    if (!channel_->SetSink(ssrc_, &broadcaster_)) {
      RTC_NOTREACHED();
    }
  }
  if (channel_) {
    channel_->SignalFirstPacketReceived.connect(
        this, &VideoRtpReceiver::OnFirstPacketReceived);
  }
}

VideoRtpReceiver::~VideoRtpReceiver() {
  // Since cricket::VideoRenderer is not reference counted,
  // we need to remove it from the channel before we are deleted.
  Stop();
}

RtpParameters VideoRtpReceiver::GetParameters() const {
  if (!channel_ || stopped_) {
    return RtpParameters();
  }
  return channel_->GetRtpReceiveParameters(ssrc_);
}

bool VideoRtpReceiver::SetParameters(const RtpParameters& parameters) {
  TRACE_EVENT0("webrtc", "VideoRtpReceiver::SetParameters");
  if (!channel_ || stopped_) {
    return false;
  }
  return channel_->SetRtpReceiveParameters(ssrc_, parameters);
}

void VideoRtpReceiver::Stop() {
  // TODO(deadbeef): Need to do more here to fully stop receiving packets.
  if (stopped_) {
    return;
  }
  source_->SetState(MediaSourceInterface::kEnded);
  source_->OnSourceDestroyed();
  if (!channel_) {
    LOG(LS_WARNING) << "VideoRtpReceiver::Stop: No video channel exists.";
  } else {
    // Allow that SetSink fail. This is the normal case when the underlying
    // media channel has already been deleted.
    channel_->SetSink(ssrc_, nullptr);
  }
  stopped_ = true;
}

void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
  observer_ = observer;
  // Deliver any notifications the observer may have missed by being set late.
  if (received_first_packet_ && observer_) {
    observer_->OnFirstPacketReceived(media_type());
  }
}

void VideoRtpReceiver::SetChannel(cricket::VideoChannel* channel) {
  if (channel_) {
    channel_->SignalFirstPacketReceived.disconnect(this);
    channel_->SetSink(ssrc_, nullptr);
  }
  channel_ = channel;
  if (channel_) {
    if (!channel_->SetSink(ssrc_, &broadcaster_)) {
      RTC_NOTREACHED();
    }
    channel_->SignalFirstPacketReceived.connect(
        this, &VideoRtpReceiver::OnFirstPacketReceived);
  }
}

void VideoRtpReceiver::OnFirstPacketReceived(cricket::BaseChannel* channel) {
  if (observer_) {
    observer_->OnFirstPacketReceived(media_type());
  }
  received_first_packet_ = true;
}

}  // namespace webrtc
