Add TransportFeedback adapter, adapting remote feedback to bwe estiamtor
When using send-side bandwidth estimation, the inter-packet delay is reported back to the sender using RTCP TransportFeedback messages. Theis data needs to be translated into a format which the bandwidth estimator (now instantiated on the send side) can use, including looking up the local absolute send time from the send time history. BUG=webrtc:4173 Review URL: https://codereview.webrtc.org/1329083005 Cr-Commit-Position: refs/heads/master@{#9929}
This commit is contained in:
parent
36d619b01e
commit
5e023eb337
@ -228,6 +228,7 @@
|
||||
'remote_bitrate_estimator/test/bwe_unittest.cc',
|
||||
'remote_bitrate_estimator/test/metric_recorder_unittest.cc',
|
||||
'remote_bitrate_estimator/test/estimators/nada_unittest.cc',
|
||||
'remote_bitrate_estimator/transport_feedback_adapter_unittest.cc',
|
||||
'rtp_rtcp/source/mock/mock_rtp_payload_strategy.h',
|
||||
'rtp_rtcp/source/byte_io_unittest.cc',
|
||||
'rtp_rtcp/source/fec_receiver_unittest.cc',
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_MOCK_MOCK_REMOTE_BITRATE_ESTIMATOR_H_
|
||||
#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_MOCK_MOCK_REMOTE_BITRATE_ESTIMATOR_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class MockRemoteBitrateEstimator : public RemoteBitrateEstimator {
|
||||
public:
|
||||
MOCK_METHOD1(IncomingPacketFeedbackVector,
|
||||
void(const std::vector<PacketInfo>&));
|
||||
MOCK_METHOD4(IncomingPacket, void(int64_t, size_t, const RTPHeader&, bool));
|
||||
MOCK_METHOD1(RemoveStream, void(unsigned int));
|
||||
MOCK_CONST_METHOD2(LatestEstimate,
|
||||
bool(std::vector<unsigned int>*, unsigned int*));
|
||||
MOCK_CONST_METHOD1(GetStats, bool(ReceiveBandwidthEstimatorStats*));
|
||||
|
||||
// From CallStatsObserver;
|
||||
MOCK_METHOD2(OnRttUpdate, void(int64_t, int64_t));
|
||||
|
||||
// From Module.
|
||||
MOCK_METHOD0(TimeUntilNextProcess, int64_t());
|
||||
MOCK_METHOD0(Process, int32_t());
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_MOCK_MOCK_REMOTE_BITRATE_ESTIMATOR_H_
|
||||
@ -19,6 +19,7 @@
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/interface/module.h"
|
||||
#include "webrtc/modules/interface/module_common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -58,34 +59,9 @@ struct ReceiveBandwidthEstimatorStats {
|
||||
std::vector<int64_t> recent_arrival_time_ms;
|
||||
};
|
||||
|
||||
struct PacketInfo {
|
||||
PacketInfo(int64_t arrival_time_ms,
|
||||
int64_t send_time_ms,
|
||||
uint16_t sequence_number,
|
||||
size_t payload_size,
|
||||
bool was_paced)
|
||||
: arrival_time_ms(arrival_time_ms),
|
||||
send_time_ms(send_time_ms),
|
||||
sequence_number(sequence_number),
|
||||
payload_size(payload_size),
|
||||
was_paced(was_paced) {}
|
||||
// Time corresponding to when the packet was received. Timestamped with the
|
||||
// receiver's clock.
|
||||
int64_t arrival_time_ms;
|
||||
// Time corresponding to when the packet was sent, timestamped with the
|
||||
// sender's clock.
|
||||
int64_t send_time_ms;
|
||||
// Packet identifier, incremented with 1 for every packet generated by the
|
||||
// sender.
|
||||
uint16_t sequence_number;
|
||||
// Size of the packet excluding RTP headers.
|
||||
size_t payload_size;
|
||||
// True if the packet was paced out by the pacer.
|
||||
bool was_paced;
|
||||
};
|
||||
|
||||
class RemoteBitrateEstimator : public CallStatsObserver, public Module {
|
||||
public:
|
||||
static const int kDefaultMinBitrateBps = 30000;
|
||||
virtual ~RemoteBitrateEstimator() {}
|
||||
|
||||
virtual void IncomingPacketFeedbackVector(
|
||||
|
||||
@ -39,6 +39,8 @@
|
||||
'remote_estimator_proxy.cc',
|
||||
'remote_estimator_proxy.h',
|
||||
'send_time_history.cc',
|
||||
'transport_feedback_adapter.cc',
|
||||
'transport_feedback_adapter.h',
|
||||
'test/bwe_test_logging.cc',
|
||||
'test/bwe_test_logging.h',
|
||||
], # source
|
||||
|
||||
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
|
||||
#include "webrtc/modules/utility/interface/process_thread.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const int64_t kNoTimestamp = -1;
|
||||
const int64_t kSendTimeHistoryWindowMs = 10000;
|
||||
const int64_t kBaseTimestampScaleFactor =
|
||||
rtcp::TransportFeedback::kDeltaScaleFactor * (1 << 8);
|
||||
const int64_t kBaseTimestampRangeSizeUs = kBaseTimestampScaleFactor * (1 << 24);
|
||||
|
||||
TransportFeedbackAdapter::TransportFeedbackAdapter(
|
||||
RtcpBandwidthObserver* bandwidth_observer,
|
||||
Clock* clock,
|
||||
ProcessThread* process_thread)
|
||||
: send_time_history_(kSendTimeHistoryWindowMs),
|
||||
rtcp_bandwidth_observer_(bandwidth_observer),
|
||||
process_thread_(process_thread),
|
||||
clock_(clock),
|
||||
current_offset_ms_(kNoTimestamp),
|
||||
last_timestamp_us_(kNoTimestamp) {}
|
||||
|
||||
TransportFeedbackAdapter::~TransportFeedbackAdapter() {
|
||||
if (bitrate_estimator_.get())
|
||||
process_thread_->DeRegisterModule(bitrate_estimator_.get());
|
||||
}
|
||||
|
||||
void TransportFeedbackAdapter::SetBitrateEstimator(
|
||||
RemoteBitrateEstimator* rbe) {
|
||||
if (bitrate_estimator_.get() != rbe) {
|
||||
bitrate_estimator_.reset(rbe);
|
||||
process_thread_->RegisterModule(rbe);
|
||||
}
|
||||
}
|
||||
|
||||
void TransportFeedbackAdapter::OnPacketSent(const PacketInfo& info) {
|
||||
rtc::CritScope cs(&lock_);
|
||||
send_time_history_.AddAndRemoveOld(info);
|
||||
}
|
||||
|
||||
void TransportFeedbackAdapter::OnTransportFeedback(
|
||||
const rtcp::TransportFeedback& feedback) {
|
||||
int64_t timestamp_us = feedback.GetBaseTimeUs();
|
||||
// Add timestamp deltas to a local time base selected on first packet arrival.
|
||||
// This won't be the true time base, but makes it easier to manually inspect
|
||||
// time stamps.
|
||||
if (last_timestamp_us_ == kNoTimestamp) {
|
||||
current_offset_ms_ = clock_->TimeInMilliseconds();
|
||||
} else {
|
||||
int64_t delta = timestamp_us - last_timestamp_us_;
|
||||
|
||||
// Detect and compensate for wrap-arounds in base time.
|
||||
if (std::abs(delta - kBaseTimestampRangeSizeUs) < std::abs(delta)) {
|
||||
delta -= kBaseTimestampRangeSizeUs; // Wrap backwards.
|
||||
} else if (std::abs(delta + kBaseTimestampRangeSizeUs) < std::abs(delta)) {
|
||||
delta += kBaseTimestampRangeSizeUs; // Wrap forwards.
|
||||
}
|
||||
|
||||
current_offset_ms_ += delta / 1000;
|
||||
}
|
||||
last_timestamp_us_ = timestamp_us;
|
||||
|
||||
uint16_t sequence_number = feedback.GetBaseSequence();
|
||||
std::vector<int64_t> delta_vec = feedback.GetReceiveDeltasUs();
|
||||
auto delta_it = delta_vec.begin();
|
||||
std::vector<PacketInfo> packet_feedback_vector;
|
||||
packet_feedback_vector.reserve(delta_vec.size());
|
||||
|
||||
{
|
||||
rtc::CritScope cs(&lock_);
|
||||
size_t failed_lookups = 0;
|
||||
int64_t offset_us = 0;
|
||||
for (auto symbol : feedback.GetStatusVector()) {
|
||||
if (symbol != rtcp::TransportFeedback::StatusSymbol::kNotReceived) {
|
||||
DCHECK(delta_it != delta_vec.end());
|
||||
offset_us += *(delta_it++);
|
||||
int64_t timestamp_ms = current_offset_ms_ + (offset_us / 1000);
|
||||
PacketInfo info = {timestamp_ms, 0, sequence_number, 0, false};
|
||||
if (send_time_history_.GetInfo(&info, true)) {
|
||||
packet_feedback_vector.push_back(info);
|
||||
} else {
|
||||
++failed_lookups;
|
||||
}
|
||||
}
|
||||
++sequence_number;
|
||||
}
|
||||
DCHECK(delta_it == delta_vec.end());
|
||||
if (failed_lookups > 0) {
|
||||
LOG(LS_WARNING) << "Failed to lookup send time for " << failed_lookups
|
||||
<< " packet" << (failed_lookups > 1 ? "s" : "")
|
||||
<< ". Send time history too small?";
|
||||
}
|
||||
}
|
||||
DCHECK(bitrate_estimator_.get() != nullptr);
|
||||
bitrate_estimator_->IncomingPacketFeedbackVector(packet_feedback_vector);
|
||||
}
|
||||
|
||||
void TransportFeedbackAdapter::OnReceiveBitrateChanged(
|
||||
const std::vector<unsigned int>& ssrcs,
|
||||
unsigned int bitrate) {
|
||||
rtcp_bandwidth_observer_->OnReceivedEstimatedBitrate(bitrate);
|
||||
}
|
||||
|
||||
void TransportFeedbackAdapter::OnRttUpdate(int64_t avg_rtt_ms,
|
||||
int64_t max_rtt_ms) {
|
||||
DCHECK(bitrate_estimator_.get() != nullptr);
|
||||
bitrate_estimator_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TRANSPORT_FEEDBACK_ADAPTER_H_
|
||||
#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TRANSPORT_FEEDBACK_ADAPTER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/base/thread_annotations.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
#include "webrtc/modules/interface/module_common_types.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ProcessThread;
|
||||
|
||||
class TransportFeedbackAdapter : public TransportFeedbackObserver,
|
||||
public CallStatsObserver,
|
||||
public RemoteBitrateObserver {
|
||||
public:
|
||||
TransportFeedbackAdapter(RtcpBandwidthObserver* bandwidth_observer,
|
||||
Clock* clock,
|
||||
ProcessThread* process_thread);
|
||||
virtual ~TransportFeedbackAdapter();
|
||||
|
||||
void OnPacketSent(const PacketInfo& info) override;
|
||||
|
||||
void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override;
|
||||
|
||||
void SetBitrateEstimator(RemoteBitrateEstimator* rbe);
|
||||
|
||||
private:
|
||||
void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
|
||||
unsigned int bitrate) override;
|
||||
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
|
||||
|
||||
rtc::CriticalSection lock_;
|
||||
SendTimeHistory send_time_history_ GUARDED_BY(&lock_);
|
||||
rtc::scoped_ptr<RtcpBandwidthObserver> rtcp_bandwidth_observer_;
|
||||
rtc::scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
|
||||
ProcessThread* const process_thread_;
|
||||
Clock* const clock_;
|
||||
int64_t current_offset_ms_;
|
||||
int64_t last_timestamp_us_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TRANSPORT_FEEDBACK_ADAPTER_H_
|
||||
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
|
||||
#include "webrtc/modules/utility/interface/mock/mock_process_thread.h"
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Invoke;
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class TransportFeedbackAdapterTest : public ::testing::Test {
|
||||
public:
|
||||
TransportFeedbackAdapterTest()
|
||||
: clock_(0),
|
||||
bitrate_estimator_(nullptr),
|
||||
receiver_estimated_bitrate_(0) {}
|
||||
|
||||
virtual ~TransportFeedbackAdapterTest() {}
|
||||
|
||||
virtual void SetUp() {
|
||||
adapter_.reset(new TransportFeedbackAdapter(
|
||||
new RtcpBandwidthObserverAdapter(this), &clock_, &process_thread_));
|
||||
|
||||
bitrate_estimator_ = new MockRemoteBitrateEstimator();
|
||||
EXPECT_CALL(process_thread_, RegisterModule(bitrate_estimator_)).Times(1);
|
||||
adapter_->SetBitrateEstimator(bitrate_estimator_);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
EXPECT_CALL(process_thread_, DeRegisterModule(bitrate_estimator_)).Times(1);
|
||||
adapter_.reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Proxy class used since TransportFeedbackAdapter will own the instance
|
||||
// passed at construction.
|
||||
class RtcpBandwidthObserverAdapter : public RtcpBandwidthObserver {
|
||||
public:
|
||||
explicit RtcpBandwidthObserverAdapter(TransportFeedbackAdapterTest* owner)
|
||||
: owner_(owner) {}
|
||||
|
||||
void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
|
||||
owner_->receiver_estimated_bitrate_ = bitrate;
|
||||
}
|
||||
|
||||
void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
|
||||
int64_t rtt,
|
||||
int64_t now_ms) override {
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
|
||||
TransportFeedbackAdapterTest* const owner_;
|
||||
};
|
||||
|
||||
void OnReceivedEstimatedBitrate(uint32_t bitrate) {}
|
||||
|
||||
void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
|
||||
int64_t rtt,
|
||||
int64_t now_ms) {}
|
||||
|
||||
void ComparePacketVectors(const std::vector<PacketInfo>& truth,
|
||||
const std::vector<PacketInfo>& input) {
|
||||
ASSERT_EQ(truth.size(), input.size());
|
||||
size_t len = truth.size();
|
||||
// truth contains the input data for the test, and input is what will be
|
||||
// sent to the bandwidth estimator. truth.arrival_tims_ms is used to
|
||||
// populate the transport feedback messages. As these times may be changed
|
||||
// (because of resolution limits in the packets, and because of the time
|
||||
// base adjustment performed by the TransportFeedbackAdapter at the first
|
||||
// packet, the truth[x].arrival_time and input[x].arrival_time may not be
|
||||
// equal. However, the difference must be the same for all x.
|
||||
int64_t arrival_time_delta =
|
||||
truth[0].arrival_time_ms - input[0].arrival_time_ms;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
EXPECT_EQ(truth[i].arrival_time_ms,
|
||||
input[i].arrival_time_ms + arrival_time_delta);
|
||||
EXPECT_EQ(truth[i].send_time_ms, input[i].send_time_ms);
|
||||
EXPECT_EQ(truth[i].sequence_number, input[i].sequence_number);
|
||||
EXPECT_EQ(truth[i].payload_size, input[i].payload_size);
|
||||
EXPECT_EQ(truth[i].was_paced, input[i].was_paced);
|
||||
}
|
||||
}
|
||||
|
||||
// Utility method, to reset arrival_time_ms before adding send time.
|
||||
void OnPacketSent(PacketInfo info) {
|
||||
info.arrival_time_ms = 0;
|
||||
adapter_->OnPacketSent(info);
|
||||
}
|
||||
|
||||
SimulatedClock clock_;
|
||||
MockProcessThread process_thread_;
|
||||
MockRemoteBitrateEstimator* bitrate_estimator_;
|
||||
rtc::scoped_ptr<TransportFeedbackAdapter> adapter_;
|
||||
|
||||
uint32_t receiver_estimated_bitrate_;
|
||||
};
|
||||
|
||||
TEST_F(TransportFeedbackAdapterTest, AdaptsFeedbackAndPopulatesSendTimes) {
|
||||
std::vector<PacketInfo> packets;
|
||||
packets.push_back(PacketInfo(100, 200, 0, 1500, true));
|
||||
packets.push_back(PacketInfo(110, 210, 1, 1500, true));
|
||||
packets.push_back(PacketInfo(120, 220, 2, 1500, true));
|
||||
packets.push_back(PacketInfo(130, 230, 3, 1500, true));
|
||||
packets.push_back(PacketInfo(140, 240, 4, 1500, true));
|
||||
|
||||
for (const PacketInfo& packet : packets)
|
||||
OnPacketSent(packet);
|
||||
|
||||
rtcp::TransportFeedback feedback;
|
||||
feedback.WithBase(packets[0].sequence_number,
|
||||
packets[0].arrival_time_ms * 1000);
|
||||
|
||||
for (const PacketInfo& packet : packets) {
|
||||
EXPECT_TRUE(feedback.WithReceivedPacket(packet.sequence_number,
|
||||
packet.arrival_time_ms * 1000));
|
||||
}
|
||||
|
||||
feedback.Build();
|
||||
|
||||
EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke(
|
||||
[packets, this](const std::vector<PacketInfo>& feedback_vector) {
|
||||
ComparePacketVectors(packets, feedback_vector);
|
||||
}));
|
||||
adapter_->OnTransportFeedback(feedback);
|
||||
}
|
||||
|
||||
TEST_F(TransportFeedbackAdapterTest, HandlesDroppedPackets) {
|
||||
std::vector<PacketInfo> packets;
|
||||
packets.push_back(PacketInfo(100, 200, 0, 1500, true));
|
||||
packets.push_back(PacketInfo(110, 210, 1, 1500, true));
|
||||
packets.push_back(PacketInfo(120, 220, 2, 1500, true));
|
||||
packets.push_back(PacketInfo(130, 230, 3, 1500, true));
|
||||
packets.push_back(PacketInfo(140, 240, 4, 1500, true));
|
||||
|
||||
const uint16_t kSendSideDropBefore = 1;
|
||||
const uint16_t kReceiveSideDropAfter = 3;
|
||||
|
||||
for (const PacketInfo& packet : packets) {
|
||||
if (packet.sequence_number >= kSendSideDropBefore)
|
||||
OnPacketSent(packet);
|
||||
}
|
||||
|
||||
rtcp::TransportFeedback feedback;
|
||||
feedback.WithBase(packets[0].sequence_number,
|
||||
packets[0].arrival_time_ms * 1000);
|
||||
|
||||
for (const PacketInfo& packet : packets) {
|
||||
if (packet.sequence_number <= kReceiveSideDropAfter) {
|
||||
EXPECT_TRUE(feedback.WithReceivedPacket(packet.sequence_number,
|
||||
packet.arrival_time_ms * 1000));
|
||||
}
|
||||
}
|
||||
|
||||
feedback.Build();
|
||||
|
||||
std::vector<PacketInfo> expected_packets(
|
||||
packets.begin() + kSendSideDropBefore,
|
||||
packets.begin() + kReceiveSideDropAfter + 1);
|
||||
|
||||
EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([expected_packets,
|
||||
this](const std::vector<PacketInfo>& feedback_vector) {
|
||||
ComparePacketVectors(expected_packets, feedback_vector);
|
||||
}));
|
||||
adapter_->OnTransportFeedback(feedback);
|
||||
}
|
||||
|
||||
TEST_F(TransportFeedbackAdapterTest, SendTimeWrapsBothWays) {
|
||||
int64_t kHighArrivalTimeMs = rtcp::TransportFeedback::kDeltaScaleFactor *
|
||||
static_cast<int64_t>(1 << 8) *
|
||||
static_cast<int64_t>((1 << 23) - 1) / 1000;
|
||||
std::vector<PacketInfo> packets;
|
||||
packets.push_back(PacketInfo(kHighArrivalTimeMs - 64, 200, 0, 1500, true));
|
||||
packets.push_back(PacketInfo(kHighArrivalTimeMs + 64, 210, 1, 1500, true));
|
||||
packets.push_back(PacketInfo(kHighArrivalTimeMs, 220, 2, 1500, true));
|
||||
|
||||
for (const PacketInfo& packet : packets)
|
||||
OnPacketSent(packet);
|
||||
|
||||
for (size_t i = 0; i < packets.size(); ++i) {
|
||||
rtc::scoped_ptr<rtcp::TransportFeedback> feedback(
|
||||
new rtcp::TransportFeedback());
|
||||
feedback->WithBase(packets[i].sequence_number,
|
||||
packets[i].arrival_time_ms * 1000);
|
||||
|
||||
EXPECT_TRUE(feedback->WithReceivedPacket(
|
||||
packets[i].sequence_number, packets[i].arrival_time_ms * 1000));
|
||||
|
||||
rtc::scoped_ptr<rtcp::RawPacket> raw_packet = feedback->Build();
|
||||
feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(),
|
||||
raw_packet->Length());
|
||||
|
||||
std::vector<PacketInfo> expected_packets;
|
||||
expected_packets.push_back(packets[i]);
|
||||
|
||||
EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([expected_packets, this](
|
||||
const std::vector<PacketInfo>& feedback_vector) {
|
||||
ComparePacketVectors(expected_packets, feedback_vector);
|
||||
}));
|
||||
adapter_->OnTransportFeedback(*feedback.get());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TransportFeedbackAdapterTest, TimestampDeltas) {
|
||||
std::vector<PacketInfo> sent_packets;
|
||||
const int64_t kSmallDeltaUs =
|
||||
rtcp::TransportFeedback::kDeltaScaleFactor * ((1 << 8) - 1);
|
||||
const int64_t kLargePositiveDeltaUs =
|
||||
rtcp::TransportFeedback::kDeltaScaleFactor *
|
||||
std::numeric_limits<int16_t>::max();
|
||||
const int64_t kLargeNegativeDeltaUs =
|
||||
rtcp::TransportFeedback::kDeltaScaleFactor *
|
||||
std::numeric_limits<int16_t>::min();
|
||||
|
||||
PacketInfo info(100, 200, 0, 1500, true);
|
||||
sent_packets.push_back(info);
|
||||
|
||||
info.send_time_ms += kSmallDeltaUs / 1000;
|
||||
info.arrival_time_ms += kSmallDeltaUs / 1000;
|
||||
++info.sequence_number;
|
||||
sent_packets.push_back(info);
|
||||
|
||||
info.send_time_ms += kLargePositiveDeltaUs / 1000;
|
||||
info.arrival_time_ms += kLargePositiveDeltaUs / 1000;
|
||||
++info.sequence_number;
|
||||
sent_packets.push_back(info);
|
||||
|
||||
info.send_time_ms += kLargeNegativeDeltaUs / 1000;
|
||||
info.arrival_time_ms += kLargeNegativeDeltaUs / 1000;
|
||||
++info.sequence_number;
|
||||
sent_packets.push_back(info);
|
||||
|
||||
// Too large, delta - will need two feedback messages.
|
||||
info.send_time_ms += (kLargePositiveDeltaUs + 1000) / 1000;
|
||||
info.arrival_time_ms += (kLargePositiveDeltaUs + 1000) / 1000;
|
||||
++info.sequence_number;
|
||||
|
||||
// Packets will be added to send history.
|
||||
for (const PacketInfo& packet : sent_packets)
|
||||
OnPacketSent(packet);
|
||||
OnPacketSent(info);
|
||||
|
||||
// Create expected feedback and send into adapter.
|
||||
rtc::scoped_ptr<rtcp::TransportFeedback> feedback(
|
||||
new rtcp::TransportFeedback());
|
||||
feedback->WithBase(sent_packets[0].sequence_number,
|
||||
sent_packets[0].arrival_time_ms * 1000);
|
||||
|
||||
for (const PacketInfo& packet : sent_packets) {
|
||||
EXPECT_TRUE(feedback->WithReceivedPacket(packet.sequence_number,
|
||||
packet.arrival_time_ms * 1000));
|
||||
}
|
||||
EXPECT_FALSE(feedback->WithReceivedPacket(info.sequence_number,
|
||||
info.arrival_time_ms * 1000));
|
||||
|
||||
rtc::scoped_ptr<rtcp::RawPacket> raw_packet = feedback->Build();
|
||||
feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(),
|
||||
raw_packet->Length());
|
||||
|
||||
std::vector<PacketInfo> received_feedback;
|
||||
|
||||
EXPECT_TRUE(feedback.get() != nullptr);
|
||||
EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke([sent_packets, &received_feedback](
|
||||
const std::vector<PacketInfo>& feedback_vector) {
|
||||
EXPECT_EQ(sent_packets.size(), feedback_vector.size());
|
||||
received_feedback = feedback_vector;
|
||||
}));
|
||||
adapter_->OnTransportFeedback(*feedback.get());
|
||||
|
||||
// Create a new feedback message and add the trailing item.
|
||||
feedback.reset(new rtcp::TransportFeedback());
|
||||
feedback->WithBase(info.sequence_number, info.arrival_time_ms * 1000);
|
||||
EXPECT_TRUE(feedback->WithReceivedPacket(info.sequence_number,
|
||||
info.arrival_time_ms * 1000));
|
||||
raw_packet = feedback->Build();
|
||||
feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(),
|
||||
raw_packet->Length());
|
||||
|
||||
EXPECT_TRUE(feedback.get() != nullptr);
|
||||
EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_))
|
||||
.Times(1)
|
||||
.WillOnce(Invoke(
|
||||
[&received_feedback](const std::vector<PacketInfo>& feedback_vector) {
|
||||
EXPECT_EQ(1u, feedback_vector.size());
|
||||
received_feedback.push_back(feedback_vector[0]);
|
||||
}));
|
||||
adapter_->OnTransportFeedback(*feedback.get());
|
||||
|
||||
sent_packets.push_back(info);
|
||||
|
||||
ComparePacketVectors(sent_packets, received_feedback);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
@ -65,7 +65,7 @@ class RtpRtcp : public Module {
|
||||
Transport* outgoing_transport;
|
||||
RtcpIntraFrameObserver* intra_frame_callback;
|
||||
RtcpBandwidthObserver* bandwidth_callback;
|
||||
SendTimeObserver* send_time_callback;
|
||||
TransportFeedbackObserver* transport_feedback_callback;
|
||||
RtcpRttStats* rtt_stats;
|
||||
RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer;
|
||||
RtpAudioFeedback* audio_messages;
|
||||
|
||||
@ -24,6 +24,9 @@
|
||||
#define TIMEOUT_SEI_MESSAGES_MS 30000 // in milliseconds
|
||||
|
||||
namespace webrtc {
|
||||
namespace rtcp {
|
||||
class TransportFeedback;
|
||||
}
|
||||
|
||||
const int kVideoPayloadTypeFrequency = 90000;
|
||||
|
||||
@ -293,15 +296,42 @@ class RtcpBandwidthObserver {
|
||||
virtual ~RtcpBandwidthObserver() {}
|
||||
};
|
||||
|
||||
class SendTimeObserver {
|
||||
public:
|
||||
SendTimeObserver() {}
|
||||
virtual ~SendTimeObserver() {}
|
||||
struct PacketInfo {
|
||||
PacketInfo(int64_t arrival_time_ms,
|
||||
int64_t send_time_ms,
|
||||
uint16_t sequence_number,
|
||||
size_t payload_size,
|
||||
bool was_paced)
|
||||
: arrival_time_ms(arrival_time_ms),
|
||||
send_time_ms(send_time_ms),
|
||||
sequence_number(sequence_number),
|
||||
payload_size(payload_size),
|
||||
was_paced(was_paced) {}
|
||||
// Time corresponding to when the packet was received. Timestamped with the
|
||||
// receiver's clock.
|
||||
int64_t arrival_time_ms;
|
||||
// Time corresponding to when the packet was sent, timestamped with the
|
||||
// sender's clock.
|
||||
int64_t send_time_ms;
|
||||
// Packet identifier, incremented with 1 for every packet generated by the
|
||||
// sender.
|
||||
uint16_t sequence_number;
|
||||
// Size of the packet excluding RTP headers.
|
||||
size_t payload_size;
|
||||
// True if the packet was paced out by the pacer.
|
||||
bool was_paced;
|
||||
};
|
||||
|
||||
// Transport-wide sequence number and timestamp (system time in milliseconds),
|
||||
// of when the packet was put on the wire.
|
||||
virtual void OnPacketSent(uint16_t transport_sequence_number,
|
||||
int64_t send_time) = 0;
|
||||
class TransportFeedbackObserver {
|
||||
public:
|
||||
TransportFeedbackObserver() {}
|
||||
virtual ~TransportFeedbackObserver() {}
|
||||
|
||||
// Note: Transport-wide sequence number as sequence number. Arrival time
|
||||
// must be set to 0.
|
||||
virtual void OnPacketSent(const PacketInfo& info) = 0;
|
||||
|
||||
virtual void OnTransportFeedback(const rtcp::TransportFeedback& feedback) = 0;
|
||||
};
|
||||
|
||||
class RtcpRttStats {
|
||||
|
||||
@ -35,6 +35,7 @@ RtpRtcp::Configuration::Configuration()
|
||||
outgoing_transport(nullptr),
|
||||
intra_frame_callback(nullptr),
|
||||
bandwidth_callback(nullptr),
|
||||
transport_feedback_callback(nullptr),
|
||||
rtt_stats(nullptr),
|
||||
rtcp_packet_type_counter_observer(nullptr),
|
||||
audio_messages(NullObjectRtpAudioFeedback()),
|
||||
@ -43,8 +44,7 @@ RtpRtcp::Configuration::Configuration()
|
||||
packet_router(nullptr),
|
||||
send_bitrate_observer(nullptr),
|
||||
send_frame_count_observer(nullptr),
|
||||
send_side_delay_observer(nullptr) {
|
||||
}
|
||||
send_side_delay_observer(nullptr) {}
|
||||
|
||||
RtpRtcp* RtpRtcp::CreateRtpRtcp(const RtpRtcp::Configuration& configuration) {
|
||||
if (configuration.clock) {
|
||||
@ -67,7 +67,7 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
|
||||
configuration.audio_messages,
|
||||
configuration.paced_sender,
|
||||
configuration.packet_router,
|
||||
configuration.send_time_callback,
|
||||
configuration.transport_feedback_callback,
|
||||
configuration.send_bitrate_observer,
|
||||
configuration.send_frame_count_observer,
|
||||
configuration.send_side_delay_observer),
|
||||
|
||||
@ -104,7 +104,7 @@ RTPSender::RTPSender(int32_t id,
|
||||
RtpAudioFeedback* audio_feedback,
|
||||
PacedSender* paced_sender,
|
||||
PacketRouter* packet_router,
|
||||
SendTimeObserver* send_time_observer,
|
||||
TransportFeedbackObserver* transport_feedback_observer,
|
||||
BitrateStatisticsObserver* bitrate_callback,
|
||||
FrameCountObserver* frame_count_observer,
|
||||
SendSideDelayObserver* send_side_delay_observer)
|
||||
@ -122,7 +122,7 @@ RTPSender::RTPSender(int32_t id,
|
||||
video_(audio ? nullptr : new RTPSenderVideo(clock, this)),
|
||||
paced_sender_(paced_sender),
|
||||
packet_router_(packet_router),
|
||||
send_time_observer_(send_time_observer),
|
||||
transport_feedback_observer_(transport_feedback_observer),
|
||||
last_capture_time_ms_sent_(0),
|
||||
send_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
transport_(transport),
|
||||
@ -676,8 +676,10 @@ size_t RTPSender::SendPadData(uint32_t timestamp,
|
||||
if (!SendPacketToNetwork(padding_packet, length))
|
||||
break;
|
||||
|
||||
if (using_transport_seq)
|
||||
send_time_observer_->OnPacketSent(transport_seq, now_ms);
|
||||
if (using_transport_seq && transport_feedback_observer_) {
|
||||
transport_feedback_observer_->OnPacketSent(
|
||||
PacketInfo(0, now_ms, transport_seq, length, true));
|
||||
}
|
||||
|
||||
bytes_sent += padding_bytes_in_packet;
|
||||
UpdateRtpStats(padding_packet, length, rtp_header, over_rtx, false);
|
||||
@ -919,9 +921,10 @@ bool RTPSender::PrepareAndSendPacket(uint8_t* buffer,
|
||||
UpdateAbsoluteSendTime(buffer_to_send_ptr, length, rtp_header, now_ms);
|
||||
|
||||
uint16_t transport_seq = 0;
|
||||
// TODO(sprang): Potentially too much overhead in IsRegistered()?
|
||||
bool using_transport_seq = rtp_header_extension_map_.IsRegistered(
|
||||
kRtpExtensionTransportSequenceNumber) &&
|
||||
packet_router_;
|
||||
packet_router_ && !is_retransmit;
|
||||
if (using_transport_seq) {
|
||||
transport_seq =
|
||||
UpdateTransportSequenceNumber(buffer_to_send_ptr, length, rtp_header);
|
||||
@ -932,8 +935,10 @@ bool RTPSender::PrepareAndSendPacket(uint8_t* buffer,
|
||||
CriticalSectionScoped lock(send_critsect_.get());
|
||||
media_has_been_sent_ = true;
|
||||
}
|
||||
if (using_transport_seq)
|
||||
send_time_observer_->OnPacketSent(transport_seq, now_ms);
|
||||
if (using_transport_seq && transport_feedback_observer_) {
|
||||
transport_feedback_observer_->OnPacketSent(
|
||||
PacketInfo(0, now_ms, transport_seq, length, true));
|
||||
}
|
||||
UpdateRtpStats(buffer_to_send_ptr, length, rtp_header, send_over_rtx,
|
||||
is_retransmit);
|
||||
return ret;
|
||||
|
||||
@ -93,7 +93,7 @@ class RTPSender : public RTPSenderInterface {
|
||||
RtpAudioFeedback* audio_feedback,
|
||||
PacedSender* paced_sender,
|
||||
PacketRouter* packet_router,
|
||||
SendTimeObserver* send_time_observer,
|
||||
TransportFeedbackObserver* transport_feedback_callback,
|
||||
BitrateStatisticsObserver* bitrate_callback,
|
||||
FrameCountObserver* frame_count_observer,
|
||||
SendSideDelayObserver* send_side_delay_observer);
|
||||
@ -396,7 +396,7 @@ class RTPSender : public RTPSenderInterface {
|
||||
|
||||
PacedSender* const paced_sender_;
|
||||
PacketRouter* const packet_router_;
|
||||
SendTimeObserver* const send_time_observer_;
|
||||
TransportFeedbackObserver* const transport_feedback_observer_;
|
||||
int64_t last_capture_time_ms_sent_;
|
||||
rtc::scoped_ptr<CriticalSectionWrapper> send_critsect_;
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ ViEChannel::ViEChannel(int32_t channel_id,
|
||||
ProcessThread* module_process_thread,
|
||||
RtcpIntraFrameObserver* intra_frame_observer,
|
||||
RtcpBandwidthObserver* bandwidth_observer,
|
||||
SendTimeObserver* send_time_observer,
|
||||
TransportFeedbackObserver* transport_feedback_observer,
|
||||
RemoteBitrateEstimator* remote_bitrate_estimator,
|
||||
RtcpRttStats* rtt_stats,
|
||||
PacedSender* paced_sender,
|
||||
@ -112,7 +112,7 @@ ViEChannel::ViEChannel(int32_t channel_id,
|
||||
paced_sender_(paced_sender),
|
||||
packet_router_(packet_router),
|
||||
bandwidth_observer_(bandwidth_observer),
|
||||
send_time_observer_(send_time_observer),
|
||||
transport_feedback_observer_(transport_feedback_observer),
|
||||
nack_history_size_sender_(kSendSidePacketHistorySize),
|
||||
max_nack_reordering_threshold_(kMaxPacketAgeToNack),
|
||||
pre_render_callback_(NULL),
|
||||
@ -127,12 +127,12 @@ ViEChannel::ViEChannel(int32_t channel_id,
|
||||
transport,
|
||||
sender ? intra_frame_observer_ : nullptr,
|
||||
sender ? bandwidth_observer_.get() : nullptr,
|
||||
sender ? send_time_observer_ : nullptr,
|
||||
transport_feedback_observer_,
|
||||
rtt_stats_,
|
||||
&rtcp_packet_type_counter_observer_,
|
||||
remote_bitrate_estimator,
|
||||
paced_sender_,
|
||||
sender_ ? packet_router_ : nullptr,
|
||||
packet_router_,
|
||||
&send_bitrate_observer_,
|
||||
&send_frame_count_observer_,
|
||||
&send_side_delay_observer_,
|
||||
@ -153,8 +153,8 @@ int32_t ViEChannel::Init() {
|
||||
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
|
||||
rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
|
||||
}
|
||||
packet_router_->AddRtpModule(rtp_rtcp_modules_[0]);
|
||||
if (sender_) {
|
||||
packet_router_->AddRtpModule(rtp_rtcp_modules_[0]);
|
||||
std::list<RtpRtcp*> send_rtp_modules(1, rtp_rtcp_modules_[0]);
|
||||
send_payload_router_->SetSendingRtpModules(send_rtp_modules);
|
||||
DCHECK(!send_payload_router_->active());
|
||||
@ -181,10 +181,8 @@ ViEChannel::~ViEChannel() {
|
||||
module_process_thread_->DeRegisterModule(vcm_);
|
||||
module_process_thread_->DeRegisterModule(&vie_sync_);
|
||||
send_payload_router_->SetSendingRtpModules(std::list<RtpRtcp*>());
|
||||
if (sender_ && packet_router_) {
|
||||
for (size_t i = 0; i < num_active_rtp_rtcp_modules_; ++i)
|
||||
packet_router_->RemoveRtpModule(rtp_rtcp_modules_[i]);
|
||||
}
|
||||
for (size_t i = 0; i < num_active_rtp_rtcp_modules_; ++i)
|
||||
packet_router_->RemoveRtpModule(rtp_rtcp_modules_[i]);
|
||||
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
||||
module_process_thread_->DeRegisterModule(rtp_rtcp);
|
||||
delete rtp_rtcp;
|
||||
@ -406,14 +404,12 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
|
||||
// Deregister previously registered modules.
|
||||
for (size_t i = num_active_modules; i < num_prev_active_modules; ++i) {
|
||||
module_process_thread_->DeRegisterModule(rtp_rtcp_modules_[i]);
|
||||
if (sender_ && packet_router_)
|
||||
packet_router_->RemoveRtpModule(rtp_rtcp_modules_[i]);
|
||||
packet_router_->RemoveRtpModule(rtp_rtcp_modules_[i]);
|
||||
}
|
||||
// Register new active modules.
|
||||
for (size_t i = num_prev_active_modules; i < num_active_modules; ++i) {
|
||||
module_process_thread_->RegisterModule(rtp_rtcp_modules_[i]);
|
||||
if (sender_ && packet_router_)
|
||||
packet_router_->AddRtpModule(rtp_rtcp_modules_[i]);
|
||||
packet_router_->AddRtpModule(rtp_rtcp_modules_[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -435,6 +431,7 @@ int32_t ViEChannel::SetReceiveCodec(const VideoCodec& video_codec) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32_t ViEChannel::RegisterExternalDecoder(const uint8_t pl_type,
|
||||
VideoDecoder* decoder,
|
||||
bool buffered_rendering,
|
||||
@ -1026,6 +1023,7 @@ CallStatsObserver* ViEChannel::GetStatsObserver() {
|
||||
int32_t ViEChannel::FrameToRender(VideoFrame& video_frame) { // NOLINT
|
||||
CriticalSectionScoped cs(crit_.get());
|
||||
|
||||
|
||||
if (pre_render_callback_ != NULL)
|
||||
pre_render_callback_->FrameCallback(&video_frame);
|
||||
|
||||
@ -1142,7 +1140,7 @@ std::vector<RtpRtcp*> ViEChannel::CreateRtpRtcpModules(
|
||||
Transport* outgoing_transport,
|
||||
RtcpIntraFrameObserver* intra_frame_callback,
|
||||
RtcpBandwidthObserver* bandwidth_callback,
|
||||
SendTimeObserver* send_time_callback,
|
||||
TransportFeedbackObserver* transport_feedback_callback,
|
||||
RtcpRttStats* rtt_stats,
|
||||
RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer,
|
||||
RemoteBitrateEstimator* remote_bitrate_estimator,
|
||||
@ -1170,7 +1168,7 @@ std::vector<RtpRtcp*> ViEChannel::CreateRtpRtcpModules(
|
||||
configuration.send_frame_count_observer = send_frame_count_observer;
|
||||
configuration.send_side_delay_observer = send_side_delay_observer;
|
||||
configuration.bandwidth_callback = bandwidth_callback;
|
||||
configuration.send_time_callback = send_time_callback;
|
||||
configuration.transport_feedback_callback = transport_feedback_callback;
|
||||
|
||||
std::vector<RtpRtcp*> modules;
|
||||
for (size_t i = 0; i < num_modules; ++i) {
|
||||
|
||||
@ -72,7 +72,7 @@ class ViEChannel : public VCMFrameTypeCallback,
|
||||
ProcessThread* module_process_thread,
|
||||
RtcpIntraFrameObserver* intra_frame_observer,
|
||||
RtcpBandwidthObserver* bandwidth_observer,
|
||||
SendTimeObserver* send_time_observer,
|
||||
TransportFeedbackObserver* transport_feedback_observer,
|
||||
RemoteBitrateEstimator* remote_bitrate_estimator,
|
||||
RtcpRttStats* rtt_stats,
|
||||
PacedSender* paced_sender,
|
||||
@ -302,7 +302,7 @@ class ViEChannel : public VCMFrameTypeCallback,
|
||||
Transport* outgoing_transport,
|
||||
RtcpIntraFrameObserver* intra_frame_callback,
|
||||
RtcpBandwidthObserver* bandwidth_callback,
|
||||
SendTimeObserver* send_time_observer,
|
||||
TransportFeedbackObserver* transport_feedback_callback,
|
||||
RtcpRttStats* rtt_stats,
|
||||
RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer,
|
||||
RemoteBitrateEstimator* remote_bitrate_estimator,
|
||||
@ -441,7 +441,7 @@ class ViEChannel : public VCMFrameTypeCallback,
|
||||
PacketRouter* const packet_router_;
|
||||
|
||||
const rtc::scoped_ptr<RtcpBandwidthObserver> bandwidth_observer_;
|
||||
SendTimeObserver* const send_time_observer_;
|
||||
TransportFeedbackObserver* const transport_feedback_observer_;
|
||||
|
||||
rtc::scoped_ptr<ThreadWrapper> decode_thread_;
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
|
||||
#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
|
||||
#include "webrtc/modules/utility/interface/process_thread.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
@ -34,7 +35,6 @@ namespace webrtc {
|
||||
namespace {
|
||||
|
||||
static const uint32_t kTimeOffsetSwitchThreshold = 30;
|
||||
static const uint32_t kMinBitrateBps = 30000;
|
||||
|
||||
class WrappingBitrateEstimator : public RemoteBitrateEstimator {
|
||||
public:
|
||||
@ -42,7 +42,7 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator {
|
||||
: observer_(observer),
|
||||
clock_(clock),
|
||||
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
min_bitrate_bps_(kMinBitrateBps),
|
||||
min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps),
|
||||
rbe_(new RemoteBitrateEstimatorSingleStream(observer_,
|
||||
clock_,
|
||||
min_bitrate_bps_)),
|
||||
@ -139,21 +139,8 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator {
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(WrappingBitrateEstimator);
|
||||
};
|
||||
|
||||
static const int64_t kSendTimeHistoryWindowMs = 2000;
|
||||
|
||||
} // namespace
|
||||
|
||||
class AdaptedSendTimeHistory : public SendTimeHistory, public SendTimeObserver {
|
||||
public:
|
||||
AdaptedSendTimeHistory() : SendTimeHistory(kSendTimeHistoryWindowMs) {}
|
||||
virtual ~AdaptedSendTimeHistory() {}
|
||||
|
||||
void OnPacketSent(uint16_t sequence_number, int64_t send_time) override {
|
||||
PacketInfo info(0, send_time, sequence_number, 0, false);
|
||||
SendTimeHistory::AddAndRemoveOld(info);
|
||||
}
|
||||
};
|
||||
|
||||
ChannelGroup::ChannelGroup(ProcessThread* process_thread)
|
||||
: remb_(new VieRemb()),
|
||||
bitrate_allocator_(new BitrateAllocator()),
|
||||
@ -172,8 +159,7 @@ ChannelGroup::ChannelGroup(ProcessThread* process_thread)
|
||||
// construction.
|
||||
bitrate_controller_(
|
||||
BitrateController::CreateBitrateController(Clock::GetRealTimeClock(),
|
||||
this)),
|
||||
send_time_history_(new AdaptedSendTimeHistory()) {
|
||||
this)) {
|
||||
remote_bitrate_estimator_.reset(new WrappingBitrateEstimator(
|
||||
remb_.get(), Clock::GetRealTimeClock()));
|
||||
|
||||
@ -250,10 +236,9 @@ bool ChannelGroup::CreateChannel(int channel_id,
|
||||
rtc::scoped_ptr<ViEChannel> channel(new ViEChannel(
|
||||
channel_id, engine_id, number_of_cores, transport, process_thread_,
|
||||
encoder_state_feedback_->GetRtcpIntraFrameObserver(),
|
||||
bitrate_controller_->CreateRtcpBandwidthObserver(),
|
||||
send_time_history_.get(), remote_bitrate_estimator_.get(),
|
||||
call_stats_->rtcp_rtt_stats(), pacer_.get(), packet_router_.get(),
|
||||
max_rtp_streams, sender));
|
||||
bitrate_controller_->CreateRtcpBandwidthObserver(), nullptr,
|
||||
remote_bitrate_estimator_.get(), call_stats_->rtcp_rtt_stats(),
|
||||
pacer_.get(), packet_router_.get(), max_rtp_streams, sender));
|
||||
if (channel->Init() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -22,7 +22,6 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AdaptedSendTimeHistory;
|
||||
class BitrateAllocator;
|
||||
class CallStats;
|
||||
class Config;
|
||||
@ -97,11 +96,10 @@ class ChannelGroup : public BitrateObserver {
|
||||
EncoderMap vie_encoder_map_ GUARDED_BY(encoder_map_crit_);
|
||||
|
||||
// Registered at construct time and assumed to outlive this class.
|
||||
ProcessThread* process_thread_;
|
||||
ProcessThread* const process_thread_;
|
||||
rtc::scoped_ptr<ProcessThread> pacer_thread_;
|
||||
|
||||
rtc::scoped_ptr<BitrateController> bitrate_controller_;
|
||||
rtc::scoped_ptr<AdaptedSendTimeHistory> send_time_history_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user