Reland "Reland "Improving robustness of feedback matching code in event log parser.""

This is a reland of 0870c70b0471c3bae16ad9a6732d812ee25446dd

Original change's description:
> Reland "Improving robustness of feedback matching code in event log parser."
> 
> This is a reland of a1e4fbb25371867349a0c2ed6ba62224735a2ec7
> 
> Original change's description:
> > Improving robustness of feedback matching code in event log parser.
> > 
> > Removes the dependency on TransportFeedbackAdapter thereby removing
> > some of the complexity that came with it, in particular, we don't fill
> > in missing packets. This makes the code easier to debug and avoids some
> > confusing logging that's not relevant for the parser.
> > 
> > Bug: webrtc:9883
> > Change-Id: I6df8425e8ab410514727c51a5e8d4981d6561f03
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133347
> > Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> > Reviewed-by: Björn Terelius <terelius@webrtc.org>
> > Commit-Queue: Sebastian Jansson <srte@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#27739}
> 
> Bug: webrtc:9883
> Change-Id: I460d0c576626614fb4ce2c3d5e3ddbb5d1c122cf
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/134106
> Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> Commit-Queue: Sebastian Jansson <srte@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#27763}

Bug: webrtc:9883
Change-Id: I1f80ed1f63ad75fbb97f5f401fe486d19c057f75
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/134462
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27829}
This commit is contained in:
Sebastian Jansson
2019-05-02 17:07:22 +02:00
committed by Commit Bot
parent 4fb12b0cae
commit b468616a69
7 changed files with 192 additions and 99 deletions

View File

@ -262,10 +262,11 @@ void TransportFeedback::LastChunk::DecodeRunLength(uint16_t chunk,
}
TransportFeedback::TransportFeedback()
: TransportFeedback(/*include_timestamps=*/true) {}
: TransportFeedback(/*include_timestamps=*/true, /*include_lost*/ false) {}
TransportFeedback::TransportFeedback(bool include_timestamps)
: base_seq_no_(0),
TransportFeedback::TransportFeedback(bool include_timestamps, bool include_lost)
: include_lost_(include_lost),
base_seq_no_(0),
num_seq_no_(0),
base_time_ticks_(0),
feedback_seq_(0),
@ -276,13 +277,15 @@ TransportFeedback::TransportFeedback(bool include_timestamps)
TransportFeedback::TransportFeedback(const TransportFeedback&) = default;
TransportFeedback::TransportFeedback(TransportFeedback&& other)
: base_seq_no_(other.base_seq_no_),
: include_lost_(other.include_lost_),
base_seq_no_(other.base_seq_no_),
num_seq_no_(other.num_seq_no_),
base_time_ticks_(other.base_time_ticks_),
feedback_seq_(other.feedback_seq_),
include_timestamps_(other.include_timestamps_),
last_timestamp_us_(other.last_timestamp_us_),
packets_(std::move(other.packets_)),
received_packets_(std::move(other.received_packets_)),
all_packets_(std::move(other.all_packets_)),
encoded_chunks_(std::move(other.encoded_chunks_)),
last_chunk_(other.last_chunk_),
size_bytes_(other.size_bytes_) {
@ -341,7 +344,7 @@ bool TransportFeedback::AddReceivedPacket(uint16_t sequence_number,
if (!AddDeltaSize(delta_size))
return false;
packets_.emplace_back(sequence_number, delta);
received_packets_.emplace_back(sequence_number, delta);
last_timestamp_us_ += delta * kDeltaScaleFactor;
if (include_timestamps_) {
size_bytes_ += delta_size;
@ -351,7 +354,13 @@ bool TransportFeedback::AddReceivedPacket(uint16_t sequence_number,
const std::vector<TransportFeedback::ReceivedPacket>&
TransportFeedback::GetReceivedPackets() const {
return packets_;
return received_packets_;
}
const std::vector<TransportFeedback::ReceivedPacket>&
TransportFeedback::GetAllPackets() const {
RTC_DCHECK(include_lost_);
return all_packets_;
}
uint16_t TransportFeedback::GetBaseSequence() const {
@ -362,6 +371,18 @@ int64_t TransportFeedback::GetBaseTimeUs() const {
return static_cast<int64_t>(base_time_ticks_) * kBaseScaleFactor;
}
int64_t TransportFeedback::GetBaseDeltaUs(int64_t prev_timestamp_us) const {
int64_t delta = GetBaseTimeUs() - prev_timestamp_us;
// Detect and compensate for wrap-arounds in base time.
if (std::abs(delta - kTimeWrapPeriodUs) < std::abs(delta)) {
delta -= kTimeWrapPeriodUs; // Wrap backwards.
} else if (std::abs(delta + kTimeWrapPeriodUs) < std::abs(delta)) {
delta += kTimeWrapPeriodUs; // Wrap forwards.
}
return delta;
}
// De-serialize packet.
bool TransportFeedback::Parse(const CommonHeader& packet) {
RTC_DCHECK_EQ(packet.type(), kPacketType);
@ -428,17 +449,23 @@ bool TransportFeedback::Parse(const CommonHeader& packet) {
}
switch (delta_size) {
case 0:
if (include_lost_)
all_packets_.emplace_back(seq_no);
break;
case 1: {
int16_t delta = payload[index];
packets_.emplace_back(seq_no, delta);
received_packets_.emplace_back(seq_no, delta);
if (include_lost_)
all_packets_.emplace_back(seq_no, delta);
last_timestamp_us_ += delta * kDeltaScaleFactor;
index += delta_size;
break;
}
case 2: {
int16_t delta = ByteReader<int16_t>::ReadBigEndian(&payload[index]);
packets_.emplace_back(seq_no, delta);
received_packets_.emplace_back(seq_no, delta);
if (include_lost_)
all_packets_.emplace_back(seq_no, delta);
last_timestamp_us_ += delta * kDeltaScaleFactor;
index += delta_size;
break;
@ -460,7 +487,14 @@ bool TransportFeedback::Parse(const CommonHeader& packet) {
for (size_t delta_size : delta_sizes) {
// Use delta sizes to detect if packet was received.
if (delta_size > 0) {
packets_.emplace_back(seq_no, 0);
received_packets_.emplace_back(seq_no, 0);
}
if (include_lost_) {
if (delta_size > 0) {
all_packets_.emplace_back(seq_no, 0);
} else {
all_packets_.emplace_back(seq_no);
}
}
++seq_no;
}
@ -503,11 +537,11 @@ bool TransportFeedback::IsConsistent() const {
return false;
}
int64_t timestamp_us = base_time_ticks_ * kBaseScaleFactor;
auto packet_it = packets_.begin();
auto packet_it = received_packets_.begin();
uint16_t seq_no = base_seq_no_;
for (DeltaSize delta_size : delta_sizes) {
if (delta_size > 0) {
if (packet_it == packets_.end()) {
if (packet_it == received_packets_.end()) {
RTC_LOG(LS_ERROR) << "Failed to find delta for seq_no " << seq_no;
return false;
}
@ -532,7 +566,7 @@ bool TransportFeedback::IsConsistent() const {
}
++seq_no;
}
if (packet_it != packets_.end()) {
if (packet_it != received_packets_.end()) {
RTC_LOG(LS_ERROR) << "Unencoded delta for seq_no "
<< packet_it->sequence_number();
return false;
@ -601,7 +635,7 @@ bool TransportFeedback::Create(uint8_t* packet,
}
if (include_timestamps_) {
for (const auto& received_packet : packets_) {
for (const auto& received_packet : received_packets_) {
int16_t delta = received_packet.delta_ticks();
if (delta >= 0 && delta <= 0xFF) {
packet[(*position)++] = delta;
@ -625,7 +659,8 @@ bool TransportFeedback::Create(uint8_t* packet,
void TransportFeedback::Clear() {
num_seq_no_ = 0;
last_timestamp_us_ = GetBaseTimeUs();
packets_.clear();
received_packets_.clear();
all_packets_.clear();
encoded_chunks_.clear();
last_chunk_.Clear();
size_bytes_ = kTransportFeedbackHeaderSizeBytes;

View File

@ -25,17 +25,23 @@ class TransportFeedback : public Rtpfb {
class ReceivedPacket {
public:
ReceivedPacket(uint16_t sequence_number, int16_t delta_ticks)
: sequence_number_(sequence_number), delta_ticks_(delta_ticks) {}
: sequence_number_(sequence_number),
delta_ticks_(delta_ticks),
received_(true) {}
explicit ReceivedPacket(uint16_t sequence_number)
: sequence_number_(sequence_number), received_(false) {}
ReceivedPacket(const ReceivedPacket&) = default;
ReceivedPacket& operator=(const ReceivedPacket&) = default;
uint16_t sequence_number() const { return sequence_number_; }
int16_t delta_ticks() const { return delta_ticks_; }
int32_t delta_us() const { return delta_ticks_ * kDeltaScaleFactor; }
bool received() const { return received_; }
private:
uint16_t sequence_number_;
int16_t delta_ticks_;
bool received_;
};
// TODO(sprang): IANA reg?
static constexpr uint8_t kFeedbackMessageType = 15;
@ -45,10 +51,11 @@ class TransportFeedback : public Rtpfb {
static constexpr size_t kMaxReportedPackets = 0xffff;
TransportFeedback();
explicit TransportFeedback(
bool include_timestamps); // If |include_timestamps| is set to false, the
// created packet will not contain the receive
// delta block.
// If |include_timestamps| is set to false, the created packet will not
// contain the receive delta block.
explicit TransportFeedback(bool include_timestamps,
bool include_lost = false);
TransportFeedback(const TransportFeedback&);
TransportFeedback(TransportFeedback&&);
@ -60,6 +67,7 @@ class TransportFeedback : public Rtpfb {
// NOTE: This method requires increasing sequence numbers (excepting wraps).
bool AddReceivedPacket(uint16_t sequence_number, int64_t timestamp_us);
const std::vector<ReceivedPacket>& GetReceivedPackets() const;
const std::vector<ReceivedPacket>& GetAllPackets() const;
uint16_t GetBaseSequence() const;
@ -69,6 +77,9 @@ class TransportFeedback : public Rtpfb {
// Get the reference time in microseconds, including any precision loss.
int64_t GetBaseTimeUs() const;
// Get the unwrapped delta between current base time and |prev_timestamp_us|.
int64_t GetBaseDeltaUs(int64_t prev_timestamp_us) const;
// Does the feedback packet contain timestamp information?
bool IncludeTimestamps() const { return include_timestamps_; }
@ -144,6 +155,7 @@ class TransportFeedback : public Rtpfb {
bool AddDeltaSize(DeltaSize delta_size);
const bool include_lost_;
uint16_t base_seq_no_;
uint16_t num_seq_no_;
int32_t base_time_ticks_;
@ -151,7 +163,8 @@ class TransportFeedback : public Rtpfb {
bool include_timestamps_;
int64_t last_timestamp_us_;
std::vector<ReceivedPacket> packets_;
std::vector<ReceivedPacket> received_packets_;
std::vector<ReceivedPacket> all_packets_;
// All but last encoded packet chunks.
std::vector<uint16_t> encoded_chunks_;
LastChunk last_chunk_;

View File

@ -15,6 +15,7 @@
#include <utility>
#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
#include "test/gmock.h"
#include "test/gtest.h"
@ -555,5 +556,51 @@ TEST(RtcpPacketTest, TransportFeedbackMoveConstructor) {
EXPECT_EQ(moved.Build(), feedback_copy.Build());
}
TEST(TransportFeedbackTest, ReportsMissingPackets) {
const uint16_t kBaseSeqNo = 1000;
const int64_t kBaseTimestampUs = 10000;
const uint8_t kFeedbackSeqNo = 90;
TransportFeedback feedback_builder(/*include_timestamps*/ true);
feedback_builder.SetBase(kBaseSeqNo, kBaseTimestampUs);
feedback_builder.SetFeedbackSequenceNumber(kFeedbackSeqNo);
feedback_builder.AddReceivedPacket(kBaseSeqNo + 0, kBaseTimestampUs);
// Packet losses indicated by jump in sequence number.
feedback_builder.AddReceivedPacket(kBaseSeqNo + 3, kBaseTimestampUs + 2000);
rtc::Buffer coded = feedback_builder.Build();
rtcp::CommonHeader header;
header.Parse(coded.data(), coded.size());
TransportFeedback feedback(/*include_timestamps*/ true,
/*include_lost*/ true);
feedback.Parse(header);
auto packets = feedback.GetAllPackets();
EXPECT_TRUE(packets[0].received());
EXPECT_FALSE(packets[1].received());
EXPECT_FALSE(packets[2].received());
EXPECT_TRUE(packets[3].received());
}
TEST(TransportFeedbackTest, ReportsMissingPacketsWithoutTimestamps) {
const uint16_t kBaseSeqNo = 1000;
const uint8_t kFeedbackSeqNo = 90;
TransportFeedback feedback_builder(/*include_timestamps*/ false);
feedback_builder.SetBase(kBaseSeqNo, 10000);
feedback_builder.SetFeedbackSequenceNumber(kFeedbackSeqNo);
feedback_builder.AddReceivedPacket(kBaseSeqNo + 0, /*timestamp_us*/ 0);
// Packet losses indicated by jump in sequence number.
feedback_builder.AddReceivedPacket(kBaseSeqNo + 3, /*timestamp_us*/ 0);
rtc::Buffer coded = feedback_builder.Build();
rtcp::CommonHeader header;
header.Parse(coded.data(), coded.size());
TransportFeedback feedback(/*include_timestamps*/ true,
/*include_lost*/ true);
feedback.Parse(header);
auto packets = feedback.GetAllPackets();
EXPECT_TRUE(packets[0].received());
EXPECT_FALSE(packets[1].received());
EXPECT_FALSE(packets[2].received());
EXPECT_TRUE(packets[3].received());
}
} // namespace
} // namespace webrtc