Mainly hlundin's patch.
Review URL: https://webrtc-codereview.appspot.com/1052004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3405 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
4782911572
commit
05e7bfeeea
@ -223,7 +223,7 @@ WebRtc_Word16 ACMNetEQ::AllocatePacketBufferByIdxSafe(
|
||||
}
|
||||
if (WebRtcNetEQ_GetRecommendedBufferSize(inst_[idx], used_codecs,
|
||||
num_codecs,
|
||||
kTCPLargeJitter,
|
||||
kTCPXLargeJitter,
|
||||
&max_num_packets,
|
||||
&buffer_size_in_bytes) != 0) {
|
||||
LogError("GetRecommendedBufferSize", idx);
|
||||
|
@ -2084,9 +2084,9 @@ int AudioCodingModuleImpl::InitStereoSlave() {
|
||||
// Minimum playout delay (Used for lip-sync).
|
||||
WebRtc_Word32 AudioCodingModuleImpl::SetMinimumPlayoutDelay(
|
||||
const WebRtc_Word32 time_ms) {
|
||||
if ((time_ms < 0) || (time_ms > 1000)) {
|
||||
if ((time_ms < 0) || (time_ms > 10000)) {
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
|
||||
"Delay must be in the range of 0-1000 milliseconds.");
|
||||
"Delay must be in the range of 0-10000 milliseconds.");
|
||||
return -1;
|
||||
}
|
||||
return neteq_.SetExtraDelay(time_ms);
|
||||
|
@ -216,7 +216,7 @@ int WebRtcNetEQ_UpdateIatStatistics(AutomodeInst_t *inst, int maxBufLen,
|
||||
streamingMode);
|
||||
if (tempvar > 0)
|
||||
{
|
||||
inst->optBufLevel = (WebRtc_UWord16) tempvar;
|
||||
inst->optBufLevel = tempvar;
|
||||
|
||||
if (streamingMode != 0)
|
||||
{
|
||||
@ -575,7 +575,7 @@ int WebRtcNetEQ_BufferLevelFilter(WebRtc_Word32 curSizeMs8, AutomodeInst_t *inst
|
||||
*
|
||||
* levelFiltFact is in Q8
|
||||
*/
|
||||
inst->buffLevelFilt = (WebRtc_UWord16) (WEBRTC_SPL_RSHIFT_W32(
|
||||
inst->buffLevelFilt = (WEBRTC_SPL_RSHIFT_W32(
|
||||
WEBRTC_SPL_MUL_16_U16(inst->levelFiltFact, inst->buffLevelFilt), 8)
|
||||
+ WEBRTC_SPL_MUL_16_16(256 - inst->levelFiltFact, curSizeFrames));
|
||||
}
|
||||
@ -589,7 +589,7 @@ int WebRtcNetEQ_BufferLevelFilter(WebRtc_Word32 curSizeMs8, AutomodeInst_t *inst
|
||||
* from samples to packets in Q8. Make sure that the filtered value is
|
||||
* non-negative.
|
||||
*/
|
||||
inst->buffLevelFilt = (WebRtc_UWord16) WEBRTC_SPL_MAX( inst->buffLevelFilt -
|
||||
inst->buffLevelFilt = WEBRTC_SPL_MAX( inst->buffLevelFilt -
|
||||
WebRtcSpl_DivW32W16(
|
||||
WEBRTC_SPL_LSHIFT_W32(inst->sampleMemory, 8), /* sampleMemory in Q8 */
|
||||
inst->packetSpeechLenSamp ), /* divide by packetSpeechLenSamp */
|
||||
|
@ -65,14 +65,14 @@ typedef struct
|
||||
|
||||
/* Filtered current buffer level */
|
||||
WebRtc_UWord16 levelFiltFact; /* filter forgetting factor in Q8 */
|
||||
WebRtc_UWord16 buffLevelFilt; /* filtered buffer level in Q8 */
|
||||
int buffLevelFilt; /* filtered buffer level in Q8 */
|
||||
|
||||
/* Inter-arrival time (iat) statistics */
|
||||
WebRtc_Word32 iatProb[MAX_IAT + 1]; /* iat probabilities in Q30 */
|
||||
WebRtc_Word16 iatProbFact; /* iat forgetting factor in Q15 */
|
||||
WebRtc_UWord32 packetIatCountSamp; /* time (in timestamps) elapsed since last
|
||||
packet arrival, based on RecOut calls */
|
||||
WebRtc_UWord16 optBufLevel; /* current optimal buffer level in Q8 */
|
||||
int optBufLevel; /* current optimal buffer level in Q8 */
|
||||
|
||||
/* Packet related information */
|
||||
WebRtc_Word16 packetSpeechLenSamp; /* speech samples per incoming packet */
|
||||
|
@ -38,11 +38,11 @@ WebRtc_UWord16 WebRtcNetEQ_BufstatsDecision(BufstatsInst_t *inst, WebRtc_Word16
|
||||
|
||||
int currentDelayMs;
|
||||
WebRtc_Word32 currSizeSamples = cur_size;
|
||||
WebRtc_Word16 extraDelayPacketsQ8 = 0;
|
||||
int extraDelayPacketsQ8 = 0;
|
||||
|
||||
/* Avoid overflow if the buffer size should be really large (cur_size is limited 256ms) */
|
||||
WebRtc_Word32 curr_sizeQ7 = WEBRTC_SPL_LSHIFT_W32(cur_size, 4);
|
||||
WebRtc_UWord16 level_limit_hi, level_limit_lo;
|
||||
int level_limit_hi, level_limit_lo;
|
||||
|
||||
inst->Automode_inst.prevTimeScale &= (prevPlayMode == MODE_SUCCESS_ACCELERATE
|
||||
|| prevPlayMode == MODE_LOWEN_ACCELERATE || prevPlayMode == MODE_SUCCESS_PREEMPTIVE
|
||||
@ -167,10 +167,11 @@ WebRtc_UWord16 WebRtcNetEQ_BufstatsDecision(BufstatsInst_t *inst, WebRtc_Word16
|
||||
if (inst->Automode_inst.extraDelayMs > 0 && inst->Automode_inst.packetSpeechLenSamp
|
||||
> 0)
|
||||
{
|
||||
extraDelayPacketsQ8 = WebRtcSpl_DivW32W16ResW16(
|
||||
(WEBRTC_SPL_MUL(inst->Automode_inst.extraDelayMs, 8 * fs_mult) << 8),
|
||||
inst->Automode_inst.packetSpeechLenSamp);
|
||||
|
||||
/* (extra delay in samples in Q8) */
|
||||
extraDelayPacketsQ8 =
|
||||
((inst->Automode_inst.extraDelayMs * 8 * fs_mult) << 8) /
|
||||
inst->Automode_inst.packetSpeechLenSamp;
|
||||
}
|
||||
|
||||
/* Check if needed packet is available */
|
||||
|
@ -93,6 +93,7 @@
|
||||
'dependencies': [
|
||||
'NetEq',
|
||||
'NetEqTestTools',
|
||||
'neteq_unittest_tools',
|
||||
'<(DEPTH)/testing/gtest.gyp:gtest',
|
||||
'<(webrtc_root)/test/test.gyp:test_support_main',
|
||||
],
|
||||
@ -100,6 +101,31 @@
|
||||
'webrtc_neteq_unittest.cc',
|
||||
],
|
||||
}, # neteq_unittests
|
||||
|
||||
{
|
||||
'target_name': 'neteq_unittest_tools',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'<(DEPTH)/testing/gmock.gyp:gmock',
|
||||
'<(DEPTH)/testing/gtest.gyp:gtest',
|
||||
'<(webrtc_root)/test/test.gyp:test_support_main',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'tools',
|
||||
],
|
||||
},
|
||||
'include_dirs': [
|
||||
'tools',
|
||||
],
|
||||
'sources': [
|
||||
'tools/input_audio_file.cc',
|
||||
'tools/input_audio_file.h',
|
||||
'tools/rtp_generator.cc',
|
||||
'tools/rtp_generator.h',
|
||||
],
|
||||
}, # neteq_unittest_tools
|
||||
|
||||
{
|
||||
'target_name': 'NetEqRTPplay',
|
||||
'type': 'executable',
|
||||
|
45
webrtc/modules/audio_coding/neteq/tools/input_audio_file.cc
Normal file
45
webrtc/modules/audio_coding/neteq/tools/input_audio_file.cc
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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/neteq/tools/input_audio_file.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
bool InputAudioFile::Read(size_t samples, int16_t* destination) {
|
||||
if (!fp_) {
|
||||
return false;
|
||||
}
|
||||
size_t bytes_read = fread(destination, sizeof(int16_t), samples, fp_);
|
||||
if (bytes_read < samples) {
|
||||
// Rewind and read the missing sampels.
|
||||
rewind(fp_);
|
||||
size_t missing_samples = samples - bytes_read;
|
||||
if (fread(destination, sizeof(int16_t), missing_samples, fp_) <
|
||||
missing_samples) {
|
||||
// Could not read enough even after rewinding the file.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputAudioFile::DuplicateInterleaved(const int16_t* source, size_t samples,
|
||||
size_t channels,
|
||||
int16_t* destination) {
|
||||
for (size_t i = 0; i < samples; ++i) {
|
||||
for (size_t j = 0; j < channels; ++j) {
|
||||
destination[i * channels + j] = source[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
54
webrtc/modules/audio_coding/neteq/tools/input_audio_file.h
Normal file
54
webrtc/modules/audio_coding/neteq/tools/input_audio_file.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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_NETEQ_TOOLS_INPUT_AUDIO_FILE_H_
|
||||
#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_INPUT_AUDIO_FILE_H_
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
// Class for handling a looping input audio file.
|
||||
class InputAudioFile {
|
||||
public:
|
||||
explicit InputAudioFile(const std::string file_name) {
|
||||
fp_ = fopen(file_name.c_str(), "rb");
|
||||
}
|
||||
|
||||
virtual ~InputAudioFile() {
|
||||
fclose(fp_);
|
||||
}
|
||||
|
||||
// Reads |samples| elements from source file to |destination|. Returns true
|
||||
// if the read was successful, otherwise false. If the file end is reached,
|
||||
// the file is rewound and reading continues from the beginning.
|
||||
// The output |destination| must have the capacity to hold |samples| elements.
|
||||
bool Read(size_t samples, int16_t* destination);
|
||||
|
||||
// Creates a multi-channel signal from a mono signal. Each sample is repeated
|
||||
// |channels| times to create an interleaved multi-channel signal where all
|
||||
// channels are identical. The output |destination| must have the capacity to
|
||||
// hold samples * channels elements.
|
||||
static void DuplicateInterleaved(const int16_t* source, size_t samples,
|
||||
size_t channels, int16_t* destination);
|
||||
|
||||
private:
|
||||
FILE* fp_;
|
||||
DISALLOW_COPY_AND_ASSIGN(InputAudioFile);
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_INPUT_AUDIO_FILE_H_
|
41
webrtc/modules/audio_coding/neteq/tools/rtp_generator.cc
Normal file
41
webrtc/modules/audio_coding/neteq/tools/rtp_generator.cc
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 <assert.h>
|
||||
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
uint32_t RtpGenerator::GetRtpHeader(uint8_t payload_type,
|
||||
size_t payload_length_samples,
|
||||
WebRtcRTPHeader* rtp_header) {
|
||||
assert(rtp_header);
|
||||
if (!rtp_header) {
|
||||
return 0;
|
||||
}
|
||||
rtp_header->header.sequenceNumber = seq_number_++;
|
||||
rtp_header->header.timestamp = timestamp_;
|
||||
timestamp_ += payload_length_samples;
|
||||
rtp_header->header.payloadType = payload_type;
|
||||
rtp_header->header.markerBit = false;
|
||||
rtp_header->header.ssrc = ssrc_;
|
||||
rtp_header->header.numCSRCs = 0;
|
||||
rtp_header->frameType = kAudioFrameSpeech;
|
||||
|
||||
uint32_t this_send_time = next_send_time_ms_;
|
||||
assert(samples_per_ms_ > 0);
|
||||
next_send_time_ms_ += payload_length_samples / samples_per_ms_;
|
||||
return this_send_time;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
53
webrtc/modules/audio_coding/neteq/tools/rtp_generator.h
Normal file
53
webrtc/modules/audio_coding/neteq/tools/rtp_generator.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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_NETEQ_TOOLS_RTP_GENERATOR_H_
|
||||
#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_RTP_GENERATOR_H_
|
||||
|
||||
#include "webrtc/modules/interface/module_common_types.h"
|
||||
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
// Class for generating RTP headers.
|
||||
class RtpGenerator {
|
||||
public:
|
||||
RtpGenerator(int samples_per_ms,
|
||||
uint16_t start_seq_number = 0,
|
||||
uint32_t start_timestamp = 0,
|
||||
uint32_t start_send_time_ms = 0,
|
||||
uint32_t ssrc = 0x12345678)
|
||||
: seq_number_(start_seq_number),
|
||||
timestamp_(start_timestamp),
|
||||
next_send_time_ms_(start_send_time_ms),
|
||||
ssrc_(ssrc),
|
||||
samples_per_ms_(samples_per_ms) {
|
||||
}
|
||||
|
||||
// Writes the next RTP header to |rtp_header|, wich will be of type
|
||||
// |payload_type|. Returns the send time for this packet (in ms). The value of
|
||||
// |payload_length_samples| determines the send time for the next packet.
|
||||
uint32_t GetRtpHeader(uint8_t payload_type, size_t payload_length_samples,
|
||||
WebRtcRTPHeader* rtp_header);
|
||||
|
||||
private:
|
||||
uint16_t seq_number_;
|
||||
uint32_t timestamp_;
|
||||
uint32_t next_send_time_ms_;
|
||||
const uint32_t ssrc_;
|
||||
const int samples_per_ms_;
|
||||
DISALLOW_COPY_AND_ASSIGN(RtpGenerator);
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_RTP_GENERATOR_H_
|
@ -339,7 +339,7 @@ int WebRtcNetEQ_GetRecommendedBufferSize(void *inst, const enum WebRtcNetEQDecod
|
||||
}
|
||||
else if (nwType == kTCPXLargeJitter)
|
||||
{
|
||||
multiplier = 20;
|
||||
multiplier = 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -514,7 +514,7 @@ int WebRtcNetEQ_SetExtraDelay(void *inst, int DelayInMs)
|
||||
{
|
||||
MainInst_t *NetEqMainInst = (MainInst_t*) inst;
|
||||
if (NetEqMainInst == NULL) return (-1);
|
||||
if ((DelayInMs < 0) || (DelayInMs > 1000))
|
||||
if ((DelayInMs < 0) || (DelayInMs > 10000))
|
||||
{
|
||||
NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
|
||||
return (-1);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "modules/audio_coding/neteq/test/NETEQTEST_CodecClass.h"
|
||||
#include "modules/audio_coding/neteq/test/NETEQTEST_NetEQClass.h"
|
||||
#include "modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
|
||||
#include "testsupport/fileutils.h"
|
||||
#include "typedefs.h" // NOLINT(build/include)
|
||||
|
||||
@ -212,7 +213,7 @@ void NetEqDecodingTest::SetUp() {
|
||||
|
||||
SelectDecoders(usedCodec);
|
||||
neteq_inst_ = new NETEQTEST_NetEQClass(usedCodec, dec_.size(), 8000,
|
||||
kTCPLargeJitter);
|
||||
kTCPXLargeJitter);
|
||||
ASSERT_TRUE(neteq_inst_);
|
||||
LoadDecoders();
|
||||
}
|
||||
@ -651,4 +652,44 @@ TEST_F(NetEqDecodingTest, NoInputDataStereo) {
|
||||
free(ms_info);
|
||||
}
|
||||
|
||||
TEST_F(NetEqDecodingTest, TestExtraDelay) {
|
||||
static const int kNumFrames = 120000; // Needed for convergence.
|
||||
int frame_index = 0;
|
||||
static const int kFrameSizeSamples = 30 * 16;
|
||||
static const int kPayloadBytes = kFrameSizeSamples * 2;
|
||||
test::InputAudioFile input_file(
|
||||
webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"));
|
||||
int16_t input[kFrameSizeSamples];
|
||||
static const int kExtraDelayMs = 5000;
|
||||
ASSERT_EQ(0, WebRtcNetEQ_SetExtraDelay(neteq_inst_->instance(),
|
||||
kExtraDelayMs));
|
||||
for (int i = 0; i < kNumFrames; ++i) {
|
||||
ASSERT_TRUE(input_file.Read(kFrameSizeSamples, input));
|
||||
WebRtcNetEQ_RTPInfo rtp_info;
|
||||
PopulateRtpInfo(frame_index, frame_index * kFrameSizeSamples, &rtp_info);
|
||||
uint8_t* payload = reinterpret_cast<uint8_t*>(input);
|
||||
ASSERT_EQ(0,
|
||||
WebRtcNetEQ_RecInRTPStruct(neteq_inst_->instance(),
|
||||
&rtp_info,
|
||||
payload,
|
||||
kPayloadBytes, 0));
|
||||
++frame_index;
|
||||
// Pull out data.
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
ASSERT_TRUE(kBlockSize16kHz == neteq_inst_->recOut(out_data_));
|
||||
}
|
||||
if (i % 100 == 0) {
|
||||
WebRtcNetEQ_NetworkStatistics network_stats;
|
||||
ASSERT_EQ(0, WebRtcNetEQ_GetNetworkStatistics(neteq_inst_->instance(),
|
||||
&network_stats));
|
||||
const int expected_lower_limit =
|
||||
std::min(i * 0.083 - 210, 0.9 * network_stats.preferredBufferSize);
|
||||
EXPECT_GE(network_stats.currentBufferSize, expected_lower_limit);
|
||||
const int expected_upper_limit =
|
||||
std::min(i * 0.083 + 255, 1.2 * network_stats.preferredBufferSize);
|
||||
EXPECT_LE(network_stats.currentBufferSize, expected_upper_limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Loading…
x
Reference in New Issue
Block a user