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

#include <vector>

#include "api/mediastreamtrackproxy.h"
#include "api/videosourceproxy.h"
#include "pc/audiotrack.h"
#include "pc/videotrack.h"
#include "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
