Update talk to 58174641 together with http://review.webrtc.org/4319005/.

R=turaj@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5287 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
index 5da42ad..ac92198 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
@@ -19,6 +19,7 @@
 #include "webrtc/common_types.h"
 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
 #include "webrtc/modules/audio_coding/main/acm2/acm_resampler.h"
+#include "webrtc/modules/audio_coding/main/acm2/call_statistics.h"
 #include "webrtc/modules/audio_coding/main/acm2/nack.h"
 #include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
 #include "webrtc/modules/audio_coding/neteq4/interface/neteq.h"
@@ -461,6 +462,7 @@
   audio_frame->vad_activity_ = previous_audio_activity_;
   SetAudioFrameActivityAndType(vad_enabled_, type, audio_frame);
   previous_audio_activity_ = audio_frame->vad_activity_;
+  call_stats_.DecodedByNetEq(audio_frame->speech_type_);
   return 0;
 }
 
@@ -761,6 +763,9 @@
     return false;
   }
 
+  // Update statistics.
+  call_stats_.DecodedBySilenceGenerator();
+
   // Set the values if already got a packet, otherwise set to default values.
   if (last_audio_decoder_ >= 0) {
     current_sample_rate_hz_ = ACMCodecDB::database_[last_audio_decoder_].plfreq;
@@ -832,6 +837,12 @@
   }
 }
 
+void AcmReceiver::GetDecodingCallStatistics(
+    AudioDecodingCallStats* stats) const {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  *stats = call_stats_.GetDecodingStatistics();
+}
+
 }  // namespace acm2
 
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver.h b/webrtc/modules/audio_coding/main/acm2/acm_receiver.h
index 9267c1e..81eb520 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_receiver.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver.h
@@ -18,6 +18,7 @@
 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
 #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
 #include "webrtc/modules/audio_coding/main/acm2/acm_resampler.h"
+#include "webrtc/modules/audio_coding/main/acm2/call_statistics.h"
 #include "webrtc/modules/audio_coding/main/acm2/initial_delay_manager.h"
 #include "webrtc/modules/audio_coding/neteq4/interface/neteq.h"
 #include "webrtc/modules/interface/module_common_types.h"
@@ -320,6 +321,10 @@
   //
   NetEqBackgroundNoiseMode BackgroundNoiseModeForTest() const;
 
+  //
+  // Get statistics of calls to GetAudio().
+  void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const;
+
  private:
   int PayloadType2CodecIndex(uint8_t payload_type) const;
 
@@ -361,6 +366,8 @@
   // initial delay is set.
   scoped_ptr<InitialDelayManager::SyncStream> missing_packets_sync_stream_;
   scoped_ptr<InitialDelayManager::SyncStream> late_packets_sync_stream_;
+
+  CallStatistics call_stats_;
 };
 
 }  // namespace acm2
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi
index 0754126..f51c3bf 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi
@@ -84,6 +84,8 @@
         'audio_coding_module.cc',
         'audio_coding_module_impl.cc',
         'audio_coding_module_impl.h',
+        'call_statistics.cc',
+        'call_statistics.h',
         'initial_delay_manager.cc',
         'initial_delay_manager.h',
         'nack.cc',
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
index ce05218..4c64e07 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
@@ -20,6 +20,7 @@
 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
 #include "webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h"
 #include "webrtc/modules/audio_coding/main/acm2/acm_resampler.h"
+#include "webrtc/modules/audio_coding/main/acm2/call_statistics.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
 #include "webrtc/system_wrappers/interface/trace.h"
@@ -1979,6 +1980,11 @@
   return kExperimentalAcmVersion;
 }
 
+void AudioCodingModuleImpl::GetDecodingCallStatistics(
+      AudioDecodingCallStats* call_stats) const {
+  receiver_.GetDecodingCallStatistics(call_stats);
+}
+
 }  // namespace acm2
 
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
index 17fab39..bc4ea0f 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
@@ -228,6 +228,8 @@
 
   std::vector<uint16_t> GetNackList(int round_trip_time_ms) const;
 
+  void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const;
+
  private:
   int UnregisterReceiveCodecSafe(int payload_type);
 
diff --git a/webrtc/modules/audio_coding/main/acm2/call_statistics.cc b/webrtc/modules/audio_coding/main/acm2/call_statistics.cc
new file mode 100644
index 0000000..9153325
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/call_statistics.cc
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/audio_coding/main/acm2/call_statistics.h"
+
+#include <cassert>
+
+namespace webrtc {
+
+namespace acm2 {
+
+void CallStatistics::DecodedByNetEq(AudioFrame::SpeechType speech_type) {
+  ++decoding_stat_.calls_to_neteq;
+  switch (speech_type) {
+    case AudioFrame::kNormalSpeech: {
+      ++decoding_stat_.decoded_normal;
+      break;
+    }
+    case AudioFrame::kPLC: {
+      ++decoding_stat_.decoded_plc;
+      break;
+    }
+    case AudioFrame::kCNG: {
+      ++decoding_stat_.decoded_cng;
+      break;
+    }
+    case AudioFrame::kPLCCNG: {
+      ++decoding_stat_.decoded_plc_cng;
+      break;
+    }
+    case AudioFrame::kUndefined: {
+      // If the audio is decoded by NetEq, |kUndefined| is not an option.
+      assert(false);
+    }
+  }
+}
+
+void CallStatistics::DecodedBySilenceGenerator() {
+  ++decoding_stat_.calls_to_silence_generator;
+}
+
+const AudioDecodingCallStats& CallStatistics::GetDecodingStatistics() const {
+  return decoding_stat_;
+}
+
+}  // namespace acm2
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/call_statistics.h b/webrtc/modules/audio_coding/main/acm2/call_statistics.h
new file mode 100644
index 0000000..2aece0f
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/call_statistics.h
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_CALL_STATISTICS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_CALL_STATISTICS_H_
+
+#include "webrtc/common_types.h"
+#include "webrtc/modules/interface/module_common_types.h"
+
+//
+// This class is for book keeping of calls to ACM. It is not useful to log API
+// calls which are supposed to be called every 10ms, e.g. PlayoutData10Ms(),
+// however, it is useful to know the number of such calls in a given time
+// interval. The current implementation covers calls to PlayoutData10Ms() with
+// detailed accounting of the decoded speech type.
+//
+// Thread Safety
+// =============
+// Please note that this class in not thread safe. The class must be protected
+// if different APIs are called from different threads.
+//
+
+namespace webrtc {
+
+namespace acm2 {
+
+class CallStatistics {
+ public:
+  CallStatistics() {}
+  ~CallStatistics() {}
+
+  // Call this method to indicate that NetEq engaged in decoding. |speech_type|
+  // is the audio-type according to NetEq.
+  void DecodedByNetEq(AudioFrame::SpeechType speech_type);
+
+  // Call this method to indicate that a decoding call resulted in generating
+  // silence, i.e. call to NetEq is bypassed and the output audio is zero.
+  void DecodedBySilenceGenerator();
+
+  // Get statistics for decoding. The statistics include the number of calls to
+  // NetEq and silence generator, as well as the type of speech pulled of off
+  // NetEq, c.f. declaration of AudioDecodingCallStats for detailed description.
+  const AudioDecodingCallStats& GetDecodingStatistics() const;
+
+ private:
+  // Reset the decoding statistics.
+  void ResetDecodingStatistics();
+
+  AudioDecodingCallStats decoding_stat_;
+};
+
+}  // namespace acm2
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_CALL_STATISTICS_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/call_statistics_unittest.cc b/webrtc/modules/audio_coding/main/acm2/call_statistics_unittest.cc
new file mode 100644
index 0000000..61aadd7
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/call_statistics_unittest.cc
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "gtest/gtest.h"
+#include "webrtc/modules/audio_coding/main/acm2/call_statistics.h"
+
+namespace webrtc {
+
+namespace acm2 {
+
+TEST(CallStatisticsTest, InitializedZero) {
+  CallStatistics call_stats;
+  AudioDecodingCallStats stats;
+
+  stats = call_stats.GetDecodingStatistics();
+  EXPECT_EQ(0, stats.calls_to_neteq);
+  EXPECT_EQ(0, stats.calls_to_silence_generator);
+  EXPECT_EQ(0, stats.decoded_normal);
+  EXPECT_EQ(0, stats.decoded_cng);
+  EXPECT_EQ(0, stats.decoded_plc);
+  EXPECT_EQ(0, stats.decoded_plc_cng);
+}
+
+TEST(CallStatisticsTest, AllCalls) {
+  CallStatistics call_stats;
+  AudioDecodingCallStats stats;
+
+  call_stats.DecodedBySilenceGenerator();
+  call_stats.DecodedByNetEq(AudioFrame::kNormalSpeech);
+  call_stats.DecodedByNetEq(AudioFrame::kPLC);
+  call_stats.DecodedByNetEq(AudioFrame::kPLCCNG);
+  call_stats.DecodedByNetEq(AudioFrame::kCNG);
+
+  stats = call_stats.GetDecodingStatistics();
+  EXPECT_EQ(4, stats.calls_to_neteq);
+  EXPECT_EQ(1, stats.calls_to_silence_generator);
+  EXPECT_EQ(1, stats.decoded_normal);
+  EXPECT_EQ(1, stats.decoded_cng);
+  EXPECT_EQ(1, stats.decoded_plc);
+  EXPECT_EQ(1, stats.decoded_plc_cng);
+}
+
+}  // namespace acm2
+
+}  // namespace webrtc
+
+
+
diff --git a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
index f8b9690..db45add 100644
--- a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
+++ b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
@@ -931,6 +931,9 @@
   // is returned.
   //
   virtual std::vector<uint16_t> GetNackList(int round_trip_time_ms) const = 0;
+
+  virtual void GetDecodingCallStatistics(
+      AudioDecodingCallStats* call_stats) const = 0;
 };
 
 struct AudioCodingModuleFactory {
diff --git a/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.cc
index 1e71a04..556f530 100644
--- a/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.cc
+++ b/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.cc
@@ -18,6 +18,7 @@
 #include "webrtc/engine_configurations.h"
 #include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
+#include "webrtc/modules/audio_coding/main/acm2/call_statistics.h"
 #include "webrtc/modules/audio_coding/main/source/acm_dtmf_detection.h"
 #include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
 #include "webrtc/modules/audio_coding/main/source/acm_resampler.h"
@@ -2273,6 +2274,9 @@
   {
     CriticalSectionScoped lock(acm_crit_sect_);
 
+    // Update call statistics.
+    call_stats_.DecodedByNetEq(audio_frame->speech_type_);
+
     if (update_nack) {
       assert(nack_.get());
       nack_->UpdateLastDecodedPacket(decoded_seq_num, decoded_timestamp);
@@ -2879,6 +2883,9 @@
     return false;
   }
 
+  // Record call to silence generator.
+  call_stats_.DecodedBySilenceGenerator();
+
   // We stop accumulating packets, if the number of packets or the total size
   // exceeds a threshold.
   int max_num_packets;
@@ -3030,6 +3037,12 @@
   return kLegacyAcmVersion;
 }
 
+void AudioCodingModuleImpl::GetDecodingCallStatistics(
+      AudioDecodingCallStats* call_stats) const {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  *call_stats = call_stats_.GetDecodingStatistics();
+}
+
 }  // namespace acm1
 
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.h b/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.h
index 7acde17..f0b22f1 100644
--- a/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.h
+++ b/webrtc/modules/audio_coding/main/source/audio_coding_module_impl.h
@@ -19,6 +19,7 @@
 #include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
 #include "webrtc/modules/audio_coding/main/source/acm_neteq.h"
 #include "webrtc/modules/audio_coding/main/source/acm_resampler.h"
+#include "webrtc/modules/audio_coding/main/acm2/call_statistics.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 
 namespace webrtc {
@@ -303,6 +304,8 @@
   // Disable NACK.
   void DisableNack();
 
+  void GetDecodingCallStatistics(AudioDecodingCallStats* call_stats) const;
+
  private:
   // Change required states after starting to receive the codec corresponding
   // to |index|.
@@ -441,6 +444,8 @@
   Clock* clock_;
   scoped_ptr<acm2::Nack> nack_;
   bool nack_enabled_;
+
+  acm2::CallStatistics call_stats_;
 };
 
 }  // namespace acm1
diff --git a/webrtc/modules/audio_coding/neteq/webrtc_neteq.c b/webrtc/modules/audio_coding/neteq/webrtc_neteq.c
index de1ccd1..fad690d 100644
--- a/webrtc/modules/audio_coding/neteq/webrtc_neteq.c
+++ b/webrtc/modules/audio_coding/neteq/webrtc_neteq.c
@@ -1104,14 +1104,6 @@
         /* If CN or internal CNG */
         *outputType = kOutputCNG;
 
-#ifdef NETEQ_VAD
-    }
-    else if ( NetEqMainInst->DSPinst.VADInst.VADDecision == 0 )
-    {
-        /* post-decode VAD says passive speaker */
-        *outputType = kOutputVADPassive;
-#endif /* NETEQ_VAD */
-
     }
     else if ((NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
         && (NetEqMainInst->DSPinst.ExpandInst.w16_expandMuteFactor == 0))
@@ -1125,6 +1117,14 @@
         /* PLC mode */
         *outputType = kOutputPLC;
 
+#ifdef NETEQ_VAD
+    }
+    else if ( NetEqMainInst->DSPinst.VADInst.VADDecision == 0 )
+    {
+        /* post-decode VAD says passive speaker */
+        *outputType = kOutputVADPassive;
+#endif /* NETEQ_VAD */
+
     }
     else
     {
diff --git a/webrtc/modules/audio_coding/neteq4/neteq_impl.cc b/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
index 73ca5e4..fb27af2 100644
--- a/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
+++ b/webrtc/modules/audio_coding/neteq4/neteq_impl.cc
@@ -1887,13 +1887,13 @@
   assert(expand_.get());
   if (last_mode_ == kModeCodecInternalCng || last_mode_ == kModeRfc3389Cng) {
     return kOutputCNG;
-  } else if (vad_->running() && !vad_->active_speech()) {
-    return kOutputVADPassive;
   } else if (last_mode_ == kModeExpand && expand_->MuteFactor(0) == 0) {
     // Expand mode has faded down to background noise only (very long expand).
     return kOutputPLCtoCNG;
   } else if (last_mode_ == kModeExpand) {
     return kOutputPLC;
+  } else if (vad_->running() && !vad_->active_speech()) {
+    return kOutputVADPassive;
   } else {
     return kOutputNormal;
   }