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