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
20namespace webrtc {
21
22// Helper class registered at the RTP module relaying callbacks to
23// EncoderStatFeedback.
24class 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
49EncoderStateFeedback::EncoderStateFeedback()
50    : crit_(CriticalSectionWrapper::CreateCriticalSection()),
51      observer_(new EncoderStateFeedbackObserver(this)) {}
52
53EncoderStateFeedback::~EncoderStateFeedback() {
54  assert(encoders_.empty());
55}
56
57void 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
67void 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
79RtcpIntraFrameObserver* EncoderStateFeedback::GetRtcpIntraFrameObserver() {
80  return observer_.get();
81}
82
83void 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
92void 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
101void 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
110void 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