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_engine/encoder_state_feedback.h" 12 13 #include <assert.h> 14 15 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" 16 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 17 #include "webrtc/video_engine/vie_encoder.h" 18 19 namespace webrtc { 20 21 // Helper class registered at the RTP module relaying callbacks to 22 // EncoderStatFeedback. 23 class EncoderStateFeedbackObserver : public RtcpIntraFrameObserver { 24 public: 25 explicit EncoderStateFeedbackObserver(EncoderStateFeedback* owner) 26 : owner_(owner) {} 27 ~EncoderStateFeedbackObserver() {} 28 29 // Implements RtcpIntraFrameObserver. 30 virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) { 31 owner_->OnReceivedIntraFrameRequest(ssrc); 32 } 33 virtual void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) { 34 owner_->OnReceivedSLI(ssrc, picture_id); 35 } 36 virtual void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) { 37 owner_->OnReceivedRPSI(ssrc, picture_id); 38 } 39 40 virtual void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) { 41 owner_->OnLocalSsrcChanged(old_ssrc, new_ssrc); 42 } 43 44 private: 45 EncoderStateFeedback* owner_; 46 }; 47 48 EncoderStateFeedback::EncoderStateFeedback() 49 : crit_(CriticalSectionWrapper::CreateCriticalSection()), 50 observer_(new EncoderStateFeedbackObserver(this)) {} 51 52 EncoderStateFeedback::~EncoderStateFeedback() { 53 assert(encoders_.empty()); 54 } 55 56 bool EncoderStateFeedback::AddEncoder(uint32_t ssrc, ViEEncoder* encoder) { 57 CriticalSectionScoped lock(crit_.get()); 58 if (encoders_.find(ssrc) != encoders_.end()) { 59 // Two encoders must not have the same ssrc. 60 return false; 61 } 62 63 encoders_[ssrc] = encoder; 64 return true; 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