NetEq::GetPlayoutTimestamp returns empty during CNG
With this change, the return value from NetEq::GetPlayoutTimestamp is empty if the latest call to NetEq::GetAudio resulted in comfort noise (codec-internal or external) being played out. This is because the playout timestamp is not updated during CNG, and can therefore not be trusted. A few unit tests were updated to reflect the change. BUG=webrtc:5669 Review URL: https://codereview.webrtc.org/1861303002 Cr-Commit-Position: refs/heads/master@{#12268}
This commit is contained in:
parent
c8d071e4e0
commit
0d96ab7dc4
@ -403,9 +403,11 @@ void NetEqImpl::DisableVad() {
|
||||
|
||||
rtc::Optional<uint32_t> NetEqImpl::GetPlayoutTimestamp() const {
|
||||
rtc::CritScope lock(&crit_sect_);
|
||||
if (first_packet_) {
|
||||
if (first_packet_ || last_mode_ == kModeRfc3389Cng ||
|
||||
last_mode_ == kModeCodecInternalCng) {
|
||||
// We don't have a valid RTP timestamp until we have decoded our first
|
||||
// RTP packet.
|
||||
// RTP packet. Also, the RTP timestamp is not accurate while playing CNG,
|
||||
// which is indicated by returning an empty value.
|
||||
return rtc::Optional<uint32_t>();
|
||||
}
|
||||
return rtc::Optional<uint32_t>(
|
||||
|
||||
@ -666,6 +666,12 @@ TEST_F(NetEqImplTest, CodecInternalCng) {
|
||||
EXPECT_CALL(mock_decoder, Channels()).WillRepeatedly(Return(1));
|
||||
EXPECT_CALL(mock_decoder, IncomingPacket(_, kPayloadLengthBytes, _, _, _))
|
||||
.WillRepeatedly(Return(0));
|
||||
EXPECT_CALL(mock_decoder, PacketDuration(_, kPayloadLengthBytes))
|
||||
.WillRepeatedly(Return(kPayloadLengthSamples));
|
||||
// Packed duration when asking the decoder for more CNG data (without a new
|
||||
// packet).
|
||||
EXPECT_CALL(mock_decoder, PacketDuration(nullptr, 0))
|
||||
.WillRepeatedly(Return(kPayloadLengthSamples));
|
||||
|
||||
// Pointee(x) verifies that first byte of the payload equals x, this makes it
|
||||
// possible to verify that the correct payload is fed to Decode().
|
||||
@ -723,8 +729,8 @@ TEST_F(NetEqImplTest, CodecInternalCng) {
|
||||
int expected_timestamp_increment[8] = {
|
||||
-1, // will not be used.
|
||||
10 * kSampleRateKhz,
|
||||
0, 0, // timestamp does not increase during CNG mode.
|
||||
0, 0,
|
||||
-1, -1, // timestamp will be empty during CNG mode; indicated by -1 here.
|
||||
-1, -1,
|
||||
50 * kSampleRateKhz, 10 * kSampleRateKhz
|
||||
};
|
||||
|
||||
@ -732,17 +738,27 @@ TEST_F(NetEqImplTest, CodecInternalCng) {
|
||||
rtc::Optional<uint32_t> last_timestamp = neteq_->GetPlayoutTimestamp();
|
||||
ASSERT_TRUE(last_timestamp);
|
||||
|
||||
// Lambda for verifying the timestamps.
|
||||
auto verify_timestamp = [&last_timestamp, &expected_timestamp_increment](
|
||||
rtc::Optional<uint32_t> ts, size_t i) {
|
||||
if (expected_timestamp_increment[i] == -1) {
|
||||
// Expect to get an empty timestamp value during CNG and PLC.
|
||||
EXPECT_FALSE(ts) << "i = " << i;
|
||||
} else {
|
||||
ASSERT_TRUE(ts) << "i = " << i;
|
||||
EXPECT_EQ(*ts, *last_timestamp + expected_timestamp_increment[i])
|
||||
<< "i = " << i;
|
||||
last_timestamp = ts;
|
||||
}
|
||||
};
|
||||
|
||||
for (size_t i = 1; i < 6; ++i) {
|
||||
ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(expected_type[i - 1], output.speech_type_);
|
||||
rtc::Optional<uint32_t> timestamp = neteq_->GetPlayoutTimestamp();
|
||||
EXPECT_TRUE(timestamp);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output));
|
||||
timestamp = neteq_->GetPlayoutTimestamp();
|
||||
ASSERT_TRUE(timestamp);
|
||||
EXPECT_EQ(*timestamp, *last_timestamp + expected_timestamp_increment[i]);
|
||||
last_timestamp = timestamp;
|
||||
SCOPED_TRACE("");
|
||||
verify_timestamp(neteq_->GetPlayoutTimestamp(), i);
|
||||
}
|
||||
|
||||
// Insert third packet, which leaves a gap from last packet.
|
||||
@ -757,10 +773,8 @@ TEST_F(NetEqImplTest, CodecInternalCng) {
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(expected_type[i - 1], output.speech_type_);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output));
|
||||
rtc::Optional<uint32_t> timestamp = neteq_->GetPlayoutTimestamp();
|
||||
ASSERT_TRUE(timestamp);
|
||||
EXPECT_EQ(*timestamp, *last_timestamp + expected_timestamp_increment[i]);
|
||||
last_timestamp = timestamp;
|
||||
SCOPED_TRACE("");
|
||||
verify_timestamp(neteq_->GetPlayoutTimestamp(), i);
|
||||
}
|
||||
|
||||
// Now check the packet buffer, and make sure it is empty.
|
||||
|
||||
@ -316,7 +316,7 @@ class NetEqDecodingTest : public ::testing::Test {
|
||||
|
||||
void DuplicateCng();
|
||||
|
||||
uint32_t PlayoutTimestamp();
|
||||
rtc::Optional<uint32_t> PlayoutTimestamp();
|
||||
|
||||
NetEq* neteq_;
|
||||
NetEq::Config config_;
|
||||
@ -720,7 +720,9 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor,
|
||||
}
|
||||
|
||||
EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
|
||||
int32_t delay_before = timestamp - PlayoutTimestamp();
|
||||
rtc::Optional<uint32_t> playout_timestamp = PlayoutTimestamp();
|
||||
ASSERT_TRUE(playout_timestamp);
|
||||
int32_t delay_before = timestamp - *playout_timestamp;
|
||||
|
||||
// Insert CNG for 1 minute (= 60000 ms).
|
||||
const int kCngPeriodMs = 100;
|
||||
@ -810,7 +812,9 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor,
|
||||
// Check that the speech starts again within reasonable time.
|
||||
double time_until_speech_returns_ms = t_ms - speech_restart_time_ms;
|
||||
EXPECT_LT(time_until_speech_returns_ms, max_time_to_speech_ms);
|
||||
int32_t delay_after = timestamp - PlayoutTimestamp();
|
||||
playout_timestamp = PlayoutTimestamp();
|
||||
ASSERT_TRUE(playout_timestamp);
|
||||
int32_t delay_after = timestamp - *playout_timestamp;
|
||||
// Compare delay before and after, and make sure it differs less than 20 ms.
|
||||
EXPECT_LE(delay_after, delay_before + delay_tolerance_ms * 16);
|
||||
EXPECT_GE(delay_after, delay_before - delay_tolerance_ms * 16);
|
||||
@ -1413,7 +1417,9 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no,
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
|
||||
// Expect delay (in samples) to be less than 2 packets.
|
||||
EXPECT_LE(timestamp - PlayoutTimestamp(),
|
||||
rtc::Optional<uint32_t> playout_timestamp = PlayoutTimestamp();
|
||||
ASSERT_TRUE(playout_timestamp);
|
||||
EXPECT_LE(timestamp - *playout_timestamp,
|
||||
static_cast<uint32_t>(kSamples * 2));
|
||||
}
|
||||
// Make sure we have actually tested wrap-around.
|
||||
@ -1489,7 +1495,9 @@ void NetEqDecodingTest::DuplicateCng() {
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
|
||||
EXPECT_EQ(timestamp - algorithmic_delay_samples, PlayoutTimestamp());
|
||||
EXPECT_FALSE(PlayoutTimestamp()); // Returns empty value during CNG.
|
||||
EXPECT_EQ(timestamp - algorithmic_delay_samples,
|
||||
out_frame_.timestamp_ + out_frame_.samples_per_channel_);
|
||||
|
||||
// Insert the same CNG packet again. Note that at this point it is old, since
|
||||
// we have already decoded the first copy of it.
|
||||
@ -1503,8 +1511,9 @@ void NetEqDecodingTest::DuplicateCng() {
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_);
|
||||
EXPECT_FALSE(PlayoutTimestamp()); // Returns empty value during CNG.
|
||||
EXPECT_EQ(timestamp - algorithmic_delay_samples,
|
||||
PlayoutTimestamp());
|
||||
out_frame_.timestamp_ + out_frame_.samples_per_channel_);
|
||||
}
|
||||
|
||||
// Insert speech again.
|
||||
@ -1517,14 +1526,14 @@ void NetEqDecodingTest::DuplicateCng() {
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_);
|
||||
rtc::Optional<uint32_t> playout_timestamp = PlayoutTimestamp();
|
||||
ASSERT_TRUE(playout_timestamp);
|
||||
EXPECT_EQ(timestamp + kSamples - algorithmic_delay_samples,
|
||||
PlayoutTimestamp());
|
||||
*playout_timestamp);
|
||||
}
|
||||
|
||||
uint32_t NetEqDecodingTest::PlayoutTimestamp() {
|
||||
rtc::Optional<uint32_t> playout_timestamp = neteq_->GetPlayoutTimestamp();
|
||||
EXPECT_TRUE(playout_timestamp);
|
||||
return playout_timestamp.value_or(0);
|
||||
rtc::Optional<uint32_t> NetEqDecodingTest::PlayoutTimestamp() {
|
||||
return neteq_->GetPlayoutTimestamp();
|
||||
}
|
||||
|
||||
TEST_F(NetEqDecodingTest, DiscardDuplicateCng) { DuplicateCng(); }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user