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:
niklas.enbom@webrtc.org 2013-01-24 18:53:43 +00:00
parent 4782911572
commit 05e7bfeeea
12 changed files with 277 additions and 16 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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',

View 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

View 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_

View 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

View 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_

View File

@ -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);

View File

@ -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