Change NetEq::GetAudio to use AudioFrame
With this change, NetEq now uses AudioFrame as output type, like the surrounding functions in ACM and VoiceEngine already do. The computational savings is probably slim, since one memcpy is removed while another one is added (both in AcmReceiver::GetAudio). More simplifications and clean-up will be done in AcmReceiver::GetAudio in future CLs. BUG=webrtc:5607 Review URL: https://codereview.webrtc.org/1750353002 Cr-Commit-Position: refs/heads/master@{#11874}
This commit is contained in:
committed by
Commit bot
parent
6459f84766
commit
6d8e011b64
@ -159,7 +159,7 @@ void AcmReceiveTestOldApi::Run() {
|
||||
while (clock_.TimeInMilliseconds() < packet->time_ms()) {
|
||||
AudioFrame output_frame;
|
||||
EXPECT_EQ(0, acm_->PlayoutData10Ms(output_freq_hz_, &output_frame));
|
||||
EXPECT_EQ(output_freq_hz_, output_frame.sample_rate_hz_);
|
||||
ASSERT_EQ(output_freq_hz_, output_frame.sample_rate_hz_);
|
||||
const size_t samples_per_block =
|
||||
static_cast<size_t>(output_freq_hz_ * 10 / 1000);
|
||||
EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_);
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/format_macros.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/safe_conversions.h"
|
||||
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
|
||||
@ -120,14 +121,12 @@ bool IsCng(int codec_id) {
|
||||
AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config)
|
||||
: last_audio_decoder_(nullptr),
|
||||
previous_audio_activity_(AudioFrame::kVadPassive),
|
||||
audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]),
|
||||
last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]),
|
||||
neteq_(NetEq::Create(config.neteq_config)),
|
||||
vad_enabled_(config.neteq_config.enable_post_decode_vad),
|
||||
clock_(config.clock),
|
||||
resampled_last_output_frame_(true) {
|
||||
assert(clock_);
|
||||
memset(audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples);
|
||||
memset(last_audio_buffer_.get(), 0, AudioFrame::kMaxDataSizeSamples);
|
||||
}
|
||||
|
||||
@ -208,19 +207,11 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
|
||||
}
|
||||
|
||||
int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
|
||||
enum NetEqOutputType type;
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
|
||||
// Accessing members, take the lock.
|
||||
rtc::CritScope lock(&crit_sect_);
|
||||
|
||||
// Always write the output to |audio_buffer_| first.
|
||||
if (neteq_->GetAudio(AudioFrame::kMaxDataSizeSamples,
|
||||
audio_buffer_.get(),
|
||||
&samples_per_channel,
|
||||
&num_channels,
|
||||
&type) != NetEq::kOK) {
|
||||
enum NetEqOutputType type;
|
||||
if (neteq_->GetAudio(audio_frame, &type) != NetEq::kOK) {
|
||||
LOG(LERROR) << "AcmReceiver::GetAudio - NetEq Failed.";
|
||||
return -1;
|
||||
}
|
||||
@ -236,44 +227,42 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
|
||||
int16_t temp_output[AudioFrame::kMaxDataSizeSamples];
|
||||
int samples_per_channel_int = resampler_.Resample10Msec(
|
||||
last_audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz,
|
||||
num_channels, AudioFrame::kMaxDataSizeSamples, temp_output);
|
||||
audio_frame->num_channels_, AudioFrame::kMaxDataSizeSamples,
|
||||
temp_output);
|
||||
if (samples_per_channel_int < 0) {
|
||||
LOG(LERROR) << "AcmReceiver::GetAudio - "
|
||||
"Resampling last_audio_buffer_ failed.";
|
||||
return -1;
|
||||
}
|
||||
samples_per_channel = static_cast<size_t>(samples_per_channel_int);
|
||||
}
|
||||
|
||||
// The audio in |audio_buffer_| is tansferred to |audio_frame_| below, either
|
||||
// through resampling, or through straight memcpy.
|
||||
// TODO(henrik.lundin) Glitches in the output may appear if the output rate
|
||||
// from NetEq changes. See WebRTC issue 3923.
|
||||
if (need_resampling) {
|
||||
int samples_per_channel_int = resampler_.Resample10Msec(
|
||||
audio_buffer_.get(), current_sample_rate_hz, desired_freq_hz,
|
||||
num_channels, AudioFrame::kMaxDataSizeSamples, audio_frame->data_);
|
||||
audio_frame->data_, current_sample_rate_hz, desired_freq_hz,
|
||||
audio_frame->num_channels_, AudioFrame::kMaxDataSizeSamples,
|
||||
audio_frame->data_);
|
||||
if (samples_per_channel_int < 0) {
|
||||
LOG(LERROR) << "AcmReceiver::GetAudio - Resampling audio_buffer_ failed.";
|
||||
return -1;
|
||||
}
|
||||
samples_per_channel = static_cast<size_t>(samples_per_channel_int);
|
||||
audio_frame->samples_per_channel_ =
|
||||
static_cast<size_t>(samples_per_channel_int);
|
||||
audio_frame->sample_rate_hz_ = desired_freq_hz;
|
||||
RTC_DCHECK_EQ(
|
||||
audio_frame->sample_rate_hz_,
|
||||
rtc::checked_cast<int>(audio_frame->samples_per_channel_ * 100));
|
||||
resampled_last_output_frame_ = true;
|
||||
} else {
|
||||
resampled_last_output_frame_ = false;
|
||||
// We might end up here ONLY if codec is changed.
|
||||
memcpy(audio_frame->data_,
|
||||
audio_buffer_.get(),
|
||||
samples_per_channel * num_channels * sizeof(int16_t));
|
||||
}
|
||||
|
||||
// Swap buffers, so that the current audio is stored in |last_audio_buffer_|
|
||||
// for next time.
|
||||
audio_buffer_.swap(last_audio_buffer_);
|
||||
|
||||
audio_frame->num_channels_ = num_channels;
|
||||
audio_frame->samples_per_channel_ = samples_per_channel;
|
||||
audio_frame->sample_rate_hz_ = static_cast<int>(samples_per_channel * 100);
|
||||
// Store current audio in |last_audio_buffer_| for next time.
|
||||
memcpy(last_audio_buffer_.get(), audio_frame->data_,
|
||||
sizeof(int16_t) * audio_frame->samples_per_channel_ *
|
||||
audio_frame->num_channels_);
|
||||
|
||||
// Should set |vad_activity| before calling SetAudioFrameActivityAndType().
|
||||
audio_frame->vad_activity_ = previous_audio_activity_;
|
||||
@ -284,6 +273,7 @@ int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
|
||||
// Computes the RTP timestamp of the first sample in |audio_frame| from
|
||||
// |GetPlayoutTimestamp|, which is the timestamp of the last sample of
|
||||
// |audio_frame|.
|
||||
// TODO(henrik.lundin) Move setting of audio_frame->timestamp_ inside NetEq.
|
||||
uint32_t playout_timestamp = 0;
|
||||
if (GetPlayoutTimestamp(&playout_timestamp)) {
|
||||
audio_frame->timestamp_ = playout_timestamp -
|
||||
|
||||
@ -280,9 +280,6 @@ class AcmReceiver {
|
||||
const Decoder* last_audio_decoder_ GUARDED_BY(crit_sect_);
|
||||
AudioFrame::VADActivity previous_audio_activity_ GUARDED_BY(crit_sect_);
|
||||
ACMResampler resampler_ GUARDED_BY(crit_sect_);
|
||||
// Used in GetAudio, declared as member to avoid allocating every 10ms.
|
||||
// TODO(henrik.lundin) Stack-allocate in GetAudio instead?
|
||||
std::unique_ptr<int16_t[]> audio_buffer_ GUARDED_BY(crit_sect_);
|
||||
std::unique_ptr<int16_t[]> last_audio_buffer_ GUARDED_BY(crit_sect_);
|
||||
CallStatistics call_stats_ GUARDED_BY(crit_sect_);
|
||||
NetEq* neteq_;
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -130,9 +131,7 @@ size_t AudioMultiVector::ReadInterleaved(size_t length,
|
||||
size_t AudioMultiVector::ReadInterleavedFromIndex(size_t start_index,
|
||||
size_t length,
|
||||
int16_t* destination) const {
|
||||
if (!destination) {
|
||||
return 0;
|
||||
}
|
||||
RTC_DCHECK(destination);
|
||||
size_t index = 0; // Number of elements written to |destination| so far.
|
||||
assert(start_index <= Size());
|
||||
start_index = std::min(start_index, Size());
|
||||
|
||||
@ -208,16 +208,6 @@ TEST_P(AudioMultiVectorTest, ReadInterleaved) {
|
||||
delete [] output;
|
||||
}
|
||||
|
||||
// Try to read to a NULL pointer. Expected to return 0.
|
||||
TEST_P(AudioMultiVectorTest, ReadInterleavedToNull) {
|
||||
AudioMultiVector vec(num_channels_);
|
||||
vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
|
||||
int16_t* output = NULL;
|
||||
// Read 5 samples.
|
||||
size_t read_samples = 5;
|
||||
EXPECT_EQ(0u, vec.ReadInterleaved(read_samples, output));
|
||||
}
|
||||
|
||||
// Test the PopFront method.
|
||||
TEST_P(AudioMultiVectorTest, PopFront) {
|
||||
AudioMultiVector vec(num_channels_);
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
namespace webrtc {
|
||||
|
||||
// Forward declarations.
|
||||
class AudioFrame;
|
||||
struct WebRtcRTPHeader;
|
||||
|
||||
struct NetEqNetworkStatistics {
|
||||
@ -163,16 +164,12 @@ class NetEq {
|
||||
uint32_t receive_timestamp) = 0;
|
||||
|
||||
// Instructs NetEq to deliver 10 ms of audio data. The data is written to
|
||||
// |output_audio|, which can hold (at least) |max_length| elements.
|
||||
// The number of channels that were written to the output is provided in
|
||||
// the output variable |num_channels|, and each channel contains
|
||||
// |samples_per_channel| elements. If more than one channel is written,
|
||||
// the samples are interleaved.
|
||||
// |audio_frame|. All data in |audio_frame| is wiped; |data_|, |interleaved_|,
|
||||
// |num_channels_|, and |samples_per_channel_| are updated upon success. If
|
||||
// an error is returned, some fields may not have been updated.
|
||||
// The speech type is written to |type|, if |type| is not NULL.
|
||||
// Returns kOK on success, or kFail in case of an error.
|
||||
virtual int GetAudio(size_t max_length, int16_t* output_audio,
|
||||
size_t* samples_per_channel, size_t* num_channels,
|
||||
NetEqOutputType* type) = 0;
|
||||
virtual int GetAudio(AudioFrame* audio_frame, NetEqOutputType* type) = 0;
|
||||
|
||||
// Associates |rtp_payload_type| with |codec| and |codec_name|, and stores the
|
||||
// information in the codec database. Returns 0 on success, -1 on failure.
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -188,25 +189,19 @@ class NetEqExternalVsInternalDecoderTest : public NetEqExternalDecoderUnitTest,
|
||||
|
||||
void GetAndVerifyOutput() override {
|
||||
NetEqOutputType output_type;
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
// Get audio from internal decoder instance.
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_internal_->GetAudio(kMaxBlockSize,
|
||||
output_internal_,
|
||||
&samples_per_channel,
|
||||
&num_channels,
|
||||
&output_type));
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
neteq_internal_->GetAudio(&output_internal_, &output_type));
|
||||
EXPECT_EQ(1u, output_internal_.num_channels_);
|
||||
EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * sample_rate_hz_ / 1000),
|
||||
samples_per_channel);
|
||||
output_internal_.samples_per_channel_);
|
||||
|
||||
// Get audio from external decoder instance.
|
||||
samples_per_channel = GetOutputAudio(kMaxBlockSize, output_, &output_type);
|
||||
GetOutputAudio(&output_, &output_type);
|
||||
|
||||
for (size_t i = 0; i < samples_per_channel; ++i) {
|
||||
ASSERT_EQ(output_[i], output_internal_[i]) <<
|
||||
"Diff in sample " << i << ".";
|
||||
for (size_t i = 0; i < output_.samples_per_channel_; ++i) {
|
||||
ASSERT_EQ(output_.data_[i], output_internal_.data_[i])
|
||||
<< "Diff in sample " << i << ".";
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,8 +222,8 @@ class NetEqExternalVsInternalDecoderTest : public NetEqExternalDecoderUnitTest,
|
||||
private:
|
||||
int sample_rate_hz_;
|
||||
std::unique_ptr<NetEq> neteq_internal_;
|
||||
int16_t output_internal_[kMaxBlockSize];
|
||||
int16_t output_[kMaxBlockSize];
|
||||
AudioFrame output_internal_;
|
||||
AudioFrame output_;
|
||||
};
|
||||
|
||||
TEST_F(NetEqExternalVsInternalDecoderTest, RunTest) {
|
||||
@ -291,9 +286,9 @@ class LargeTimestampJumpTest : public NetEqExternalDecoderUnitTest,
|
||||
}
|
||||
|
||||
void GetAndVerifyOutput() override {
|
||||
size_t num_samples;
|
||||
AudioFrame output;
|
||||
NetEqOutputType output_type;
|
||||
num_samples = GetOutputAudio(kMaxBlockSize, output_, &output_type);
|
||||
GetOutputAudio(&output, &output_type);
|
||||
UpdateState(output_type);
|
||||
|
||||
if (test_state_ == kExpandPhase || test_state_ == kFadedExpandPhase) {
|
||||
@ -301,8 +296,9 @@ class LargeTimestampJumpTest : public NetEqExternalDecoderUnitTest,
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_samples; ++i) {
|
||||
if (output_[i] != 0)
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
for (size_t i = 0; i < output.samples_per_channel_; ++i) {
|
||||
if (output.data_[i] != 0)
|
||||
return;
|
||||
}
|
||||
EXPECT_TRUE(false)
|
||||
@ -321,9 +317,6 @@ class LargeTimestampJumpTest : public NetEqExternalDecoderUnitTest,
|
||||
}
|
||||
|
||||
TestStates test_state_;
|
||||
|
||||
private:
|
||||
int16_t output_[kMaxBlockSize];
|
||||
};
|
||||
|
||||
TEST_F(LargeTimestampJumpTest, JumpLongerThanHalfRange) {
|
||||
|
||||
@ -148,13 +148,13 @@ int NetEqImpl::InsertSyncPacket(const WebRtcRTPHeader& rtp_header,
|
||||
return kOK;
|
||||
}
|
||||
|
||||
int NetEqImpl::GetAudio(size_t max_length, int16_t* output_audio,
|
||||
size_t* samples_per_channel, size_t* num_channels,
|
||||
NetEqOutputType* type) {
|
||||
int NetEqImpl::GetAudio(AudioFrame* audio_frame, NetEqOutputType* type) {
|
||||
TRACE_EVENT0("webrtc", "NetEqImpl::GetAudio");
|
||||
rtc::CritScope lock(&crit_sect_);
|
||||
int error = GetAudioInternal(max_length, output_audio, samples_per_channel,
|
||||
num_channels);
|
||||
int error = GetAudioInternal(audio_frame);
|
||||
RTC_DCHECK_EQ(
|
||||
audio_frame->sample_rate_hz_,
|
||||
rtc::checked_cast<int>(audio_frame->samples_per_channel_ * 100));
|
||||
if (error != 0) {
|
||||
error_code_ = error;
|
||||
return kFail;
|
||||
@ -162,8 +162,7 @@ int NetEqImpl::GetAudio(size_t max_length, int16_t* output_audio,
|
||||
if (type) {
|
||||
*type = LastOutputType();
|
||||
}
|
||||
last_output_sample_rate_hz_ =
|
||||
rtc::checked_cast<int>(*samples_per_channel * 100);
|
||||
last_output_sample_rate_hz_ = audio_frame->sample_rate_hz_;
|
||||
RTC_DCHECK(last_output_sample_rate_hz_ == 8000 ||
|
||||
last_output_sample_rate_hz_ == 16000 ||
|
||||
last_output_sample_rate_hz_ == 32000 ||
|
||||
@ -739,10 +738,7 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetEqImpl::GetAudioInternal(size_t max_length,
|
||||
int16_t* output,
|
||||
size_t* samples_per_channel,
|
||||
size_t* num_channels) {
|
||||
int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame) {
|
||||
PacketList packet_list;
|
||||
DtmfEvent dtmf_event;
|
||||
Operations operation;
|
||||
@ -857,16 +853,18 @@ int NetEqImpl::GetAudioInternal(size_t max_length,
|
||||
// Extract data from |sync_buffer_| to |output|.
|
||||
size_t num_output_samples_per_channel = output_size_samples_;
|
||||
size_t num_output_samples = output_size_samples_ * sync_buffer_->Channels();
|
||||
if (num_output_samples > max_length) {
|
||||
LOG(LS_WARNING) << "Output array is too short. " << max_length << " < " <<
|
||||
output_size_samples_ << " * " << sync_buffer_->Channels();
|
||||
num_output_samples = max_length;
|
||||
num_output_samples_per_channel = max_length / sync_buffer_->Channels();
|
||||
if (num_output_samples > AudioFrame::kMaxDataSizeSamples) {
|
||||
LOG(LS_WARNING) << "Output array is too short. "
|
||||
<< AudioFrame::kMaxDataSizeSamples << " < "
|
||||
<< output_size_samples_ << " * "
|
||||
<< sync_buffer_->Channels();
|
||||
num_output_samples = AudioFrame::kMaxDataSizeSamples;
|
||||
num_output_samples_per_channel =
|
||||
AudioFrame::kMaxDataSizeSamples / sync_buffer_->Channels();
|
||||
}
|
||||
const size_t samples_from_sync =
|
||||
sync_buffer_->GetNextAudioInterleaved(num_output_samples_per_channel,
|
||||
output);
|
||||
*num_channels = sync_buffer_->Channels();
|
||||
sync_buffer_->GetNextAudioInterleaved(num_output_samples_per_channel,
|
||||
audio_frame);
|
||||
audio_frame->sample_rate_hz_ = fs_hz_;
|
||||
if (sync_buffer_->FutureLength() < expand_->overlap_length()) {
|
||||
// The sync buffer should always contain |overlap_length| samples, but now
|
||||
// too many samples have been extracted. Reinstall the |overlap_length|
|
||||
@ -877,22 +875,22 @@ int NetEqImpl::GetAudioInternal(size_t max_length,
|
||||
sync_buffer_->set_next_index(sync_buffer_->next_index() -
|
||||
missing_lookahead_samples);
|
||||
}
|
||||
if (samples_from_sync != output_size_samples_) {
|
||||
LOG(LS_ERROR) << "samples_from_sync (" << samples_from_sync
|
||||
if (audio_frame->samples_per_channel_ != output_size_samples_) {
|
||||
LOG(LS_ERROR) << "audio_frame->samples_per_channel_ ("
|
||||
<< audio_frame->samples_per_channel_
|
||||
<< ") != output_size_samples_ (" << output_size_samples_
|
||||
<< ")";
|
||||
// TODO(minyue): treatment of under-run, filling zeros
|
||||
memset(output, 0, num_output_samples * sizeof(int16_t));
|
||||
*samples_per_channel = output_size_samples_;
|
||||
memset(audio_frame->data_, 0, num_output_samples * sizeof(int16_t));
|
||||
return kSampleUnderrun;
|
||||
}
|
||||
*samples_per_channel = output_size_samples_;
|
||||
|
||||
// Should always have overlap samples left in the |sync_buffer_|.
|
||||
RTC_DCHECK_GE(sync_buffer_->FutureLength(), expand_->overlap_length());
|
||||
|
||||
if (play_dtmf) {
|
||||
return_value = DtmfOverdub(dtmf_event, sync_buffer_->Channels(), output);
|
||||
return_value =
|
||||
DtmfOverdub(dtmf_event, sync_buffer_->Channels(), audio_frame->data_);
|
||||
}
|
||||
|
||||
// Update the background noise parameters if last operation wrote data
|
||||
|
||||
@ -96,19 +96,7 @@ class NetEqImpl : public webrtc::NetEq {
|
||||
int InsertSyncPacket(const WebRtcRTPHeader& rtp_header,
|
||||
uint32_t receive_timestamp) override;
|
||||
|
||||
// Instructs NetEq to deliver 10 ms of audio data. The data is written to
|
||||
// |output_audio|, which can hold (at least) |max_length| elements.
|
||||
// The number of channels that were written to the output is provided in
|
||||
// the output variable |num_channels|, and each channel contains
|
||||
// |samples_per_channel| elements. If more than one channel is written,
|
||||
// the samples are interleaved.
|
||||
// The speech type is written to |type|, if |type| is not NULL.
|
||||
// Returns kOK on success, or kFail in case of an error.
|
||||
int GetAudio(size_t max_length,
|
||||
int16_t* output_audio,
|
||||
size_t* samples_per_channel,
|
||||
size_t* num_channels,
|
||||
NetEqOutputType* type) override;
|
||||
int GetAudio(AudioFrame* audio_frame, NetEqOutputType* type) override;
|
||||
|
||||
int RegisterPayloadType(NetEqDecoder codec,
|
||||
const std::string& codec_name,
|
||||
@ -211,16 +199,9 @@ class NetEqImpl : public webrtc::NetEq {
|
||||
bool is_sync_packet)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
|
||||
|
||||
// Delivers 10 ms of audio data. The data is written to |output|, which can
|
||||
// hold (at least) |max_length| elements. The number of channels that were
|
||||
// written to the output is provided in the output variable |num_channels|,
|
||||
// and each channel contains |samples_per_channel| elements. If more than one
|
||||
// channel is written, the samples are interleaved.
|
||||
// Delivers 10 ms of audio data. The data is written to |audio_frame|.
|
||||
// Returns 0 on success, otherwise an error code.
|
||||
int GetAudioInternal(size_t max_length,
|
||||
int16_t* output,
|
||||
size_t* samples_per_channel,
|
||||
size_t* num_channels)
|
||||
int GetAudioInternal(AudioFrame* audio_frame)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
|
||||
|
||||
// Provides a decision to the GetAudioInternal method. The decision what to
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "webrtc/modules/audio_coding/neteq/preemptive_expand.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/timestamp_scaler.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
|
||||
using ::testing::AtLeast;
|
||||
using ::testing::Return;
|
||||
@ -464,16 +465,11 @@ TEST_F(NetEqImplTest, VerifyTimestampPropagation) {
|
||||
|
||||
// Pull audio once.
|
||||
const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000);
|
||||
int16_t output[kMaxOutputSize];
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
AudioFrame output;
|
||||
NetEqOutputType type;
|
||||
EXPECT_EQ(
|
||||
NetEq::kOK,
|
||||
neteq_->GetAudio(
|
||||
kMaxOutputSize, output, &samples_per_channel, &num_channels, &type));
|
||||
ASSERT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
|
||||
// Start with a simple check that the fake decoder is behaving as expected.
|
||||
@ -485,7 +481,8 @@ TEST_F(NetEqImplTest, VerifyTimestampPropagation) {
|
||||
// timestamp should match the playout timestamp.
|
||||
uint32_t timestamp = 0;
|
||||
EXPECT_TRUE(neteq_->GetPlayoutTimestamp(×tamp));
|
||||
EXPECT_EQ(rtp_header.header.timestamp + output[samples_per_channel - 1],
|
||||
EXPECT_EQ(rtp_header.header.timestamp +
|
||||
output.data_[output.samples_per_channel_ - 1],
|
||||
timestamp);
|
||||
|
||||
// Check the timestamp for the last value in the sync buffer. This should
|
||||
@ -497,8 +494,9 @@ TEST_F(NetEqImplTest, VerifyTimestampPropagation) {
|
||||
|
||||
// Check that the number of samples still to play from the sync buffer add
|
||||
// up with what was already played out.
|
||||
EXPECT_EQ(kPayloadLengthSamples - output[samples_per_channel - 1],
|
||||
sync_buffer->FutureLength());
|
||||
EXPECT_EQ(
|
||||
kPayloadLengthSamples - output.data_[output.samples_per_channel_ - 1],
|
||||
sync_buffer->FutureLength());
|
||||
}
|
||||
|
||||
TEST_F(NetEqImplTest, ReorderedPacket) {
|
||||
@ -543,16 +541,11 @@ TEST_F(NetEqImplTest, ReorderedPacket) {
|
||||
|
||||
// Pull audio once.
|
||||
const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000);
|
||||
int16_t output[kMaxOutputSize];
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
AudioFrame output;
|
||||
NetEqOutputType type;
|
||||
EXPECT_EQ(
|
||||
NetEq::kOK,
|
||||
neteq_->GetAudio(
|
||||
kMaxOutputSize, output, &samples_per_channel, &num_channels, &type));
|
||||
ASSERT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
|
||||
// Insert two more packets. The first one is out of order, and is already too
|
||||
@ -578,12 +571,9 @@ TEST_F(NetEqImplTest, ReorderedPacket) {
|
||||
Return(kPayloadLengthSamples)));
|
||||
|
||||
// Pull audio once.
|
||||
EXPECT_EQ(
|
||||
NetEq::kOK,
|
||||
neteq_->GetAudio(
|
||||
kMaxOutputSize, output, &samples_per_channel, &num_channels, &type));
|
||||
ASSERT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
|
||||
// Now check the packet buffer, and make sure it is empty, since the
|
||||
@ -620,16 +610,12 @@ TEST_F(NetEqImplTest, FirstPacketUnknown) {
|
||||
|
||||
// Pull audio once.
|
||||
const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000);
|
||||
int16_t output[kMaxOutputSize];
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
AudioFrame output;
|
||||
NetEqOutputType type;
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
ASSERT_LE(samples_per_channel, kMaxOutputSize);
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
ASSERT_LE(output.samples_per_channel_, kMaxOutputSize);
|
||||
EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputPLC, type);
|
||||
|
||||
// Register the payload type.
|
||||
@ -647,12 +633,10 @@ TEST_F(NetEqImplTest, FirstPacketUnknown) {
|
||||
|
||||
// Pull audio repeatedly and make sure we get normal output, that is not PLC.
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
ASSERT_LE(samples_per_channel, kMaxOutputSize);
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
ASSERT_LE(output.samples_per_channel_, kMaxOutputSize);
|
||||
EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputNormal, type)
|
||||
<< "NetEq did not decode the packets as expected.";
|
||||
}
|
||||
@ -732,9 +716,7 @@ TEST_F(NetEqImplTest, CodecInternalCng) {
|
||||
neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
|
||||
|
||||
const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateKhz);
|
||||
int16_t output[kMaxOutputSize];
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
AudioFrame output;
|
||||
uint32_t timestamp;
|
||||
uint32_t last_timestamp;
|
||||
NetEqOutputType type;
|
||||
@ -752,19 +734,15 @@ TEST_F(NetEqImplTest, CodecInternalCng) {
|
||||
50 * kSampleRateKhz, 10 * kSampleRateKhz
|
||||
};
|
||||
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_TRUE(neteq_->GetPlayoutTimestamp(&last_timestamp));
|
||||
|
||||
for (size_t i = 1; i < 6; ++i) {
|
||||
ASSERT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(expected_type[i - 1], type);
|
||||
EXPECT_TRUE(neteq_->GetPlayoutTimestamp(×tamp));
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_TRUE(neteq_->GetPlayoutTimestamp(×tamp));
|
||||
EXPECT_EQ(timestamp, last_timestamp + expected_timestamp_increment[i]);
|
||||
last_timestamp = timestamp;
|
||||
@ -778,12 +756,10 @@ TEST_F(NetEqImplTest, CodecInternalCng) {
|
||||
neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
|
||||
|
||||
for (size_t i = 6; i < 8; ++i) {
|
||||
ASSERT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(expected_type[i - 1], type);
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_TRUE(neteq_->GetPlayoutTimestamp(×tamp));
|
||||
EXPECT_EQ(timestamp, last_timestamp + expected_timestamp_increment[i]);
|
||||
last_timestamp = timestamp;
|
||||
@ -871,24 +847,23 @@ TEST_F(NetEqImplTest, UnsupportedDecoder) {
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
|
||||
|
||||
const size_t kMaxOutputSize = 10 * kSampleRateHz / 1000 * kChannels;
|
||||
int16_t output[kMaxOutputSize];
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
AudioFrame output;
|
||||
NetEqOutputType type;
|
||||
|
||||
EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(kMaxOutputSize, output,
|
||||
&samples_per_channel, &num_channels,
|
||||
&type));
|
||||
// First call to GetAudio will try to decode the "faulty" packet.
|
||||
// Expect kFail return value...
|
||||
EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&output, &type));
|
||||
// ... and kOtherDecoderError error code.
|
||||
EXPECT_EQ(NetEq::kOtherDecoderError, neteq_->LastError());
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel * kChannels);
|
||||
EXPECT_EQ(kChannels, num_channels);
|
||||
// Output size and number of channels should be correct.
|
||||
const size_t kExpectedOutputSize = 10 * (kSampleRateHz / 1000) * kChannels;
|
||||
EXPECT_EQ(kExpectedOutputSize, output.samples_per_channel_ * kChannels);
|
||||
EXPECT_EQ(kChannels, output.num_channels_);
|
||||
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(kMaxOutputSize, output,
|
||||
&samples_per_channel, &num_channels,
|
||||
&type));
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel * kChannels);
|
||||
EXPECT_EQ(kChannels, num_channels);
|
||||
// Second call to GetAudio will decode the packet that is ok. No errors are
|
||||
// expected.
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_EQ(kExpectedOutputSize, output.samples_per_channel_ * kChannels);
|
||||
EXPECT_EQ(kChannels, output.num_channels_);
|
||||
}
|
||||
|
||||
// This test inserts packets until the buffer is flushed. After that, it asks
|
||||
@ -978,15 +953,11 @@ TEST_F(NetEqImplTest, DecodedPayloadTooShort) {
|
||||
|
||||
// Pull audio once.
|
||||
const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000);
|
||||
int16_t output[kMaxOutputSize];
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
AudioFrame output;
|
||||
NetEqOutputType type;
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
ASSERT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
ASSERT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
|
||||
EXPECT_CALL(mock_decoder, Die());
|
||||
@ -1075,43 +1046,33 @@ TEST_F(NetEqImplTest, DecodingError) {
|
||||
|
||||
// Pull audio.
|
||||
const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000);
|
||||
int16_t output[kMaxOutputSize];
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
AudioFrame output;
|
||||
NetEqOutputType type;
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
|
||||
// Pull audio again. Decoder fails.
|
||||
EXPECT_EQ(NetEq::kFail,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError());
|
||||
EXPECT_EQ(kDecoderErrorCode, neteq_->LastDecoderError());
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
// TODO(minyue): should NetEq better give kOutputPLC, since it is actually an
|
||||
// expansion.
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
|
||||
// Pull audio again, should continue an expansion.
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputPLC, type);
|
||||
|
||||
// Pull audio again, should behave normal.
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
|
||||
EXPECT_CALL(mock_decoder, Die());
|
||||
@ -1196,35 +1157,27 @@ TEST_F(NetEqImplTest, DecodingErrorDuringInternalCng) {
|
||||
|
||||
// Pull audio.
|
||||
const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000);
|
||||
int16_t output[kMaxOutputSize];
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
AudioFrame output;
|
||||
NetEqOutputType type;
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputCNG, type);
|
||||
|
||||
// Pull audio again. Decoder fails.
|
||||
EXPECT_EQ(NetEq::kFail,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError());
|
||||
EXPECT_EQ(kDecoderErrorCode, neteq_->LastDecoderError());
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
// TODO(minyue): should NetEq better give kOutputPLC, since it is actually an
|
||||
// expansion.
|
||||
EXPECT_EQ(kOutputCNG, type);
|
||||
|
||||
// Pull audio again, should resume codec CNG.
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, samples_per_channel);
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &type));
|
||||
EXPECT_EQ(kMaxOutputSize, output.samples_per_channel_);
|
||||
EXPECT_EQ(1u, output.num_channels_);
|
||||
EXPECT_EQ(kOutputCNG, type);
|
||||
|
||||
EXPECT_CALL(mock_decoder, Die());
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
@ -83,7 +84,6 @@ class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
|
||||
public:
|
||||
static const int kPayloadSizeByte = 30;
|
||||
static const int kFrameSizeMs = 20;
|
||||
static const int kMaxOutputSize = 960; // 10 ms * 48 kHz * 2 channels.
|
||||
|
||||
enum logic {
|
||||
kIgnore,
|
||||
@ -195,7 +195,7 @@ struct NetEqNetworkStatsCheck {
|
||||
InsertPacket(rtp_header_, payload_, next_send_time);
|
||||
}
|
||||
}
|
||||
GetOutputAudio(kMaxOutputSize, output_, &output_type);
|
||||
GetOutputAudio(&output_frame_, &output_type);
|
||||
time_now += kOutputLengthMs;
|
||||
}
|
||||
CheckNetworkStatistics(expects);
|
||||
@ -269,7 +269,7 @@ struct NetEqNetworkStatsCheck {
|
||||
uint32_t last_lost_time_;
|
||||
uint32_t packet_loss_interval_;
|
||||
uint8_t payload_[kPayloadSizeByte];
|
||||
int16_t output_[kMaxOutputSize];
|
||||
AudioFrame output_frame_;
|
||||
};
|
||||
|
||||
TEST(NetEqNetworkStatsTest, DecodeFec) {
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "webrtc/modules/audio_coding/neteq/include/neteq.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -69,7 +70,6 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
|
||||
input_multi_channel_ = new int16_t[frame_size_samples_ * num_channels_];
|
||||
encoded_multi_channel_ = new uint8_t[frame_size_samples_ * 2 *
|
||||
num_channels_];
|
||||
output_multi_channel_ = new int16_t[kMaxBlockSize * num_channels_];
|
||||
}
|
||||
|
||||
~NetEqStereoTest() {
|
||||
@ -79,7 +79,6 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
|
||||
delete [] encoded_;
|
||||
delete [] input_multi_channel_;
|
||||
delete [] encoded_multi_channel_;
|
||||
delete [] output_multi_channel_;
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
@ -164,8 +163,9 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
|
||||
virtual void VerifyOutput(size_t num_samples) {
|
||||
for (size_t i = 0; i < num_samples; ++i) {
|
||||
for (size_t j = 0; j < num_channels_; ++j) {
|
||||
ASSERT_EQ(output_[i], output_multi_channel_[i * num_channels_ + j]) <<
|
||||
"Diff in sample " << i << ", channel " << j << ".";
|
||||
ASSERT_EQ(output_.data_[i],
|
||||
output_multi_channel_.data_[i * num_channels_ + j])
|
||||
<< "Diff in sample " << i << ", channel " << j << ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,22 +213,15 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
|
||||
}
|
||||
NetEqOutputType output_type;
|
||||
// Get audio from mono instance.
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_mono_->GetAudio(kMaxBlockSize, output_,
|
||||
&samples_per_channel, &num_channels,
|
||||
&output_type));
|
||||
EXPECT_EQ(1u, num_channels);
|
||||
EXPECT_EQ(output_size_samples_, samples_per_channel);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_mono_->GetAudio(&output_, &output_type));
|
||||
EXPECT_EQ(1u, output_.num_channels_);
|
||||
EXPECT_EQ(output_size_samples_, output_.samples_per_channel_);
|
||||
// Get audio from multi-channel instance.
|
||||
ASSERT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(kMaxBlockSize * num_channels_,
|
||||
output_multi_channel_,
|
||||
&samples_per_channel, &num_channels,
|
||||
&output_type));
|
||||
EXPECT_EQ(num_channels_, num_channels);
|
||||
EXPECT_EQ(output_size_samples_, samples_per_channel);
|
||||
neteq_->GetAudio(&output_multi_channel_, &output_type));
|
||||
EXPECT_EQ(num_channels_, output_multi_channel_.num_channels_);
|
||||
EXPECT_EQ(output_size_samples_,
|
||||
output_multi_channel_.samples_per_channel_);
|
||||
std::ostringstream ss;
|
||||
ss << "Lap number " << k << ".";
|
||||
SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
|
||||
@ -253,8 +246,8 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
|
||||
int16_t* input_multi_channel_;
|
||||
uint8_t* encoded_;
|
||||
uint8_t* encoded_multi_channel_;
|
||||
int16_t output_[kMaxBlockSize];
|
||||
int16_t* output_multi_channel_;
|
||||
AudioFrame output_;
|
||||
AudioFrame output_multi_channel_;
|
||||
WebRtcRTPHeader rtp_header_mono_;
|
||||
WebRtcRTPHeader rtp_header_;
|
||||
size_t payload_size_bytes_;
|
||||
@ -360,14 +353,16 @@ class NetEqStereoTestLosses : public NetEqStereoTest {
|
||||
// TODO(hlundin): NetEq is not giving bitexact results for these cases.
|
||||
virtual void VerifyOutput(size_t num_samples) {
|
||||
for (size_t i = 0; i < num_samples; ++i) {
|
||||
auto first_channel_sample = output_multi_channel_[i * num_channels_];
|
||||
auto first_channel_sample =
|
||||
output_multi_channel_.data_[i * num_channels_];
|
||||
for (size_t j = 0; j < num_channels_; ++j) {
|
||||
const int kErrorMargin = 200;
|
||||
EXPECT_NEAR(output_[i], output_multi_channel_[i * num_channels_ + j],
|
||||
EXPECT_NEAR(output_.data_[i],
|
||||
output_multi_channel_.data_[i * num_channels_ + j],
|
||||
kErrorMargin)
|
||||
<< "Diff in sample " << i << ", channel " << j << ".";
|
||||
EXPECT_EQ(first_channel_sample,
|
||||
output_multi_channel_[i * num_channels_ + j]);
|
||||
output_multi_channel_.data_[i * num_channels_ + j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
@ -279,7 +280,6 @@ class NetEqDecodingTest : public ::testing::Test {
|
||||
static const size_t kBlockSize16kHz = kTimeStepMs * 16;
|
||||
static const size_t kBlockSize32kHz = kTimeStepMs * 32;
|
||||
static const size_t kBlockSize48kHz = kTimeStepMs * 48;
|
||||
static const size_t kMaxBlockSize = kBlockSize48kHz;
|
||||
static const int kInitSampleRateHz = 8000;
|
||||
|
||||
NetEqDecodingTest();
|
||||
@ -288,7 +288,7 @@ class NetEqDecodingTest : public ::testing::Test {
|
||||
void SelectDecoders(NetEqDecoder* used_codec);
|
||||
void LoadDecoders();
|
||||
void OpenInputFile(const std::string &rtp_file);
|
||||
void Process(size_t* out_len);
|
||||
void Process();
|
||||
|
||||
void DecodeAndCompare(const std::string& rtp_file,
|
||||
const std::string& ref_file,
|
||||
@ -323,7 +323,7 @@ class NetEqDecodingTest : public ::testing::Test {
|
||||
std::unique_ptr<test::RtpFileSource> rtp_source_;
|
||||
std::unique_ptr<test::Packet> packet_;
|
||||
unsigned int sim_clock_;
|
||||
int16_t out_data_[kMaxBlockSize];
|
||||
AudioFrame out_frame_;
|
||||
int output_sample_rate_;
|
||||
int algorithmic_delay_ms_;
|
||||
};
|
||||
@ -333,7 +333,6 @@ const int NetEqDecodingTest::kTimeStepMs;
|
||||
const size_t NetEqDecodingTest::kBlockSize8kHz;
|
||||
const size_t NetEqDecodingTest::kBlockSize16kHz;
|
||||
const size_t NetEqDecodingTest::kBlockSize32kHz;
|
||||
const size_t NetEqDecodingTest::kMaxBlockSize;
|
||||
const int NetEqDecodingTest::kInitSampleRateHz;
|
||||
|
||||
NetEqDecodingTest::NetEqDecodingTest()
|
||||
@ -343,7 +342,6 @@ NetEqDecodingTest::NetEqDecodingTest()
|
||||
output_sample_rate_(kInitSampleRateHz),
|
||||
algorithmic_delay_ms_(0) {
|
||||
config_.sample_rate_hz = kInitSampleRateHz;
|
||||
memset(out_data_, 0, sizeof(out_data_));
|
||||
}
|
||||
|
||||
void NetEqDecodingTest::SetUp() {
|
||||
@ -406,7 +404,7 @@ void NetEqDecodingTest::OpenInputFile(const std::string &rtp_file) {
|
||||
rtp_source_.reset(test::RtpFileSource::Create(rtp_file));
|
||||
}
|
||||
|
||||
void NetEqDecodingTest::Process(size_t* out_len) {
|
||||
void NetEqDecodingTest::Process() {
|
||||
// Check if time to receive.
|
||||
while (packet_ && sim_clock_ >= packet_->time_ms()) {
|
||||
if (packet_->payload_length_bytes() > 0) {
|
||||
@ -429,14 +427,12 @@ void NetEqDecodingTest::Process(size_t* out_len) {
|
||||
|
||||
// Get audio from NetEq.
|
||||
NetEqOutputType type;
|
||||
size_t num_channels;
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, out_len,
|
||||
&num_channels, &type));
|
||||
ASSERT_TRUE((*out_len == kBlockSize8kHz) ||
|
||||
(*out_len == kBlockSize16kHz) ||
|
||||
(*out_len == kBlockSize32kHz) ||
|
||||
(*out_len == kBlockSize48kHz));
|
||||
output_sample_rate_ = static_cast<int>(*out_len / 10 * 1000);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_TRUE((out_frame_.samples_per_channel_ == kBlockSize8kHz) ||
|
||||
(out_frame_.samples_per_channel_ == kBlockSize16kHz) ||
|
||||
(out_frame_.samples_per_channel_ == kBlockSize32kHz) ||
|
||||
(out_frame_.samples_per_channel_ == kBlockSize48kHz));
|
||||
output_sample_rate_ = out_frame_.sample_rate_hz_;
|
||||
EXPECT_EQ(output_sample_rate_, neteq_->last_output_sample_rate_hz());
|
||||
|
||||
// Increase time.
|
||||
@ -473,9 +469,9 @@ void NetEqDecodingTest::DecodeAndCompare(const std::string& rtp_file,
|
||||
std::ostringstream ss;
|
||||
ss << "Lap number " << i++ << " in DecodeAndCompare while loop";
|
||||
SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
|
||||
size_t out_len = 0;
|
||||
ASSERT_NO_FATAL_FAILURE(Process(&out_len));
|
||||
ASSERT_NO_FATAL_FAILURE(ref_files.ProcessReference(out_data_, out_len));
|
||||
ASSERT_NO_FATAL_FAILURE(Process());
|
||||
ASSERT_NO_FATAL_FAILURE(ref_files.ProcessReference(
|
||||
out_frame_.data_, out_frame_.samples_per_channel_));
|
||||
|
||||
// Query the network statistics API once per second
|
||||
if (sim_clock_ % 1000 == 0) {
|
||||
@ -615,12 +611,9 @@ TEST_F(NetEqDecodingTestFaxMode, TestFrameWaitingTimeStatistics) {
|
||||
}
|
||||
// Pull out all data.
|
||||
for (size_t i = 0; i < num_frames; ++i) {
|
||||
size_t out_len;
|
||||
size_t num_channels;
|
||||
NetEqOutputType type;
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
|
||||
&num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
}
|
||||
|
||||
NetEqNetworkStatistics stats;
|
||||
@ -660,12 +653,9 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimeNegative) {
|
||||
}
|
||||
|
||||
// Pull out data once.
|
||||
size_t out_len;
|
||||
size_t num_channels;
|
||||
NetEqOutputType type;
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
|
||||
&num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
}
|
||||
|
||||
NetEqNetworkStatistics network_stats;
|
||||
@ -691,12 +681,9 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimePositive) {
|
||||
}
|
||||
|
||||
// Pull out data once.
|
||||
size_t out_len;
|
||||
size_t num_channels;
|
||||
NetEqOutputType type;
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
|
||||
&num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
}
|
||||
|
||||
NetEqNetworkStatistics network_stats;
|
||||
@ -716,8 +703,6 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor,
|
||||
const size_t kPayloadBytes = kSamples * 2;
|
||||
double next_input_time_ms = 0.0;
|
||||
double t_ms;
|
||||
size_t out_len;
|
||||
size_t num_channels;
|
||||
NetEqOutputType type;
|
||||
|
||||
// Insert speech for 5 seconds.
|
||||
@ -735,9 +720,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor,
|
||||
next_input_time_ms += static_cast<double>(kFrameSizeMs) * drift_factor;
|
||||
}
|
||||
// Pull out data once.
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
|
||||
&num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
}
|
||||
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
@ -763,9 +747,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor,
|
||||
next_input_time_ms += static_cast<double>(kCngPeriodMs) * drift_factor;
|
||||
}
|
||||
// Pull out data once.
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
|
||||
&num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
}
|
||||
|
||||
EXPECT_EQ(kOutputCNG, type);
|
||||
@ -777,10 +760,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor,
|
||||
const double loop_end_time = t_ms + network_freeze_ms;
|
||||
for (; t_ms < loop_end_time; t_ms += 10) {
|
||||
// Pull out data once.
|
||||
ASSERT_EQ(0,
|
||||
neteq_->GetAudio(
|
||||
kMaxBlockSize, out_data_, &out_len, &num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
EXPECT_EQ(kOutputCNG, type);
|
||||
}
|
||||
bool pull_once = pull_audio_during_freeze;
|
||||
@ -791,11 +772,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor,
|
||||
if (pull_once && next_input_time_ms >= pull_time_ms) {
|
||||
pull_once = false;
|
||||
// Pull out data once.
|
||||
ASSERT_EQ(
|
||||
0,
|
||||
neteq_->GetAudio(
|
||||
kMaxBlockSize, out_data_, &out_len, &num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
EXPECT_EQ(kOutputCNG, type);
|
||||
t_ms += 10;
|
||||
}
|
||||
@ -828,9 +806,8 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor,
|
||||
next_input_time_ms += kFrameSizeMs * drift_factor;
|
||||
}
|
||||
// Pull out data once.
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
|
||||
&num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
// Increase clock.
|
||||
t_ms += 10;
|
||||
}
|
||||
@ -953,14 +930,10 @@ TEST_F(NetEqDecodingTest, MAYBE_DecoderError) {
|
||||
NetEqOutputType type;
|
||||
// Set all of |out_data_| to 1, and verify that it was set to 0 by the call
|
||||
// to GetAudio.
|
||||
for (size_t i = 0; i < kMaxBlockSize; ++i) {
|
||||
out_data_[i] = 1;
|
||||
for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) {
|
||||
out_frame_.data_[i] = 1;
|
||||
}
|
||||
size_t num_channels;
|
||||
size_t samples_per_channel;
|
||||
EXPECT_EQ(NetEq::kFail,
|
||||
neteq_->GetAudio(kMaxBlockSize, out_data_,
|
||||
&samples_per_channel, &num_channels, &type));
|
||||
EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&out_frame_, &type));
|
||||
// Verify that there is a decoder error to check.
|
||||
EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError());
|
||||
|
||||
@ -980,13 +953,14 @@ TEST_F(NetEqDecodingTest, MAYBE_DecoderError) {
|
||||
std::ostringstream ss;
|
||||
ss << "i = " << i;
|
||||
SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
|
||||
EXPECT_EQ(0, out_data_[i]);
|
||||
EXPECT_EQ(0, out_frame_.data_[i]);
|
||||
}
|
||||
for (size_t i = kExpectedOutputLength; i < kMaxBlockSize; ++i) {
|
||||
for (size_t i = kExpectedOutputLength; i < AudioFrame::kMaxDataSizeSamples;
|
||||
++i) {
|
||||
std::ostringstream ss;
|
||||
ss << "i = " << i;
|
||||
SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
|
||||
EXPECT_EQ(1, out_data_[i]);
|
||||
EXPECT_EQ(1, out_frame_.data_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -994,14 +968,10 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) {
|
||||
NetEqOutputType type;
|
||||
// Set all of |out_data_| to 1, and verify that it was set to 0 by the call
|
||||
// to GetAudio.
|
||||
for (size_t i = 0; i < kMaxBlockSize; ++i) {
|
||||
out_data_[i] = 1;
|
||||
for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) {
|
||||
out_frame_.data_[i] = 1;
|
||||
}
|
||||
size_t num_channels;
|
||||
size_t samples_per_channel;
|
||||
EXPECT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_,
|
||||
&samples_per_channel,
|
||||
&num_channels, &type));
|
||||
EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
// Verify that the first block of samples is set to 0.
|
||||
static const int kExpectedOutputLength =
|
||||
kInitSampleRateHz / 100; // 10 ms at initial sample rate.
|
||||
@ -1009,7 +979,7 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) {
|
||||
std::ostringstream ss;
|
||||
ss << "i = " << i;
|
||||
SCOPED_TRACE(ss.str()); // Print out the parameter values on failure.
|
||||
EXPECT_EQ(0, out_data_[i]);
|
||||
EXPECT_EQ(0, out_frame_.data_[i]);
|
||||
}
|
||||
// Verify that the sample rate did not change from the initial configuration.
|
||||
EXPECT_EQ(config_.sample_rate_hz, neteq_->last_output_sample_rate_hz());
|
||||
@ -1037,7 +1007,7 @@ class NetEqBgnTest : public NetEqDecodingTest {
|
||||
}
|
||||
|
||||
NetEqOutputType type;
|
||||
int16_t output[kBlockSize32kHz]; // Maximum size is chosen.
|
||||
AudioFrame output;
|
||||
test::AudioLoop input;
|
||||
// We are using the same 32 kHz input file for all tests, regardless of
|
||||
// |sampling_rate_hz|. The output may sound weird, but the test is still
|
||||
@ -1053,9 +1023,6 @@ class NetEqBgnTest : public NetEqDecodingTest {
|
||||
PopulateRtpInfo(0, 0, &rtp_info);
|
||||
rtp_info.header.payloadType = payload_type;
|
||||
|
||||
size_t number_channels = 0;
|
||||
size_t samples_per_channel = 0;
|
||||
|
||||
uint32_t receive_timestamp = 0;
|
||||
for (int n = 0; n < 10; ++n) { // Insert few packets and get audio.
|
||||
auto block = input.GetNextBlock();
|
||||
@ -1064,19 +1031,13 @@ class NetEqBgnTest : public NetEqDecodingTest {
|
||||
WebRtcPcm16b_Encode(block.data(), block.size(), payload);
|
||||
ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2);
|
||||
|
||||
number_channels = 0;
|
||||
samples_per_channel = 0;
|
||||
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
|
||||
payload, enc_len_bytes),
|
||||
receive_timestamp));
|
||||
ASSERT_EQ(0,
|
||||
neteq_->GetAudio(kBlockSize32kHz,
|
||||
output,
|
||||
&samples_per_channel,
|
||||
&number_channels,
|
||||
&type));
|
||||
ASSERT_EQ(1u, number_channels);
|
||||
ASSERT_EQ(expected_samples_per_channel, samples_per_channel);
|
||||
output.Reset();
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&output, &type));
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_);
|
||||
ASSERT_EQ(kOutputNormal, type);
|
||||
|
||||
// Next packet.
|
||||
@ -1085,20 +1046,14 @@ class NetEqBgnTest : public NetEqDecodingTest {
|
||||
receive_timestamp += expected_samples_per_channel;
|
||||
}
|
||||
|
||||
number_channels = 0;
|
||||
samples_per_channel = 0;
|
||||
output.Reset();
|
||||
|
||||
// Get audio without inserting packets, expecting PLC and PLC-to-CNG. Pull
|
||||
// one frame without checking speech-type. This is the first frame pulled
|
||||
// without inserting any packet, and might not be labeled as PLC.
|
||||
ASSERT_EQ(0,
|
||||
neteq_->GetAudio(kBlockSize32kHz,
|
||||
output,
|
||||
&samples_per_channel,
|
||||
&number_channels,
|
||||
&type));
|
||||
ASSERT_EQ(1u, number_channels);
|
||||
ASSERT_EQ(expected_samples_per_channel, samples_per_channel);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&output, &type));
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_);
|
||||
|
||||
// To be able to test the fading of background noise we need at lease to
|
||||
// pull 611 frames.
|
||||
@ -1109,22 +1064,17 @@ class NetEqBgnTest : public NetEqDecodingTest {
|
||||
const int kNumPlcToCngTestFrames = 20;
|
||||
bool plc_to_cng = false;
|
||||
for (int n = 0; n < kFadingThreshold + kNumPlcToCngTestFrames; ++n) {
|
||||
number_channels = 0;
|
||||
samples_per_channel = 0;
|
||||
memset(output, 1, sizeof(output)); // Set to non-zero.
|
||||
ASSERT_EQ(0,
|
||||
neteq_->GetAudio(kBlockSize32kHz,
|
||||
output,
|
||||
&samples_per_channel,
|
||||
&number_channels,
|
||||
&type));
|
||||
ASSERT_EQ(1u, number_channels);
|
||||
ASSERT_EQ(expected_samples_per_channel, samples_per_channel);
|
||||
output.Reset();
|
||||
memset(output.data_, 1, sizeof(output.data_)); // Set to non-zero.
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&output, &type));
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_);
|
||||
if (type == kOutputPLCtoCNG) {
|
||||
plc_to_cng = true;
|
||||
double sum_squared = 0;
|
||||
for (size_t k = 0; k < number_channels * samples_per_channel; ++k)
|
||||
sum_squared += output[k] * output[k];
|
||||
for (size_t k = 0;
|
||||
k < output.num_channels_ * output.samples_per_channel_; ++k)
|
||||
sum_squared += output.data_[k] * output.data_[k];
|
||||
TestCondition(sum_squared, n > kFadingThreshold);
|
||||
} else {
|
||||
EXPECT_EQ(kOutputPLC, type);
|
||||
@ -1282,7 +1232,7 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) {
|
||||
PopulateRtpInfo(0, 0, &rtp_info);
|
||||
const size_t kPayloadBytes = kBlockSize16kHz * sizeof(int16_t);
|
||||
uint8_t payload[kPayloadBytes];
|
||||
int16_t decoded[kBlockSize16kHz];
|
||||
AudioFrame output;
|
||||
int algorithmic_frame_delay = algorithmic_delay_ms_ / 10 + 1;
|
||||
for (size_t n = 0; n < kPayloadBytes; ++n) {
|
||||
payload[n] = (rand() & 0xF0) + 1; // Non-zero random sequence.
|
||||
@ -1290,16 +1240,12 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) {
|
||||
// Insert some packets which decode to noise. We are not interested in
|
||||
// actual decoded values.
|
||||
NetEqOutputType output_type;
|
||||
size_t num_channels;
|
||||
size_t samples_per_channel;
|
||||
uint32_t receive_timestamp = 0;
|
||||
for (int n = 0; n < 100; ++n) {
|
||||
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp));
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
|
||||
&samples_per_channel, &num_channels,
|
||||
&output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
|
||||
ASSERT_EQ(1u, num_channels);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_);
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
|
||||
rtp_info.header.sequenceNumber++;
|
||||
rtp_info.header.timestamp += kBlockSize16kHz;
|
||||
@ -1313,13 +1259,12 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) {
|
||||
// Insert sync-packets, the decoded sequence should be all-zero.
|
||||
for (int n = 0; n < kNumSyncPackets; ++n) {
|
||||
ASSERT_EQ(0, neteq_->InsertSyncPacket(rtp_info, receive_timestamp));
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
|
||||
&samples_per_channel, &num_channels,
|
||||
&output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
|
||||
ASSERT_EQ(1u, num_channels);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_);
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
if (n > algorithmic_frame_delay) {
|
||||
EXPECT_TRUE(IsAllZero(decoded, samples_per_channel * num_channels));
|
||||
EXPECT_TRUE(IsAllZero(
|
||||
output.data_, output.samples_per_channel_ * output.num_channels_));
|
||||
}
|
||||
rtp_info.header.sequenceNumber++;
|
||||
rtp_info.header.timestamp += kBlockSize16kHz;
|
||||
@ -1330,12 +1275,11 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) {
|
||||
// network statistics would show some packet loss.
|
||||
for (int n = 0; n <= algorithmic_frame_delay + 10; ++n) {
|
||||
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp));
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
|
||||
&samples_per_channel, &num_channels,
|
||||
&output_type));
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type));
|
||||
if (n >= algorithmic_frame_delay + 1) {
|
||||
// Expect that this frame contain samples from regular RTP.
|
||||
EXPECT_TRUE(IsAllNonZero(decoded, samples_per_channel * num_channels));
|
||||
EXPECT_TRUE(IsAllNonZero(
|
||||
output.data_, output.samples_per_channel_ * output.num_channels_));
|
||||
}
|
||||
rtp_info.header.sequenceNumber++;
|
||||
rtp_info.header.timestamp += kBlockSize16kHz;
|
||||
@ -1359,24 +1303,20 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) {
|
||||
PopulateRtpInfo(0, 0, &rtp_info);
|
||||
const size_t kPayloadBytes = kBlockSize16kHz * sizeof(int16_t);
|
||||
uint8_t payload[kPayloadBytes];
|
||||
int16_t decoded[kBlockSize16kHz];
|
||||
AudioFrame output;
|
||||
for (size_t n = 0; n < kPayloadBytes; ++n) {
|
||||
payload[n] = (rand() & 0xF0) + 1; // Non-zero random sequence.
|
||||
}
|
||||
// Insert some packets which decode to noise. We are not interested in
|
||||
// actual decoded values.
|
||||
NetEqOutputType output_type;
|
||||
size_t num_channels;
|
||||
size_t samples_per_channel;
|
||||
uint32_t receive_timestamp = 0;
|
||||
int algorithmic_frame_delay = algorithmic_delay_ms_ / 10 + 1;
|
||||
for (int n = 0; n < algorithmic_frame_delay; ++n) {
|
||||
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp));
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
|
||||
&samples_per_channel, &num_channels,
|
||||
&output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
|
||||
ASSERT_EQ(1u, num_channels);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_);
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
rtp_info.header.sequenceNumber++;
|
||||
rtp_info.header.timestamp += kBlockSize16kHz;
|
||||
receive_timestamp += kBlockSize16kHz;
|
||||
@ -1411,12 +1351,11 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) {
|
||||
|
||||
// Decode.
|
||||
for (int n = 0; n < kNumSyncPackets; ++n) {
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
|
||||
&samples_per_channel, &num_channels,
|
||||
&output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
|
||||
ASSERT_EQ(1u, num_channels);
|
||||
EXPECT_TRUE(IsAllNonZero(decoded, samples_per_channel * num_channels));
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_);
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
EXPECT_TRUE(IsAllNonZero(
|
||||
output.data_, output.samples_per_channel_ * output.num_channels_));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1432,10 +1371,6 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no,
|
||||
const int kSamples = kBlockSize16kHz * kBlocksPerFrame;
|
||||
const size_t kPayloadBytes = kSamples * sizeof(int16_t);
|
||||
double next_input_time_ms = 0.0;
|
||||
int16_t decoded[kBlockSize16kHz];
|
||||
size_t num_channels;
|
||||
size_t samples_per_channel;
|
||||
NetEqOutputType output_type;
|
||||
uint32_t receive_timestamp = 0;
|
||||
|
||||
// Insert speech for 2 seconds.
|
||||
@ -1482,11 +1417,11 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no,
|
||||
timestamp_wrapped |= timestamp < last_timestamp;
|
||||
}
|
||||
// Pull out data once.
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded,
|
||||
&samples_per_channel, &num_channels,
|
||||
&output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, samples_per_channel);
|
||||
ASSERT_EQ(1u, num_channels);
|
||||
AudioFrame output;
|
||||
NetEqOutputType output_type;
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&output, &output_type));
|
||||
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_);
|
||||
ASSERT_EQ(1u, output.num_channels_);
|
||||
|
||||
// Expect delay (in samples) to be less than 2 packets.
|
||||
EXPECT_LE(timestamp - PlayoutTimestamp(),
|
||||
@ -1536,8 +1471,6 @@ void NetEqDecodingTest::DuplicateCng() {
|
||||
algorithmic_delay_ms_ * kSampleRateKhz, 5 * kSampleRateKhz / 8);
|
||||
// Insert three speech packets. Three are needed to get the frame length
|
||||
// correct.
|
||||
size_t out_len;
|
||||
size_t num_channels;
|
||||
NetEqOutputType type;
|
||||
uint8_t payload[kPayloadBytes] = {0};
|
||||
WebRtcRTPHeader rtp_info;
|
||||
@ -1548,10 +1481,8 @@ void NetEqDecodingTest::DuplicateCng() {
|
||||
timestamp += kSamples;
|
||||
|
||||
// Pull audio once.
|
||||
ASSERT_EQ(0,
|
||||
neteq_->GetAudio(
|
||||
kMaxBlockSize, out_data_, &out_len, &num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
}
|
||||
// Verify speech output.
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
@ -1567,10 +1498,8 @@ void NetEqDecodingTest::DuplicateCng() {
|
||||
rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0));
|
||||
|
||||
// Pull audio once and make sure CNG is played.
|
||||
ASSERT_EQ(0,
|
||||
neteq_->GetAudio(
|
||||
kMaxBlockSize, out_data_, &out_len, &num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
EXPECT_EQ(kOutputCNG, type);
|
||||
EXPECT_EQ(timestamp - algorithmic_delay_samples, PlayoutTimestamp());
|
||||
|
||||
@ -1583,10 +1512,8 @@ void NetEqDecodingTest::DuplicateCng() {
|
||||
// Pull audio until we have played |kCngPeriodMs| of CNG. Start at 10 ms since
|
||||
// we have already pulled out CNG once.
|
||||
for (int cng_time_ms = 10; cng_time_ms < kCngPeriodMs; cng_time_ms += 10) {
|
||||
ASSERT_EQ(0,
|
||||
neteq_->GetAudio(
|
||||
kMaxBlockSize, out_data_, &out_len, &num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
EXPECT_EQ(kOutputCNG, type);
|
||||
EXPECT_EQ(timestamp - algorithmic_delay_samples,
|
||||
PlayoutTimestamp());
|
||||
@ -1599,10 +1526,8 @@ void NetEqDecodingTest::DuplicateCng() {
|
||||
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0));
|
||||
|
||||
// Pull audio once and verify that the output is speech again.
|
||||
ASSERT_EQ(0,
|
||||
neteq_->GetAudio(
|
||||
kMaxBlockSize, out_data_, &out_len, &num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
EXPECT_EQ(timestamp + kSamples - algorithmic_delay_samples,
|
||||
PlayoutTimestamp());
|
||||
@ -1639,12 +1564,9 @@ TEST_F(NetEqDecodingTest, CngFirst) {
|
||||
timestamp += kCngPeriodSamples;
|
||||
|
||||
// Pull audio once and make sure CNG is played.
|
||||
size_t out_len;
|
||||
size_t num_channels;
|
||||
NetEqOutputType type;
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
|
||||
&num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
EXPECT_EQ(kOutputCNG, type);
|
||||
|
||||
// Insert some speech packets.
|
||||
@ -1655,9 +1577,8 @@ TEST_F(NetEqDecodingTest, CngFirst) {
|
||||
timestamp += kSamples;
|
||||
|
||||
// Pull audio once.
|
||||
ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len,
|
||||
&num_channels, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_len);
|
||||
ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &type));
|
||||
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_);
|
||||
}
|
||||
// Verify speech output.
|
||||
EXPECT_EQ(kOutputNormal, type);
|
||||
|
||||
@ -8,10 +8,9 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <algorithm> // Access to min.
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/sync_buffer.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -71,16 +70,18 @@ void SyncBuffer::ReplaceAtIndex(const AudioMultiVector& insert_this,
|
||||
ReplaceAtIndex(insert_this, insert_this.Size(), position);
|
||||
}
|
||||
|
||||
size_t SyncBuffer::GetNextAudioInterleaved(size_t requested_len,
|
||||
int16_t* output) {
|
||||
if (!output) {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
size_t samples_to_read = std::min(FutureLength(), requested_len);
|
||||
ReadInterleavedFromIndex(next_index_, samples_to_read, output);
|
||||
next_index_ += samples_to_read;
|
||||
return samples_to_read;
|
||||
void SyncBuffer::GetNextAudioInterleaved(size_t requested_len,
|
||||
AudioFrame* output) {
|
||||
RTC_DCHECK(output);
|
||||
const size_t samples_to_read = std::min(FutureLength(), requested_len);
|
||||
output->Reset();
|
||||
const size_t tot_samples_read =
|
||||
ReadInterleavedFromIndex(next_index_, samples_to_read, output->data_);
|
||||
const size_t samples_read_per_channel = tot_samples_read / Channels();
|
||||
next_index_ += samples_read_per_channel;
|
||||
output->interleaved_ = true;
|
||||
output->num_channels_ = Channels();
|
||||
output->samples_per_channel_ = samples_read_per_channel;
|
||||
}
|
||||
|
||||
void SyncBuffer::IncreaseEndTimestamp(uint32_t increment) {
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/audio_multi_vector.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -65,8 +66,10 @@ class SyncBuffer : public AudioMultiVector {
|
||||
|
||||
// Reads |requested_len| samples from each channel and writes them interleaved
|
||||
// into |output|. The |next_index_| is updated to point to the sample to read
|
||||
// next time.
|
||||
size_t GetNextAudioInterleaved(size_t requested_len, int16_t* output);
|
||||
// next time. The AudioFrame |output| is first reset, and the |data_|,
|
||||
// |interleaved_|, |num_channels_|, and |samples_per_channel_| fields are
|
||||
// updated.
|
||||
void GetNextAudioInterleaved(size_t requested_len, AudioFrame* output);
|
||||
|
||||
// Adds |increment| to |end_timestamp_|.
|
||||
void IncreaseEndTimestamp(uint32_t increment);
|
||||
|
||||
@ -140,20 +140,29 @@ TEST(SyncBuffer, GetNextAudioInterleaved) {
|
||||
|
||||
// Read to interleaved output. Read in two batches, where each read operation
|
||||
// should automatically update the |net_index_| in the SyncBuffer.
|
||||
int16_t output[kChannels * kNewLen];
|
||||
// Note that |samples_read| is the number of samples read from each channel.
|
||||
// That is, the number of samples written to |output| is
|
||||
// |samples_read| * |kChannels|.
|
||||
size_t samples_read = sync_buffer.GetNextAudioInterleaved(kNewLen / 2,
|
||||
output);
|
||||
samples_read +=
|
||||
sync_buffer.GetNextAudioInterleaved(kNewLen / 2,
|
||||
&output[samples_read * kChannels]);
|
||||
EXPECT_EQ(kNewLen, samples_read);
|
||||
AudioFrame output1;
|
||||
sync_buffer.GetNextAudioInterleaved(kNewLen / 2, &output1);
|
||||
EXPECT_EQ(kChannels, output1.num_channels_);
|
||||
EXPECT_EQ(kNewLen / 2, output1.samples_per_channel_);
|
||||
|
||||
AudioFrame output2;
|
||||
sync_buffer.GetNextAudioInterleaved(kNewLen / 2, &output2);
|
||||
EXPECT_EQ(kChannels, output2.num_channels_);
|
||||
EXPECT_EQ(kNewLen / 2, output2.samples_per_channel_);
|
||||
|
||||
// Verify the data.
|
||||
int16_t* output_ptr = output;
|
||||
for (size_t i = 0; i < kNewLen; ++i) {
|
||||
int16_t* output_ptr = output1.data_;
|
||||
for (size_t i = 0; i < kNewLen / 2; ++i) {
|
||||
for (size_t channel = 0; channel < kChannels; ++channel) {
|
||||
EXPECT_EQ(new_data[channel][i], *output_ptr);
|
||||
++output_ptr;
|
||||
}
|
||||
}
|
||||
output_ptr = output2.data_;
|
||||
for (size_t i = kNewLen / 2; i < kNewLen; ++i) {
|
||||
for (size_t channel = 0; channel < kChannels; ++channel) {
|
||||
EXPECT_EQ(new_data[channel][i], *output_ptr);
|
||||
++output_ptr;
|
||||
|
||||
@ -43,23 +43,14 @@ void NetEqExternalDecoderTest::InsertPacket(
|
||||
neteq_->InsertPacket(rtp_header, payload, receive_timestamp));
|
||||
}
|
||||
|
||||
size_t NetEqExternalDecoderTest::GetOutputAudio(size_t max_length,
|
||||
int16_t* output,
|
||||
NetEqOutputType* output_type) {
|
||||
void NetEqExternalDecoderTest::GetOutputAudio(AudioFrame* output,
|
||||
NetEqOutputType* output_type) {
|
||||
// Get audio from regular instance.
|
||||
size_t samples_per_channel;
|
||||
size_t num_channels;
|
||||
EXPECT_EQ(NetEq::kOK,
|
||||
neteq_->GetAudio(max_length,
|
||||
output,
|
||||
&samples_per_channel,
|
||||
&num_channels,
|
||||
output_type));
|
||||
EXPECT_EQ(channels_, num_channels);
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(output, output_type));
|
||||
EXPECT_EQ(channels_, output->num_channels_);
|
||||
EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * sample_rate_hz_ / 1000),
|
||||
samples_per_channel);
|
||||
output->samples_per_channel_);
|
||||
EXPECT_EQ(sample_rate_hz_, neteq_->last_output_sample_rate_hz());
|
||||
return samples_per_channel;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
@ -42,10 +42,8 @@ class NetEqExternalDecoderTest {
|
||||
rtc::ArrayView<const uint8_t> payload,
|
||||
uint32_t receive_timestamp);
|
||||
|
||||
// Get 10 ms of audio data. The data is written to |output|, which can hold
|
||||
// (at least) |max_length| elements. Returns number of samples.
|
||||
size_t GetOutputAudio(size_t max_length, int16_t* output,
|
||||
NetEqOutputType* output_type);
|
||||
// Get 10 ms of audio data.
|
||||
void GetOutputAudio(AudioFrame* output, NetEqOutputType* output_type);
|
||||
|
||||
NetEq* neteq() { return neteq_.get(); }
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "webrtc/modules/audio_coding/neteq/include/neteq.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/system_wrappers/include/clock.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
@ -103,21 +104,15 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms,
|
||||
}
|
||||
|
||||
// Get output audio, but don't do anything with it.
|
||||
static const int kMaxChannels = 1;
|
||||
static const size_t kMaxSamplesPerMs = 48000 / 1000;
|
||||
static const int kOutputBlockSizeMs = 10;
|
||||
static const size_t kOutDataLen =
|
||||
kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels;
|
||||
int16_t out_data[kOutDataLen];
|
||||
size_t num_channels;
|
||||
size_t samples_per_channel;
|
||||
int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel,
|
||||
&num_channels, NULL);
|
||||
AudioFrame out_frame;
|
||||
int error = neteq->GetAudio(&out_frame, NULL);
|
||||
if (error != NetEq::kOK)
|
||||
return -1;
|
||||
|
||||
assert(samples_per_channel == static_cast<size_t>(kSampRateHz * 10 / 1000));
|
||||
assert(out_frame.samples_per_channel_ ==
|
||||
static_cast<size_t>(kSampRateHz * 10 / 1000));
|
||||
|
||||
static const int kOutputBlockSizeMs = 10;
|
||||
time_now_ms += kOutputBlockSizeMs;
|
||||
if (time_now_ms >= runtime_ms / 2 && !drift_flipped) {
|
||||
// Apply negative drift second half of simulation.
|
||||
|
||||
@ -220,7 +220,6 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms,
|
||||
out_sampling_khz_(out_sampling_khz),
|
||||
in_size_samples_(
|
||||
static_cast<size_t>(in_sampling_khz_ * block_duration_ms_)),
|
||||
out_size_samples_(static_cast<size_t>(out_sampling_khz_ * kOutputSizeMs)),
|
||||
payload_size_bytes_(0),
|
||||
max_payload_bytes_(0),
|
||||
in_file_(new ResampleInputAudioFile(FLAGS_in_filename,
|
||||
@ -249,7 +248,6 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms,
|
||||
neteq_.reset(NetEq::Create(config));
|
||||
max_payload_bytes_ = in_size_samples_ * channels_ * sizeof(int16_t);
|
||||
in_data_.reset(new int16_t[in_size_samples_ * channels_]);
|
||||
out_data_.reset(new int16_t[out_size_samples_ * channels_]);
|
||||
}
|
||||
|
||||
NetEqQualityTest::~NetEqQualityTest() {
|
||||
@ -393,18 +391,18 @@ int NetEqQualityTest::Transmit() {
|
||||
}
|
||||
|
||||
int NetEqQualityTest::DecodeBlock() {
|
||||
size_t channels;
|
||||
size_t samples;
|
||||
int ret = neteq_->GetAudio(out_size_samples_ * channels_, &out_data_[0],
|
||||
&samples, &channels, NULL);
|
||||
int ret = neteq_->GetAudio(&out_frame_, NULL);
|
||||
|
||||
if (ret != NetEq::kOK) {
|
||||
return -1;
|
||||
} else {
|
||||
assert(channels == channels_);
|
||||
assert(samples == static_cast<size_t>(kOutputSizeMs * out_sampling_khz_));
|
||||
RTC_CHECK(output_->WriteArray(out_data_.get(), samples * channels));
|
||||
return static_cast<int>(samples);
|
||||
RTC_DCHECK_EQ(out_frame_.num_channels_, channels_);
|
||||
RTC_DCHECK_EQ(out_frame_.samples_per_channel_,
|
||||
static_cast<size_t>(kOutputSizeMs * out_sampling_khz_));
|
||||
RTC_CHECK(output_->WriteArray(
|
||||
out_frame_.data_,
|
||||
out_frame_.samples_per_channel_ * out_frame_.num_channels_));
|
||||
return static_cast<int>(out_frame_.samples_per_channel_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
using google::RegisterFlagValidator;
|
||||
@ -113,9 +114,6 @@ class NetEqQualityTest : public ::testing::Test {
|
||||
// Number of samples per channel in a frame.
|
||||
const size_t in_size_samples_;
|
||||
|
||||
// Expected output number of samples per channel in a frame.
|
||||
const size_t out_size_samples_;
|
||||
|
||||
size_t payload_size_bytes_;
|
||||
size_t max_payload_bytes_;
|
||||
|
||||
@ -129,7 +127,7 @@ class NetEqQualityTest : public ::testing::Test {
|
||||
|
||||
std::unique_ptr<int16_t[]> in_data_;
|
||||
rtc::Buffer payload_;
|
||||
std::unique_ptr<int16_t[]> out_data_;
|
||||
AudioFrame out_frame_;
|
||||
WebRtcRTPHeader rtp_header_;
|
||||
|
||||
size_t total_payload_size_bytes_;
|
||||
|
||||
@ -382,8 +382,6 @@ size_t ReplacePayload(webrtc::test::InputAudioFile* replacement_audio_file,
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
static const int kMaxChannels = 5;
|
||||
static const size_t kMaxSamplesPerMs = 48000 / 1000;
|
||||
static const int kOutputBlockSizeMs = 10;
|
||||
|
||||
std::string program_name = argv[0];
|
||||
@ -606,26 +604,19 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Check if it is time to get output audio.
|
||||
while (time_now_ms >= next_output_time_ms && output_event_available) {
|
||||
static const size_t kOutDataLen =
|
||||
kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels;
|
||||
int16_t out_data[kOutDataLen];
|
||||
size_t num_channels;
|
||||
size_t samples_per_channel;
|
||||
int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel,
|
||||
&num_channels, NULL);
|
||||
webrtc::AudioFrame out_frame;
|
||||
int error = neteq->GetAudio(&out_frame, NULL);
|
||||
if (error != NetEq::kOK) {
|
||||
std::cerr << "GetAudio returned error code " <<
|
||||
neteq->LastError() << std::endl;
|
||||
} else {
|
||||
// Calculate sample rate from output size.
|
||||
sample_rate_hz = rtc::checked_cast<int>(
|
||||
1000 * samples_per_channel / kOutputBlockSizeMs);
|
||||
sample_rate_hz = out_frame.sample_rate_hz_;
|
||||
}
|
||||
|
||||
// Write to file.
|
||||
// TODO(hlundin): Make writing to file optional.
|
||||
size_t write_len = samples_per_channel * num_channels;
|
||||
if (!output->WriteArray(out_data, write_len)) {
|
||||
if (!output->WriteArray(out_frame.data_, out_frame.samples_per_channel_ *
|
||||
out_frame.num_channels_)) {
|
||||
std::cerr << "Error while writing to file" << std::endl;
|
||||
webrtc::Trace::ReturnTrace();
|
||||
exit(1);
|
||||
|
||||
Reference in New Issue
Block a user