Adding two new stats to VoiceReceiverInfo

There have been requests of two new stats namely

speech_expand_rate and secondary_decoded_rate.

BUG=3867
R=henrik.lundin@webrtc.org, henrika@webrtc.org, tommi@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/40789004

Cr-Commit-Position: refs/heads/master@{#8415}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8415 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
minyue@webrtc.org 2015-02-18 15:24:13 +00:00
parent 8fbdcfd73f
commit c0bd7be0df
17 changed files with 100 additions and 85 deletions

View File

@ -779,6 +779,8 @@ struct VoiceReceiverInfo : public MediaReceiverInfo {
delay_estimate_ms(0),
audio_level(0),
expand_rate(0),
speech_expand_rate(0),
secondary_decoded_rate(0),
decoding_calls_to_silence_generator(0),
decoding_calls_to_neteq(0),
decoding_normal(0),
@ -794,8 +796,12 @@ struct VoiceReceiverInfo : public MediaReceiverInfo {
int jitter_buffer_preferred_ms;
int delay_estimate_ms;
int audio_level;
// fraction of synthesized speech inserted through pre-emptive expansion
// fraction of synthesized audio inserted through expansion.
float expand_rate;
// fraction of synthesized speech inserted through expansion.
float speech_expand_rate;
// fraction of data out of secondary decoding, including FEC and RED.
float secondary_decoded_rate;
int decoding_calls_to_silence_generator;
int decoding_calls_to_neteq;
int decoding_normal;

View File

@ -65,6 +65,25 @@ static const int kOpusBandwidthWb = 8000;
static const int kOpusBandwidthSwb = 12000;
static const int kOpusBandwidthFb = 20000;
static const webrtc::NetworkStatistics kNetStats = {
1, // uint16_t currentBufferSize;
2, // uint16_t preferredBufferSize;
true, // bool jitterPeaksFound;
1234, // uint16_t currentPacketLossRate;
567, // uint16_t currentDiscardRate;
8901, // uint16_t currentExpandRate;
234, // uint16_t currentSpeechExpandRate;
5678, // uint16_t currentPreemptiveRate;
9012, // uint16_t currentAccelerateRate;
3456, // uint16_t currentSecondaryDecodedRate;
7890, // int32_t clockDriftPPM;
54, // meanWaitingTimeMs;
32, // int medianWaitingTimeMs;
1, // int minWaitingTimeMs;
98, // int maxWaitingTimeMs;
7654, // int addedSamples;
}; // These random but non-trivial numbers are used for testing.
// Verify the header extension ID, if enabled, is within the bounds specified in
// [RFC5285]: 1-14 inclusive.
#define WEBRTC_CHECK_HEADER_EXTENSION_ID(enable, id) \
@ -823,7 +842,13 @@ class FakeWebRtcVoiceEngine
virtual bool BuiltInAECIsAvailable() const { return false; }
// webrtc::VoENetEqStats
WEBRTC_STUB(GetNetworkStatistics, (int, webrtc::NetworkStatistics&));
WEBRTC_FUNC(GetNetworkStatistics, (int channel,
webrtc::NetworkStatistics& ns)) {
WEBRTC_CHECK_CHANNEL(channel);
memcpy(&ns, &kNetStats, sizeof(webrtc::NetworkStatistics));
return 0;
}
WEBRTC_FUNC_CONST(GetDecodingCallStatistics, (int channel,
webrtc::AudioDecodingCallStats*)) {
WEBRTC_CHECK_CHANNEL(channel);

View File

@ -3413,6 +3413,10 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
rinfo.jitter_buffer_preferred_ms = ns.preferredBufferSize;
rinfo.expand_rate =
static_cast<float>(ns.currentExpandRate) / (1 << 14);
rinfo.speech_expand_rate =
static_cast<float>(ns.currentSpeechExpandRate) / (1 << 14);
rinfo.secondary_decoded_rate =
static_cast<float>(ns.currentSecondaryDecodedRate) / (1 << 14);
}
webrtc::AudioDecodingCallStats ds;

View File

@ -1992,6 +1992,12 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStatsWithMultipleSendStreams) {
EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].packets_lost);
EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].ext_seqnum);
EXPECT_EQ(kPcmuCodec.name, info.receivers[0].codec_name);
EXPECT_EQ(static_cast<float>(cricket::kNetStats.currentExpandRate) /
(1 << 14), info.receivers[0].expand_rate);
EXPECT_EQ(static_cast<float>(cricket::kNetStats.currentSpeechExpandRate) /
(1 << 14), info.receivers[0].speech_expand_rate);
EXPECT_EQ(static_cast<float>(cricket::kNetStats.currentSecondaryDecodedRate) /
(1 << 14), info.receivers[0].secondary_decoded_rate);
}
// Test that we can add and remove receive streams, and do proper send/playout.
@ -2319,6 +2325,12 @@ TEST_F(WebRtcVoiceEngineTestFake, GetStats) {
EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].packets_lost);
EXPECT_EQ(cricket::kIntStatValue, info.receivers[0].ext_seqnum);
EXPECT_EQ(kPcmuCodec.name, info.receivers[0].codec_name);
EXPECT_EQ(static_cast<float>(cricket::kNetStats.currentExpandRate) /
(1 << 14), info.receivers[0].expand_rate);
EXPECT_EQ(static_cast<float>(cricket::kNetStats.currentSpeechExpandRate) /
(1 << 14), info.receivers[0].speech_expand_rate);
EXPECT_EQ(static_cast<float>(cricket::kNetStats.currentSecondaryDecodedRate) /
(1 << 14), info.receivers[0].secondary_decoded_rate);
// TODO(sriniv): Add testing for more receiver fields.
}

View File

@ -346,14 +346,19 @@ struct NetworkStatistics // NETEQ statistics
uint16_t currentPacketLossRate;
// Late loss rate; fraction between 0 and 1, scaled to Q14.
uint16_t currentDiscardRate;
// fraction (of original stream) of synthesized speech inserted through
// fraction (of original stream) of synthesized audio inserted through
// expansion (in Q14)
uint16_t currentExpandRate;
// fraction (of original stream) of synthesized speech inserted through
// expansion (in Q14)
uint16_t currentSpeechExpandRate;
// fraction of synthesized speech inserted through pre-emptive expansion
// (in Q14)
uint16_t currentPreemptiveRate;
// fraction of data removed through acceleration (in Q14)
uint16_t currentAccelerateRate;
// fraction of data coming from secondary decoding (in Q14)
uint16_t currentSecondaryDecodedRate;
// clock-drift in parts-per-million (negative or positive)
int32_t clockDriftPPM;
// average packet waiting time in the jitter buffer (ms)

View File

@ -639,7 +639,7 @@ int AcmReceiver::LastAudioCodec(CodecInst* codec) const {
return 0;
}
void AcmReceiver::NetworkStatistics(ACMNetworkStatistics* acm_stat) {
void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) {
NetEqNetworkStatistics neteq_stat;
// NetEq function always returns zero, so we don't check the return value.
neteq_->NetworkStatistics(&neteq_stat);
@ -650,8 +650,10 @@ void AcmReceiver::NetworkStatistics(ACMNetworkStatistics* acm_stat) {
acm_stat->currentPacketLossRate = neteq_stat.packet_loss_rate;
acm_stat->currentDiscardRate = neteq_stat.packet_discard_rate;
acm_stat->currentExpandRate = neteq_stat.expand_rate;
acm_stat->currentSpeechExpandRate = neteq_stat.speech_expand_rate;
acm_stat->currentPreemptiveRate = neteq_stat.preemptive_rate;
acm_stat->currentAccelerateRate = neteq_stat.accelerate_rate;
acm_stat->currentSecondaryDecodedRate = neteq_stat.secondary_decoded_rate;
acm_stat->clockDriftPPM = neteq_stat.clockdrift_ppm;
acm_stat->addedSamples = neteq_stat.added_zero_samples;

View File

@ -191,7 +191,7 @@ class AcmReceiver {
// Output:
// - statistics : The current network statistics.
//
void NetworkStatistics(ACMNetworkStatistics* statistics);
void GetNetworkStatistics(NetworkStatistics* statistics);
//
// Enable post-decoding VAD.

View File

@ -1451,8 +1451,8 @@ int AudioCodingModuleImpl::PlayoutData10Ms(int desired_freq_hz,
// TODO(turajs) change the return value to void. Also change the corresponding
// NetEq function.
int AudioCodingModuleImpl::NetworkStatistics(ACMNetworkStatistics* statistics) {
receiver_.NetworkStatistics(statistics);
int AudioCodingModuleImpl::GetNetworkStatistics(NetworkStatistics* statistics) {
receiver_.GetNetworkStatistics(statistics);
return 0;
}
@ -1841,8 +1841,8 @@ bool AudioCodingImpl::Get10MsAudio(AudioFrame* audio_frame) {
return acm_old_->PlayoutData10Ms(playout_frequency_hz_, audio_frame) == 0;
}
bool AudioCodingImpl::NetworkStatistics(
ACMNetworkStatistics* network_statistics) {
bool AudioCodingImpl::GetNetworkStatistics(
NetworkStatistics* network_statistics) {
FATAL() << "Not implemented yet.";
return false;
}

View File

@ -198,7 +198,7 @@ class AudioCodingModuleImpl : public AudioCodingModule {
// Statistics
//
virtual int NetworkStatistics(ACMNetworkStatistics* statistics) OVERRIDE;
virtual int GetNetworkStatistics(NetworkStatistics* statistics) OVERRIDE;
// GET RED payload for iSAC. The method id called when 'this' ACM is
// the default ACM.
@ -418,8 +418,8 @@ class AudioCodingImpl : public AudioCoding {
virtual bool Get10MsAudio(AudioFrame* audio_frame) OVERRIDE;
virtual bool NetworkStatistics(
ACMNetworkStatistics* network_statistics) OVERRIDE;
virtual bool GetNetworkStatistics(
NetworkStatistics* network_statistics) OVERRIDE;
virtual bool EnableNack(size_t max_nack_list_size) OVERRIDE;

View File

@ -909,7 +909,7 @@ class AudioCodingModule: public Module {
//
///////////////////////////////////////////////////////////////////////////
// int32_t NetworkStatistics()
// int32_t GetNetworkStatistics()
// Get network statistics. Note that the internal statistics of NetEq are
// reset by this call.
//
@ -920,8 +920,8 @@ class AudioCodingModule: public Module {
// -1 if failed to set the network statistics,
// 0 if statistics are set successfully.
//
virtual int32_t NetworkStatistics(
ACMNetworkStatistics* network_statistics) = 0;
virtual int32_t GetNetworkStatistics(
NetworkStatistics* network_statistics) = 0;
//
// Set an initial delay for playout.
@ -1107,7 +1107,7 @@ class AudioCoding {
// Returns the network statistics. Note that the internal statistics of NetEq
// are reset by this call. Returns true if successful, false otherwise.
virtual bool NetworkStatistics(ACMNetworkStatistics* network_statistics) = 0;
virtual bool GetNetworkStatistics(NetworkStatistics* network_statistics) = 0;
// Enables NACK and sets the maximum size of the NACK list. If NACK is already
// enabled then the maximum NACK list size is modified accordingly. Returns

View File

@ -144,48 +144,6 @@ enum ACMAMRPackingFormat {
AMRFileStorage = 2
};
///////////////////////////////////////////////////////////////////////////
//
// Struct containing network statistics
//
// -currentBufferSize : current jitter buffer size in ms
// -preferredBufferSize : preferred (optimal) buffer size in ms
// -jitterPeaksFound : indicate if peaky-jitter mode is engaged, that is,
// if severe but sparse network delays have occurred.
// -currentPacketLossRate : loss rate (network + late) (in Q14)
// -currentDiscardRate : late loss rate (in Q14)
// -currentExpandRate : fraction (of original stream) of synthesized
// speech inserted through expansion (in Q14)
// -currentPreemptiveRate : fraction of synthesized speech inserted through
// pre-emptive expansion (in Q14)
// -currentAccelerateRate : fraction of data removed through acceleration
// (in Q14)
// -clockDriftPPM : clock-drift between sender and receiver in parts-
// per-million. Positive means that receiver sample
// rate is higher than sender sample rate.
// -meanWaitingTimeMs : average packet waiting time in the buffer
// -medianWaitingTimeMs : median packet waiting time in the buffer
// -minWaitingTimeMs : min packet waiting time in the buffer
// -maxWaitingTimeMs : max packet waiting time in the buffer
// -addedSamples : samples inserted because of packet loss in off mode
typedef struct {
uint16_t currentBufferSize;
uint16_t preferredBufferSize;
bool jitterPeaksFound;
uint16_t currentPacketLossRate;
uint16_t currentDiscardRate;
uint16_t currentExpandRate;
uint16_t currentPreemptiveRate;
uint16_t currentAccelerateRate;
int32_t clockDriftPPM;
int meanWaitingTimeMs;
int medianWaitingTimeMs;
int minWaitingTimeMs;
int maxWaitingTimeMs;
int addedSamples;
} ACMNetworkStatistics;
///////////////////////////////////////////////////////////////////////////
//
// Enumeration of background noise mode a mapping from NetEQ interface.

View File

@ -785,8 +785,8 @@ void APITest::TestDelay(char side) {
*myMinDelay = (rand() % 1000) + 1;
ACMNetworkStatistics networkStat;
CHECK_ERROR_MT(myACM->NetworkStatistics(&networkStat));
NetworkStatistics networkStat;
CHECK_ERROR_MT(myACM->GetNetworkStatistics(&networkStat));
if (!_randomTest) {
fprintf(stdout, "\n\nJitter Statistics at Side %c\n", side);
@ -803,10 +803,14 @@ void APITest::TestDelay(char side) {
networkStat.currentDiscardRate);
fprintf(stdout, "expand rate............. %d\n",
networkStat.currentExpandRate);
fprintf(stdout, "speech expand rate...... %d\n",
networkStat.currentSpeechExpandRate);
fprintf(stdout, "Preemptive rate......... %d\n",
networkStat.currentPreemptiveRate);
fprintf(stdout, "Accelerate rate......... %d\n",
networkStat.currentAccelerateRate);
fprintf(stdout, "Secondary decoded rate.. %d\n",
networkStat.currentSecondaryDecodedRate);
fprintf(stdout, "Clock-drift............. %d\n", networkStat.clockDriftPPM);
fprintf(stdout, "Mean waiting time....... %d\n",
networkStat.meanWaitingTimeMs);

View File

@ -196,8 +196,8 @@ class DelayTest {
// Print delay information every 16 frame
if ((num_frames & 0x3F) == 0x3F) {
ACMNetworkStatistics statistics;
acm_b_->NetworkStatistics(&statistics);
NetworkStatistics statistics;
acm_b_->GetNetworkStatistics(&statistics);
fprintf(stdout, "delay: min=%3d max=%3d mean=%3d median=%3d"
" ts-based average = %6.3f, "
"curr buff-lev = %4u opt buff-lev = %4u \n",

View File

@ -219,8 +219,8 @@ class InsertPacketWithTiming {
// Jitter buffer delay.
void Delay(int* optimal_delay, int* current_delay) {
ACMNetworkStatistics statistics;
receive_acm_->NetworkStatistics(&statistics);
NetworkStatistics statistics;
receive_acm_->GetNetworkStatistics(&statistics);
*optimal_delay = statistics.preferredBufferSize;
*current_delay = statistics.currentBufferSize;
}

View File

@ -185,8 +185,8 @@ class TargetDelayTest : public ::testing::Test {
}
int GetCurrentOptimalDelayMs() {
ACMNetworkStatistics stats;
acm_->NetworkStatistics(&stats);
NetworkStatistics stats;
acm_->GetNetworkStatistics(&stats);
return stats.preferredBufferSize;
}

View File

@ -3686,12 +3686,7 @@ Channel::GetNetworkStatistics(NetworkStatistics& stats)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::GetNetworkStatistics()");
ACMNetworkStatistics acm_stats;
int return_value = audio_coding_->NetworkStatistics(&acm_stats);
if (return_value >= 0) {
memcpy(&stats, &acm_stats, sizeof(NetworkStatistics));
}
return return_value;
return audio_coding_->GetNetworkStatistics(&stats);
}
void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const {

View File

@ -23,31 +23,35 @@ TEST_F(NetEQStatsTest, ManualPrintStatisticsAfterRunningAWhile) {
TEST_LOG("Inspect these statistics and ensure they make sense.\n");
TEST_LOG(" currentAccelerateRate = %hu \n",
TEST_LOG(" currentAccelerateRate = %hu \n",
network_statistics.currentAccelerateRate);
TEST_LOG(" currentBufferSize = %hu \n",
TEST_LOG(" currentBufferSize = %hu \n",
network_statistics.currentBufferSize);
TEST_LOG(" currentDiscardRate = %hu \n",
TEST_LOG(" currentSecondaryDecodedRate = %hu \n",
network_statistics.currentSecondaryDecodedRate);
TEST_LOG(" currentDiscardRate = %hu \n",
network_statistics.currentDiscardRate);
TEST_LOG(" currentExpandRate = %hu \n",
TEST_LOG(" currentExpandRate = %hu \n",
network_statistics.currentExpandRate);
TEST_LOG(" currentPacketLossRate = %hu \n",
TEST_LOG(" currentPacketLossRate = %hu \n",
network_statistics.currentPacketLossRate);
TEST_LOG(" currentPreemptiveRate = %hu \n",
TEST_LOG(" currentPreemptiveRate = %hu \n",
network_statistics.currentPreemptiveRate);
TEST_LOG(" preferredBufferSize = %hu \n",
TEST_LOG(" currentSpeechExpandRate = %hu \n",
network_statistics.currentSpeechExpandRate);
TEST_LOG(" preferredBufferSize = %hu \n",
network_statistics.preferredBufferSize);
TEST_LOG(" jitterPeaksFound = %i \n",
TEST_LOG(" jitterPeaksFound = %i \n",
network_statistics.jitterPeaksFound);
TEST_LOG(" clockDriftPPM = %i \n",
TEST_LOG(" clockDriftPPM = %i \n",
network_statistics.clockDriftPPM);
TEST_LOG(" meanWaitingTimeMs = %i \n",
TEST_LOG(" meanWaitingTimeMs = %i \n",
network_statistics.meanWaitingTimeMs);
TEST_LOG(" medianWaitingTimeMs = %i \n",
TEST_LOG(" medianWaitingTimeMs = %i \n",
network_statistics.medianWaitingTimeMs);
TEST_LOG(" minWaitingTimeMs = %i \n",
TEST_LOG(" minWaitingTimeMs = %i \n",
network_statistics.minWaitingTimeMs);
TEST_LOG(" maxWaitingTimeMs = %i \n",
TEST_LOG(" maxWaitingTimeMs = %i \n",
network_statistics.maxWaitingTimeMs);
// This is only set to a non-zero value in off-mode.