
Taking care of the case when the raw waiting times vector from NetEQ is zero length. Also adding a new unittest to cover this case. BUG=http://code.google.com/p/webrtc/issues/detail?id=218 TEST=AcmNetEqTest.TestZeroLengthWaitingTimesVector Review URL: http://webrtc-codereview.appspot.com/349003 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1370 4adac7df-926f-26a2-2b94-8c16560cd09d
146 lines
5.4 KiB
C++
146 lines
5.4 KiB
C++
/*
|
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
// This file contains unit tests for ACM's NetEQ wrapper (class ACMNetEQ).
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
|
|
#include "modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
|
#include "modules/audio_coding/main/source/acm_codec_database.h"
|
|
#include "modules/audio_coding/main/source/acm_neteq.h"
|
|
#include "modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h"
|
|
#include "modules/interface/module_common_types.h"
|
|
#include "typedefs.h" // NOLINT(build/include)
|
|
|
|
namespace webrtc {
|
|
|
|
class AcmNetEqTest : public ::testing::Test {
|
|
protected:
|
|
static const size_t kMaxPayloadLen = 5760; // 60 ms, 48 kHz, 16 bit samples.
|
|
static const int kPcm16WbPayloadType = 94;
|
|
AcmNetEqTest() {}
|
|
virtual void SetUp();
|
|
virtual void TearDown() {}
|
|
|
|
void InsertZeroPacket(uint16_t sequence_number,
|
|
uint32_t timestamp,
|
|
uint8_t payload_type,
|
|
uint32_t ssrc,
|
|
bool marker_bit,
|
|
size_t len_payload_bytes);
|
|
void PullData(int expected_num_samples);
|
|
|
|
ACMNetEQ neteq_;
|
|
};
|
|
|
|
void AcmNetEqTest::SetUp() {
|
|
ASSERT_EQ(0, neteq_.Init());
|
|
ASSERT_EQ(0, neteq_.AllocatePacketBuffer(ACMCodecDB::NetEQDecoders(),
|
|
ACMCodecDB::kNumCodecs));
|
|
WebRtcNetEQ_CodecDef codec_def;
|
|
SET_CODEC_PAR(codec_def, kDecoderPCM16Bwb, kPcm16WbPayloadType, NULL, 16000);
|
|
SET_PCM16B_WB_FUNCTIONS(codec_def);
|
|
ASSERT_EQ(0, neteq_.AddCodec(&codec_def, true));
|
|
}
|
|
|
|
void AcmNetEqTest::InsertZeroPacket(uint16_t sequence_number,
|
|
uint32_t timestamp,
|
|
uint8_t payload_type,
|
|
uint32_t ssrc,
|
|
bool marker_bit,
|
|
size_t len_payload_bytes) {
|
|
ASSERT_TRUE(len_payload_bytes <= kMaxPayloadLen);
|
|
uint16_t payload[kMaxPayloadLen] = {0};
|
|
WebRtcRTPHeader rtp_header;
|
|
rtp_header.header.sequenceNumber = sequence_number;
|
|
rtp_header.header.timestamp = timestamp;
|
|
rtp_header.header.ssrc = ssrc;
|
|
rtp_header.header.payloadType = payload_type;
|
|
rtp_header.header.markerBit = marker_bit;
|
|
rtp_header.type.Audio.channel = 1;
|
|
ASSERT_EQ(0, neteq_.RecIn(reinterpret_cast<WebRtc_Word8*>(payload),
|
|
len_payload_bytes, rtp_header));
|
|
}
|
|
|
|
void AcmNetEqTest::PullData(int expected_num_samples) {
|
|
AudioFrame out_frame;
|
|
ASSERT_EQ(0, neteq_.RecOut(out_frame));
|
|
ASSERT_EQ(expected_num_samples, out_frame._payloadDataLengthInSamples);
|
|
}
|
|
|
|
TEST_F(AcmNetEqTest, NetworkStatistics) {
|
|
// Use fax mode to avoid time-scaling. This is to simplify the testing of
|
|
// packet waiting times in the packet buffer.
|
|
neteq_.SetPlayoutMode(fax);
|
|
// Insert 31 dummy packets at once. Each packet contains 10 ms 16 kHz audio.
|
|
int num_frames = 30;
|
|
const int kSamples = 10 * 16;
|
|
const int kPayloadBytes = kSamples * 2;
|
|
int i, j;
|
|
for (i = 0; i < num_frames; ++i) {
|
|
InsertZeroPacket(i, i * kSamples, kPcm16WbPayloadType, 0x1234, false,
|
|
kPayloadBytes);
|
|
}
|
|
// Pull out data once.
|
|
PullData(kSamples);
|
|
// Insert one more packet (to produce different mean and median).
|
|
i = num_frames;
|
|
InsertZeroPacket(i, i * kSamples, kPcm16WbPayloadType, 0x1234, false,
|
|
kPayloadBytes);
|
|
// Pull out all data.
|
|
for (j = 1; j < num_frames + 1; ++j) {
|
|
PullData(kSamples);
|
|
}
|
|
|
|
ACMNetworkStatistics stats;
|
|
ASSERT_EQ(0, neteq_.NetworkStatistics(&stats));
|
|
EXPECT_EQ(0, stats.currentBufferSize);
|
|
EXPECT_EQ(0, stats.preferredBufferSize);
|
|
EXPECT_FALSE(stats.jitterPeaksFound);
|
|
EXPECT_EQ(0, stats.currentPacketLossRate);
|
|
EXPECT_EQ(0, stats.currentDiscardRate);
|
|
EXPECT_EQ(0, stats.currentExpandRate);
|
|
EXPECT_EQ(0, stats.currentPreemptiveRate);
|
|
EXPECT_EQ(0, stats.currentAccelerateRate);
|
|
EXPECT_EQ(-916, stats.clockDriftPPM); // Initial value is slightly off.
|
|
EXPECT_EQ(300, stats.maxWaitingTimeMs);
|
|
EXPECT_EQ(159, stats.meanWaitingTimeMs);
|
|
EXPECT_EQ(160, stats.medianWaitingTimeMs);
|
|
}
|
|
|
|
TEST_F(AcmNetEqTest, TestZeroLengthWaitingTimesVector) {
|
|
// Insert one packet.
|
|
const int kSamples = 10 * 16;
|
|
const int kPayloadBytes = kSamples * 2;
|
|
int i = 0;
|
|
InsertZeroPacket(i, i * kSamples, kPcm16WbPayloadType, 0x1234, false,
|
|
kPayloadBytes);
|
|
// Do not pull out any data.
|
|
|
|
ACMNetworkStatistics stats;
|
|
ASSERT_EQ(0, neteq_.NetworkStatistics(&stats));
|
|
EXPECT_EQ(0, stats.currentBufferSize);
|
|
EXPECT_EQ(0, stats.preferredBufferSize);
|
|
EXPECT_FALSE(stats.jitterPeaksFound);
|
|
EXPECT_EQ(0, stats.currentPacketLossRate);
|
|
EXPECT_EQ(0, stats.currentDiscardRate);
|
|
EXPECT_EQ(0, stats.currentExpandRate);
|
|
EXPECT_EQ(0, stats.currentPreemptiveRate);
|
|
EXPECT_EQ(0, stats.currentAccelerateRate);
|
|
EXPECT_EQ(-916, stats.clockDriftPPM); // Initial value is slightly off.
|
|
EXPECT_EQ(-1, stats.maxWaitingTimeMs);
|
|
EXPECT_EQ(-1, stats.meanWaitingTimeMs);
|
|
EXPECT_EQ(-1, stats.medianWaitingTimeMs);
|
|
}
|
|
|
|
} // namespace
|