ACM test are modified to run with both ACM1 and ACM2.
Beside the changes in test files. acm2/acm_generic_codec.cc and acm2/audio_coding_module_impl.cc are modified to fix a bug.
Also, nack{.cc, .h, _unittest.cc} are removed form main/sourc as nack files in both ACM1 and ACM2 are essentially identical.
R=andrew@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/2192005
git-svn-id: http://webrtc.googlecode.com/svn/trunk@4908 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -318,11 +318,7 @@ int16_t ACMGenericCodec::Encode(uint8_t* bitstream,
|
|||||||
// break from the loop
|
// break from the loop
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
done = in_audio_ix_read_ >= frame_len_smpl_ * num_channels_;
|
||||||
// TODO(andrew): This should be multiplied by the number of
|
|
||||||
// channels, right?
|
|
||||||
// http://code.google.com/p/webrtc/issues/detail?id=714
|
|
||||||
done = in_audio_ix_read_ >= frame_len_smpl_;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (status >= 0) {
|
if (status >= 0) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h"
|
||||||
#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
|
#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
|
||||||
#include "webrtc/modules/audio_coding/neteq4/tools/rtp_generator.h"
|
#include "webrtc/modules/audio_coding/neteq4/tools/rtp_generator.h"
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
@@ -39,7 +40,7 @@ class AcmReceiverTest : public AudioPacketizationCallback,
|
|||||||
protected:
|
protected:
|
||||||
AcmReceiverTest()
|
AcmReceiverTest()
|
||||||
: receiver_(new AcmReceiver),
|
: receiver_(new AcmReceiver),
|
||||||
acm_(AudioCodingModule::Create(0)),
|
acm_(new AudioCodingModuleImpl(0)),
|
||||||
timestamp_(0),
|
timestamp_(0),
|
||||||
packet_sent_(false),
|
packet_sent_(false),
|
||||||
last_packet_send_timestamp_(timestamp_),
|
last_packet_send_timestamp_(timestamp_),
|
||||||
|
|||||||
@@ -1469,7 +1469,7 @@ int AudioCodingModuleImpl::SetVADSafe(bool enable_dtx,
|
|||||||
|
|
||||||
// If a send codec is registered, set VAD/DTX for the codec.
|
// If a send codec is registered, set VAD/DTX for the codec.
|
||||||
if (HaveValidEncoder("SetVAD") && codecs_[current_send_codec_idx_]->SetVAD(
|
if (HaveValidEncoder("SetVAD") && codecs_[current_send_codec_idx_]->SetVAD(
|
||||||
&enable_dtx, &enable_vad, &mode) < 0) {
|
&dtx_enabled_, &vad_enabled_, &vad_mode_) < 0) {
|
||||||
// SetVAD failed.
|
// SetVAD failed.
|
||||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
|
||||||
"SetVAD failed");
|
"SetVAD failed");
|
||||||
|
|||||||
@@ -22,7 +22,12 @@ InitialDelayManager::InitialDelayManager(int initial_delay_ms,
|
|||||||
buffered_audio_ms_(0),
|
buffered_audio_ms_(0),
|
||||||
buffering_(true),
|
buffering_(true),
|
||||||
playout_timestamp_(0),
|
playout_timestamp_(0),
|
||||||
late_packet_threshold_(late_packet_threshold) {}
|
late_packet_threshold_(late_packet_threshold) {
|
||||||
|
last_packet_rtp_info_.header.payloadType = kInvalidPayloadType;
|
||||||
|
last_packet_rtp_info_.header.ssrc = 0;
|
||||||
|
last_packet_rtp_info_.header.sequenceNumber = 0;
|
||||||
|
last_packet_rtp_info_.header.timestamp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void InitialDelayManager::UpdateLastReceivedPacket(
|
void InitialDelayManager::UpdateLastReceivedPacket(
|
||||||
const WebRtcRTPHeader& rtp_info,
|
const WebRtcRTPHeader& rtp_info,
|
||||||
@@ -53,7 +58,9 @@ void InitialDelayManager::UpdateLastReceivedPacket(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_codec) {
|
// Either if it is a new packet or the first packet record and set variables.
|
||||||
|
if (new_codec ||
|
||||||
|
last_packet_rtp_info_.header.payloadType == kInvalidPayloadType) {
|
||||||
timestamp_step_ = 0;
|
timestamp_step_ = 0;
|
||||||
if (type == kAudioPacket)
|
if (type == kAudioPacket)
|
||||||
audio_payload_type_ = rtp_info.header.payloadType;
|
audio_payload_type_ = rtp_info.header.payloadType;
|
||||||
|
|||||||
@@ -103,8 +103,6 @@
|
|||||||
'acm_resampler.h',
|
'acm_resampler.h',
|
||||||
'audio_coding_module_impl.cc',
|
'audio_coding_module_impl.cc',
|
||||||
'audio_coding_module_impl.h',
|
'audio_coding_module_impl.h',
|
||||||
'nack.cc',
|
|
||||||
'nack.h',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "webrtc/modules/audio_coding/main/source/acm_dtmf_detection.h"
|
#include "webrtc/modules/audio_coding/main/source/acm_dtmf_detection.h"
|
||||||
#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
|
#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
|
||||||
#include "webrtc/modules/audio_coding/main/source/acm_resampler.h"
|
#include "webrtc/modules/audio_coding/main/source/acm_resampler.h"
|
||||||
#include "webrtc/modules/audio_coding/main/source/nack.h"
|
#include "webrtc/modules/audio_coding/main/acm2/nack.h"
|
||||||
#include "webrtc/system_wrappers/interface/clock.h"
|
#include "webrtc/system_wrappers/interface/clock.h"
|
||||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||||
#include "webrtc/system_wrappers/interface/logging.h"
|
#include "webrtc/system_wrappers/interface/logging.h"
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ struct WebRtcACMCodecParams;
|
|||||||
class CriticalSectionWrapper;
|
class CriticalSectionWrapper;
|
||||||
class RWLockWrapper;
|
class RWLockWrapper;
|
||||||
class Clock;
|
class Clock;
|
||||||
|
class Nack;
|
||||||
|
|
||||||
namespace acm1 {
|
namespace acm1 {
|
||||||
|
|
||||||
class ACMDTMFDetection;
|
class ACMDTMFDetection;
|
||||||
class ACMGenericCodec;
|
class ACMGenericCodec;
|
||||||
class Nack;
|
|
||||||
|
|
||||||
class AudioCodingModuleImpl : public AudioCodingModule {
|
class AudioCodingModuleImpl : public AudioCodingModule {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1,229 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "webrtc/modules/audio_coding/main/source/nack.h"
|
|
||||||
|
|
||||||
#include <assert.h> // For assert.
|
|
||||||
|
|
||||||
#include <algorithm> // For std::max.
|
|
||||||
|
|
||||||
#include "webrtc/modules/interface/module_common_types.h"
|
|
||||||
#include "webrtc/system_wrappers/interface/logging.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
namespace acm1 {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const int kDefaultSampleRateKhz = 48;
|
|
||||||
const int kDefaultPacketSizeMs = 20;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
Nack::Nack(int nack_threshold_packets)
|
|
||||||
: nack_threshold_packets_(nack_threshold_packets),
|
|
||||||
sequence_num_last_received_rtp_(0),
|
|
||||||
timestamp_last_received_rtp_(0),
|
|
||||||
any_rtp_received_(false),
|
|
||||||
sequence_num_last_decoded_rtp_(0),
|
|
||||||
timestamp_last_decoded_rtp_(0),
|
|
||||||
any_rtp_decoded_(false),
|
|
||||||
sample_rate_khz_(kDefaultSampleRateKhz),
|
|
||||||
samples_per_packet_(sample_rate_khz_ * kDefaultPacketSizeMs),
|
|
||||||
max_nack_list_size_(kNackListSizeLimit) {}
|
|
||||||
|
|
||||||
Nack* Nack::Create(int nack_threshold_packets) {
|
|
||||||
return new Nack(nack_threshold_packets);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::UpdateSampleRate(int sample_rate_hz) {
|
|
||||||
assert(sample_rate_hz > 0);
|
|
||||||
sample_rate_khz_ = sample_rate_hz / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::UpdateLastReceivedPacket(uint16_t sequence_number,
|
|
||||||
uint32_t timestamp) {
|
|
||||||
// Just record the value of sequence number and timestamp if this is the
|
|
||||||
// first packet.
|
|
||||||
if (!any_rtp_received_) {
|
|
||||||
sequence_num_last_received_rtp_ = sequence_number;
|
|
||||||
timestamp_last_received_rtp_ = timestamp;
|
|
||||||
any_rtp_received_ = true;
|
|
||||||
// If no packet is decoded, to have a reasonable estimate of time-to-play
|
|
||||||
// use the given values.
|
|
||||||
if (!any_rtp_decoded_) {
|
|
||||||
sequence_num_last_decoded_rtp_ = sequence_number;
|
|
||||||
timestamp_last_decoded_rtp_ = timestamp;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sequence_number == sequence_num_last_received_rtp_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Received RTP should not be in the list.
|
|
||||||
nack_list_.erase(sequence_number);
|
|
||||||
|
|
||||||
// If this is an old sequence number, no more action is required, return.
|
|
||||||
if (IsNewerSequenceNumber(sequence_num_last_received_rtp_, sequence_number))
|
|
||||||
return;
|
|
||||||
|
|
||||||
UpdateSamplesPerPacket(sequence_number, timestamp);
|
|
||||||
|
|
||||||
UpdateList(sequence_number);
|
|
||||||
|
|
||||||
sequence_num_last_received_rtp_ = sequence_number;
|
|
||||||
timestamp_last_received_rtp_ = timestamp;
|
|
||||||
LimitNackListSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::UpdateSamplesPerPacket(uint16_t sequence_number_current_received_rtp,
|
|
||||||
uint32_t timestamp_current_received_rtp) {
|
|
||||||
uint32_t timestamp_increase = timestamp_current_received_rtp -
|
|
||||||
timestamp_last_received_rtp_;
|
|
||||||
uint16_t sequence_num_increase = sequence_number_current_received_rtp -
|
|
||||||
sequence_num_last_received_rtp_;
|
|
||||||
|
|
||||||
samples_per_packet_ = timestamp_increase / sequence_num_increase;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::UpdateList(uint16_t sequence_number_current_received_rtp) {
|
|
||||||
// Some of the packets which were considered late, now are considered missing.
|
|
||||||
ChangeFromLateToMissing(sequence_number_current_received_rtp);
|
|
||||||
|
|
||||||
if (IsNewerSequenceNumber(sequence_number_current_received_rtp,
|
|
||||||
sequence_num_last_received_rtp_ + 1))
|
|
||||||
AddToList(sequence_number_current_received_rtp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::ChangeFromLateToMissing(
|
|
||||||
uint16_t sequence_number_current_received_rtp) {
|
|
||||||
NackList::const_iterator lower_bound = nack_list_.lower_bound(
|
|
||||||
static_cast<uint16_t>(sequence_number_current_received_rtp -
|
|
||||||
nack_threshold_packets_));
|
|
||||||
|
|
||||||
for (NackList::iterator it = nack_list_.begin(); it != lower_bound; ++it)
|
|
||||||
it->second.is_missing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Nack::EstimateTimestamp(uint16_t sequence_num) {
|
|
||||||
uint16_t sequence_num_diff = sequence_num - sequence_num_last_received_rtp_;
|
|
||||||
return sequence_num_diff * samples_per_packet_ + timestamp_last_received_rtp_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::AddToList(uint16_t sequence_number_current_received_rtp) {
|
|
||||||
assert(!any_rtp_decoded_ || IsNewerSequenceNumber(
|
|
||||||
sequence_number_current_received_rtp, sequence_num_last_decoded_rtp_));
|
|
||||||
|
|
||||||
// Packets with sequence numbers older than |upper_bound_missing| are
|
|
||||||
// considered missing, and the rest are considered late.
|
|
||||||
uint16_t upper_bound_missing = sequence_number_current_received_rtp -
|
|
||||||
nack_threshold_packets_;
|
|
||||||
|
|
||||||
for (uint16_t n = sequence_num_last_received_rtp_ + 1;
|
|
||||||
IsNewerSequenceNumber(sequence_number_current_received_rtp, n); ++n) {
|
|
||||||
bool is_missing = IsNewerSequenceNumber(upper_bound_missing, n);
|
|
||||||
uint32_t timestamp = EstimateTimestamp(n);
|
|
||||||
NackElement nack_element(TimeToPlay(timestamp), timestamp, is_missing);
|
|
||||||
nack_list_.insert(nack_list_.end(), std::make_pair(n, nack_element));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::UpdateEstimatedPlayoutTimeBy10ms() {
|
|
||||||
while (!nack_list_.empty() &&
|
|
||||||
nack_list_.begin()->second.time_to_play_ms <= 10)
|
|
||||||
nack_list_.erase(nack_list_.begin());
|
|
||||||
|
|
||||||
for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end(); ++it)
|
|
||||||
it->second.time_to_play_ms -= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::UpdateLastDecodedPacket(uint16_t sequence_number,
|
|
||||||
uint32_t timestamp) {
|
|
||||||
if (IsNewerSequenceNumber(sequence_number, sequence_num_last_decoded_rtp_) ||
|
|
||||||
!any_rtp_decoded_) {
|
|
||||||
sequence_num_last_decoded_rtp_ = sequence_number;
|
|
||||||
timestamp_last_decoded_rtp_ = timestamp;
|
|
||||||
// Packets in the list with sequence numbers less than the
|
|
||||||
// sequence number of the decoded RTP should be removed from the lists.
|
|
||||||
// They will be discarded by the jitter buffer if they arrive.
|
|
||||||
nack_list_.erase(nack_list_.begin(), nack_list_.upper_bound(
|
|
||||||
sequence_num_last_decoded_rtp_));
|
|
||||||
|
|
||||||
// Update estimated time-to-play.
|
|
||||||
for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end();
|
|
||||||
++it)
|
|
||||||
it->second.time_to_play_ms = TimeToPlay(it->second.estimated_timestamp);
|
|
||||||
} else {
|
|
||||||
assert(sequence_number == sequence_num_last_decoded_rtp_);
|
|
||||||
|
|
||||||
// Same sequence number as before. 10 ms is elapsed, update estimations for
|
|
||||||
// time-to-play.
|
|
||||||
UpdateEstimatedPlayoutTimeBy10ms();
|
|
||||||
|
|
||||||
// Update timestamp for better estimate of time-to-play, for packets which
|
|
||||||
// are added to NACK list later on.
|
|
||||||
timestamp_last_decoded_rtp_ += sample_rate_khz_ * 10;
|
|
||||||
}
|
|
||||||
any_rtp_decoded_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Nack::NackList Nack::GetNackList() const {
|
|
||||||
return nack_list_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::Reset() {
|
|
||||||
nack_list_.clear();
|
|
||||||
|
|
||||||
sequence_num_last_received_rtp_ = 0;
|
|
||||||
timestamp_last_received_rtp_ = 0;
|
|
||||||
any_rtp_received_ = false;
|
|
||||||
sequence_num_last_decoded_rtp_ = 0;
|
|
||||||
timestamp_last_decoded_rtp_ = 0;
|
|
||||||
any_rtp_decoded_ = false;
|
|
||||||
sample_rate_khz_ = kDefaultSampleRateKhz;
|
|
||||||
samples_per_packet_ = sample_rate_khz_ * kDefaultPacketSizeMs;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Nack::SetMaxNackListSize(size_t max_nack_list_size) {
|
|
||||||
if (max_nack_list_size == 0 || max_nack_list_size > kNackListSizeLimit)
|
|
||||||
return -1;
|
|
||||||
max_nack_list_size_ = max_nack_list_size;
|
|
||||||
LimitNackListSize();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nack::LimitNackListSize() {
|
|
||||||
uint16_t limit = sequence_num_last_received_rtp_ -
|
|
||||||
static_cast<uint16_t>(max_nack_list_size_) - 1;
|
|
||||||
nack_list_.erase(nack_list_.begin(), nack_list_.upper_bound(limit));
|
|
||||||
}
|
|
||||||
|
|
||||||
int Nack::TimeToPlay(uint32_t timestamp) const {
|
|
||||||
uint32_t timestamp_increase = timestamp - timestamp_last_decoded_rtp_;
|
|
||||||
return timestamp_increase / sample_rate_khz_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't erase elements with time-to-play shorter than round-trip-time.
|
|
||||||
std::vector<uint16_t> Nack::GetNackList(int round_trip_time_ms) const {
|
|
||||||
std::vector<uint16_t> sequence_numbers;
|
|
||||||
for (NackList::const_iterator it = nack_list_.begin(); it != nack_list_.end();
|
|
||||||
++it) {
|
|
||||||
if (it->second.is_missing &&
|
|
||||||
it->second.time_to_play_ms > round_trip_time_ms)
|
|
||||||
sequence_numbers.push_back(it->first);
|
|
||||||
}
|
|
||||||
return sequence_numbers;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace acm1
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_NACK_H_
|
|
||||||
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_NACK_H_
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
|
||||||
#include "webrtc/test/testsupport/gtest_prod_util.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// The Nack class keeps track of the lost packets, an estimate of time-to-play
|
|
||||||
// for each packet is also given.
|
|
||||||
//
|
|
||||||
// Every time a packet is pushed into NetEq, LastReceivedPacket() has to be
|
|
||||||
// called to update the NACK list.
|
|
||||||
//
|
|
||||||
// Every time 10ms audio is pulled from NetEq LastDecodedPacket() should be
|
|
||||||
// called, and time-to-play is updated at that moment.
|
|
||||||
//
|
|
||||||
// If packet N is received, any packet prior to |N - NackThreshold| which is not
|
|
||||||
// arrived is considered lost, and should be labeled as "missing" (the size of
|
|
||||||
// the list might be limited and older packet eliminated from the list). Packets
|
|
||||||
// |N - NackThreshold|, |N - NackThreshold + 1|, ..., |N - 1| are considered
|
|
||||||
// "late." A "late" packet with sequence number K is changed to "missing" any
|
|
||||||
// time a packet with sequence number newer than |K + NackList| is arrived.
|
|
||||||
//
|
|
||||||
// The Nack class has to know about the sample rate of the packets to compute
|
|
||||||
// time-to-play. So sample rate should be set as soon as the first packet is
|
|
||||||
// received. If there is a change in the receive codec (sender changes codec)
|
|
||||||
// then Nack should be reset. This is because NetEQ would flush its buffer and
|
|
||||||
// re-transmission is meaning less for old packet. Therefore, in that case,
|
|
||||||
// after reset the sampling rate has to be updated.
|
|
||||||
//
|
|
||||||
// Thread Safety
|
|
||||||
// =============
|
|
||||||
// Please note that this class in not thread safe. The class must be protected
|
|
||||||
// if different APIs are called from different threads.
|
|
||||||
//
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
namespace acm1 {
|
|
||||||
|
|
||||||
class Nack {
|
|
||||||
public:
|
|
||||||
// A limit for the size of the NACK list.
|
|
||||||
static const size_t kNackListSizeLimit = 500; // 10 seconds for 20 ms frame
|
|
||||||
// packets.
|
|
||||||
// Factory method.
|
|
||||||
static Nack* Create(int nack_threshold_packets);
|
|
||||||
|
|
||||||
~Nack() {}
|
|
||||||
|
|
||||||
// Set a maximum for the size of the NACK list. If the last received packet
|
|
||||||
// has sequence number of N, then NACK list will not contain any element
|
|
||||||
// with sequence number earlier than N - |max_nack_list_size|.
|
|
||||||
//
|
|
||||||
// The largest maximum size is defined by |kNackListSizeLimit|
|
|
||||||
int SetMaxNackListSize(size_t max_nack_list_size);
|
|
||||||
|
|
||||||
// Set the sampling rate.
|
|
||||||
//
|
|
||||||
// If associated sampling rate of the received packets is changed, call this
|
|
||||||
// function to update sampling rate. Note that if there is any change in
|
|
||||||
// received codec then NetEq will flush its buffer and NACK has to be reset.
|
|
||||||
// After Reset() is called sampling rate has to be set.
|
|
||||||
void UpdateSampleRate(int sample_rate_hz);
|
|
||||||
|
|
||||||
// Update the sequence number and the timestamp of the last decoded RTP. This
|
|
||||||
// API should be called every time 10 ms audio is pulled from NetEq.
|
|
||||||
void UpdateLastDecodedPacket(uint16_t sequence_number, uint32_t timestamp);
|
|
||||||
|
|
||||||
// Update the sequence number and the timestamp of the last received RTP. This
|
|
||||||
// API should be called every time a packet pushed into ACM.
|
|
||||||
void UpdateLastReceivedPacket(uint16_t sequence_number, uint32_t timestamp);
|
|
||||||
|
|
||||||
// Get a list of "missing" packets which have expected time-to-play larger
|
|
||||||
// than the given round-trip-time (in milliseconds).
|
|
||||||
// Note: Late packets are not included.
|
|
||||||
std::vector<uint16_t> GetNackList(int round_trip_time_ms) const;
|
|
||||||
|
|
||||||
// Reset to default values. The NACK list is cleared.
|
|
||||||
// |nack_threshold_packets_| & |max_nack_list_size_| preserve their values.
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// This test need to access the private method GetNackList().
|
|
||||||
FRIEND_TEST_ALL_PREFIXES(NackTest, EstimateTimestampAndTimeToPlay);
|
|
||||||
|
|
||||||
struct NackElement {
|
|
||||||
NackElement(int initial_time_to_play_ms,
|
|
||||||
uint32_t initial_timestamp,
|
|
||||||
bool missing)
|
|
||||||
: time_to_play_ms(initial_time_to_play_ms),
|
|
||||||
estimated_timestamp(initial_timestamp),
|
|
||||||
is_missing(missing) {}
|
|
||||||
|
|
||||||
// Estimated time (ms) left for this packet to be decoded. This estimate is
|
|
||||||
// updated every time jitter buffer decodes a packet.
|
|
||||||
int time_to_play_ms;
|
|
||||||
|
|
||||||
// A guess about the timestamp of the missing packet, it is used for
|
|
||||||
// estimation of |time_to_play_ms|. The estimate might be slightly wrong if
|
|
||||||
// there has been frame-size change since the last received packet and the
|
|
||||||
// missing packet. However, the risk of this is low, and in case of such
|
|
||||||
// errors, there will be a minor misestimation in time-to-play of missing
|
|
||||||
// packets. This will have a very minor effect on NACK performance.
|
|
||||||
uint32_t estimated_timestamp;
|
|
||||||
|
|
||||||
// True if the packet is considered missing. Otherwise indicates packet is
|
|
||||||
// late.
|
|
||||||
bool is_missing;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NackListCompare {
|
|
||||||
public:
|
|
||||||
bool operator() (uint16_t sequence_number_old,
|
|
||||||
uint16_t sequence_number_new) const {
|
|
||||||
return IsNewerSequenceNumber(sequence_number_new, sequence_number_old);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<uint16_t, NackElement, NackListCompare> NackList;
|
|
||||||
|
|
||||||
// Constructor.
|
|
||||||
explicit Nack(int nack_threshold_packets);
|
|
||||||
|
|
||||||
// This API is used only for testing to assess whether time-to-play is
|
|
||||||
// computed correctly.
|
|
||||||
NackList GetNackList() const;
|
|
||||||
|
|
||||||
// Given the |sequence_number_current_received_rtp| of currently received RTP,
|
|
||||||
// recognize packets which are not arrive and add to the list.
|
|
||||||
void AddToList(uint16_t sequence_number_current_received_rtp);
|
|
||||||
|
|
||||||
// This function subtracts 10 ms of time-to-play for all packets in NACK list.
|
|
||||||
// This is called when 10 ms elapsed with no new RTP packet decoded.
|
|
||||||
void UpdateEstimatedPlayoutTimeBy10ms();
|
|
||||||
|
|
||||||
// Given the |sequence_number_current_received_rtp| and
|
|
||||||
// |timestamp_current_received_rtp| of currently received RTP update number
|
|
||||||
// of samples per packet.
|
|
||||||
void UpdateSamplesPerPacket(uint16_t sequence_number_current_received_rtp,
|
|
||||||
uint32_t timestamp_current_received_rtp);
|
|
||||||
|
|
||||||
// Given the |sequence_number_current_received_rtp| of currently received RTP
|
|
||||||
// update the list. That is; some packets will change from late to missing,
|
|
||||||
// some packets are inserted as missing and some inserted as late.
|
|
||||||
void UpdateList(uint16_t sequence_number_current_received_rtp);
|
|
||||||
|
|
||||||
// Packets which are considered late for too long (according to
|
|
||||||
// |nack_threshold_packets_|) are flagged as missing.
|
|
||||||
void ChangeFromLateToMissing(uint16_t sequence_number_current_received_rtp);
|
|
||||||
|
|
||||||
// Packets which have sequence number older that
|
|
||||||
// |sequence_num_last_received_rtp_| - |max_nack_list_size_| are removed
|
|
||||||
// from the NACK list.
|
|
||||||
void LimitNackListSize();
|
|
||||||
|
|
||||||
// Estimate timestamp of a missing packet given its sequence number.
|
|
||||||
uint32_t EstimateTimestamp(uint16_t sequence_number);
|
|
||||||
|
|
||||||
// Compute time-to-play given a timestamp.
|
|
||||||
int TimeToPlay(uint32_t timestamp) const;
|
|
||||||
|
|
||||||
// If packet N is arrived, any packet prior to N - |nack_threshold_packets_|
|
|
||||||
// which is not arrived is considered missing, and should be in NACK list.
|
|
||||||
// Also any packet in the range of N-1 and N - |nack_threshold_packets_|,
|
|
||||||
// exclusive, which is not arrived is considered late, and should should be
|
|
||||||
// in the list of late packets.
|
|
||||||
const int nack_threshold_packets_;
|
|
||||||
|
|
||||||
// Valid if a packet is received.
|
|
||||||
uint16_t sequence_num_last_received_rtp_;
|
|
||||||
uint32_t timestamp_last_received_rtp_;
|
|
||||||
bool any_rtp_received_; // If any packet received.
|
|
||||||
|
|
||||||
// Valid if a packet is decoded.
|
|
||||||
uint16_t sequence_num_last_decoded_rtp_;
|
|
||||||
uint32_t timestamp_last_decoded_rtp_;
|
|
||||||
bool any_rtp_decoded_; // If any packet decoded.
|
|
||||||
|
|
||||||
int sample_rate_khz_; // Sample rate in kHz.
|
|
||||||
|
|
||||||
// Number of samples per packet. We update this every time we receive a
|
|
||||||
// packet, not only for consecutive packets.
|
|
||||||
int samples_per_packet_;
|
|
||||||
|
|
||||||
// A list of missing packets to be retransmitted. Components of the list
|
|
||||||
// contain the sequence number of missing packets and the estimated time that
|
|
||||||
// each pack is going to be played out.
|
|
||||||
NackList nack_list_;
|
|
||||||
|
|
||||||
// NACK list will not keep track of missing packets prior to
|
|
||||||
// |sequence_num_last_received_rtp_| - |max_nack_list_size_|.
|
|
||||||
size_t max_nack_list_size_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace acm1
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
|
|
||||||
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_NACK_H_
|
|
||||||
@@ -1,487 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "webrtc/modules/audio_coding/main/source/nack.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "webrtc/typedefs.h"
|
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
namespace acm1 {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const int kNackThreshold = 3;
|
|
||||||
const int kSampleRateHz = 16000;
|
|
||||||
const int kPacketSizeMs = 30;
|
|
||||||
const uint32_t kTimestampIncrement = 480; // 30 ms.
|
|
||||||
const int kShortRoundTripTimeMs = 1;
|
|
||||||
|
|
||||||
bool IsNackListCorrect(const std::vector<uint16_t>& nack_list,
|
|
||||||
const uint16_t* lost_sequence_numbers,
|
|
||||||
size_t num_lost_packets) {
|
|
||||||
if (nack_list.size() != num_lost_packets)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (num_lost_packets == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
for (size_t k = 0; k < nack_list.size(); ++k) {
|
|
||||||
int seq_num = nack_list[k];
|
|
||||||
bool seq_num_matched = false;
|
|
||||||
for (size_t n = 0; n < num_lost_packets; ++n) {
|
|
||||||
if (seq_num == lost_sequence_numbers[n]) {
|
|
||||||
seq_num_matched = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!seq_num_matched)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
TEST(NackTest, EmptyListWhenNoPacketLoss) {
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
|
|
||||||
int seq_num = 1;
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
|
|
||||||
std::vector<uint16_t> nack_list;
|
|
||||||
for (int n = 0; n < 100; n++) {
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
seq_num++;
|
|
||||||
timestamp += kTimestampIncrement;
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(nack_list.empty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(NackTest, NoNackIfReorderWithinNackThreshold) {
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
|
|
||||||
int seq_num = 1;
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
std::vector<uint16_t> nack_list;
|
|
||||||
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(nack_list.empty());
|
|
||||||
int num_late_packets = kNackThreshold + 1;
|
|
||||||
|
|
||||||
// Push in reverse order
|
|
||||||
while (num_late_packets > 0) {
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num + num_late_packets, timestamp +
|
|
||||||
num_late_packets * kTimestampIncrement);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(nack_list.empty());
|
|
||||||
num_late_packets--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(NackTest, LatePacketsMovedToNackThenNackListDoesNotChange) {
|
|
||||||
const uint16_t kSequenceNumberLostPackets[] = { 2, 3, 4, 5, 6, 7, 8, 9 };
|
|
||||||
static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
|
|
||||||
sizeof(kSequenceNumberLostPackets[0]);
|
|
||||||
|
|
||||||
for (int k = 0; k < 2; k++) { // Two iteration with/without wrap around.
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
|
|
||||||
uint16_t sequence_num_lost_packets[kNumAllLostPackets];
|
|
||||||
for (int n = 0; n < kNumAllLostPackets; n++) {
|
|
||||||
sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] + k *
|
|
||||||
65531; // Have wrap around in sequence numbers for |k == 1|.
|
|
||||||
}
|
|
||||||
uint16_t seq_num = sequence_num_lost_packets[0] - 1;
|
|
||||||
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
std::vector<uint16_t> nack_list;
|
|
||||||
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(nack_list.empty());
|
|
||||||
|
|
||||||
seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
|
|
||||||
timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
|
|
||||||
int num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
|
|
||||||
|
|
||||||
for (int n = 0; n < kNackThreshold + 1; ++n) {
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
|
|
||||||
num_lost_packets));
|
|
||||||
seq_num++;
|
|
||||||
timestamp += kTimestampIncrement;
|
|
||||||
num_lost_packets++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int n = 0; n < 100; ++n) {
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
|
|
||||||
kNumAllLostPackets));
|
|
||||||
seq_num++;
|
|
||||||
timestamp += kTimestampIncrement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(NackTest, ArrivedPacketsAreRemovedFromNackList) {
|
|
||||||
const uint16_t kSequenceNumberLostPackets[] = { 2, 3, 4, 5, 6, 7, 8, 9 };
|
|
||||||
static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
|
|
||||||
sizeof(kSequenceNumberLostPackets[0]);
|
|
||||||
|
|
||||||
for (int k = 0; k < 2; ++k) { // Two iteration with/without wrap around.
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
|
|
||||||
uint16_t sequence_num_lost_packets[kNumAllLostPackets];
|
|
||||||
for (int n = 0; n < kNumAllLostPackets; ++n) {
|
|
||||||
sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] + k *
|
|
||||||
65531; // Wrap around for |k == 1|.
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t seq_num = sequence_num_lost_packets[0] - 1;
|
|
||||||
uint32_t timestamp = 0;
|
|
||||||
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(nack_list.empty());
|
|
||||||
|
|
||||||
size_t index_retransmitted_rtp = 0;
|
|
||||||
uint32_t timestamp_retransmitted_rtp = timestamp + kTimestampIncrement;
|
|
||||||
|
|
||||||
seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
|
|
||||||
timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
|
|
||||||
size_t num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
|
|
||||||
for (int n = 0; n < kNumAllLostPackets; ++n) {
|
|
||||||
// Number of lost packets does not change for the first
|
|
||||||
// |kNackThreshold + 1| packets, one is added to the list and one is
|
|
||||||
// removed. Thereafter, the list shrinks every iteration.
|
|
||||||
if (n >= kNackThreshold + 1)
|
|
||||||
num_lost_packets--;
|
|
||||||
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(IsNackListCorrect(
|
|
||||||
nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
|
|
||||||
num_lost_packets));
|
|
||||||
seq_num++;
|
|
||||||
timestamp += kTimestampIncrement;
|
|
||||||
|
|
||||||
// Retransmission of a lost RTP.
|
|
||||||
nack->UpdateLastReceivedPacket(
|
|
||||||
sequence_num_lost_packets[index_retransmitted_rtp],
|
|
||||||
timestamp_retransmitted_rtp);
|
|
||||||
index_retransmitted_rtp++;
|
|
||||||
timestamp_retransmitted_rtp += kTimestampIncrement;
|
|
||||||
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(IsNackListCorrect(
|
|
||||||
nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
|
|
||||||
num_lost_packets - 1)); // One less lost packet in the list.
|
|
||||||
}
|
|
||||||
ASSERT_TRUE(nack_list.empty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assess if estimation of timestamps and time-to-play is correct. Introduce all
|
|
||||||
// combinations that timestamps and sequence numbers might have wrap around.
|
|
||||||
TEST(NackTest, EstimateTimestampAndTimeToPlay) {
|
|
||||||
const uint16_t kLostPackets[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
|
||||||
11, 12, 13, 14, 15 };
|
|
||||||
static const int kNumAllLostPackets = sizeof(kLostPackets) /
|
|
||||||
sizeof(kLostPackets[0]);
|
|
||||||
|
|
||||||
|
|
||||||
for (int k = 0; k < 4; ++k) {
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
|
|
||||||
// Sequence number wrap around if |k| is 2 or 3;
|
|
||||||
int seq_num_offset = (k < 2) ? 0 : 65531;
|
|
||||||
|
|
||||||
// Timestamp wrap around if |k| is 1 or 3.
|
|
||||||
uint32_t timestamp_offset = (k & 0x1) ?
|
|
||||||
static_cast<uint32_t>(0xffffffff) - 6 : 0;
|
|
||||||
|
|
||||||
uint32_t timestamp_lost_packets[kNumAllLostPackets];
|
|
||||||
uint16_t seq_num_lost_packets[kNumAllLostPackets];
|
|
||||||
for (int n = 0; n < kNumAllLostPackets; ++n) {
|
|
||||||
timestamp_lost_packets[n] = timestamp_offset + kLostPackets[n] *
|
|
||||||
kTimestampIncrement;
|
|
||||||
seq_num_lost_packets[n] = seq_num_offset + kLostPackets[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
// We and to push two packets before lost burst starts.
|
|
||||||
uint16_t seq_num = seq_num_lost_packets[0] - 2;
|
|
||||||
uint32_t timestamp = timestamp_lost_packets[0] - 2 * kTimestampIncrement;
|
|
||||||
|
|
||||||
const uint16_t first_seq_num = seq_num;
|
|
||||||
const uint32_t first_timestamp = timestamp;
|
|
||||||
|
|
||||||
// Two consecutive packets to have a correct estimate of timestamp increase.
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
seq_num++;
|
|
||||||
timestamp += kTimestampIncrement;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
|
|
||||||
// A packet after the last one which is supposed to be lost.
|
|
||||||
seq_num = seq_num_lost_packets[kNumAllLostPackets - 1] + 1;
|
|
||||||
timestamp = timestamp_lost_packets[kNumAllLostPackets - 1] +
|
|
||||||
kTimestampIncrement;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
|
|
||||||
Nack::NackList nack_list = nack->GetNackList();
|
|
||||||
EXPECT_EQ(static_cast<size_t>(kNumAllLostPackets), nack_list.size());
|
|
||||||
|
|
||||||
// Pretend the first packet is decoded.
|
|
||||||
nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
|
|
||||||
nack_list = nack->GetNackList();
|
|
||||||
|
|
||||||
Nack::NackList::iterator it = nack_list.begin();
|
|
||||||
while (it != nack_list.end()) {
|
|
||||||
seq_num = it->first - seq_num_offset;
|
|
||||||
int index = seq_num - kLostPackets[0];
|
|
||||||
EXPECT_EQ(timestamp_lost_packets[index], it->second.estimated_timestamp);
|
|
||||||
EXPECT_EQ((index + 2) * kPacketSizeMs, it->second.time_to_play_ms);
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pretend 10 ms is passed, and we had pulled audio from NetEq, it still
|
|
||||||
// reports the same sequence number as decoded, time-to-play should be
|
|
||||||
// updated by 10 ms.
|
|
||||||
nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
|
|
||||||
nack_list = nack->GetNackList();
|
|
||||||
it = nack_list.begin();
|
|
||||||
while (it != nack_list.end()) {
|
|
||||||
seq_num = it->first - seq_num_offset;
|
|
||||||
int index = seq_num - kLostPackets[0];
|
|
||||||
EXPECT_EQ((index + 2) * kPacketSizeMs - 10, it->second.time_to_play_ms);
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(NackTest, MissingPacketsPriorToLastDecodedRtpShouldNotBeInNackList) {
|
|
||||||
for (int m = 0; m < 2; ++m) {
|
|
||||||
uint16_t seq_num_offset = (m == 0) ? 0 : 65531; // Wrap around if |m| is 1.
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
|
|
||||||
// Two consecutive packets to have a correct estimate of timestamp increase.
|
|
||||||
uint16_t seq_num = 0;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
|
|
||||||
seq_num * kTimestampIncrement);
|
|
||||||
seq_num++;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
|
|
||||||
seq_num * kTimestampIncrement);
|
|
||||||
|
|
||||||
// Skip 10 packets (larger than NACK threshold).
|
|
||||||
const int kNumLostPackets = 10;
|
|
||||||
seq_num += kNumLostPackets + 1;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
|
|
||||||
seq_num * kTimestampIncrement);
|
|
||||||
|
|
||||||
const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
|
|
||||||
std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_EQ(kExpectedListSize, nack_list.size());
|
|
||||||
|
|
||||||
for (int k = 0; k < 2; ++k) {
|
|
||||||
// Decoding of the first and the second arrived packets.
|
|
||||||
for (int n = 0; n < kPacketSizeMs / 10; ++n) {
|
|
||||||
nack->UpdateLastDecodedPacket(seq_num_offset + k,
|
|
||||||
k * kTimestampIncrement);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_EQ(kExpectedListSize, nack_list.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decoding of the last received packet.
|
|
||||||
nack->UpdateLastDecodedPacket(seq_num + seq_num_offset,
|
|
||||||
seq_num * kTimestampIncrement);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(nack_list.empty());
|
|
||||||
|
|
||||||
// Make sure list of late packets is also empty. To check that, push few
|
|
||||||
// packets, if the late list is not empty its content will pop up in NACK
|
|
||||||
// list.
|
|
||||||
for (int n = 0; n < kNackThreshold + 10; ++n) {
|
|
||||||
seq_num++;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
|
|
||||||
seq_num * kTimestampIncrement);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(nack_list.empty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(NackTest, Reset) {
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
|
|
||||||
// Two consecutive packets to have a correct estimate of timestamp increase.
|
|
||||||
uint16_t seq_num = 0;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
|
|
||||||
seq_num++;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
|
|
||||||
|
|
||||||
// Skip 10 packets (larger than NACK threshold).
|
|
||||||
const int kNumLostPackets = 10;
|
|
||||||
seq_num += kNumLostPackets + 1;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
|
|
||||||
|
|
||||||
const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
|
|
||||||
std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_EQ(kExpectedListSize, nack_list.size());
|
|
||||||
|
|
||||||
nack->Reset();
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(nack_list.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(NackTest, ListSizeAppliedFromBeginning) {
|
|
||||||
const size_t kNackListSize = 10;
|
|
||||||
for (int m = 0; m < 2; ++m) {
|
|
||||||
uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if |m| is 1.
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
nack->SetMaxNackListSize(kNackListSize);
|
|
||||||
|
|
||||||
uint16_t seq_num = seq_num_offset;
|
|
||||||
uint32_t timestamp = 0x12345678;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
|
|
||||||
// Packet lost more than NACK-list size limit.
|
|
||||||
uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
|
|
||||||
|
|
||||||
seq_num += num_lost_packets + 1;
|
|
||||||
timestamp += (num_lost_packets + 1) * kTimestampIncrement;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
|
|
||||||
std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_EQ(kNackListSize - kNackThreshold, nack_list.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(NackTest, ChangeOfListSizeAppliedAndOldElementsRemoved) {
|
|
||||||
const size_t kNackListSize = 10;
|
|
||||||
for (int m = 0; m < 2; ++m) {
|
|
||||||
uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if |m| is 1.
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
|
|
||||||
uint16_t seq_num = seq_num_offset;
|
|
||||||
uint32_t timestamp = 0x87654321;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
|
|
||||||
// Packet lost more than NACK-list size limit.
|
|
||||||
uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
|
|
||||||
|
|
||||||
scoped_array<uint16_t> seq_num_lost(new uint16_t[num_lost_packets]);
|
|
||||||
for (int n = 0; n < num_lost_packets; ++n) {
|
|
||||||
seq_num_lost[n] = ++seq_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
++seq_num;
|
|
||||||
timestamp += (num_lost_packets + 1) * kTimestampIncrement;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
size_t expected_size = num_lost_packets - kNackThreshold;
|
|
||||||
|
|
||||||
std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_EQ(expected_size, nack_list.size());
|
|
||||||
|
|
||||||
nack->SetMaxNackListSize(kNackListSize);
|
|
||||||
expected_size = kNackListSize - kNackThreshold;
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(IsNackListCorrect(
|
|
||||||
nack_list, &seq_num_lost[num_lost_packets - kNackListSize],
|
|
||||||
expected_size));
|
|
||||||
|
|
||||||
// NACK list does not change size but the content is changing. The oldest
|
|
||||||
// element is removed and one from late list is inserted.
|
|
||||||
size_t n;
|
|
||||||
for (n = 1; n <= static_cast<size_t>(kNackThreshold); ++n) {
|
|
||||||
++seq_num;
|
|
||||||
timestamp += kTimestampIncrement;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(IsNackListCorrect(
|
|
||||||
nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
|
|
||||||
expected_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
// NACK list should shrink.
|
|
||||||
for (; n < kNackListSize; ++n) {
|
|
||||||
++seq_num;
|
|
||||||
timestamp += kTimestampIncrement;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
--expected_size;
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(IsNackListCorrect(
|
|
||||||
nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
|
|
||||||
expected_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
// After this packet, NACK list should be empty.
|
|
||||||
++seq_num;
|
|
||||||
timestamp += kTimestampIncrement;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
nack_list = nack->GetNackList(kShortRoundTripTimeMs);
|
|
||||||
EXPECT_TRUE(nack_list.empty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(NackTest, RoudTripTimeIsApplied) {
|
|
||||||
const int kNackListSize = 200;
|
|
||||||
scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
|
|
||||||
nack->UpdateSampleRate(kSampleRateHz);
|
|
||||||
nack->SetMaxNackListSize(kNackListSize);
|
|
||||||
|
|
||||||
uint16_t seq_num = 0;
|
|
||||||
uint32_t timestamp = 0x87654321;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
|
|
||||||
// Packet lost more than NACK-list size limit.
|
|
||||||
uint16_t kNumLostPackets = kNackThreshold + 5;
|
|
||||||
|
|
||||||
seq_num += (1 + kNumLostPackets);
|
|
||||||
timestamp += (1 + kNumLostPackets) * kTimestampIncrement;
|
|
||||||
nack->UpdateLastReceivedPacket(seq_num, timestamp);
|
|
||||||
|
|
||||||
// Expected time-to-play are:
|
|
||||||
// kPacketSizeMs - 10, 2*kPacketSizeMs - 10, 3*kPacketSizeMs - 10, ...
|
|
||||||
//
|
|
||||||
// sequence number: 1, 2, 3, 4, 5
|
|
||||||
// time-to-play: 20, 50, 80, 110, 140
|
|
||||||
//
|
|
||||||
std::vector<uint16_t> nack_list = nack->GetNackList(100);
|
|
||||||
ASSERT_EQ(2u, nack_list.size());
|
|
||||||
EXPECT_EQ(4, nack_list[0]);
|
|
||||||
EXPECT_EQ(5, nack_list[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace acm1
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
@@ -11,4 +11,3 @@
|
|||||||
#include "ACMTest.h"
|
#include "ACMTest.h"
|
||||||
|
|
||||||
ACMTest::~ACMTest() {}
|
ACMTest::~ACMTest() {}
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,14 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ACMTEST_H
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_ACMTEST_H_
|
||||||
#define ACMTEST_H
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_ACMTEST_H_
|
||||||
|
|
||||||
class ACMTest {
|
class ACMTest {
|
||||||
public:
|
public:
|
||||||
|
ACMTest() {}
|
||||||
virtual ~ACMTest() = 0;
|
virtual ~ACMTest() = 0;
|
||||||
virtual void Perform() = 0;
|
virtual void Perform() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_ACMTEST_H_
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
#include "webrtc/common.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/engine_configurations.h"
|
#include "webrtc/engine_configurations.h"
|
||||||
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
||||||
@@ -54,9 +55,9 @@ void APITest::Wait(uint32_t waitLengthMs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
APITest::APITest()
|
APITest::APITest(const Config& config)
|
||||||
: _acmA(AudioCodingModule::Create(1)),
|
: _acmA(config.Get<AudioCodingModuleFactory>().Create(1)),
|
||||||
_acmB(AudioCodingModule::Create(2)),
|
_acmB(config.Get<AudioCodingModuleFactory>().Create(2)),
|
||||||
_channel_A2B(NULL),
|
_channel_A2B(NULL),
|
||||||
_channel_B2A(NULL),
|
_channel_B2A(NULL),
|
||||||
_writeToFile(true),
|
_writeToFile(true),
|
||||||
@@ -238,12 +239,12 @@ int16_t APITest::SetUp() {
|
|||||||
//--- Set A-to-B channel
|
//--- Set A-to-B channel
|
||||||
_channel_A2B = new Channel(2);
|
_channel_A2B = new Channel(2);
|
||||||
CHECK_ERROR_MT(_acmA->RegisterTransportCallback(_channel_A2B));
|
CHECK_ERROR_MT(_acmA->RegisterTransportCallback(_channel_A2B));
|
||||||
_channel_A2B->RegisterReceiverACM(_acmB);
|
_channel_A2B->RegisterReceiverACM(_acmB.get());
|
||||||
|
|
||||||
//--- Set B-to-A channel
|
//--- Set B-to-A channel
|
||||||
_channel_B2A = new Channel(1);
|
_channel_B2A = new Channel(1);
|
||||||
CHECK_ERROR_MT(_acmB->RegisterTransportCallback(_channel_B2A));
|
CHECK_ERROR_MT(_acmB->RegisterTransportCallback(_channel_B2A));
|
||||||
_channel_B2A->RegisterReceiverACM(_acmA);
|
_channel_B2A->RegisterReceiverACM(_acmA.get());
|
||||||
|
|
||||||
//--- EVENT TIMERS
|
//--- EVENT TIMERS
|
||||||
// A
|
// A
|
||||||
@@ -729,11 +730,11 @@ void APITest::TestDelay(char side) {
|
|||||||
estimDelayCB.SetArithMean(true);
|
estimDelayCB.SetArithMean(true);
|
||||||
|
|
||||||
if (side == 'A') {
|
if (side == 'A') {
|
||||||
myACM = _acmA;
|
myACM = _acmA.get();
|
||||||
myChannel = _channel_B2A;
|
myChannel = _channel_B2A;
|
||||||
myMinDelay = &_minDelayA;
|
myMinDelay = &_minDelayA;
|
||||||
} else {
|
} else {
|
||||||
myACM = _acmB;
|
myACM = _acmB.get();
|
||||||
myChannel = _channel_A2B;
|
myChannel = _channel_A2B;
|
||||||
myMinDelay = &_minDelayB;
|
myMinDelay = &_minDelayB;
|
||||||
}
|
}
|
||||||
@@ -845,14 +846,14 @@ void APITest::TestRegisteration(char sendSide) {
|
|||||||
|
|
||||||
switch (sendSide) {
|
switch (sendSide) {
|
||||||
case 'A': {
|
case 'A': {
|
||||||
sendACM = _acmA;
|
sendACM = _acmA.get();
|
||||||
receiveACM = _acmB;
|
receiveACM = _acmB.get();
|
||||||
thereIsDecoder = &_thereIsDecoderB;
|
thereIsDecoder = &_thereIsDecoderB;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'B': {
|
case 'B': {
|
||||||
sendACM = _acmB;
|
sendACM = _acmB.get();
|
||||||
receiveACM = _acmA;
|
receiveACM = _acmA.get();
|
||||||
thereIsDecoder = &_thereIsDecoderA;
|
thereIsDecoder = &_thereIsDecoderA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -964,17 +965,17 @@ void APITest::TestPlayout(char receiveSide) {
|
|||||||
AudioPlayoutMode* playoutMode = NULL;
|
AudioPlayoutMode* playoutMode = NULL;
|
||||||
switch (receiveSide) {
|
switch (receiveSide) {
|
||||||
case 'A': {
|
case 'A': {
|
||||||
receiveACM = _acmA;
|
receiveACM = _acmA.get();
|
||||||
playoutMode = &_playoutModeA;
|
playoutMode = &_playoutModeA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'B': {
|
case 'B': {
|
||||||
receiveACM = _acmB;
|
receiveACM = _acmB.get();
|
||||||
playoutMode = &_playoutModeB;
|
playoutMode = &_playoutModeB;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
receiveACM = _acmA;
|
receiveACM = _acmA.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t receiveFreqHz = receiveACM->ReceiveFrequency();
|
int32_t receiveFreqHz = receiveACM->ReceiveFrequency();
|
||||||
@@ -1018,7 +1019,6 @@ void APITest::TestPlayout(char receiveSide) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set/get receiver VAD status & mode.
|
|
||||||
void APITest::TestSendVAD(char side) {
|
void APITest::TestSendVAD(char side) {
|
||||||
if (_randomTest) {
|
if (_randomTest) {
|
||||||
return;
|
return;
|
||||||
@@ -1044,14 +1044,14 @@ void APITest::TestSendVAD(char side) {
|
|||||||
dtx = &_sendDTXA;
|
dtx = &_sendDTXA;
|
||||||
mode = &_sendVADModeA;
|
mode = &_sendVADModeA;
|
||||||
myChannel = _channel_A2B;
|
myChannel = _channel_A2B;
|
||||||
myACM = _acmA;
|
myACM = _acmA.get();
|
||||||
} else {
|
} else {
|
||||||
AudioCodingModule::Codec(_codecCntrB, &myCodec);
|
AudioCodingModule::Codec(_codecCntrB, &myCodec);
|
||||||
vad = &_sendVADB;
|
vad = &_sendVADB;
|
||||||
dtx = &_sendDTXB;
|
dtx = &_sendDTXB;
|
||||||
mode = &_sendVADModeB;
|
mode = &_sendVADModeB;
|
||||||
myChannel = _channel_B2A;
|
myChannel = _channel_B2A;
|
||||||
myACM = _acmB;
|
myACM = _acmB.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckVADStatus(side);
|
CheckVADStatus(side);
|
||||||
@@ -1137,7 +1137,7 @@ void APITest::ChangeCodec(char side) {
|
|||||||
fprintf(stdout, "Reset Encoder Side A \n");
|
fprintf(stdout, "Reset Encoder Side A \n");
|
||||||
}
|
}
|
||||||
if (side == 'A') {
|
if (side == 'A') {
|
||||||
myACM = _acmA;
|
myACM = _acmA.get();
|
||||||
codecCntr = &_codecCntrA;
|
codecCntr = &_codecCntrA;
|
||||||
{
|
{
|
||||||
WriteLockScoped wl(_apiTestRWLock);
|
WriteLockScoped wl(_apiTestRWLock);
|
||||||
@@ -1148,7 +1148,7 @@ void APITest::ChangeCodec(char side) {
|
|||||||
mode = &_sendVADModeA;
|
mode = &_sendVADModeA;
|
||||||
myChannel = _channel_A2B;
|
myChannel = _channel_A2B;
|
||||||
} else {
|
} else {
|
||||||
myACM = _acmB;
|
myACM = _acmB.get();
|
||||||
codecCntr = &_codecCntrB;
|
codecCntr = &_codecCntrB;
|
||||||
{
|
{
|
||||||
WriteLockScoped wl(_apiTestRWLock);
|
WriteLockScoped wl(_apiTestRWLock);
|
||||||
|
|||||||
@@ -8,18 +8,22 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef API_TEST_H
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_APITEST_H_
|
||||||
#define API_TEST_H
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_APITEST_H_
|
||||||
|
|
||||||
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/Channel.h"
|
#include "webrtc/modules/audio_coding/main/test/Channel.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
enum APITESTAction {
|
enum APITESTAction {
|
||||||
TEST_CHANGE_CODEC_ONLY = 0,
|
TEST_CHANGE_CODEC_ONLY = 0,
|
||||||
DTX_TEST = 1
|
DTX_TEST = 1
|
||||||
@@ -27,7 +31,7 @@ enum APITESTAction {
|
|||||||
|
|
||||||
class APITest : public ACMTest {
|
class APITest : public ACMTest {
|
||||||
public:
|
public:
|
||||||
APITest();
|
explicit APITest(const Config& config);
|
||||||
~APITest();
|
~APITest();
|
||||||
|
|
||||||
void Perform();
|
void Perform();
|
||||||
@@ -78,8 +82,8 @@ class APITest : public ACMTest {
|
|||||||
bool APIRunB();
|
bool APIRunB();
|
||||||
|
|
||||||
//--- ACMs
|
//--- ACMs
|
||||||
AudioCodingModule* _acmA;
|
scoped_ptr<AudioCodingModule> _acmA;
|
||||||
AudioCodingModule* _acmB;
|
scoped_ptr<AudioCodingModule> _acmB;
|
||||||
|
|
||||||
//--- Channels
|
//--- Channels
|
||||||
Channel* _channel_A2B;
|
Channel* _channel_A2B;
|
||||||
@@ -160,4 +164,4 @@ class APITest : public ACMTest {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_APITEST_H_
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CHANNEL_H
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_CHANNEL_H_
|
||||||
#define CHANNEL_H
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_CHANNEL_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -121,4 +121,4 @@ class Channel : public AudioPacketizationCallback {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_CHANNEL_H_
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
|
#include "webrtc/common.h"
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
@@ -241,14 +242,16 @@ void Receiver::Run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EncodeDecodeTest::EncodeDecodeTest() {
|
EncodeDecodeTest::EncodeDecodeTest(const Config& config)
|
||||||
|
: config_(config) {
|
||||||
_testMode = 2;
|
_testMode = 2;
|
||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile(
|
Trace::SetTraceFile(
|
||||||
(webrtc::test::OutputPath() + "acm_encdec_trace.txt").c_str());
|
(webrtc::test::OutputPath() + "acm_encdec_trace.txt").c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
EncodeDecodeTest::EncodeDecodeTest(int testMode) {
|
EncodeDecodeTest::EncodeDecodeTest(int testMode, const Config& config)
|
||||||
|
: config_(config) {
|
||||||
//testMode == 0 for autotest
|
//testMode == 0 for autotest
|
||||||
//testMode == 1 for testing all codecs/parameters
|
//testMode == 1 for testing all codecs/parameters
|
||||||
//testMode > 1 for specific user-input test (as it was used before)
|
//testMode > 1 for specific user-input test (as it was used before)
|
||||||
@@ -270,7 +273,8 @@ void EncodeDecodeTest::Perform() {
|
|||||||
codePars[1] = 0;
|
codePars[1] = 0;
|
||||||
codePars[2] = 0;
|
codePars[2] = 0;
|
||||||
|
|
||||||
scoped_ptr<AudioCodingModule> acm(AudioCodingModule::Create(0));
|
scoped_ptr<AudioCodingModule> acm(
|
||||||
|
config_.Get<AudioCodingModuleFactory>().Create(0));
|
||||||
struct CodecInst sendCodecTmp;
|
struct CodecInst sendCodecTmp;
|
||||||
numCodecs = acm->NumberOfCodecs();
|
numCodecs = acm->NumberOfCodecs();
|
||||||
|
|
||||||
@@ -325,7 +329,8 @@ void EncodeDecodeTest::Perform() {
|
|||||||
|
|
||||||
void EncodeDecodeTest::EncodeToFile(int fileType, int codeId, int* codePars,
|
void EncodeDecodeTest::EncodeToFile(int fileType, int codeId, int* codePars,
|
||||||
int testMode) {
|
int testMode) {
|
||||||
scoped_ptr<AudioCodingModule> acm(AudioCodingModule::Create(1));
|
scoped_ptr<AudioCodingModule> acm(
|
||||||
|
config_.Get<AudioCodingModuleFactory>().Create(1));
|
||||||
RTPFile rtpFile;
|
RTPFile rtpFile;
|
||||||
std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
|
std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
|
||||||
rtpFile.Open(fileName.c_str(), "wb+");
|
rtpFile.Open(fileName.c_str(), "wb+");
|
||||||
|
|||||||
@@ -13,16 +13,18 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "ACMTest.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
#include "audio_coding_module.h"
|
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
||||||
#include "RTPFile.h"
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
#include "PCMFile.h"
|
#include "webrtc/modules/audio_coding/main/test/RTPFile.h"
|
||||||
#include "typedefs.h"
|
#include "webrtc/typedefs.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
#define MAX_INCOMING_PAYLOAD 8096
|
#define MAX_INCOMING_PAYLOAD 8096
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
// TestPacketization callback which writes the encoded payloads to file
|
// TestPacketization callback which writes the encoded payloads to file
|
||||||
class TestPacketization : public AudioPacketizationCallback {
|
class TestPacketization : public AudioPacketizationCallback {
|
||||||
public:
|
public:
|
||||||
@@ -90,8 +92,8 @@ class Receiver {
|
|||||||
|
|
||||||
class EncodeDecodeTest : public ACMTest {
|
class EncodeDecodeTest : public ACMTest {
|
||||||
public:
|
public:
|
||||||
EncodeDecodeTest();
|
explicit EncodeDecodeTest(const Config& config);
|
||||||
EncodeDecodeTest(int testMode);
|
EncodeDecodeTest(int testMode, const Config& config);
|
||||||
virtual void Perform();
|
virtual void Perform();
|
||||||
|
|
||||||
uint16_t _playoutFreq;
|
uint16_t _playoutFreq;
|
||||||
@@ -100,6 +102,8 @@ class EncodeDecodeTest : public ACMTest {
|
|||||||
private:
|
private:
|
||||||
void EncodeToFile(int fileType, int codeId, int* codePars, int testMode);
|
void EncodeToFile(int fileType, int codeId, int* codePars, int testMode);
|
||||||
|
|
||||||
|
const Config& config_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Sender _sender;
|
Sender _sender;
|
||||||
Receiver _receiver;
|
Receiver _receiver;
|
||||||
@@ -107,4 +111,4 @@ class EncodeDecodeTest : public ACMTest {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_ENCODEDECODETEST_H_
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "module_common_types.h"
|
#include "webrtc/modules/interface/module_common_types.h"
|
||||||
#include "typedefs.h"
|
#include "webrtc/typedefs.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
|||||||
@@ -8,16 +8,17 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RTPFILE_H
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_RTPFILE_H_
|
||||||
#define RTPFILE_H
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_RTPFILE_H_
|
||||||
|
|
||||||
#include "audio_coding_module.h"
|
|
||||||
#include "module_common_types.h"
|
|
||||||
#include "typedefs.h"
|
|
||||||
#include "rw_lock_wrapper.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
|
#include "webrtc/modules/interface/module_common_types.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||||
|
#include "webrtc/typedefs.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class RTPStream {
|
class RTPStream {
|
||||||
@@ -113,4 +114,5 @@ class RTPFile : public RTPStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
#endif
|
|
||||||
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_RTPFILE_H_
|
||||||
|
|||||||
@@ -8,15 +8,15 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ACM_TEST_SPATIAL_AUDIO_H
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_SPATIALAUDIO_H_
|
||||||
#define ACM_TEST_SPATIAL_AUDIO_H
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_SPATIALAUDIO_H_
|
||||||
|
|
||||||
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/Channel.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "ACMTest.h"
|
|
||||||
#include "Channel.h"
|
|
||||||
#include "PCMFile.h"
|
|
||||||
#include "audio_coding_module.h"
|
|
||||||
#include "utility.h"
|
|
||||||
|
|
||||||
#define MAX_FILE_NAME_LENGTH_BYTE 500
|
#define MAX_FILE_NAME_LENGTH_BYTE 500
|
||||||
|
|
||||||
@@ -44,4 +44,4 @@ class SpatialAudio : public ACMTest {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_SPATIALAUDIO_H_
|
||||||
|
|||||||
@@ -99,9 +99,9 @@ void TestPack::reset_payload_size() {
|
|||||||
payload_size_ = 0;
|
payload_size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestAllCodecs::TestAllCodecs(int test_mode)
|
TestAllCodecs::TestAllCodecs(int test_mode, const Config& config)
|
||||||
: acm_a_(AudioCodingModule::Create(0)),
|
: acm_a_(config.Get<AudioCodingModuleFactory>().Create(0)),
|
||||||
acm_b_(AudioCodingModule::Create(1)),
|
acm_b_(config.Get<AudioCodingModuleFactory>().Create(1)),
|
||||||
channel_a_to_b_(NULL),
|
channel_a_to_b_(NULL),
|
||||||
test_count_(0),
|
test_count_(0),
|
||||||
packet_size_samples_(0),
|
packet_size_samples_(0),
|
||||||
|
|||||||
@@ -8,17 +8,20 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TEST_ALL_CODECS_H_
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TESTALLCODECS_H_
|
||||||
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TEST_ALL_CODECS_H_
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TESTALLCODECS_H_
|
||||||
|
|
||||||
|
#include "webrtc/common.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/Channel.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "ACMTest.h"
|
#include "webrtc/typedefs.h"
|
||||||
#include "Channel.h"
|
|
||||||
#include "PCMFile.h"
|
|
||||||
#include "typedefs.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
class TestPack : public AudioPacketizationCallback {
|
class TestPack : public AudioPacketizationCallback {
|
||||||
public:
|
public:
|
||||||
TestPack();
|
TestPack();
|
||||||
@@ -47,7 +50,7 @@ class TestPack : public AudioPacketizationCallback {
|
|||||||
|
|
||||||
class TestAllCodecs : public ACMTest {
|
class TestAllCodecs : public ACMTest {
|
||||||
public:
|
public:
|
||||||
TestAllCodecs(int test_mode);
|
TestAllCodecs(int test_mode, const Config& config);
|
||||||
~TestAllCodecs();
|
~TestAllCodecs();
|
||||||
|
|
||||||
void Perform();
|
void Perform();
|
||||||
@@ -77,4 +80,4 @@ class TestAllCodecs : public ACMTest {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TEST_ALL_CODECS_H_
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TESTALLCODECS_H_
|
||||||
|
|||||||
@@ -8,24 +8,24 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "TestFEC.h"
|
#include "webrtc/modules/audio_coding/main/test/TestFEC.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "audio_coding_module_typedefs.h"
|
#include "webrtc/common.h"
|
||||||
#include "common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "engine_configurations.h"
|
#include "webrtc/engine_configurations.h"
|
||||||
#include "trace.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
||||||
#include "utility.h"
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/trace.h"
|
||||||
#include "webrtc/test/testsupport/fileutils.h"
|
#include "webrtc/test/testsupport/fileutils.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
TestFEC::TestFEC()
|
TestFEC::TestFEC(const Config& config)
|
||||||
: _acmA(AudioCodingModule::Create(0)),
|
: _acmA(config.Get<AudioCodingModuleFactory>().Create(0)),
|
||||||
_acmB(AudioCodingModule::Create(1)),
|
_acmB(config.Get<AudioCodingModuleFactory>().Create(1)),
|
||||||
_channelA2B(NULL),
|
_channelA2B(NULL),
|
||||||
_testCntr(0) {
|
_testCntr(0) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,19 +8,21 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TEST_FEC_H
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TESTFEC_H_
|
||||||
#define TEST_FEC_H
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TESTFEC_H_
|
||||||
|
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/Channel.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "ACMTest.h"
|
|
||||||
#include "Channel.h"
|
|
||||||
#include "PCMFile.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
class TestFEC : public ACMTest {
|
class TestFEC : public ACMTest {
|
||||||
public:
|
public:
|
||||||
TestFEC();
|
explicit TestFEC(const Config& config);
|
||||||
~TestFEC();
|
~TestFEC();
|
||||||
|
|
||||||
void Perform();
|
void Perform();
|
||||||
@@ -45,4 +47,4 @@ class TestFEC : public ACMTest {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TESTFEC_H_
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "webrtc/common.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/engine_configurations.h"
|
#include "webrtc/engine_configurations.h"
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
||||||
@@ -108,9 +108,9 @@ void TestPackStereo::set_lost_packet(bool lost) {
|
|||||||
lost_packet_ = lost;
|
lost_packet_ = lost;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestStereo::TestStereo(int test_mode)
|
TestStereo::TestStereo(int test_mode, const Config& config)
|
||||||
: acm_a_(AudioCodingModule::Create(0)),
|
: acm_a_(config.Get<AudioCodingModuleFactory>().Create(0)),
|
||||||
acm_b_(AudioCodingModule::Create(1)),
|
acm_b_(config.Get<AudioCodingModuleFactory>().Create(1)),
|
||||||
channel_a2b_(NULL),
|
channel_a2b_(NULL),
|
||||||
test_cntr_(0),
|
test_cntr_(0),
|
||||||
pack_size_samp_(0),
|
pack_size_samp_(0),
|
||||||
|
|||||||
@@ -8,18 +8,20 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TEST_STEREO_H_
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TESTSTEREO_H_
|
||||||
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TEST_STEREO_H_
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TESTSTEREO_H_
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "ACMTest.h"
|
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
||||||
#include "Channel.h"
|
#include "webrtc/modules/audio_coding/main/test/Channel.h"
|
||||||
#include "PCMFile.h"
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
enum StereoMonoMode {
|
enum StereoMonoMode {
|
||||||
kNotSet,
|
kNotSet,
|
||||||
kMono,
|
kMono,
|
||||||
@@ -60,7 +62,7 @@ class TestPackStereo : public AudioPacketizationCallback {
|
|||||||
|
|
||||||
class TestStereo : public ACMTest {
|
class TestStereo : public ACMTest {
|
||||||
public:
|
public:
|
||||||
TestStereo(int test_mode);
|
TestStereo(int test_mode, const Config& config);
|
||||||
~TestStereo();
|
~TestStereo();
|
||||||
|
|
||||||
void Perform();
|
void Perform();
|
||||||
@@ -114,4 +116,4 @@ class TestStereo : public ACMTest {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TEST_STEREO_H_
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TESTSTEREO_H_
|
||||||
|
|||||||
@@ -12,19 +12,20 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "webrtc/common.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/engine_configurations.h"
|
#include "webrtc/engine_configurations.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
|
||||||
#include "webrtc/test/testsupport/fileutils.h"
|
|
||||||
#include "webrtc/system_wrappers/interface/trace.h"
|
#include "webrtc/system_wrappers/interface/trace.h"
|
||||||
|
#include "webrtc/test/testsupport/fileutils.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
TestVADDTX::TestVADDTX()
|
TestVADDTX::TestVADDTX(const Config& config)
|
||||||
: _acmA(AudioCodingModule::Create(0)),
|
: _acmA(config.Get<AudioCodingModuleFactory>().Create(0)),
|
||||||
_acmB(AudioCodingModule::Create(1)),
|
_acmB(config.Get<AudioCodingModuleFactory>().Create(1)),
|
||||||
_channelA2B(NULL) {
|
_channelA2B(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,16 +8,18 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TEST_VAD_DTX_H
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TESTVADDTX_H_
|
||||||
#define TEST_VAD_DTX_H
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TESTVADDTX_H_
|
||||||
|
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/Channel.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "ACMTest.h"
|
|
||||||
#include "Channel.h"
|
|
||||||
#include "PCMFile.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool statusDTX;
|
bool statusDTX;
|
||||||
bool statusVAD;
|
bool statusVAD;
|
||||||
@@ -47,7 +49,7 @@ class ActivityMonitor : public ACMVADCallback {
|
|||||||
|
|
||||||
class TestVADDTX : public ACMTest {
|
class TestVADDTX : public ACMTest {
|
||||||
public:
|
public:
|
||||||
TestVADDTX();
|
explicit TestVADDTX(const Config& config);
|
||||||
~TestVADDTX();
|
~TestVADDTX();
|
||||||
|
|
||||||
void Perform();
|
void Perform();
|
||||||
@@ -82,4 +84,4 @@ class TestVADDTX : public ACMTest {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TESTVADDTX_H_
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
#include "webrtc/common.h"
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/APITest.h"
|
#include "webrtc/modules/audio_coding/main/test/APITest.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h"
|
#include "webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h"
|
||||||
@@ -23,11 +24,11 @@
|
|||||||
#include "webrtc/modules/audio_coding/main/test/TestStereo.h"
|
#include "webrtc/modules/audio_coding/main/test/TestStereo.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/TestVADDTX.h"
|
#include "webrtc/modules/audio_coding/main/test/TestVADDTX.h"
|
||||||
#include "webrtc/modules/audio_coding/main/test/TwoWayCommunication.h"
|
#include "webrtc/modules/audio_coding/main/test/TwoWayCommunication.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
#include "webrtc/system_wrappers/interface/trace.h"
|
#include "webrtc/system_wrappers/interface/trace.h"
|
||||||
#include "webrtc/test/testsupport/fileutils.h"
|
#include "webrtc/test/testsupport/fileutils.h"
|
||||||
#include "webrtc/test/testsupport/gtest_disable.h"
|
#include "webrtc/test/testsupport/gtest_disable.h"
|
||||||
|
|
||||||
using webrtc::AudioCodingModule;
|
|
||||||
using webrtc::Trace;
|
using webrtc::Trace;
|
||||||
|
|
||||||
// This parameter is used to describe how to run the tests. It is normally
|
// This parameter is used to describe how to run the tests. It is normally
|
||||||
@@ -38,7 +39,14 @@ TEST(AudioCodingModuleTest, TestAllCodecs) {
|
|||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
||||||
"acm_allcodecs_trace.txt").c_str());
|
"acm_allcodecs_trace.txt").c_str());
|
||||||
webrtc::TestAllCodecs(ACM_TEST_MODE).Perform();
|
webrtc::Config config;
|
||||||
|
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
webrtc::TestAllCodecs(ACM_TEST_MODE, config).Perform();
|
||||||
|
|
||||||
|
UseNewAcm(&config);
|
||||||
|
webrtc::TestAllCodecs(ACM_TEST_MODE, config).Perform();
|
||||||
|
|
||||||
Trace::ReturnTrace();
|
Trace::ReturnTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +54,14 @@ TEST(AudioCodingModuleTest, DISABLED_ON_ANDROID(TestEncodeDecode)) {
|
|||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
||||||
"acm_encodedecode_trace.txt").c_str());
|
"acm_encodedecode_trace.txt").c_str());
|
||||||
webrtc::EncodeDecodeTest(ACM_TEST_MODE).Perform();
|
webrtc::Config config;
|
||||||
|
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
webrtc::EncodeDecodeTest(ACM_TEST_MODE, config).Perform();
|
||||||
|
|
||||||
|
UseNewAcm(&config);
|
||||||
|
webrtc::EncodeDecodeTest(ACM_TEST_MODE, config).Perform();
|
||||||
|
|
||||||
Trace::ReturnTrace();
|
Trace::ReturnTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +69,14 @@ TEST(AudioCodingModuleTest, DISABLED_ON_ANDROID(TestFEC)) {
|
|||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
||||||
"acm_fec_trace.txt").c_str());
|
"acm_fec_trace.txt").c_str());
|
||||||
webrtc::TestFEC().Perform();
|
webrtc::Config config;
|
||||||
|
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
webrtc::TestFEC(config).Perform();
|
||||||
|
|
||||||
|
UseNewAcm(&config);
|
||||||
|
webrtc::TestFEC(config).Perform();
|
||||||
|
|
||||||
Trace::ReturnTrace();
|
Trace::ReturnTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +84,14 @@ TEST(AudioCodingModuleTest, DISABLED_ON_ANDROID(TestIsac)) {
|
|||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
||||||
"acm_isac_trace.txt").c_str());
|
"acm_isac_trace.txt").c_str());
|
||||||
webrtc::ISACTest(ACM_TEST_MODE).Perform();
|
webrtc::Config config;
|
||||||
|
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
webrtc::ISACTest(ACM_TEST_MODE, config).Perform();
|
||||||
|
|
||||||
|
UseNewAcm(&config);
|
||||||
|
webrtc::ISACTest(ACM_TEST_MODE, config).Perform();
|
||||||
|
|
||||||
Trace::ReturnTrace();
|
Trace::ReturnTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +99,14 @@ TEST(AudioCodingModuleTest, DISABLED_ON_ANDROID(TwoWayCommunication)) {
|
|||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
||||||
"acm_twowaycom_trace.txt").c_str());
|
"acm_twowaycom_trace.txt").c_str());
|
||||||
webrtc::TwoWayCommunication(ACM_TEST_MODE).Perform();
|
webrtc::Config config;
|
||||||
|
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
webrtc::TwoWayCommunication(ACM_TEST_MODE, config).Perform();
|
||||||
|
|
||||||
|
UseNewAcm(&config);
|
||||||
|
webrtc::TwoWayCommunication(ACM_TEST_MODE, config).Perform();
|
||||||
|
|
||||||
Trace::ReturnTrace();
|
Trace::ReturnTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +114,14 @@ TEST(AudioCodingModuleTest, DISABLED_ON_ANDROID(TestStereo)) {
|
|||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
||||||
"acm_stereo_trace.txt").c_str());
|
"acm_stereo_trace.txt").c_str());
|
||||||
webrtc::TestStereo(ACM_TEST_MODE).Perform();
|
|
||||||
|
webrtc::Config config;
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
|
||||||
|
webrtc::TestStereo(ACM_TEST_MODE, config).Perform();
|
||||||
|
UseNewAcm(&config);
|
||||||
|
|
||||||
|
webrtc::TestStereo(ACM_TEST_MODE, config).Perform();
|
||||||
Trace::ReturnTrace();
|
Trace::ReturnTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +129,14 @@ TEST(AudioCodingModuleTest, DISABLED_ON_ANDROID(TestVADDTX)) {
|
|||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
||||||
"acm_vaddtx_trace.txt").c_str());
|
"acm_vaddtx_trace.txt").c_str());
|
||||||
webrtc::TestVADDTX().Perform();
|
webrtc::Config config;
|
||||||
|
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
webrtc::TestVADDTX(config).Perform();
|
||||||
|
|
||||||
|
UseNewAcm(&config);
|
||||||
|
webrtc::TestVADDTX(config).Perform();
|
||||||
|
|
||||||
Trace::ReturnTrace();
|
Trace::ReturnTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +144,14 @@ TEST(AudioCodingModuleTest, TestOpus) {
|
|||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
||||||
"acm_opus_trace.txt").c_str());
|
"acm_opus_trace.txt").c_str());
|
||||||
webrtc::OpusTest().Perform();
|
webrtc::Config config;
|
||||||
|
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
webrtc::OpusTest(config).Perform();
|
||||||
|
|
||||||
|
UseNewAcm(&config);
|
||||||
|
webrtc::OpusTest(config).Perform();
|
||||||
|
|
||||||
Trace::ReturnTrace();
|
Trace::ReturnTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +162,14 @@ TEST(AudioCodingModuleTest, TestOpus) {
|
|||||||
Trace::CreateTrace();
|
Trace::CreateTrace();
|
||||||
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
Trace::SetTraceFile((webrtc::test::OutputPath() +
|
||||||
"acm_apitest_trace.txt").c_str());
|
"acm_apitest_trace.txt").c_str());
|
||||||
webrtc::APITest().Perform();
|
webrtc::Config config;
|
||||||
|
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
webrtc::APITest(config).Perform();
|
||||||
|
|
||||||
|
UseNewAcm(&config);
|
||||||
|
webrtc::APITest(config).Perform();
|
||||||
|
|
||||||
Trace::ReturnTrace();
|
Trace::ReturnTrace();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,25 +18,25 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "common_types.h"
|
|
||||||
#include "engine_configurations.h"
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "PCMFile.h"
|
#include "webrtc/engine_configurations.h"
|
||||||
#include "trace.h"
|
#include "webrtc/common.h"
|
||||||
#include "utility.h"
|
#include "webrtc/common_types.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/trace.h"
|
||||||
#include "webrtc/test/testsupport/fileutils.h"
|
#include "webrtc/test/testsupport/fileutils.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
#define MAX_FILE_NAME_LENGTH_BYTE 500
|
#define MAX_FILE_NAME_LENGTH_BYTE 500
|
||||||
|
|
||||||
TwoWayCommunication::TwoWayCommunication(int testMode)
|
TwoWayCommunication::TwoWayCommunication(int testMode, const Config& config)
|
||||||
: _acmA(AudioCodingModule::Create(1)),
|
: _acmA(config.Get<AudioCodingModuleFactory>().Create(1)),
|
||||||
_acmB(AudioCodingModule::Create(2)),
|
_acmB(config.Get<AudioCodingModuleFactory>().Create(2)),
|
||||||
_acmRefA(AudioCodingModule::Create(3)),
|
_acmRefA(config.Get<AudioCodingModuleFactory>().Create(3)),
|
||||||
_acmRefB(AudioCodingModule::Create(4)),
|
_acmRefB(config.Get<AudioCodingModuleFactory>().Create(4)),
|
||||||
_testMode(testMode) {
|
_testMode(testMode) { }
|
||||||
}
|
|
||||||
|
|
||||||
TwoWayCommunication::~TwoWayCommunication() {
|
TwoWayCommunication::~TwoWayCommunication() {
|
||||||
delete _channel_A2B;
|
delete _channel_A2B;
|
||||||
|
|||||||
@@ -8,21 +8,23 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TWO_WAY_COMMUNICATION_H
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TWOWAYCOMMUNICATION_H_
|
||||||
#define TWO_WAY_COMMUNICATION_H
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TWOWAYCOMMUNICATION_H_
|
||||||
|
|
||||||
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/Channel.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "ACMTest.h"
|
|
||||||
#include "Channel.h"
|
|
||||||
#include "PCMFile.h"
|
|
||||||
#include "audio_coding_module.h"
|
|
||||||
#include "utility.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
class TwoWayCommunication : public ACMTest {
|
class TwoWayCommunication : public ACMTest {
|
||||||
public:
|
public:
|
||||||
TwoWayCommunication(int testMode = 1);
|
TwoWayCommunication(int testMode, const Config& config);
|
||||||
~TwoWayCommunication();
|
~TwoWayCommunication();
|
||||||
|
|
||||||
void Perform();
|
void Perform();
|
||||||
@@ -57,4 +59,4 @@ class TwoWayCommunication : public ACMTest {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_TWOWAYCOMMUNICATION_H_
|
||||||
|
|||||||
@@ -8,25 +8,35 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../acm2/acm_common_defs.h"
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "audio_coding_module.h"
|
#include "webrtc/common.h"
|
||||||
#include "PCMFile.h"
|
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
||||||
#include "module_common_types.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
#include "scoped_ptr.h"
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
#include "typedefs.h"
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
|
#include "webrtc/modules/interface/module_common_types.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
|
#include "webrtc/typedefs.h"
|
||||||
#include "webrtc/test/testsupport/fileutils.h"
|
#include "webrtc/test/testsupport/fileutils.h"
|
||||||
#include "webrtc/test/testsupport/gtest_disable.h"
|
#include "webrtc/test/testsupport/gtest_disable.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class DualStreamTest :
|
class DualStreamTest : public AudioPacketizationCallback {
|
||||||
public AudioPacketizationCallback,
|
public:
|
||||||
public ::testing::Test {
|
explicit DualStreamTest(const Config& config);
|
||||||
protected:
|
|
||||||
DualStreamTest();
|
|
||||||
~DualStreamTest();
|
~DualStreamTest();
|
||||||
|
|
||||||
|
void RunTest(int frame_size_primary_samples,
|
||||||
|
int num_channels_primary,
|
||||||
|
int sampling_rate,
|
||||||
|
bool start_in_sync,
|
||||||
|
int num_channels_input);
|
||||||
|
|
||||||
|
void ApiTest();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
int32_t SendData(FrameType frameType, uint8_t payload_type,
|
int32_t SendData(FrameType frameType, uint8_t payload_type,
|
||||||
uint32_t timestamp, const uint8_t* payload_data,
|
uint32_t timestamp, const uint8_t* payload_data,
|
||||||
uint16_t payload_size,
|
uint16_t payload_size,
|
||||||
@@ -83,10 +93,10 @@ class DualStreamTest :
|
|||||||
bool received_payload_[kMaxNumStreams];
|
bool received_payload_[kMaxNumStreams];
|
||||||
};
|
};
|
||||||
|
|
||||||
DualStreamTest::DualStreamTest()
|
DualStreamTest::DualStreamTest(const Config& config)
|
||||||
: acm_dual_stream_(AudioCodingModule::Create(0)),
|
: acm_dual_stream_(config.Get<AudioCodingModuleFactory>().Create(0)),
|
||||||
acm_ref_primary_(AudioCodingModule::Create(1)),
|
acm_ref_primary_(config.Get<AudioCodingModuleFactory>().Create(1)),
|
||||||
acm_ref_secondary_(AudioCodingModule::Create(2)),
|
acm_ref_secondary_(config.Get<AudioCodingModuleFactory>().Create(2)),
|
||||||
payload_ref_is_stored_(),
|
payload_ref_is_stored_(),
|
||||||
payload_dual_is_stored_(),
|
payload_dual_is_stored_(),
|
||||||
timestamp_ref_(),
|
timestamp_ref_(),
|
||||||
@@ -94,11 +104,9 @@ DualStreamTest::DualStreamTest()
|
|||||||
num_received_payloads_ref_(),
|
num_received_payloads_ref_(),
|
||||||
num_compared_payloads_(),
|
num_compared_payloads_(),
|
||||||
last_timestamp_(),
|
last_timestamp_(),
|
||||||
received_payload_() {
|
received_payload_() {}
|
||||||
}
|
|
||||||
|
|
||||||
DualStreamTest::~DualStreamTest() {
|
DualStreamTest::~DualStreamTest() {}
|
||||||
}
|
|
||||||
|
|
||||||
void DualStreamTest::PopulateCodecInstances(int frame_size_primary_ms,
|
void DualStreamTest::PopulateCodecInstances(int frame_size_primary_ms,
|
||||||
int num_channels_primary,
|
int num_channels_primary,
|
||||||
@@ -380,106 +388,17 @@ int32_t DualStreamTest::SendData(FrameType frameType, uint8_t payload_type,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mono input, mono primary WB 20 ms frame.
|
void DualStreamTest::RunTest(int frame_size_primary_samples,
|
||||||
TEST_F(DualStreamTest,
|
int num_channels_primary,
|
||||||
DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb20Ms)) {
|
int sampling_rate,
|
||||||
InitializeSender(20, 1, 16000);
|
bool start_in_sync,
|
||||||
Perform(true, 1);
|
int num_channels_input) {
|
||||||
}
|
InitializeSender(
|
||||||
|
frame_size_primary_samples, num_channels_primary, sampling_rate);
|
||||||
|
Perform(start_in_sync, num_channels_input);
|
||||||
|
};
|
||||||
|
|
||||||
// Mono input, stereo primary WB 20 ms frame.
|
void DualStreamTest::ApiTest() {
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncMonoInput_StereoPrimaryWb20Ms)) {
|
|
||||||
InitializeSender(20, 2, 16000);
|
|
||||||
Perform(true, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mono input, mono primary SWB 20 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimarySwb20Ms)) {
|
|
||||||
InitializeSender(20, 1, 32000);
|
|
||||||
Perform(true, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mono input, stereo primary SWB 20 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimarySwb20Ms)) {
|
|
||||||
InitializeSender(20, 2, 32000);
|
|
||||||
Perform(true, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mono input, mono primary WB 40 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb40Ms)) {
|
|
||||||
InitializeSender(40, 1, 16000);
|
|
||||||
Perform(true, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mono input, stereo primary WB 40 ms frame
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimaryWb40Ms)) {
|
|
||||||
InitializeSender(40, 2, 16000);
|
|
||||||
Perform(true, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stereo input, mono primary WB 20 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb20Ms)) {
|
|
||||||
InitializeSender(20, 1, 16000);
|
|
||||||
Perform(true, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stereo input, stereo primary WB 20 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb20Ms)) {
|
|
||||||
InitializeSender(20, 2, 16000);
|
|
||||||
Perform(true, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stereo input, mono primary SWB 20 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimarySwb20Ms)) {
|
|
||||||
InitializeSender(20, 1, 32000);
|
|
||||||
Perform(true, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stereo input, stereo primary SWB 20 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimarySwb20Ms)) {
|
|
||||||
InitializeSender(20, 2, 32000);
|
|
||||||
Perform(true, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stereo input, mono primary WB 40 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb40Ms)) {
|
|
||||||
InitializeSender(40, 1, 16000);
|
|
||||||
Perform(true, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stereo input, stereo primary WB 40 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb40Ms)) {
|
|
||||||
InitializeSender(40, 2, 16000);
|
|
||||||
Perform(true, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asynchronous test, ACM is fed with data then secondary coder is registered.
|
|
||||||
// Mono input, mono primary WB 20 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb20Ms)) {
|
|
||||||
InitializeSender(20, 1, 16000);
|
|
||||||
Perform(false, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mono input, mono primary WB 20 ms frame.
|
|
||||||
TEST_F(DualStreamTest,
|
|
||||||
DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb40Ms)) {
|
|
||||||
InitializeSender(40, 1, 16000);
|
|
||||||
Perform(false, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(DualStreamTest, DISABLED_ON_ANDROID(Api)) {
|
|
||||||
PopulateCodecInstances(20, 1, 16000);
|
PopulateCodecInstances(20, 1, 16000);
|
||||||
CodecInst my_codec;
|
CodecInst my_codec;
|
||||||
ASSERT_EQ(0, acm_dual_stream_->InitializeSender());
|
ASSERT_EQ(0, acm_dual_stream_->InitializeSender());
|
||||||
@@ -530,5 +449,171 @@ TEST_F(DualStreamTest, DISABLED_ON_ANDROID(Api)) {
|
|||||||
EXPECT_EQ(VADVeryAggr, vad_mode);
|
EXPECT_EQ(VADVeryAggr, vad_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
DualStreamTest* CreateLegacy() {
|
||||||
|
Config config;
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
DualStreamTest* test = new DualStreamTest(config);
|
||||||
|
return test;
|
||||||
}
|
}
|
||||||
// namespace webrtc
|
|
||||||
|
DualStreamTest* CreateNew() {
|
||||||
|
Config config;
|
||||||
|
UseNewAcm(&config);
|
||||||
|
DualStreamTest* test = new DualStreamTest(config);
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Mono input, mono primary WB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb20Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(20, 1, 16000, true, 1);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(20, 1, 16000, true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mono input, stereo primary WB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncMonoInput_StereoPrimaryWb20Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(20, 2, 16000, true, 1);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(20, 2, 16000, true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mono input, mono primary SWB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimarySwb20Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(20, 1, 32000, true, 1);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(20, 1, 32000, true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mono input, stereo primary SWB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimarySwb20Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(20, 2, 32000, true, 1);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(20, 2, 32000, true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mono input, mono primary WB 40 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb40Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateNew());
|
||||||
|
test->RunTest(40, 1, 16000, true, 1);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(40, 1, 16000, true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mono input, stereo primary WB 40 ms frame
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimaryWb40Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateNew());
|
||||||
|
test->RunTest(40, 2, 16000, true, 1);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(40, 2, 16000, true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stereo input, mono primary WB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb20Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(20, 1, 16000, true, 2);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(20, 1, 16000, true, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stereo input, stereo primary WB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb20Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(20, 2, 16000, true, 2);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(20, 2, 16000, true, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stereo input, mono primary SWB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimarySwb20Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(20, 1, 32000, true, 2);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(20, 1, 32000, true, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stereo input, stereo primary SWB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimarySwb20Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(20, 2, 32000, true, 2);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(20, 2, 32000, true, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stereo input, mono primary WB 40 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb40Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(40, 1, 16000, true, 2);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(40, 1, 16000, true, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stereo input, stereo primary WB 40 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb40Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(40, 2, 16000, true, 2);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(40, 2, 16000, true, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Asynchronous test, ACM is fed with data then secondary coder is registered.
|
||||||
|
// Mono input, mono primary WB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb20Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(20, 1, 16000, false, 1);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(20, 1, 16000, false, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mono input, mono primary WB 20 ms frame.
|
||||||
|
TEST(DualStreamTest,
|
||||||
|
DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb40Ms)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->RunTest(40, 1, 16000, false, 1);
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RunTest(40, 1, 16000, false, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DualStreamTest, DISABLED_ON_ANDROID(ApiTest)) {
|
||||||
|
scoped_ptr<DualStreamTest> test(CreateLegacy());
|
||||||
|
test->ApiTest();
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->ApiTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|||||||
@@ -86,9 +86,9 @@ int16_t SetISAConfig(ACMTestISACConfig& isacConfig, AudioCodingModule* acm,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ISACTest::ISACTest(int testMode)
|
ISACTest::ISACTest(int testMode, const Config& config)
|
||||||
: _acmA(AudioCodingModule::Create(1)),
|
: _acmA(config.Get<AudioCodingModuleFactory>().Create(1)),
|
||||||
_acmB(AudioCodingModule::Create(2)),
|
_acmB(config.Get<AudioCodingModuleFactory>().Create(2)),
|
||||||
_testMode(testMode) {
|
_testMode(testMode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,23 +8,26 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ACM_ISAC_TEST_H
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_ISACTEST_H_
|
||||||
#define ACM_ISAC_TEST_H
|
#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_ISACTEST_H_
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "ACMTest.h"
|
#include "webrtc/common.h"
|
||||||
#include "Channel.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "PCMFile.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
#include "audio_coding_module.h"
|
#include "webrtc/modules/audio_coding/main/test/ACMTest.h"
|
||||||
#include "utility.h"
|
#include "webrtc/modules/audio_coding/main/test/Channel.h"
|
||||||
#include "common_types.h"
|
#include "webrtc/modules/audio_coding/main/test/PCMFile.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
|
|
||||||
#define MAX_FILE_NAME_LENGTH_BYTE 500
|
#define MAX_FILE_NAME_LENGTH_BYTE 500
|
||||||
#define NO_OF_CLIENTS 15
|
#define NO_OF_CLIENTS 15
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
struct ACMTestISACConfig {
|
struct ACMTestISACConfig {
|
||||||
int32_t currentRateBitPerSec;
|
int32_t currentRateBitPerSec;
|
||||||
int16_t currentFrameSizeMsec;
|
int16_t currentFrameSizeMsec;
|
||||||
@@ -38,7 +41,7 @@ struct ACMTestISACConfig {
|
|||||||
|
|
||||||
class ISACTest : public ACMTest {
|
class ISACTest : public ACMTest {
|
||||||
public:
|
public:
|
||||||
ISACTest(int testMode);
|
ISACTest(int testMode, const Config& config);
|
||||||
~ISACTest();
|
~ISACTest();
|
||||||
|
|
||||||
void Perform();
|
void Perform();
|
||||||
@@ -77,4 +80,4 @@ class ISACTest : public ACMTest {
|
|||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_ISACTEST_H_
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "webrtc/common.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/engine_configurations.h"
|
#include "webrtc/engine_configurations.h"
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
double FrameRms(AudioFrame& frame) {
|
double FrameRms(AudioFrame& frame) {
|
||||||
int samples = frame.num_channels_ * frame.samples_per_channel_;
|
int samples = frame.num_channels_ * frame.samples_per_channel_;
|
||||||
double rms = 0;
|
double rms = 0;
|
||||||
@@ -42,19 +44,14 @@ double FrameRms(AudioFrame& frame) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class InitialPlayoutDelayTest : public ::testing::Test {
|
class InitialPlayoutDelayTest {
|
||||||
protected:
|
public:
|
||||||
|
explicit InitialPlayoutDelayTest(const Config& config)
|
||||||
InitialPlayoutDelayTest()
|
: acm_a_(config.Get<AudioCodingModuleFactory>().Create(0)),
|
||||||
: acm_a_(AudioCodingModule::Create(0)),
|
acm_b_(config.Get<AudioCodingModuleFactory>().Create(1)),
|
||||||
acm_b_(AudioCodingModule::Create(1)),
|
channel_a2b_(NULL) {}
|
||||||
channel_a2b_(NULL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~InitialPlayoutDelayTest() {
|
~InitialPlayoutDelayTest() {
|
||||||
}
|
|
||||||
|
|
||||||
void TearDown() {
|
|
||||||
if (channel_a2b_ != NULL) {
|
if (channel_a2b_ != NULL) {
|
||||||
delete channel_a2b_;
|
delete channel_a2b_;
|
||||||
channel_a2b_ = NULL;
|
channel_a2b_ = NULL;
|
||||||
@@ -62,8 +59,11 @@ class InitialPlayoutDelayTest : public ::testing::Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetUp() {
|
void SetUp() {
|
||||||
acm_b_->InitializeReceiver();
|
ASSERT_TRUE(acm_a_.get() != NULL);
|
||||||
acm_a_->InitializeReceiver();
|
ASSERT_TRUE(acm_b_.get() != NULL);
|
||||||
|
|
||||||
|
EXPECT_EQ(0, acm_b_->InitializeReceiver());
|
||||||
|
EXPECT_EQ(0, acm_a_->InitializeReceiver());
|
||||||
|
|
||||||
// Register all L16 codecs in receiver.
|
// Register all L16 codecs in receiver.
|
||||||
CodecInst codec;
|
CodecInst codec;
|
||||||
@@ -82,6 +82,45 @@ class InitialPlayoutDelayTest : public ::testing::Test {
|
|||||||
channel_a2b_->RegisterReceiverACM(acm_b_.get());
|
channel_a2b_->RegisterReceiverACM(acm_b_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NbMono() {
|
||||||
|
CodecInst codec;
|
||||||
|
AudioCodingModule::Codec("L16", &codec, 8000, 1);
|
||||||
|
Run(codec, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WbMono() {
|
||||||
|
CodecInst codec;
|
||||||
|
AudioCodingModule::Codec("L16", &codec, 16000, 1);
|
||||||
|
Run(codec, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwbMono() {
|
||||||
|
CodecInst codec;
|
||||||
|
AudioCodingModule::Codec("L16", &codec, 32000, 1);
|
||||||
|
Run(codec, 1500); // NetEq buffer is not sufficiently large for 3 sec of
|
||||||
|
// PCM16 super-wideband.
|
||||||
|
}
|
||||||
|
|
||||||
|
void NbStereo() {
|
||||||
|
CodecInst codec;
|
||||||
|
AudioCodingModule::Codec("L16", &codec, 8000, 2);
|
||||||
|
Run(codec, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WbStereo() {
|
||||||
|
CodecInst codec;
|
||||||
|
AudioCodingModule::Codec("L16", &codec, 16000, 2);
|
||||||
|
Run(codec, 1500);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwbStereo() {
|
||||||
|
CodecInst codec;
|
||||||
|
AudioCodingModule::Codec("L16", &codec, 32000, 2);
|
||||||
|
Run(codec, 600); // NetEq buffer is not sufficiently large for 3 sec of
|
||||||
|
// PCM16 super-wideband.
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
void Run(CodecInst codec, int initial_delay_ms) {
|
void Run(CodecInst codec, int initial_delay_ms) {
|
||||||
AudioFrame in_audio_frame;
|
AudioFrame in_audio_frame;
|
||||||
AudioFrame out_audio_frame;
|
AudioFrame out_audio_frame;
|
||||||
@@ -119,43 +158,72 @@ class InitialPlayoutDelayTest : public ::testing::Test {
|
|||||||
Channel* channel_a2b_;
|
Channel* channel_a2b_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F( InitialPlayoutDelayTest, NbMono) {
|
namespace {
|
||||||
CodecInst codec;
|
|
||||||
AudioCodingModule::Codec("L16", &codec, 8000, 1);
|
InitialPlayoutDelayTest* CreateLegacy() {
|
||||||
Run(codec, 3000);
|
Config config;
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
InitialPlayoutDelayTest* test = new InitialPlayoutDelayTest(config);
|
||||||
|
test->SetUp();
|
||||||
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F( InitialPlayoutDelayTest, WbMono) {
|
InitialPlayoutDelayTest* CreateNew() {
|
||||||
CodecInst codec;
|
Config config;
|
||||||
AudioCodingModule::Codec("L16", &codec, 16000, 1);
|
UseNewAcm(&config);
|
||||||
Run(codec, 3000);
|
InitialPlayoutDelayTest* test = new InitialPlayoutDelayTest(config);
|
||||||
|
test->SetUp();
|
||||||
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F( InitialPlayoutDelayTest, SwbMono) {
|
} // namespace
|
||||||
CodecInst codec;
|
|
||||||
AudioCodingModule::Codec("L16", &codec, 32000, 1);
|
TEST(InitialPlayoutDelayTest, NbMono) {
|
||||||
Run(codec, 2000); // NetEq buffer is not sufficiently large for 3 sec of
|
scoped_ptr<InitialPlayoutDelayTest> test(CreateLegacy());
|
||||||
// PCM16 super-wideband.
|
test->NbMono();
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->NbMono();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F( InitialPlayoutDelayTest, NbStereo) {
|
TEST(InitialPlayoutDelayTest, WbMono) {
|
||||||
CodecInst codec;
|
scoped_ptr<InitialPlayoutDelayTest> test(CreateLegacy());
|
||||||
AudioCodingModule::Codec("L16", &codec, 8000, 2);
|
test->WbMono();
|
||||||
Run(codec, 3000);
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->WbMono();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F( InitialPlayoutDelayTest, WbStereo) {
|
TEST(InitialPlayoutDelayTest, SwbMono) {
|
||||||
CodecInst codec;
|
scoped_ptr<InitialPlayoutDelayTest> test(CreateLegacy());
|
||||||
AudioCodingModule::Codec("L16", &codec, 16000, 2);
|
test->SwbMono();
|
||||||
Run(codec, 3000);
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->SwbMono();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F( InitialPlayoutDelayTest, SwbStereo) {
|
TEST(InitialPlayoutDelayTest, NbStereo) {
|
||||||
CodecInst codec;
|
scoped_ptr<InitialPlayoutDelayTest> test(CreateLegacy());
|
||||||
AudioCodingModule::Codec("L16", &codec, 32000, 2);
|
test->NbStereo();
|
||||||
Run(codec, 2000); // NetEq buffer is not sufficiently large for 3 sec of
|
|
||||||
// PCM16 super-wideband.
|
test.reset(CreateNew());
|
||||||
|
test->NbStereo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(InitialPlayoutDelayTest, WbStereo) {
|
||||||
|
scoped_ptr<InitialPlayoutDelayTest> test(CreateLegacy());
|
||||||
|
test->WbStereo();
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->WbStereo();
|
||||||
}
|
}
|
||||||
// namespace webrtc
|
|
||||||
|
TEST(InitialPlayoutDelayTest, SwbStereo) {
|
||||||
|
scoped_ptr<InitialPlayoutDelayTest> test(CreateLegacy());
|
||||||
|
test->SwbStereo();
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->SwbStereo();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
#include "webrtc/common.h" // Config.
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/engine_configurations.h"
|
#include "webrtc/engine_configurations.h"
|
||||||
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
|
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
|
||||||
@@ -28,8 +29,8 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
OpusTest::OpusTest()
|
OpusTest::OpusTest(const Config& config)
|
||||||
: acm_receiver_(AudioCodingModule::Create(0)),
|
: acm_receiver_(config.Get<AudioCodingModuleFactory>().Create(0)),
|
||||||
channel_a2b_(NULL),
|
channel_a2b_(NULL),
|
||||||
counter_(0),
|
counter_(0),
|
||||||
payload_type_(255),
|
payload_type_(255),
|
||||||
@@ -321,7 +322,7 @@ void OpusTest::Run(TestPackStereo* channel, int channels, int bitrate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run received side of ACM.
|
// Run received side of ACM.
|
||||||
CHECK_ERROR(acm_receiver_->PlayoutData10Ms(out_freq_hz_b, &audio_frame));
|
ASSERT_EQ(0, acm_receiver_->PlayoutData10Ms(out_freq_hz_b, &audio_frame));
|
||||||
|
|
||||||
// Write output speech to file.
|
// Write output speech to file.
|
||||||
out_file_.Write10MsData(
|
out_file_.Write10MsData(
|
||||||
|
|||||||
@@ -23,9 +23,11 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
class OpusTest : public ACMTest {
|
class OpusTest : public ACMTest {
|
||||||
public:
|
public:
|
||||||
OpusTest();
|
explicit OpusTest(const Config& config);
|
||||||
~OpusTest();
|
~OpusTest();
|
||||||
|
|
||||||
void Perform();
|
void Perform();
|
||||||
|
|||||||
@@ -9,8 +9,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "webrtc/common.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
|
#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||||||
#include "webrtc/modules/interface/module_common_types.h"
|
#include "webrtc/modules/interface/module_common_types.h"
|
||||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "webrtc/system_wrappers/interface/sleep.h"
|
#include "webrtc/system_wrappers/interface/sleep.h"
|
||||||
@@ -18,22 +21,14 @@
|
|||||||
#include "webrtc/test/testsupport/gtest_disable.h"
|
#include "webrtc/test/testsupport/gtest_disable.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
class TargetDelayTest : public ::testing::Test {
|
|
||||||
protected:
|
|
||||||
static const int kSampleRateHz = 16000;
|
|
||||||
static const int kNum10msPerFrame = 2;
|
|
||||||
static const int kFrameSizeSamples = 320; // 20 ms @ 16 kHz.
|
|
||||||
// payload-len = frame-samples * 2 bytes/sample.
|
|
||||||
static const int kPayloadLenBytes = 320 * 2;
|
|
||||||
// Inter-arrival time in number of packets in a jittery channel. One is no
|
|
||||||
// jitter.
|
|
||||||
static const int kInterarrivalJitterPacket = 2;
|
|
||||||
|
|
||||||
TargetDelayTest()
|
|
||||||
: acm_(AudioCodingModule::Create(0)) {}
|
|
||||||
|
|
||||||
~TargetDelayTest() {
|
class TargetDelayTest {
|
||||||
}
|
public:
|
||||||
|
explicit TargetDelayTest(const Config& config)
|
||||||
|
: acm_(config.Get<AudioCodingModuleFactory>().Create(0)) {}
|
||||||
|
|
||||||
|
~TargetDelayTest() {}
|
||||||
|
|
||||||
void SetUp() {
|
void SetUp() {
|
||||||
EXPECT_TRUE(acm_.get() != NULL);
|
EXPECT_TRUE(acm_.get() != NULL);
|
||||||
@@ -51,13 +46,107 @@ class TargetDelayTest : public ::testing::Test {
|
|||||||
rtp_info_.type.Audio.channel = 1;
|
rtp_info_.type.Audio.channel = 1;
|
||||||
rtp_info_.type.Audio.isCNG = false;
|
rtp_info_.type.Audio.isCNG = false;
|
||||||
rtp_info_.frameType = kAudioFrameSpeech;
|
rtp_info_.frameType = kAudioFrameSpeech;
|
||||||
|
|
||||||
|
int16_t audio[kFrameSizeSamples];
|
||||||
|
const int kRange = 0x7FF; // 2047, easy for masking.
|
||||||
|
for (int n = 0; n < kFrameSizeSamples; ++n)
|
||||||
|
audio[n] = (rand() & kRange) - kRange / 2;
|
||||||
|
WebRtcPcm16b_Encode(audio, kFrameSizeSamples, payload_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OutOfRangeInput() {
|
||||||
|
EXPECT_EQ(-1, SetMinimumDelay(-1));
|
||||||
|
EXPECT_EQ(-1, SetMinimumDelay(10001));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NoTargetDelayBufferSizeChanges() {
|
||||||
|
for (int n = 0; n < 30; ++n) // Run enough iterations.
|
||||||
|
Run(true);
|
||||||
|
int clean_optimal_delay = GetCurrentOptimalDelayMs();
|
||||||
|
Run(false); // Run with jitter.
|
||||||
|
int jittery_optimal_delay = GetCurrentOptimalDelayMs();
|
||||||
|
EXPECT_GT(jittery_optimal_delay, clean_optimal_delay);
|
||||||
|
int required_delay = RequiredDelay();
|
||||||
|
EXPECT_GT(required_delay, 0);
|
||||||
|
EXPECT_NEAR(required_delay, jittery_optimal_delay, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WithTargetDelayBufferNotChanging() {
|
||||||
|
// A target delay that is one packet larger than jitter.
|
||||||
|
const int kTargetDelayMs = (kInterarrivalJitterPacket + 1) *
|
||||||
|
kNum10msPerFrame * 10;
|
||||||
|
ASSERT_EQ(0, SetMinimumDelay(kTargetDelayMs));
|
||||||
|
for (int n = 0; n < 30; ++n) // Run enough iterations to fill the buffer.
|
||||||
|
Run(true);
|
||||||
|
int clean_optimal_delay = GetCurrentOptimalDelayMs();
|
||||||
|
EXPECT_EQ(kTargetDelayMs, clean_optimal_delay);
|
||||||
|
Run(false); // Run with jitter.
|
||||||
|
int jittery_optimal_delay = GetCurrentOptimalDelayMs();
|
||||||
|
EXPECT_EQ(jittery_optimal_delay, clean_optimal_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequiredDelayAtCorrectRange() {
|
||||||
|
for (int n = 0; n < 30; ++n) // Run clean and store delay.
|
||||||
|
Run(true);
|
||||||
|
int clean_optimal_delay = GetCurrentOptimalDelayMs();
|
||||||
|
|
||||||
|
// A relatively large delay.
|
||||||
|
const int kTargetDelayMs = (kInterarrivalJitterPacket + 10) *
|
||||||
|
kNum10msPerFrame * 10;
|
||||||
|
ASSERT_EQ(0, SetMinimumDelay(kTargetDelayMs));
|
||||||
|
for (int n = 0; n < 300; ++n) // Run enough iterations to fill the buffer.
|
||||||
|
Run(true);
|
||||||
|
Run(false); // Run with jitter.
|
||||||
|
|
||||||
|
int jittery_optimal_delay = GetCurrentOptimalDelayMs();
|
||||||
|
EXPECT_EQ(kTargetDelayMs, jittery_optimal_delay);
|
||||||
|
|
||||||
|
int required_delay = RequiredDelay();
|
||||||
|
|
||||||
|
// Checking |required_delay| is in correct range.
|
||||||
|
EXPECT_GT(required_delay, 0);
|
||||||
|
EXPECT_GT(jittery_optimal_delay, required_delay);
|
||||||
|
EXPECT_GT(required_delay, clean_optimal_delay);
|
||||||
|
|
||||||
|
// A tighter check for the value of |required_delay|.
|
||||||
|
// The jitter forces a delay of
|
||||||
|
// |kInterarrivalJitterPacket * kNum10msPerFrame * 10| milliseconds. So we
|
||||||
|
// expect |required_delay| be close to that.
|
||||||
|
EXPECT_NEAR(kInterarrivalJitterPacket * kNum10msPerFrame * 10,
|
||||||
|
required_delay, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TargetDelayBufferMinMax() {
|
||||||
|
const int kTargetMinDelayMs = kNum10msPerFrame * 10;
|
||||||
|
ASSERT_EQ(0, SetMinimumDelay(kTargetMinDelayMs));
|
||||||
|
for (int m = 0; m < 30; ++m) // Run enough iterations to fill the buffer.
|
||||||
|
Run(true);
|
||||||
|
int clean_optimal_delay = GetCurrentOptimalDelayMs();
|
||||||
|
EXPECT_EQ(kTargetMinDelayMs, clean_optimal_delay);
|
||||||
|
|
||||||
|
const int kTargetMaxDelayMs = 2 * (kNum10msPerFrame * 10);
|
||||||
|
ASSERT_EQ(0, SetMaximumDelay(kTargetMaxDelayMs));
|
||||||
|
for (int n = 0; n < 30; ++n) // Run enough iterations to fill the buffer.
|
||||||
|
Run(false);
|
||||||
|
|
||||||
|
int capped_optimal_delay = GetCurrentOptimalDelayMs();
|
||||||
|
EXPECT_EQ(kTargetMaxDelayMs, capped_optimal_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int kSampleRateHz = 16000;
|
||||||
|
static const int kNum10msPerFrame = 2;
|
||||||
|
static const int kFrameSizeSamples = 320; // 20 ms @ 16 kHz.
|
||||||
|
// payload-len = frame-samples * 2 bytes/sample.
|
||||||
|
static const int kPayloadLenBytes = 320 * 2;
|
||||||
|
// Inter-arrival time in number of packets in a jittery channel. One is no
|
||||||
|
// jitter.
|
||||||
|
static const int kInterarrivalJitterPacket = 2;
|
||||||
|
|
||||||
void Push() {
|
void Push() {
|
||||||
rtp_info_.header.timestamp += kFrameSizeSamples;
|
rtp_info_.header.timestamp += kFrameSizeSamples;
|
||||||
rtp_info_.header.sequenceNumber++;
|
rtp_info_.header.sequenceNumber++;
|
||||||
uint8_t payload[kPayloadLenBytes]; // Doesn't need to be initialized.
|
ASSERT_EQ(0, acm_->IncomingPacket(payload_, kFrameSizeSamples * 2,
|
||||||
ASSERT_EQ(0, acm_->IncomingPacket(payload, kFrameSizeSamples * 2,
|
|
||||||
rtp_info_));
|
rtp_info_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,85 +199,69 @@ class TargetDelayTest : public ::testing::Test {
|
|||||||
|
|
||||||
scoped_ptr<AudioCodingModule> acm_;
|
scoped_ptr<AudioCodingModule> acm_;
|
||||||
WebRtcRTPHeader rtp_info_;
|
WebRtcRTPHeader rtp_info_;
|
||||||
|
uint8_t payload_[kPayloadLenBytes];
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(TargetDelayTest, DISABLED_ON_ANDROID(OutOfRangeInput)) {
|
|
||||||
EXPECT_EQ(-1, SetMinimumDelay(-1));
|
namespace {
|
||||||
EXPECT_EQ(-1, SetMinimumDelay(10001));
|
|
||||||
|
TargetDelayTest* CreateLegacy() {
|
||||||
|
Config config;
|
||||||
|
UseLegacyAcm(&config);
|
||||||
|
TargetDelayTest* test = new TargetDelayTest(config);
|
||||||
|
test->SetUp();
|
||||||
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TargetDelayTest, DISABLED_ON_ANDROID(NoTargetDelayBufferSizeChanges)) {
|
TargetDelayTest* CreateNew() {
|
||||||
for (int n = 0; n < 30; ++n) // Run enough iterations.
|
Config config;
|
||||||
Run(true);
|
UseNewAcm(&config);
|
||||||
int clean_optimal_delay = GetCurrentOptimalDelayMs();
|
TargetDelayTest* test = new TargetDelayTest(config);
|
||||||
Run(false); // Run with jitter.
|
test->SetUp();
|
||||||
int jittery_optimal_delay = GetCurrentOptimalDelayMs();
|
return test;
|
||||||
EXPECT_GT(jittery_optimal_delay, clean_optimal_delay);
|
|
||||||
int required_delay = RequiredDelay();
|
|
||||||
EXPECT_GT(required_delay, 0);
|
|
||||||
EXPECT_NEAR(required_delay, jittery_optimal_delay, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TargetDelayTest, DISABLED_ON_ANDROID(WithTargetDelayBufferNotChanging)) {
|
} // namespace
|
||||||
// A target delay that is one packet larger than jitter.
|
|
||||||
const int kTargetDelayMs = (kInterarrivalJitterPacket + 1) *
|
TEST(TargetDelayTest, DISABLED_ON_ANDROID(OutOfRangeInput)) {
|
||||||
kNum10msPerFrame * 10;
|
scoped_ptr<TargetDelayTest> test(CreateLegacy());
|
||||||
ASSERT_EQ(0, SetMinimumDelay(kTargetDelayMs));
|
test->OutOfRangeInput();
|
||||||
for (int n = 0; n < 30; ++n) // Run enough iterations to fill up the buffer.
|
|
||||||
Run(true);
|
test.reset(CreateNew());
|
||||||
int clean_optimal_delay = GetCurrentOptimalDelayMs();
|
test->OutOfRangeInput();
|
||||||
EXPECT_EQ(kTargetDelayMs, clean_optimal_delay);
|
|
||||||
Run(false); // Run with jitter.
|
|
||||||
int jittery_optimal_delay = GetCurrentOptimalDelayMs();
|
|
||||||
EXPECT_EQ(jittery_optimal_delay, clean_optimal_delay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TargetDelayTest, DISABLED_ON_ANDROID(RequiredDelayAtCorrectRange)) {
|
TEST(TargetDelayTest, DISABLED_ON_ANDROID(NoTargetDelayBufferSizeChanges)) {
|
||||||
for (int n = 0; n < 30; ++n) // Run clean and store delay.
|
scoped_ptr<TargetDelayTest> test(CreateLegacy());
|
||||||
Run(true);
|
test->NoTargetDelayBufferSizeChanges();
|
||||||
int clean_optimal_delay = GetCurrentOptimalDelayMs();
|
|
||||||
|
|
||||||
// A relatively large delay.
|
test.reset(CreateNew());
|
||||||
const int kTargetDelayMs = (kInterarrivalJitterPacket + 10) *
|
test->NoTargetDelayBufferSizeChanges();
|
||||||
kNum10msPerFrame * 10;
|
|
||||||
ASSERT_EQ(0, SetMinimumDelay(kTargetDelayMs));
|
|
||||||
for (int n = 0; n < 300; ++n) // Run enough iterations to fill up the buffer.
|
|
||||||
Run(true);
|
|
||||||
Run(false); // Run with jitter.
|
|
||||||
|
|
||||||
int jittery_optimal_delay = GetCurrentOptimalDelayMs();
|
|
||||||
EXPECT_EQ(kTargetDelayMs, jittery_optimal_delay);
|
|
||||||
|
|
||||||
int required_delay = RequiredDelay();
|
|
||||||
|
|
||||||
// Checking |required_delay| is in correct range.
|
|
||||||
EXPECT_GT(required_delay, 0);
|
|
||||||
EXPECT_GT(jittery_optimal_delay, required_delay);
|
|
||||||
EXPECT_GT(required_delay, clean_optimal_delay);
|
|
||||||
|
|
||||||
// A tighter check for the value of |required_delay|.
|
|
||||||
// The jitter forces a delay of
|
|
||||||
// |kInterarrivalJitterPacket * kNum10msPerFrame * 10| milliseconds. So we
|
|
||||||
// expect |required_delay| be close to that.
|
|
||||||
EXPECT_NEAR(kInterarrivalJitterPacket * kNum10msPerFrame * 10,
|
|
||||||
required_delay, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TargetDelayTest, DISABLED_ON_ANDROID(TargetDelayBufferMinMax)) {
|
TEST(TargetDelayTest, DISABLED_ON_ANDROID(WithTargetDelayBufferNotChanging)) {
|
||||||
const int kTargetMinDelayMs = kNum10msPerFrame * 10;
|
scoped_ptr<TargetDelayTest> test(CreateLegacy());
|
||||||
ASSERT_EQ(0, SetMinimumDelay(kTargetMinDelayMs));
|
test->WithTargetDelayBufferNotChanging();
|
||||||
for (int m = 0; m < 30; ++m) // Run enough iterations to fill up the buffer.
|
|
||||||
Run(true);
|
|
||||||
int clean_optimal_delay = GetCurrentOptimalDelayMs();
|
|
||||||
EXPECT_EQ(kTargetMinDelayMs, clean_optimal_delay);
|
|
||||||
|
|
||||||
const int kTargetMaxDelayMs = 2 * (kNum10msPerFrame * 10);
|
test.reset(CreateNew());
|
||||||
ASSERT_EQ(0, SetMaximumDelay(kTargetMaxDelayMs));
|
test->WithTargetDelayBufferNotChanging();
|
||||||
for (int n = 0; n < 30; ++n) // Run enough iterations to fill up the buffer.
|
|
||||||
Run(false);
|
|
||||||
|
|
||||||
int capped_optimal_delay = GetCurrentOptimalDelayMs();
|
|
||||||
EXPECT_EQ(kTargetMaxDelayMs, capped_optimal_delay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // webrtc
|
TEST(TargetDelayTest, DISABLED_ON_ANDROID(RequiredDelayAtCorrectRange)) {
|
||||||
|
scoped_ptr<TargetDelayTest> test(CreateLegacy());
|
||||||
|
test->RequiredDelayAtCorrectRange();
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->RequiredDelayAtCorrectRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TargetDelayTest, DISABLED_ON_ANDROID(TargetDelayBufferMinMax)) {
|
||||||
|
scoped_ptr<TargetDelayTest> test(CreateLegacy());
|
||||||
|
test->TargetDelayBufferMinMax();
|
||||||
|
|
||||||
|
test.reset(CreateNew());
|
||||||
|
test->TargetDelayBufferMinMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
#include "webrtc/common.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
||||||
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
||||||
@@ -329,4 +330,14 @@ int32_t VADCallback::InFrameType(int16_t frameType) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UseLegacyAcm(webrtc::Config* config) {
|
||||||
|
config->Set<webrtc::AudioCodingModuleFactory>(
|
||||||
|
new webrtc::AudioCodingModuleFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UseNewAcm(webrtc::Config* config) {
|
||||||
|
config->Set<webrtc::AudioCodingModuleFactory>(
|
||||||
|
new webrtc::NewAudioCodingModuleFactory());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@@ -143,6 +143,10 @@ class VADCallback : public ACMVADCallback {
|
|||||||
uint32_t _numFrameTypes[6];
|
uint32_t _numFrameTypes[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void UseLegacyAcm(webrtc::Config* config);
|
||||||
|
|
||||||
|
void UseNewAcm(webrtc::Config* config);
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_UTILITY_H_
|
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_UTILITY_H_
|
||||||
|
|||||||
@@ -64,6 +64,9 @@
|
|||||||
{
|
{
|
||||||
'target_name': 'modules_unittests',
|
'target_name': 'modules_unittests',
|
||||||
'type': '<(gtest_target_type)',
|
'type': '<(gtest_target_type)',
|
||||||
|
'defines': [
|
||||||
|
'<@(audio_coding_defines)',
|
||||||
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'audio_coding_module',
|
'audio_coding_module',
|
||||||
'audio_processing',
|
'audio_processing',
|
||||||
@@ -98,8 +101,10 @@
|
|||||||
'<(webrtc_root)/common_video/common_video.gyp:frame_generator',
|
'<(webrtc_root)/common_video/common_video.gyp:frame_generator',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'audio_coding/main/acm2/acm_receiver_unittest.cc',
|
||||||
|
'audio_coding/main/acm2/initial_delay_manager_unittest.cc',
|
||||||
|
'audio_coding/main/acm2/nack_unittest.cc',
|
||||||
'audio_coding/main/source/acm_neteq_unittest.cc',
|
'audio_coding/main/source/acm_neteq_unittest.cc',
|
||||||
'audio_coding/main/source/nack_unittest.cc',
|
|
||||||
'audio_coding/codecs/cng/cng_unittest.cc',
|
'audio_coding/codecs/cng/cng_unittest.cc',
|
||||||
'audio_coding/codecs/isac/fix/source/filters_unittest.cc',
|
'audio_coding/codecs/isac/fix/source/filters_unittest.cc',
|
||||||
'audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc',
|
'audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc',
|
||||||
|
|||||||
Reference in New Issue
Block a user