Revert 5259 "Callback for send bitrate estimates"

CL is causing flakiness in RampUpTest.WithoutPacing.

> Callback for send bitrate estimates
>
> BUG=2235
> R=mflodman@webrtc.org, pbos@webrtc.org, stefan@webrtc.org
>
> Review URL: https://webrtc-codereview.appspot.com/4459004

R=mflodman@webrtc.org, pbos@webrtc.org
TBR=mflodman

Review URL: https://webrtc-codereview.appspot.com/5579005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5261 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
sprang@webrtc.org 2013-12-11 14:07:33 +00:00
parent f9bdbe3619
commit 096e8d9f94
15 changed files with 67 additions and 290 deletions

View File

@ -285,11 +285,14 @@ class StreamDataCountersCallback {
// Rate statistics for a stream
struct BitrateStatistics {
BitrateStatistics() : bitrate_bps(0), packet_rate(0), timestamp_ms(0) {}
BitrateStatistics()
: bitrate_(0),
packet_rate(0),
now(0) {}
uint32_t bitrate_bps; // Bitrate in bits per second.
uint32_t packet_rate; // Packet rate in packets per second.
uint64_t timestamp_ms; // Ntp timestamp in ms at time of rate estimation.
uint32_t bitrate_;
uint32_t packet_rate;
uint64_t now;
};
// Callback, used to notify an observer whenever new rates have been estimated.

View File

@ -300,13 +300,6 @@ class RtpRtcp : public Module {
uint32_t* fecRate,
uint32_t* nackRate) const = 0;
/*
* Called on any new send bitrate estimate.
*/
virtual void RegisterVideoBitrateObserver(
BitrateStatisticsObserver* observer) = 0;
virtual BitrateStatisticsObserver* GetVideoBitrateObserver() const = 0;
/*
* Used by the codec module to deliver a video or audio frame for
* packetization.

View File

@ -100,8 +100,6 @@ class MockRtpRtcp : public RtpRtcp {
bool());
MOCK_CONST_METHOD4(BitrateSent,
void(uint32_t* totalRate, uint32_t* videoRate, uint32_t* fecRate, uint32_t* nackRate));
MOCK_METHOD1(RegisterVideoBitrateObserver, void(BitrateStatisticsObserver*));
MOCK_CONST_METHOD0(GetVideoBitrateObserver, BitrateStatisticsObserver*(void));
MOCK_CONST_METHOD1(EstimatedReceiveBandwidth,
int(uint32_t* available_bandwidth));
MOCK_METHOD8(SendOutgoingData,

View File

@ -15,7 +15,7 @@
namespace webrtc {
Bitrate::Bitrate(Clock* clock, Observer* observer)
Bitrate::Bitrate(Clock* clock)
: clock_(clock),
crit_(CriticalSectionWrapper::CreateCriticalSection()),
packet_rate_(0),
@ -23,15 +23,12 @@ Bitrate::Bitrate(Clock* clock, Observer* observer)
bitrate_next_idx_(0),
time_last_rate_update_(0),
bytes_count_(0),
packet_count_(0),
observer_(observer) {
packet_count_(0) {
memset(packet_rate_array_, 0, sizeof(packet_rate_array_));
memset(bitrate_diff_ms_, 0, sizeof(bitrate_diff_ms_));
memset(bitrate_array_, 0, sizeof(bitrate_array_));
}
Bitrate::~Bitrate() {}
void Bitrate::Update(const int32_t bytes) {
CriticalSectionScoped cs(crit_.get());
bytes_count_ += bytes;
@ -74,7 +71,7 @@ int64_t Bitrate::time_last_rate_update() const {
void Bitrate::Process() {
// Triggered by timer.
CriticalSectionScoped cs(crit_.get());
int64_t now = clock_->CurrentNtpInMilliseconds();
int64_t now = clock_->TimeInMilliseconds();
int64_t diff_ms = now - time_last_rate_update_;
if (diff_ms < 100) {
@ -108,14 +105,6 @@ void Bitrate::Process() {
packet_count_ = 0;
packet_rate_ = static_cast<uint32_t>(sum_packetrateMS / sum_diffMS);
bitrate_ = static_cast<uint32_t>(sum_bitrateMS / sum_diffMS);
if (observer_) {
BitrateStatistics stats;
stats.bitrate_bps = bitrate_;
stats.packet_rate = packet_rate_;
stats.timestamp_ms = now;
observer_->BitrateUpdated(stats);
}
}
} // namespace webrtc

View File

@ -27,9 +27,7 @@ class CriticalSectionWrapper;
class Bitrate {
public:
class Observer;
Bitrate(Clock* clock, Observer* observer);
virtual ~Bitrate();
explicit Bitrate(Clock* clock);
// Calculates rates.
void Process();
@ -48,14 +46,6 @@ class Bitrate {
int64_t time_last_rate_update() const;
class Observer {
public:
Observer() {}
virtual ~Observer() {}
virtual void BitrateUpdated(const BitrateStatistics& stats) = 0;
};
protected:
Clock* clock_;
@ -70,7 +60,6 @@ class Bitrate {
int64_t time_last_rate_update_;
uint32_t bytes_count_;
uint32_t packet_count_;
Observer* const observer_;
};
} // namespace webrtc

View File

@ -27,7 +27,7 @@ StreamStatistician::~StreamStatistician() {}
StreamStatisticianImpl::StreamStatisticianImpl(Clock* clock)
: clock_(clock),
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
incoming_bitrate_(clock, NULL),
incoming_bitrate_(clock),
ssrc_(0),
max_reordering_threshold_(kDefaultMaxReorderingThreshold),
jitter_q4_(0),

View File

@ -1559,7 +1559,7 @@ void ModuleRtpRtcpImpl::BitrateSent(uint32_t* total_rate,
return;
}
if (total_rate != NULL)
*total_rate = rtp_sender_.BitrateSent();
*total_rate = rtp_sender_.BitrateLast();
if (video_rate != NULL)
*video_rate = rtp_sender_.VideoBitrateSent();
if (fec_rate != NULL)
@ -1568,31 +1568,6 @@ void ModuleRtpRtcpImpl::BitrateSent(uint32_t* total_rate,
*nack_rate = rtp_sender_.NackOverheadRate();
}
void ModuleRtpRtcpImpl::RegisterVideoBitrateObserver(
BitrateStatisticsObserver* observer) {
{
CriticalSectionScoped cs(critical_section_module_ptrs_.get());
if (!child_modules_.empty()) {
for (std::list<ModuleRtpRtcpImpl*>::const_iterator it =
child_modules_.begin();
it != child_modules_.end();
++it) {
RtpRtcp* module = *it;
if (module)
module->RegisterVideoBitrateObserver(observer);
++it;
}
return;
}
}
rtp_sender_.RegisterBitrateObserver(observer);
}
BitrateStatisticsObserver* ModuleRtpRtcpImpl::GetVideoBitrateObserver() const {
return rtp_sender_.GetBitrateObserver();
}
// Bad state of RTP receiver request a keyframe.
void ModuleRtpRtcpImpl::OnRequestIntraFrame() {
RequestKeyFrame();

View File

@ -349,11 +349,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
uint32_t* fec_rate,
uint32_t* nackRate) const OVERRIDE;
virtual void RegisterVideoBitrateObserver(BitrateStatisticsObserver* observer)
OVERRIDE;
virtual BitrateStatisticsObserver* GetVideoBitrateObserver() const OVERRIDE;
virtual uint32_t SendTimeOfSendReport(const uint32_t send_report);
virtual bool SendTimeOfXrRrReport(uint32_t mid_ntp, int64_t* time_ms) const;

View File

@ -39,56 +39,30 @@ const char* FrameTypeToString(const FrameType frame_type) {
} // namespace
RTPSender::RTPSender(const int32_t id,
const bool audio,
Clock* clock,
Transport* transport,
RtpAudioFeedback* audio_feedback,
PacedSender* paced_sender)
: clock_(clock),
bitrate_sent_(clock, this),
id_(id),
audio_configured_(audio),
audio_(NULL),
video_(NULL),
paced_sender_(paced_sender),
RTPSender::RTPSender(const int32_t id, const bool audio, Clock *clock,
Transport *transport, RtpAudioFeedback *audio_feedback,
PacedSender *paced_sender)
: Bitrate(clock), id_(id), audio_configured_(audio), audio_(NULL),
video_(NULL), paced_sender_(paced_sender),
send_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
transport_(transport),
sending_media_(true), // Default to sending media.
max_payload_length_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP.
target_send_bitrate_(0),
packet_over_head_(28),
payload_type_(-1),
payload_type_map_(),
rtp_header_extension_map_(),
transmission_time_offset_(0),
absolute_send_time_(0),
transport_(transport), sending_media_(true), // Default to sending media.
max_payload_length_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP.
target_send_bitrate_(0), packet_over_head_(28), payload_type_(-1),
payload_type_map_(), rtp_header_extension_map_(),
transmission_time_offset_(0), absolute_send_time_(0),
// NACK.
nack_byte_count_times_(),
nack_byte_count_(),
nack_bitrate_(clock, NULL),
nack_byte_count_times_(), nack_byte_count_(), nack_bitrate_(clock),
packet_history_(clock),
// Statistics
statistics_crit_(CriticalSectionWrapper::CreateCriticalSection()),
frame_count_observer_(NULL),
rtp_stats_callback_(NULL),
bitrate_callback_(NULL),
frame_count_observer_(NULL), rtp_stats_callback_(NULL),
// RTP variables
start_time_stamp_forced_(false),
start_time_stamp_(0),
ssrc_db_(*SSRCDatabase::GetSSRCDatabase()),
remote_ssrc_(0),
sequence_number_forced_(false),
ssrc_forced_(false),
timestamp_(0),
capture_time_ms_(0),
last_timestamp_time_ms_(0),
last_packet_marker_bit_(false),
num_csrcs_(0),
csrcs_(),
include_csrcs_(true),
rtx_(kRtxOff),
payload_type_rtx_(-1) {
start_time_stamp_(0), ssrc_db_(*SSRCDatabase::GetSSRCDatabase()),
remote_ssrc_(0), sequence_number_forced_(false), ssrc_forced_(false),
timestamp_(0), capture_time_ms_(0), last_timestamp_time_ms_(0),
last_packet_marker_bit_(false), num_csrcs_(0), csrcs_(),
include_csrcs_(true), rtx_(kRtxOff), payload_type_rtx_(-1) {
memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
memset(nack_byte_count_, 0, sizeof(nack_byte_count_));
memset(csrcs_, 0, sizeof(csrcs_));
@ -134,7 +108,7 @@ void RTPSender::SetTargetSendBitrate(const uint32_t bits) {
}
uint16_t RTPSender::ActualSendBitrateKbit() const {
return (uint16_t)(bitrate_sent_.BitrateNow() / 1000);
return (uint16_t)(Bitrate::BitrateNow() / 1000);
}
uint32_t RTPSender::VideoBitrateSent() const {
@ -471,7 +445,7 @@ bool RTPSender::SendPaddingAccordingToBitrate(
int64_t capture_time_ms) {
// Current bitrate since last estimate(1 second) averaged with the
// estimate since then, to get the most up to date bitrate.
uint32_t current_bitrate = bitrate_sent_.BitrateNow();
uint32_t current_bitrate = BitrateNow();
int bitrate_diff = target_send_bitrate_ * 1000 - current_bitrate;
if (bitrate_diff <= 0) {
return true;
@ -853,7 +827,7 @@ void RTPSender::UpdateRtpStats(const uint8_t* buffer,
ssrc = ssrc_;
}
bitrate_sent_.Update(size);
Bitrate::Update(size);
++counters->packets;
if (IsFecPacket(buffer, header)) {
++counters->fec_packets;
@ -974,7 +948,7 @@ void RTPSender::UpdateDelayStatistics(int64_t capture_time_ms, int64_t now_ms) {
void RTPSender::ProcessBitrate() {
CriticalSectionScoped cs(send_critsect_);
bitrate_sent_.Process();
Bitrate::Process();
nack_bitrate_.Process();
if (audio_configured_) {
return;
@ -1614,24 +1588,4 @@ StreamDataCountersCallback* RTPSender::GetRtpStatisticsCallback() const {
return rtp_stats_callback_;
}
void RTPSender::RegisterBitrateObserver(BitrateStatisticsObserver* observer) {
CriticalSectionScoped cs(statistics_crit_.get());
if (observer != NULL)
assert(bitrate_callback_ == NULL);
bitrate_callback_ = observer;
}
BitrateStatisticsObserver* RTPSender::GetBitrateObserver() const {
CriticalSectionScoped cs(statistics_crit_.get());
return bitrate_callback_;
}
uint32_t RTPSender::BitrateSent() const { return bitrate_sent_.BitrateLast(); }
void RTPSender::BitrateUpdated(const BitrateStatistics& stats) {
CriticalSectionScoped cs(statistics_crit_.get());
if (bitrate_callback_) {
bitrate_callback_->Notify(stats, ssrc_);
}
}
} // namespace webrtc

View File

@ -63,7 +63,7 @@ class RTPSenderInterface {
PacedSender::Priority priority) = 0;
};
class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
class RTPSender : public Bitrate, public RTPSenderInterface {
public:
RTPSender(const int32_t id, const bool audio, Clock *clock,
Transport *transport, RtpAudioFeedback *audio_feedback,
@ -275,14 +275,6 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
void RegisterRtpStatisticsCallback(StreamDataCountersCallback* callback);
StreamDataCountersCallback* GetRtpStatisticsCallback() const;
// Called on new send bitrate estimate.
void RegisterBitrateObserver(BitrateStatisticsObserver* observer);
BitrateStatisticsObserver* GetBitrateObserver() const;
uint32_t BitrateSent() const;
virtual void BitrateUpdated(const BitrateStatistics& stats) OVERRIDE;
protected:
int32_t CheckPayloadType(const int8_t payload_type,
RtpVideoCodecTypes *video_type);
@ -326,9 +318,6 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
bool is_retransmit);
bool IsFecPacket(const uint8_t* buffer, const RTPHeader& header) const;
Clock* clock_;
Bitrate bitrate_sent_;
int32_t id_;
const bool audio_configured_;
RTPSenderAudio *audio_;
@ -366,7 +355,6 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
StreamDataCounters rtp_stats_;
StreamDataCounters rtx_rtp_stats_;
StreamDataCountersCallback* rtp_stats_callback_;
BitrateStatisticsObserver* bitrate_callback_;
// RTP variables
bool start_time_stamp_forced_;

View File

@ -38,7 +38,6 @@ const uint32_t kAbsoluteSendTime = 0x00aabbcc;
const uint8_t kAudioLevel = 0x5a;
const uint8_t kAudioLevelExtensionId = 9;
const int kAudioPayload = 103;
const uint64_t kStartTime = 123456789;
} // namespace
using testing::_;
@ -82,12 +81,12 @@ class LoopbackTransportTest : public webrtc::Transport {
class RtpSenderTest : public ::testing::Test {
protected:
RtpSenderTest()
: fake_clock_(kStartTime),
mock_paced_sender_(),
rtp_sender_(),
payload_(kPayload),
transport_(),
kMarkerBit(true) {
: fake_clock_(123456789),
mock_paced_sender_(),
rtp_sender_(),
payload_(kPayload),
transport_(),
kMarkerBit(true) {
EXPECT_CALL(mock_paced_sender_,
SendPacket(_, _, _, _, _, _)).WillRepeatedly(testing::Return(true));
}
@ -780,73 +779,6 @@ TEST_F(RtpSenderTest, FrameCountCallbacks) {
rtp_sender_->RegisterFrameCountObserver(NULL);
}
TEST_F(RtpSenderTest, BitrateCallbacks) {
class TestCallback : public BitrateStatisticsObserver {
public:
TestCallback()
: BitrateStatisticsObserver(), num_calls_(0), ssrc_(0), bitrate_() {}
virtual ~TestCallback() {}
virtual void Notify(const BitrateStatistics& stats, uint32_t ssrc) {
++num_calls_;
ssrc_ = ssrc;
bitrate_ = stats;
}
uint32_t num_calls_;
uint32_t ssrc_;
BitrateStatistics bitrate_;
} callback;
// Simulate kNumPackets sent with kPacketInterval ms intervals.
const uint32_t kNumPackets = 15;
const uint32_t kPacketInterval = 20;
// Overhead = 12 bytes RTP header + 1 byte generic header.
const uint32_t kPacketOverhead = 13;
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
const uint8_t payload_type = 127;
ASSERT_EQ(
0,
rtp_sender_->RegisterPayload(payload_name, payload_type, 90000, 0, 1500));
uint8_t payload[] = {47, 11, 32, 93, 89};
rtp_sender_->SetStorePacketsStatus(true, 1);
uint32_t ssrc = rtp_sender_->SSRC();
rtp_sender_->RegisterBitrateObserver(&callback);
// Initial process call so we get a new time window.
rtp_sender_->ProcessBitrate();
uint64_t start_time = fake_clock_.CurrentNtpInMilliseconds();
// Send a few frames.
for (uint32_t i = 0; i < kNumPackets; ++i) {
ASSERT_EQ(0,
rtp_sender_->SendOutgoingData(kVideoFrameKey,
payload_type,
1234,
4321,
payload,
sizeof(payload),
0));
fake_clock_.AdvanceTimeMilliseconds(kPacketInterval);
}
rtp_sender_->ProcessBitrate();
const uint32_t expected_packet_rate = 1000 / kPacketInterval;
EXPECT_EQ(1U, callback.num_calls_);
EXPECT_EQ(ssrc, callback.ssrc_);
EXPECT_EQ(start_time + (kNumPackets * kPacketInterval),
callback.bitrate_.timestamp_ms);
EXPECT_EQ(expected_packet_rate, callback.bitrate_.packet_rate);
EXPECT_EQ((kPacketOverhead + sizeof(payload)) * 8 * expected_packet_rate,
callback.bitrate_.bitrate_bps);
rtp_sender_->RegisterBitrateObserver(NULL);
}
class RtpSenderAudioTest : public RtpSenderTest {
protected:
RtpSenderAudioTest() {}

View File

@ -32,26 +32,27 @@ struct RtpPacket {
RTPSenderVideo::RTPSenderVideo(const int32_t id,
Clock* clock,
RTPSenderInterface* rtpSender)
: _id(id),
_rtpSender(*rtpSender),
_sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()),
_videoType(kRtpVideoGeneric),
_videoCodecInformation(NULL),
_maxBitrate(0),
_retransmissionSettings(kRetransmitBaseLayer),
RTPSenderInterface* rtpSender) :
_id(id),
_rtpSender(*rtpSender),
_sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()),
// Generic FEC
_fec(id),
_fecEnabled(false),
_payloadTypeRED(-1),
_payloadTypeFEC(-1),
_numberFirstPartition(0),
delta_fec_params_(),
key_fec_params_(),
producer_fec_(&_fec),
_fecOverheadRate(clock, NULL),
_videoBitrate(clock, NULL) {
_videoType(kRtpVideoGeneric),
_videoCodecInformation(NULL),
_maxBitrate(0),
_retransmissionSettings(kRetransmitBaseLayer),
// Generic FEC
_fec(id),
_fecEnabled(false),
_payloadTypeRED(-1),
_payloadTypeFEC(-1),
_numberFirstPartition(0),
delta_fec_params_(),
key_fec_params_(),
producer_fec_(&_fec),
_fecOverheadRate(clock),
_videoBitrate(clock) {
memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
memset(&key_fec_params_, 0, sizeof(key_fec_params_));
delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;

View File

@ -359,7 +359,6 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
rtp_rtcp->RegisterSendFrameCountObserver(NULL);
rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
rtp_rtcp->RegisterVideoBitrateObserver(NULL);
simulcast_rtp_rtcp_.pop_back();
removed_rtp_rtcp_.push_front(rtp_rtcp);
}
@ -420,8 +419,6 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
rtp_rtcp_->GetSendChannelRtcpStatisticsCallback());
rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(
rtp_rtcp_->GetSendChannelRtpStatisticsCallback());
rtp_rtcp->RegisterVideoBitrateObserver(
rtp_rtcp_->GetVideoBitrateObserver());
}
// |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old
// modules can be deleted after this step.
@ -435,7 +432,6 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
rtp_rtcp->RegisterSendFrameCountObserver(NULL);
rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
rtp_rtcp->RegisterVideoBitrateObserver(NULL);
simulcast_rtp_rtcp_.pop_back();
removed_rtp_rtcp_.push_front(rtp_rtcp);
}
@ -1431,17 +1427,6 @@ bool ViEChannel::GetSendSideDelay(int* avg_send_delay,
return valid_estimate;
}
void ViEChannel::RegisterSendBitrateObserver(
BitrateStatisticsObserver* observer) {
rtp_rtcp_->RegisterVideoBitrateObserver(observer);
CriticalSectionScoped cs(rtp_rtcp_cs_.get());
for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
it != simulcast_rtp_rtcp_.end();
it++) {
(*it)->RegisterVideoBitrateObserver(observer);
}
}
void ViEChannel::GetEstimatedReceiveBandwidth(
uint32_t* estimated_bandwidth) const {
vie_receiver_.EstimatedReceiveBandwidth(estimated_bandwidth);

View File

@ -202,9 +202,6 @@ class ViEChannel
bool GetSendSideDelay(int* avg_send_delay, int* max_send_delay) const;
void GetEstimatedReceiveBandwidth(uint32_t* estimated_bandwidth) const;
// Called on any new send bitrate estimate.
void RegisterSendBitrateObserver(BitrateStatisticsObserver* observer);
int32_t StartRTPDump(const char file_nameUTF8[1024],
RTPDirections direction);
int32_t StopRTPDump(RTPDirections direction);

View File

@ -1206,38 +1206,16 @@ int ViERTP_RTCPImpl::DeregisterReceiveChannelRtpStatisticsCallback(
// TODO(sprang): Implement
return -1;
}
// Called whenever the send bitrate is updated.
int ViERTP_RTCPImpl::RegisterSendBitrateObserver(
const int video_channel,
BitrateStatisticsObserver* observer) {
WEBRTC_TRACE(kTraceApiCall,
kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s(channel: %d)",
__FUNCTION__,
video_channel);
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
ViEChannel* vie_channel = cs.Channel(video_channel);
assert(vie_channel != NULL);
vie_channel->RegisterSendBitrateObserver(observer);
return 0;
int channel, BitrateStatisticsObserver* callback) {
// TODO(sprang): Implement
return -1;
}
int ViERTP_RTCPImpl::DeregisterSendBitrateObserver(
const int video_channel,
BitrateStatisticsObserver* observer) {
WEBRTC_TRACE(kTraceApiCall,
kTraceVideo,
ViEId(shared_data_->instance_id(), video_channel),
"%s(channel: %d)",
__FUNCTION__,
video_channel);
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
ViEChannel* vie_channel = cs.Channel(video_channel);
assert(vie_channel != NULL);
vie_channel->RegisterSendBitrateObserver(NULL);
return 0;
int channel, BitrateStatisticsObserver* callback) {
// TODO(sprang): Implement
return -1;
}
int ViERTP_RTCPImpl::RegisterSendFrameCountObserver(