Nack count returned on OnReceivedPacket.

OnReceivedPacket now return the number of times the packet has been nacked. Also some minor refactoring.

BUG=webrtc:5514
R=stefan@webrtc.org

Review URL: https://codereview.webrtc.org/1972123002 .

Cr-Commit-Position: refs/heads/master@{#12717}
This commit is contained in:
philipel
2016-05-13 11:12:00 +02:00
parent 2ebe5b1cd8
commit 1a830c2c66
3 changed files with 68 additions and 39 deletions

View File

@ -49,17 +49,17 @@ NackModule::NackModule(Clock* clock,
running_(true),
initialized_(false),
rtt_ms_(kDefaultRttMs),
last_seq_num_(0),
newest_seq_num_(0),
next_process_time_ms_(-1) {
RTC_DCHECK(clock_);
RTC_DCHECK(nack_sender_);
RTC_DCHECK(keyframe_request_sender_);
}
void NackModule::OnReceivedPacket(const VCMPacket& packet) {
int NackModule::OnReceivedPacket(const VCMPacket& packet) {
rtc::CritScope lock(&crit_);
if (!running_)
return;
return -1;
uint16_t seq_num = packet.seqNum;
// TODO(philipel): When the packet includes information whether it is
// retransmitted or not, use that value instead. For
@ -69,40 +69,48 @@ void NackModule::OnReceivedPacket(const VCMPacket& packet) {
bool is_keyframe = packet.isFirstPacket && packet.frameType == kVideoFrameKey;
if (!initialized_) {
last_seq_num_ = seq_num;
newest_seq_num_ = seq_num;
if (is_keyframe)
keyframe_list_.insert(seq_num);
initialized_ = true;
return;
return 0;
}
if (seq_num == last_seq_num_)
return;
// Since the |newest_seq_num_| is a packet we have actually received we know
// that packet has never been Nacked.
if (seq_num == newest_seq_num_)
return 0;
if (AheadOf(last_seq_num_, seq_num)) {
if (AheadOf(newest_seq_num_, seq_num)) {
// An out of order packet has been received.
nack_list_.erase(seq_num);
auto nack_list_it = nack_list_.find(seq_num);
int nacks_sent_for_packet = 0;
if (nack_list_it != nack_list_.end()) {
nacks_sent_for_packet = nack_list_it->second.retries;
nack_list_.erase(nack_list_it);
}
if (!is_retransmitted)
UpdateReorderingStatistics(seq_num);
return;
} else {
AddPacketsToNack(last_seq_num_ + 1, seq_num);
last_seq_num_ = seq_num;
// Keep track of new keyframes.
if (is_keyframe)
keyframe_list_.insert(seq_num);
// And remove old ones so we don't accumulate keyframes.
auto it = keyframe_list_.lower_bound(seq_num - kMaxPacketAge);
if (it != keyframe_list_.begin())
keyframe_list_.erase(keyframe_list_.begin(), it);
// Are there any nacks that are waiting for this seq_num.
std::vector<uint16_t> nack_batch = GetNackBatch(kSeqNumOnly);
if (!nack_batch.empty())
nack_sender_->SendNack(nack_batch);
return nacks_sent_for_packet;
}
AddPacketsToNack(newest_seq_num_ + 1, seq_num);
newest_seq_num_ = seq_num;
// Keep track of new keyframes.
if (is_keyframe)
keyframe_list_.insert(seq_num);
// And remove old ones so we don't accumulate keyframes.
auto it = keyframe_list_.lower_bound(seq_num - kMaxPacketAge);
if (it != keyframe_list_.begin())
keyframe_list_.erase(keyframe_list_.begin(), it);
// Are there any nacks that are waiting for this seq_num.
std::vector<uint16_t> nack_batch = GetNackBatch(kSeqNumOnly);
if (!nack_batch.empty())
nack_sender_->SendNack(nack_batch);
return 0;
}
void NackModule::ClearUpTo(uint16_t seq_num) {
@ -215,7 +223,7 @@ std::vector<uint16_t> NackModule::GetNackBatch(NackFilterOptions options) {
auto it = nack_list_.begin();
while (it != nack_list_.end()) {
if (consider_seq_num && it->second.sent_at_time == -1 &&
AheadOrAt(last_seq_num_, it->second.send_at_seq_num)) {
AheadOrAt(newest_seq_num_, it->second.send_at_seq_num)) {
nack_batch.emplace_back(it->second.seq_num);
++it->second.retries;
it->second.sent_at_time = now_ms;
@ -248,8 +256,8 @@ std::vector<uint16_t> NackModule::GetNackBatch(NackFilterOptions options) {
}
void NackModule::UpdateReorderingStatistics(uint16_t seq_num) {
RTC_DCHECK(AheadOf(last_seq_num_, seq_num));
uint16_t diff = ReverseDiff(last_seq_num_, seq_num);
RTC_DCHECK(AheadOf(newest_seq_num_, seq_num));
uint16_t diff = ReverseDiff(newest_seq_num_, seq_num);
reordering_histogram_.Add(diff);
}

View File

@ -32,7 +32,7 @@ class NackModule : public Module {
NackSender* nack_sender,
KeyFrameRequestSender* keyframe_request_sender);
void OnReceivedPacket(const VCMPacket& packet);
int OnReceivedPacket(const VCMPacket& packet);
void ClearUpTo(uint16_t seq_num);
void UpdateRtt(int64_t rtt_ms);
void Clear();
@ -59,11 +59,6 @@ class NackModule : public Module {
int64_t sent_at_time;
int retries;
};
struct SeqNumComparator {
bool operator()(uint16_t s1, uint16_t s2) const { return AheadOf(s2, s1); }
};
void AddPacketsToNack(uint16_t seq_num_start, uint16_t seq_num_end)
EXCLUSIVE_LOCKS_REQUIRED(crit_);
@ -87,13 +82,15 @@ class NackModule : public Module {
NackSender* const nack_sender_;
KeyFrameRequestSender* const keyframe_request_sender_;
std::map<uint16_t, NackInfo, SeqNumComparator> nack_list_ GUARDED_BY(crit_);
std::set<uint16_t, SeqNumComparator> keyframe_list_ GUARDED_BY(crit_);
std::map<uint16_t, NackInfo, DescendingSeqNumComp<uint16_t>> nack_list_
GUARDED_BY(crit_);
std::set<uint16_t, DescendingSeqNumComp<uint16_t>> keyframe_list_
GUARDED_BY(crit_);
video_coding::Histogram reordering_histogram_ GUARDED_BY(crit_);
bool running_ GUARDED_BY(crit_);
bool initialized_ GUARDED_BY(crit_);
int64_t rtt_ms_ GUARDED_BY(crit_);
uint16_t last_seq_num_ GUARDED_BY(crit_);
uint16_t newest_seq_num_ GUARDED_BY(crit_);
int64_t next_process_time_ms_ GUARDED_BY(crit_);
};

View File

@ -290,4 +290,28 @@ TEST_F(TestNackModule, ClearUpToWrap) {
EXPECT_EQ(0, sent_nacks_[0]);
}
TEST_F(TestNackModule, PacketNackCount) {
VCMPacket packet;
packet.seqNum = 0;
EXPECT_EQ(0, nack_module_.OnReceivedPacket(packet));
packet.seqNum = 2;
EXPECT_EQ(0, nack_module_.OnReceivedPacket(packet));
packet.seqNum = 1;
EXPECT_EQ(1, nack_module_.OnReceivedPacket(packet));
sent_nacks_.clear();
nack_module_.UpdateRtt(100);
packet.seqNum = 5;
EXPECT_EQ(0, nack_module_.OnReceivedPacket(packet));
clock_->AdvanceTimeMilliseconds(100);
nack_module_.Process();
clock_->AdvanceTimeMilliseconds(100);
nack_module_.Process();
packet.seqNum = 3;
EXPECT_EQ(3, nack_module_.OnReceivedPacket(packet));
packet.seqNum = 4;
EXPECT_EQ(3, nack_module_.OnReceivedPacket(packet));
EXPECT_EQ(0, nack_module_.OnReceivedPacket(packet));
}
} // namespace webrtc