1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/video/encoder_state_feedback.h" 12 13 #include <assert.h> 14 15 #include "webrtc/base/checks.h" 16 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 17 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" 18 #include "webrtc/video/vie_encoder.h" 19 20 namespace webrtc { 21 22 // Helper class registered at the RTP module relaying callbacks to 23 // EncoderStatFeedback. 24 class EncoderStateFeedbackObserver : public RtcpIntraFrameObserver { 25 public: 26 explicit EncoderStateFeedbackObserver(EncoderStateFeedback* owner) 27 : owner_(owner) {} 28 ~EncoderStateFeedbackObserver() {} 29 30 // Implements RtcpIntraFrameObserver. 31 virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) { 32 owner_->OnReceivedIntraFrameRequest(ssrc); 33 } 34 virtual void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) { 35 owner_->OnReceivedSLI(ssrc, picture_id); 36 } 37 virtual void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) { 38 owner_->OnReceivedRPSI(ssrc, picture_id); 39 } 40 41 virtual void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) { 42 owner_->OnLocalSsrcChanged(old_ssrc, new_ssrc); 43 } 44 45 private: 46 EncoderStateFeedback* owner_; 47 }; 48 49 EncoderStateFeedback::EncoderStateFeedback() 50 : crit_(CriticalSectionWrapper::CreateCriticalSection()), 51 observer_(new EncoderStateFeedbackObserver(this)) {} 52 53 EncoderStateFeedback::~EncoderStateFeedback() { 54 assert(encoders_.empty()); 55 } 56 57 void EncoderStateFeedback::AddEncoder(const std::vector<uint32_t>& ssrcs, 58 ViEEncoder* encoder) { 59 RTC_DCHECK(!ssrcs.empty()); 60 CriticalSectionScoped lock(crit_.get()); 61 for (uint32_t ssrc : ssrcs) { 62 RTC_DCHECK(encoders_.find(ssrc) == encoders_.end()); 63 encoders_[ssrc] = encoder; 64 } 65 } 66 67 void EncoderStateFeedback::RemoveEncoder(const ViEEncoder* encoder) { 68 CriticalSectionScoped lock(crit_.get()); 69 SsrcEncoderMap::iterator it = encoders_.begin(); 70 while (it != encoders_.end()) { 71 if (it->second == encoder) { 72 encoders_.erase(it++); 73 } else { 74 ++it; 75 } 76 } 77 } 78 79 RtcpIntraFrameObserver* EncoderStateFeedback::GetRtcpIntraFrameObserver() { 80 return observer_.get(); 81 } 82 83 void EncoderStateFeedback::OnReceivedIntraFrameRequest(uint32_t ssrc) { 84 CriticalSectionScoped lock(crit_.get()); 85 SsrcEncoderMap::iterator it = encoders_.find(ssrc); 86 if (it == encoders_.end()) 87 return; 88 89 it->second->OnReceivedIntraFrameRequest(ssrc); 90 } 91 92 void EncoderStateFeedback::OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) { 93 CriticalSectionScoped lock(crit_.get()); 94 SsrcEncoderMap::iterator it = encoders_.find(ssrc); 95 if (it == encoders_.end()) 96 return; 97 98 it->second->OnReceivedSLI(ssrc, picture_id); 99 } 100 101 void EncoderStateFeedback::OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) { 102 CriticalSectionScoped lock(crit_.get()); 103 SsrcEncoderMap::iterator it = encoders_.find(ssrc); 104 if (it == encoders_.end()) 105 return; 106 107 it->second->OnReceivedRPSI(ssrc, picture_id); 108 } 109 110 void EncoderStateFeedback::OnLocalSsrcChanged(uint32_t old_ssrc, 111 uint32_t new_ssrc) { 112 CriticalSectionScoped lock(crit_.get()); 113 SsrcEncoderMap::iterator it = encoders_.find(old_ssrc); 114 if (it == encoders_.end() || encoders_.find(new_ssrc) != encoders_.end()) { 115 return; 116 } 117 118 ViEEncoder* encoder = it->second; 119 encoders_.erase(it); 120 encoders_[new_ssrc] = encoder; 121 encoder->OnLocalSsrcChanged(old_ssrc, new_ssrc); 122 } 123 124 } // namespace webrtc 125