/* * 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/encoder_state_feedback.h" #include #include "webrtc/base/checks.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" #include "webrtc/video_engine/vie_encoder.h" namespace webrtc { // Helper class registered at the RTP module relaying callbacks to // EncoderStatFeedback. class EncoderStateFeedbackObserver : public RtcpIntraFrameObserver { public: explicit EncoderStateFeedbackObserver(EncoderStateFeedback* owner) : owner_(owner) {} ~EncoderStateFeedbackObserver() {} // Implements RtcpIntraFrameObserver. virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) { owner_->OnReceivedIntraFrameRequest(ssrc); } virtual void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) { owner_->OnReceivedSLI(ssrc, picture_id); } virtual void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) { owner_->OnReceivedRPSI(ssrc, picture_id); } virtual void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) { owner_->OnLocalSsrcChanged(old_ssrc, new_ssrc); } private: EncoderStateFeedback* owner_; }; EncoderStateFeedback::EncoderStateFeedback() : crit_(CriticalSectionWrapper::CreateCriticalSection()), observer_(new EncoderStateFeedbackObserver(this)) {} EncoderStateFeedback::~EncoderStateFeedback() { assert(encoders_.empty()); } void EncoderStateFeedback::AddEncoder(const std::vector& ssrcs, ViEEncoder* encoder) { RTC_DCHECK(!ssrcs.empty()); CriticalSectionScoped lock(crit_.get()); for (uint32_t ssrc : ssrcs) { RTC_DCHECK(encoders_.find(ssrc) == encoders_.end()); encoders_[ssrc] = encoder; } } void EncoderStateFeedback::RemoveEncoder(const ViEEncoder* encoder) { CriticalSectionScoped lock(crit_.get()); SsrcEncoderMap::iterator it = encoders_.begin(); while (it != encoders_.end()) { if (it->second == encoder) { encoders_.erase(it++); } else { ++it; } } } RtcpIntraFrameObserver* EncoderStateFeedback::GetRtcpIntraFrameObserver() { return observer_.get(); } void EncoderStateFeedback::OnReceivedIntraFrameRequest(uint32_t ssrc) { CriticalSectionScoped lock(crit_.get()); SsrcEncoderMap::iterator it = encoders_.find(ssrc); if (it == encoders_.end()) return; it->second->OnReceivedIntraFrameRequest(ssrc); } void EncoderStateFeedback::OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) { CriticalSectionScoped lock(crit_.get()); SsrcEncoderMap::iterator it = encoders_.find(ssrc); if (it == encoders_.end()) return; it->second->OnReceivedSLI(ssrc, picture_id); } void EncoderStateFeedback::OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) { CriticalSectionScoped lock(crit_.get()); SsrcEncoderMap::iterator it = encoders_.find(ssrc); if (it == encoders_.end()) return; it->second->OnReceivedRPSI(ssrc, picture_id); } void EncoderStateFeedback::OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) { CriticalSectionScoped lock(crit_.get()); SsrcEncoderMap::iterator it = encoders_.find(old_ssrc); if (it == encoders_.end() || encoders_.find(new_ssrc) != encoders_.end()) { return; } ViEEncoder* encoder = it->second; encoders_.erase(it); encoders_[new_ssrc] = encoder; encoder->OnLocalSsrcChanged(old_ssrc, new_ssrc); } } // namespace webrtc