| /* | 
 |  *  Copyright (c) 2012 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_engine/vie_channel_group.h" | 
 |  | 
 | #include "webrtc/common.h" | 
 | #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" | 
 | #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" | 
 | #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" | 
 | #include "webrtc/modules/utility/interface/process_thread.h" | 
 | #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" | 
 | #include "webrtc/video_engine/call_stats.h" | 
 | #include "webrtc/video_engine/encoder_state_feedback.h" | 
 | #include "webrtc/video_engine/vie_channel.h" | 
 | #include "webrtc/video_engine/vie_encoder.h" | 
 | #include "webrtc/video_engine/vie_remb.h" | 
 |  | 
 | namespace webrtc { | 
 | namespace { | 
 |  | 
 | class WrappingBitrateEstimator : public RemoteBitrateEstimator { | 
 |  public: | 
 |   WrappingBitrateEstimator(RemoteBitrateObserver* observer, Clock* clock, | 
 |                            ProcessThread* process_thread) | 
 |       : observer_(observer), | 
 |         clock_(clock), | 
 |         process_thread_(process_thread), | 
 |         crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), | 
 |         rbe_(RemoteBitrateEstimatorFactory().Create(observer_, clock_)), | 
 |         receive_absolute_send_time_(false) { | 
 |     assert(process_thread_ != NULL); | 
 |     process_thread_->RegisterModule(rbe_.get()); | 
 |   } | 
 |   virtual ~WrappingBitrateEstimator() { | 
 |     process_thread_->DeRegisterModule(rbe_.get()); | 
 |   } | 
 |  | 
 |   void SetReceiveAbsoluteSendTimeStatus(bool enable) { | 
 |     CriticalSectionScoped cs(crit_sect_.get()); | 
 |     if (enable == receive_absolute_send_time_) { | 
 |       return; | 
 |     } | 
 |  | 
 |     process_thread_->DeRegisterModule(rbe_.get()); | 
 |     if (enable) { | 
 |       rbe_.reset(AbsoluteSendTimeRemoteBitrateEstimatorFactory().Create( | 
 |           observer_, clock_)); | 
 |     } else { | 
 |       rbe_.reset(RemoteBitrateEstimatorFactory().Create(observer_, clock_)); | 
 |     } | 
 |     process_thread_->RegisterModule(rbe_.get()); | 
 |  | 
 |     receive_absolute_send_time_ = enable; | 
 |   } | 
 |  | 
 |   virtual void IncomingPacket(int64_t arrival_time_ms, | 
 |                               int payload_size, | 
 |                               const RTPHeader& header) { | 
 |     CriticalSectionScoped cs(crit_sect_.get()); | 
 |     rbe_->IncomingPacket(arrival_time_ms, payload_size, header); | 
 |   } | 
 |  | 
 |   virtual int32_t Process() { | 
 |     assert(false && "Not supposed to register the WrappingBitrateEstimator!"); | 
 |     return 0; | 
 |   } | 
 |  | 
 |   virtual int32_t TimeUntilNextProcess() { | 
 |     assert(false && "Not supposed to register the WrappingBitrateEstimator!"); | 
 |     return 0; | 
 |   } | 
 |  | 
 |   virtual void OnRttUpdate(uint32_t rtt) { | 
 |     CriticalSectionScoped cs(crit_sect_.get()); | 
 |     rbe_->OnRttUpdate(rtt); | 
 |   } | 
 |  | 
 |   virtual void RemoveStream(unsigned int ssrc) { | 
 |     CriticalSectionScoped cs(crit_sect_.get()); | 
 |     rbe_->RemoveStream(ssrc); | 
 |   } | 
 |  | 
 |   virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs, | 
 |                               unsigned int* bitrate_bps) const { | 
 |     CriticalSectionScoped cs(crit_sect_.get()); | 
 |     return rbe_->LatestEstimate(ssrcs, bitrate_bps); | 
 |   } | 
 |  | 
 |  private: | 
 |   RemoteBitrateObserver* observer_; | 
 |   Clock* clock_; | 
 |   ProcessThread* process_thread_; | 
 |   scoped_ptr<CriticalSectionWrapper> crit_sect_; | 
 |   scoped_ptr<RemoteBitrateEstimator> rbe_; | 
 |   bool receive_absolute_send_time_; | 
 |  | 
 |   DISALLOW_IMPLICIT_CONSTRUCTORS(WrappingBitrateEstimator); | 
 | }; | 
 | }  // namespace | 
 |  | 
 | ChannelGroup::ChannelGroup(ProcessThread* process_thread, | 
 |                            const Config& config) | 
 |     : remb_(new VieRemb()), | 
 |       bitrate_controller_(BitrateController::CreateBitrateController()), | 
 |       call_stats_(new CallStats()), | 
 |       remote_bitrate_estimator_(new WrappingBitrateEstimator(remb_.get(), | 
 |                                 Clock::GetRealTimeClock(), process_thread)), | 
 |       encoder_state_feedback_(new EncoderStateFeedback()), | 
 |       process_thread_(process_thread) { | 
 |   call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get()); | 
 |   process_thread->RegisterModule(call_stats_.get()); | 
 | } | 
 |  | 
 | ChannelGroup::~ChannelGroup() { | 
 |   call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get()); | 
 |   process_thread_->DeRegisterModule(call_stats_.get()); | 
 |   assert(channels_.empty()); | 
 |   assert(!remb_->InUse()); | 
 | } | 
 |  | 
 | void ChannelGroup::AddChannel(int channel_id) { | 
 |   channels_.insert(channel_id); | 
 | } | 
 |  | 
 | void ChannelGroup::RemoveChannel(int channel_id, unsigned int ssrc) { | 
 |   channels_.erase(channel_id); | 
 |   remote_bitrate_estimator_->RemoveStream(ssrc); | 
 | } | 
 |  | 
 | bool ChannelGroup::HasChannel(int channel_id) { | 
 |   return channels_.find(channel_id) != channels_.end(); | 
 | } | 
 |  | 
 | bool ChannelGroup::Empty() { | 
 |   return channels_.empty(); | 
 | } | 
 |  | 
 | BitrateController* ChannelGroup::GetBitrateController() { | 
 |   return bitrate_controller_.get(); | 
 | } | 
 |  | 
 | RemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() { | 
 |   return remote_bitrate_estimator_.get(); | 
 | } | 
 |  | 
 | CallStats* ChannelGroup::GetCallStats() { | 
 |   return call_stats_.get(); | 
 | } | 
 |  | 
 | EncoderStateFeedback* ChannelGroup::GetEncoderStateFeedback() { | 
 |   return encoder_state_feedback_.get(); | 
 | } | 
 |  | 
 | bool ChannelGroup::SetChannelRembStatus(int channel_id, bool sender, | 
 |                                         bool receiver, ViEChannel* channel) { | 
 |   // Update the channel state. | 
 |   if (sender || receiver) { | 
 |     if (!channel->EnableRemb(true)) { | 
 |       return false; | 
 |     } | 
 |   } else { | 
 |     channel->EnableRemb(false); | 
 |   } | 
 |   // Update the REMB instance with necessary RTP modules. | 
 |   RtpRtcp* rtp_module = channel->rtp_rtcp(); | 
 |   if (sender) { | 
 |     remb_->AddRembSender(rtp_module); | 
 |   } else { | 
 |     remb_->RemoveRembSender(rtp_module); | 
 |   } | 
 |   if (receiver) { | 
 |     remb_->AddReceiveChannel(rtp_module); | 
 |   } else { | 
 |     remb_->RemoveReceiveChannel(rtp_module); | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | void ChannelGroup::SetReceiveAbsoluteSendTimeStatus(bool enable) { | 
 |   static_cast<WrappingBitrateEstimator*>(remote_bitrate_estimator_.get())-> | 
 |       SetReceiveAbsoluteSendTimeStatus(enable); | 
 | } | 
 | }  // namespace webrtc |