Revise jitter value when payload frequency changes.

Bug: None
Change-Id: I81ec880479b3d19efc24ada62643cdc03292988d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/279222
Commit-Queue: Anton Podavalov <tonypo@google.com>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38445}
This commit is contained in:
Anton Podavalov
2022-10-19 09:58:22 -07:00
committed by WebRTC LUCI CQ
parent c5f8f800a2
commit ea40563e34
3 changed files with 325 additions and 1 deletions

View File

@ -142,7 +142,6 @@ void StreamStatisticianImpl::UpdateCounters(const RtpPacketReceived& packet) {
}
last_received_timestamp_ = packet.Timestamp();
last_receive_time_ms_ = now_ms;
last_payload_type_frequency_ = packet.payload_type_frequency();
}
void StreamStatisticianImpl::UpdateJitter(const RtpPacketReceived& packet,
@ -156,6 +155,8 @@ void StreamStatisticianImpl::UpdateJitter(const RtpPacketReceived& packet,
time_diff_samples = std::abs(time_diff_samples);
ReviseFrequencyAndJitter(packet.payload_type_frequency());
// lib_jingle sometimes deliver crazy jumps in TS for the same stream.
// If this happens, don't update jitter value. Use 5 secs video frequency
// as the threshold.
@ -166,6 +167,38 @@ void StreamStatisticianImpl::UpdateJitter(const RtpPacketReceived& packet,
}
}
void StreamStatisticianImpl::ReviseFrequencyAndJitter(
int payload_type_frequency) {
if (payload_type_frequency == last_payload_type_frequency_) {
return;
}
if (payload_type_frequency != 0) {
if (last_payload_type_frequency_ != 0) {
// Value in "jitter_q4_" variable is a number of samples.
// I.e. jitter = timestamp (ms) * frequency (kHz).
// Since the frequency has changed we have to update the number of samples
// accordingly. The new value should rely on a new frequency.
// If we don't do such procedure we end up with the number of samples that
// cannot be converted into milliseconds correctly
// (i.e. jitter_ms = jitter_q4_ >> 4 / (payload_type_frequency / 1000)).
// In such case, the number of samples has a "mix".
// Doing so we pretend that everything prior and including the current
// packet were computed on packet's frequency.
jitter_q4_ = static_cast<int>(static_cast<uint64_t>(jitter_q4_) *
payload_type_frequency /
last_payload_type_frequency_);
}
// If last_payload_type_frequency_ is not present, the jitter_q4_
// variable has its initial value.
// Keep last_payload_type_frequency_ up to date and non-zero (set).
last_payload_type_frequency_ = payload_type_frequency;
}
}
void StreamStatisticianImpl::SetMaxReorderingThreshold(
int max_reordering_threshold) {
max_reordering_threshold_ = max_reordering_threshold;

View File

@ -65,6 +65,7 @@ class StreamStatisticianImpl : public StreamStatisticianImplInterface {
bool IsRetransmitOfOldPacket(const RtpPacketReceived& packet,
int64_t now_ms) const;
void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms);
void ReviseFrequencyAndJitter(int payload_type_frequency);
// Updates StreamStatistician for out of order packets.
// Returns true if packet considered to be out of order.
bool UpdateOutOfOrder(const RtpPacketReceived& packet,

View File

@ -55,6 +55,25 @@ RtpPacketReceived CreateRtpPacket(uint32_t ssrc,
return packet;
}
RtpPacketReceived MakeRtpPacket(int payload_type_frequency,
uint32_t timestamp) {
RtpPacketReceived packet =
CreateRtpPacket(kSsrc1,
/*header_size=*/12, kPacketSize1 - 12,
/*padding_size=*/0);
packet.SetTimestamp(timestamp);
packet.set_payload_type_frequency(payload_type_frequency);
return packet;
}
RtpPacketReceived MakeNextRtpPacket(const RtpPacketReceived& previous_packet,
int payload_type_frequency,
uint32_t timestamp) {
RtpPacketReceived packet = MakeRtpPacket(payload_type_frequency, timestamp);
packet.SetSequenceNumber(previous_packet.SequenceNumber() + 1);
return packet;
}
RtpPacketReceived CreateRtpPacket(uint32_t ssrc, size_t packet_size) {
return CreateRtpPacket(ssrc, 12, packet_size - 12, 0);
}
@ -67,6 +86,10 @@ void IncrementSequenceNumber(RtpPacketReceived* packet) {
IncrementSequenceNumber(packet, 1);
}
uint32_t GetJitter(const ReceiveStatistics& stats) {
return stats.GetStatistician(kSsrc1)->GetStats().jitter;
}
class ReceiveStatisticsTest : public ::testing::TestWithParam<bool> {
public:
ReceiveStatisticsTest()
@ -607,5 +630,272 @@ TEST_P(ReceiveStatisticsTest, SimpleJitterComputation) {
statistician->GetStats().interarrival_jitter);
}
TEST(ReviseJitterTest, AllPacketsHaveSamePayloadTypeFrequency) {
SimulatedClock clock(0);
std::unique_ptr<ReceiveStatistics> statistics =
ReceiveStatistics::Create(&clock);
RtpPacketReceived packet1 = MakeRtpPacket(/*payload_type_frequency=*/8'000,
/*timestamp=*/1);
RtpPacketReceived packet2 = MakeNextRtpPacket(
packet1, /*payload_type_frequency=*/8'000, /*timestamp=*/1 + 160);
RtpPacketReceived packet3 = MakeNextRtpPacket(
packet2, /*payload_type_frequency=*/8'000, /*timestamp=*/1 + 2 * 160);
statistics->OnRtpPacket(packet1);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet2);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet3);
// packet1: no jitter calculation
// packet2: jitter = 0[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 0[jitter] + 8)
// / 16 = 240
// packet3: jitter = 240[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 240[jitter] + 8)
// / 16 = 465
// final jitter: 465 / 16 = 29
EXPECT_EQ(GetJitter(*statistics), 29U);
}
TEST(ReviseJitterTest, AllPacketsHaveDifferentPayloadTypeFrequency) {
SimulatedClock clock(0);
std::unique_ptr<ReceiveStatistics> statistics =
ReceiveStatistics::Create(&clock);
RtpPacketReceived packet1 = MakeRtpPacket(/*payload_type_frequency=*/8'000,
/*timestamp=*/1);
RtpPacketReceived packet2 = MakeNextRtpPacket(
packet1, /*payload_type_frequency=*/8'000, /*timestamp=*/1 + 160);
RtpPacketReceived packet3 = MakeNextRtpPacket(
packet2, /*payload_type_frequency=*/48'000, /*timestamp=*/1 + 160 + 960);
statistics->OnRtpPacket(packet1);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet2);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet3);
// packet1: no jitter calculation
// packet2: jitter = 0[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 0[jitter] + 8)
// / 16 = 240
// packet3: revised jitter: 240 * 48[frequency KHz] / 8[frequency KHz] = 1'440
// jitter = 1'440[jitter] + (abs(50[receive time ms] *
// 48[frequency KHz] - 960[timestamp diff]) * 16 - 1'440[jitter] + 8)
// / 16 = 2'790
// final jitter: 2'790 / 16 = 174
EXPECT_EQ(GetJitter(*statistics), 174U);
}
TEST(ReviseJitterTest,
FirstPacketPayloadTypeFrequencyIsZeroAndFrequencyChanged) {
SimulatedClock clock(0);
std::unique_ptr<ReceiveStatistics> statistics =
ReceiveStatistics::Create(&clock);
RtpPacketReceived packet1 = MakeRtpPacket(/*payload_type_frequency=*/0,
/*timestamp=*/1);
RtpPacketReceived packet2 = MakeNextRtpPacket(
packet1, /*payload_type_frequency=*/8'000, /*timestamp=*/1 + 160);
RtpPacketReceived packet3 = MakeNextRtpPacket(
packet2, /*payload_type_frequency=*/48'000, /*timestamp=*/1 + 160 + 960);
statistics->OnRtpPacket(packet1);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet2);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet3);
// packet1: no jitter calculation
// packet2: jitter = 0[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 0[jitter] + 8)
// / 16 = 240
// packet3: revised jitter: 240 * 48[frequency KHz] / 8[frequency KHz] = 1'440
// jitter = 1'440[jitter] + (abs(50[receive time ms] *
// 48[frequency KHz] - 960[timestamp diff]) * 16 - 1'440[jitter] + 8)
// / 16 = 2'790
// final jitter: 2'790 / 16 = 174
EXPECT_EQ(GetJitter(*statistics), 174U);
}
TEST(ReviseJitterTest,
FirstPacketPayloadTypeFrequencyIsZeroAndFrequencyNotChanged) {
SimulatedClock clock(0);
std::unique_ptr<ReceiveStatistics> statistics =
ReceiveStatistics::Create(&clock);
RtpPacketReceived packet1 = MakeRtpPacket(/*payload_type_frequency=*/0,
/*timestamp=*/1);
RtpPacketReceived packet2 = MakeNextRtpPacket(
packet1, /*payload_type_frequency=*/8'000, /*timestamp=*/1 + 160);
RtpPacketReceived packet3 = MakeNextRtpPacket(
packet2, /*payload_type_frequency=*/8'000, /*timestamp=*/1 + 160 + 160);
statistics->OnRtpPacket(packet1);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet2);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet3);
// packet1: no jitter calculation
// packet2: jitter = 0[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 0[jitter] + 8)
// / 16 = 240
// packet3: jitter = 240[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 240[jitter] + 8)
// / 16 = 465
// final jitter: 465 / 16 = 29
EXPECT_EQ(GetJitter(*statistics), 29U);
}
TEST(ReviseJitterTest,
TwoFirstPacketPayloadTypeFrequencyIsZeroAndFrequencyChanged) {
SimulatedClock clock(0);
std::unique_ptr<ReceiveStatistics> statistics =
ReceiveStatistics::Create(&clock);
RtpPacketReceived packet1 = MakeRtpPacket(/*payload_type_frequency=*/0,
/*timestamp=*/1);
RtpPacketReceived packet2 = MakeNextRtpPacket(
packet1, /*payload_type_frequency=*/0, /*timestamp=*/1 + 160);
RtpPacketReceived packet3 = MakeNextRtpPacket(
packet2, /*payload_type_frequency=*/48'000, /*timestamp=*/1 + 160 + 960);
RtpPacketReceived packet4 =
MakeNextRtpPacket(packet3, /*payload_type_frequency=*/8'000,
/*timestamp=*/1 + 160 + 960 + 160);
statistics->OnRtpPacket(packet1);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet2);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet3);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet4);
// packet1: no jitter calculation
// packet2: jitter = 0[jitter] + (abs(50[receive time ms] *
// 0[frequency KHz] - 160[timestamp diff]) * 16 - 0[jitter] + 8)
// / 16 = 160
// packet3: jitter = 160[jitter] + (abs(50[receive time ms] *
// 48[frequency KHz] - 960[timestamp diff]) * 16 - 160[jitter] + 8)
// / 16 = 1'590
// packet4: revised jitter: 1'590 * 8[frequency KHz] / 48[frequency KHz] = 265
// packet4: jitter = 265[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 265[jitter] + 8)
// / 16 = 488
// final jitter: 488 / 16 = 30
EXPECT_EQ(GetJitter(*statistics), 30U);
}
TEST(ReviseJitterTest,
TwoFirstPacketPayloadTypeFrequencyIsZeroAndFrequencyNotChanged) {
SimulatedClock clock(0);
std::unique_ptr<ReceiveStatistics> statistics =
ReceiveStatistics::Create(&clock);
RtpPacketReceived packet1 = MakeRtpPacket(/*payload_type_frequency=*/0,
/*timestamp=*/1);
RtpPacketReceived packet2 = MakeNextRtpPacket(
packet1, /*payload_type_frequency=*/0, /*timestamp=*/1 + 160);
RtpPacketReceived packet3 = MakeNextRtpPacket(
packet2, /*payload_type_frequency=*/8'000, /*timestamp=*/1 + 160 + 160);
RtpPacketReceived packet4 =
MakeNextRtpPacket(packet3, /*payload_type_frequency=*/8'000,
/*timestamp=*/1 + 160 + 160 + 160);
statistics->OnRtpPacket(packet1);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet2);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet3);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet4);
// packet1: no jitter calculation
// packet2: jitter = 0[jitter] + (abs(50[receive time ms] *
// 0[frequency KHz] - 160[timestamp diff]) * 16 - 0[jitter] + 8)
// / 16 = 160
// packet3: jitter = 160[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 160[jitter] + 8)
// / 16 = 390
// packet4: jitter = 390[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 390[jitter] + 8)
// / 16 = 606
// final jitter: 606 / 16 = 37
EXPECT_EQ(GetJitter(*statistics), 37U);
}
TEST(ReviseJitterTest,
MiddlePacketPayloadTypeFrequencyIsZeroAndFrequencyChanged) {
SimulatedClock clock(0);
std::unique_ptr<ReceiveStatistics> statistics =
ReceiveStatistics::Create(&clock);
RtpPacketReceived packet1 = MakeRtpPacket(/*payload_type_frequency=*/48'000,
/*timestamp=*/1);
RtpPacketReceived packet2 = MakeNextRtpPacket(
packet1, /*payload_type_frequency=*/48'000, /*timestamp=*/1 + 960);
RtpPacketReceived packet3 = MakeNextRtpPacket(
packet2, /*payload_type_frequency=*/0, /*timestamp=*/1 + 960 + 55);
RtpPacketReceived packet4 =
MakeNextRtpPacket(packet3, /*payload_type_frequency=*/8'000,
/*timestamp=*/1 + 960 + 55 + 160);
statistics->OnRtpPacket(packet1);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet2);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet3);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet4);
// packet1: no jitter calculation
// packet2: jitter = 0[jitter] + (abs(50[receive time ms] *
// 48[frequency KHz] - 960[timestamp diff]) * 16 - 0[jitter] + 8)
// / 16 = 1'440
// packet3: jitter = 1'440[jitter] + (abs(50[receive time ms] *
// 0[frequency KHz] - 55[timestamp diff]) * 16 - 1'440[jitter] + 8)
// / 16 = 1'405
// packet4: revised jitter: 1'405 * 8[frequency KHz] / 48[frequency KHz] = 234
// jitter = 234[jitter] + (abs(50[receive time ms] *
// 8[frequency KHz] - 160[timestamp diff]) * 16 - 234[jitter] + 8)
// / 16 = 459
// final jitter: 459 / 16 = 28
EXPECT_EQ(GetJitter(*statistics), 28U);
}
TEST(ReviseJitterTest,
MiddlePacketPayloadTypeFrequencyIsZeroAndFrequencyNotChanged) {
SimulatedClock clock(0);
std::unique_ptr<ReceiveStatistics> statistics =
ReceiveStatistics::Create(&clock);
RtpPacketReceived packet1 = MakeRtpPacket(/*payload_type_frequency=*/48'000,
/*timestamp=*/1);
RtpPacketReceived packet2 = MakeNextRtpPacket(
packet1, /*payload_type_frequency=*/48'000, /*timestamp=*/1 + 960);
RtpPacketReceived packet3 = MakeNextRtpPacket(
packet2, /*payload_type_frequency=*/0, /*timestamp=*/1 + 960 + 55);
RtpPacketReceived packet4 =
MakeNextRtpPacket(packet3, /*payload_type_frequency=*/48'000,
/*timestamp=*/1 + 960 + 55 + 960);
statistics->OnRtpPacket(packet1);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet2);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet3);
clock.AdvanceTimeMilliseconds(50);
statistics->OnRtpPacket(packet4);
// packet1: no jitter calculation
// packet2: jitter = 0[jitter] + (abs(50[receive time ms] *
// 48[frequency KHz] - 960[timestamp diff]) * 16 - 0[jitter] + 8)
// / 16 = 1'440
// packet3: jitter = 1'440[jitter] + (abs(50[receive time ms] *
// 0[frequency KHz] - 55[timestamp diff]) * 16 - 1'440[jitter] + 8)
// / 16 = 1'405
// packet4: jitter = 1'405[jitter] + (abs(50[receive time ms] *
// 48[frequency KHz] - 960[timestamp diff]) * 16 - 1'405[jitter] + 8)
// / 16 = 2'757
// final jitter: 2'757 / 16 = 172
EXPECT_EQ(GetJitter(*statistics), 172U);
}
} // namespace
} // namespace webrtc