Adds fixed PL loss mode to neteq_quality_test.
It will be available in all inheriting tests. The mode allows setting start time and duration for every loss event. Bug: webrtc:8877 Change-Id: Ife36db6d431387083ac22406a0814e02117100bc Reviewed-on: https://webrtc-review.googlesource.com/51822 Commit-Queue: Alex Narest <alexnarest@webrtc.org> Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22005}
This commit is contained in:
@ -62,8 +62,10 @@ DEFINE_int(runtime_ms, 10000, "Simulated runtime (milliseconds).");
|
|||||||
|
|
||||||
DEFINE_int(packet_loss_rate, 10, "Percentile of packet loss.");
|
DEFINE_int(packet_loss_rate, 10, "Percentile of packet loss.");
|
||||||
|
|
||||||
DEFINE_int(random_loss_mode, 1,
|
DEFINE_int(random_loss_mode,
|
||||||
"Random loss mode: 0--no loss, 1--uniform loss, 2--Gilbert Elliot loss.");
|
kUniformLoss,
|
||||||
|
"Random loss mode: 0--no loss, 1--uniform loss, 2--Gilbert Elliot "
|
||||||
|
"loss, 3--fixed loss.");
|
||||||
|
|
||||||
DEFINE_int(burst_length, 30,
|
DEFINE_int(burst_length, 30,
|
||||||
"Burst length in milliseconds, only valid for Gilbert Elliot loss.");
|
"Burst length in milliseconds, only valid for Gilbert Elliot loss.");
|
||||||
@ -72,6 +74,12 @@ DEFINE_float(drift_factor, 0.0, "Time drift factor.");
|
|||||||
|
|
||||||
DEFINE_int(preload_packets, 0, "Preload the buffer with this many packets.");
|
DEFINE_int(preload_packets, 0, "Preload the buffer with this many packets.");
|
||||||
|
|
||||||
|
DEFINE_string(loss_events,
|
||||||
|
"",
|
||||||
|
"List of loss events time and duration separated by comma: "
|
||||||
|
"<first_event_time> <first_event_duration>, <second_event_time> "
|
||||||
|
"<second_event_duration>, ...");
|
||||||
|
|
||||||
// ProbTrans00Solver() is to calculate the transition probability from no-loss
|
// ProbTrans00Solver() is to calculate the transition probability from no-loss
|
||||||
// state to itself in a modified Gilbert Elliot packet loss model. The result is
|
// state to itself in a modified Gilbert Elliot packet loss model. The result is
|
||||||
// to achieve the target packet loss rate |loss_rate|, when a packet is not
|
// to achieve the target packet loss rate |loss_rate|, when a packet is not
|
||||||
@ -157,8 +165,9 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms,
|
|||||||
RTC_CHECK(FLAG_packet_loss_rate >= 0 && FLAG_packet_loss_rate <= 100)
|
RTC_CHECK(FLAG_packet_loss_rate >= 0 && FLAG_packet_loss_rate <= 100)
|
||||||
<< "Invalid packet loss percentile, should be between 0 and 100.";
|
<< "Invalid packet loss percentile, should be between 0 and 100.";
|
||||||
|
|
||||||
RTC_CHECK(FLAG_random_loss_mode >= 0 && FLAG_random_loss_mode <= 2)
|
RTC_CHECK(FLAG_random_loss_mode >= 0 && FLAG_random_loss_mode < kLastLossMode)
|
||||||
<< "Invalid random packet loss mode, should be between 0 and 2.";
|
<< "Invalid random packet loss mode, should be between 0 and "
|
||||||
|
<< kLastLossMode - 1 << ".";
|
||||||
|
|
||||||
RTC_CHECK_GE(FLAG_burst_length, kPacketLossTimeUnitMs)
|
RTC_CHECK_GE(FLAG_burst_length, kPacketLossTimeUnitMs)
|
||||||
<< "Invalid burst length, should be greater than or equal to "
|
<< "Invalid burst length, should be greater than or equal to "
|
||||||
@ -197,7 +206,7 @@ NetEqQualityTest::~NetEqQualityTest() {
|
|||||||
log_file_.close();
|
log_file_.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NoLoss::Lost() {
|
bool NoLoss::Lost(int now_ms) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +214,7 @@ UniformLoss::UniformLoss(double loss_rate)
|
|||||||
: loss_rate_(loss_rate) {
|
: loss_rate_(loss_rate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UniformLoss::Lost() {
|
bool UniformLoss::Lost(int now_ms) {
|
||||||
int drop_this = rand();
|
int drop_this = rand();
|
||||||
return (drop_this < loss_rate_ * RAND_MAX);
|
return (drop_this < loss_rate_ * RAND_MAX);
|
||||||
}
|
}
|
||||||
@ -219,20 +228,41 @@ GilbertElliotLoss::GilbertElliotLoss(double prob_trans_11, double prob_trans_01)
|
|||||||
|
|
||||||
GilbertElliotLoss::~GilbertElliotLoss() {}
|
GilbertElliotLoss::~GilbertElliotLoss() {}
|
||||||
|
|
||||||
bool GilbertElliotLoss::Lost() {
|
bool GilbertElliotLoss::Lost(int now_ms) {
|
||||||
// Simulate bursty channel (Gilbert model).
|
// Simulate bursty channel (Gilbert model).
|
||||||
// (1st order) Markov chain model with memory of the previous/last
|
// (1st order) Markov chain model with memory of the previous/last
|
||||||
// packet state (lost or received).
|
// packet state (lost or received).
|
||||||
if (lost_last_) {
|
if (lost_last_) {
|
||||||
// Previous packet was not received.
|
// Previous packet was not received.
|
||||||
uniform_loss_model_->set_loss_rate(prob_trans_11_);
|
uniform_loss_model_->set_loss_rate(prob_trans_11_);
|
||||||
return lost_last_ = uniform_loss_model_->Lost();
|
return lost_last_ = uniform_loss_model_->Lost(now_ms);
|
||||||
} else {
|
} else {
|
||||||
uniform_loss_model_->set_loss_rate(prob_trans_01_);
|
uniform_loss_model_->set_loss_rate(prob_trans_01_);
|
||||||
return lost_last_ = uniform_loss_model_->Lost();
|
return lost_last_ = uniform_loss_model_->Lost(now_ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FixedLossModel::FixedLossModel(
|
||||||
|
std::set<FixedLossEvent, FixedLossEventCmp> loss_events)
|
||||||
|
: loss_events_(loss_events) {
|
||||||
|
loss_events_it_ = loss_events_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedLossModel::~FixedLossModel() {}
|
||||||
|
|
||||||
|
bool FixedLossModel::Lost(int now_ms) {
|
||||||
|
if (loss_events_it_ != loss_events_.end() &&
|
||||||
|
now_ms > loss_events_it_->start_ms) {
|
||||||
|
if (now_ms <= loss_events_it_->start_ms + loss_events_it_->duration_ms) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
++loss_events_it_;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void NetEqQualityTest::SetUp() {
|
void NetEqQualityTest::SetUp() {
|
||||||
ASSERT_EQ(0,
|
ASSERT_EQ(0,
|
||||||
neteq_->RegisterPayloadType(decoder_type_, "noname", kPayloadType));
|
neteq_->RegisterPayloadType(decoder_type_, "noname", kPayloadType));
|
||||||
@ -240,7 +270,7 @@ void NetEqQualityTest::SetUp() {
|
|||||||
|
|
||||||
int units = block_duration_ms_ / kPacketLossTimeUnitMs;
|
int units = block_duration_ms_ / kPacketLossTimeUnitMs;
|
||||||
switch (FLAG_random_loss_mode) {
|
switch (FLAG_random_loss_mode) {
|
||||||
case 1: {
|
case kUniformLoss: {
|
||||||
// |unit_loss_rate| is the packet loss rate for each unit time interval
|
// |unit_loss_rate| is the packet loss rate for each unit time interval
|
||||||
// (kPacketLossTimeUnitMs). Since a packet loss event is generated if any
|
// (kPacketLossTimeUnitMs). Since a packet loss event is generated if any
|
||||||
// of |block_duration_ms_ / kPacketLossTimeUnitMs| unit time intervals of
|
// of |block_duration_ms_ / kPacketLossTimeUnitMs| unit time intervals of
|
||||||
@ -252,7 +282,7 @@ void NetEqQualityTest::SetUp() {
|
|||||||
loss_model_.reset(new UniformLoss(unit_loss_rate));
|
loss_model_.reset(new UniformLoss(unit_loss_rate));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: {
|
case kGilbertElliotLoss: {
|
||||||
// |FLAG_burst_length| should be integer times of kPacketLossTimeUnitMs.
|
// |FLAG_burst_length| should be integer times of kPacketLossTimeUnitMs.
|
||||||
ASSERT_EQ(0, FLAG_burst_length % kPacketLossTimeUnitMs);
|
ASSERT_EQ(0, FLAG_burst_length % kPacketLossTimeUnitMs);
|
||||||
|
|
||||||
@ -278,6 +308,25 @@ void NetEqQualityTest::SetUp() {
|
|||||||
1.0f - prob_trans_00));
|
1.0f - prob_trans_00));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kFixedLoss: {
|
||||||
|
std::istringstream loss_events_stream(FLAG_loss_events);
|
||||||
|
std::string loss_event_string;
|
||||||
|
std::set<FixedLossEvent, FixedLossEventCmp> loss_events;
|
||||||
|
while (std::getline(loss_events_stream, loss_event_string, ',')) {
|
||||||
|
std::vector<int> loss_event_params;
|
||||||
|
std::istringstream loss_event_params_stream(loss_event_string);
|
||||||
|
std::copy(std::istream_iterator<int>(loss_event_params_stream),
|
||||||
|
std::istream_iterator<int>(),
|
||||||
|
std::back_inserter(loss_event_params));
|
||||||
|
RTC_CHECK_EQ(loss_event_params.size(), 2);
|
||||||
|
auto result = loss_events.insert(
|
||||||
|
FixedLossEvent(loss_event_params[0], loss_event_params[1]));
|
||||||
|
RTC_CHECK(result.second);
|
||||||
|
}
|
||||||
|
RTC_CHECK_GT(loss_events.size(), 0);
|
||||||
|
loss_model_.reset(new FixedLossModel(loss_events));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
loss_model_.reset(new NoLoss);
|
loss_model_.reset(new NoLoss);
|
||||||
break;
|
break;
|
||||||
@ -299,7 +348,7 @@ bool NetEqQualityTest::PacketLost() {
|
|||||||
// same packet loss profile.
|
// same packet loss profile.
|
||||||
bool lost = false;
|
bool lost = false;
|
||||||
for (int idx = 0; idx < cycles; idx ++) {
|
for (int idx = 0; idx < cycles; idx ++) {
|
||||||
if (loss_model_->Lost()) {
|
if (loss_model_->Lost(decoded_time_ms_)) {
|
||||||
// The packet will be lost if any of the drawings indicates a loss, but
|
// The packet will be lost if any of the drawings indicates a loss, but
|
||||||
// the loop has to go on to make sure that codecs with different block
|
// the loop has to go on to make sure that codecs with different block
|
||||||
// lengths keep the same pace.
|
// lengths keep the same pace.
|
||||||
|
@ -27,21 +27,29 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
enum LossModes {
|
||||||
|
kNoLoss,
|
||||||
|
kUniformLoss,
|
||||||
|
kGilbertElliotLoss,
|
||||||
|
kFixedLoss,
|
||||||
|
kLastLossMode
|
||||||
|
};
|
||||||
|
|
||||||
class LossModel {
|
class LossModel {
|
||||||
public:
|
public:
|
||||||
virtual ~LossModel() {};
|
virtual ~LossModel() {};
|
||||||
virtual bool Lost() = 0;
|
virtual bool Lost(int now_ms) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NoLoss : public LossModel {
|
class NoLoss : public LossModel {
|
||||||
public:
|
public:
|
||||||
bool Lost() override;
|
bool Lost(int now_ms) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UniformLoss : public LossModel {
|
class UniformLoss : public LossModel {
|
||||||
public:
|
public:
|
||||||
UniformLoss(double loss_rate);
|
UniformLoss(double loss_rate);
|
||||||
bool Lost() override;
|
bool Lost(int now_ms) override;
|
||||||
void set_loss_rate(double loss_rate) { loss_rate_ = loss_rate; }
|
void set_loss_rate(double loss_rate) { loss_rate_ = loss_rate; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -52,7 +60,7 @@ class GilbertElliotLoss : public LossModel {
|
|||||||
public:
|
public:
|
||||||
GilbertElliotLoss(double prob_trans_11, double prob_trans_01);
|
GilbertElliotLoss(double prob_trans_11, double prob_trans_01);
|
||||||
~GilbertElliotLoss() override;
|
~GilbertElliotLoss() override;
|
||||||
bool Lost() override;
|
bool Lost(int now_ms) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Prob. of losing current packet, when previous packet is lost.
|
// Prob. of losing current packet, when previous packet is lost.
|
||||||
@ -63,6 +71,31 @@ class GilbertElliotLoss : public LossModel {
|
|||||||
std::unique_ptr<UniformLoss> uniform_loss_model_;
|
std::unique_ptr<UniformLoss> uniform_loss_model_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FixedLossEvent {
|
||||||
|
int start_ms;
|
||||||
|
int duration_ms;
|
||||||
|
FixedLossEvent(int start_ms, int duration_ms)
|
||||||
|
: start_ms(start_ms), duration_ms(duration_ms) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FixedLossEventCmp {
|
||||||
|
bool operator()(const FixedLossEvent& l_event,
|
||||||
|
const FixedLossEvent& r_event) const {
|
||||||
|
return l_event.start_ms < r_event.start_ms;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FixedLossModel : public LossModel {
|
||||||
|
public:
|
||||||
|
FixedLossModel(std::set<FixedLossEvent, FixedLossEventCmp> loss_events);
|
||||||
|
~FixedLossModel() override;
|
||||||
|
bool Lost(int now_ms) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::set<FixedLossEvent, FixedLossEventCmp> loss_events_;
|
||||||
|
std::set<FixedLossEvent, FixedLossEventCmp>::iterator loss_events_it_;
|
||||||
|
};
|
||||||
|
|
||||||
class NetEqQualityTest : public ::testing::Test {
|
class NetEqQualityTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
NetEqQualityTest(int block_duration_ms,
|
NetEqQualityTest(int block_duration_ms,
|
||||||
|
Reference in New Issue
Block a user