Backed out 4 changesets (bug 1456115) for Asan Mochitest filures "AddressSanitizer: stack-overflow /celt/bands.c:1437:4 in quant_all_bands". CLOSED TREE
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Tue, 24 Apr 2018 21:47:07 +0300
changeset 468986 d1e4fdc346700b6c3705766c6f54afbbed071e58
parent 468985 ce20f90c85a5fca99b59f05bcd8788b2bbb06150
child 468987 bc95f676ecde3a0fc26c67fd95f8c21db1a23353
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1456115
milestone61.0a1
backs out3379d4fc07f6802fb46fa3c0ce639d4afac85adf
9c77f5b53b564d73386fb6c74f4f4d8a321d3492
e48268ffa4d8c92fa5f740929625bde722c78b65
bffecfd92808acbf5f3ab2d16482ac8f020c5892
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1456115) for Asan Mochitest filures "AddressSanitizer: stack-overflow /celt/bands.c:1437:4 in quant_all_bands". CLOSED TREE Backed out changeset 3379d4fc07f6 (bug 1456115) Backed out changeset 9c77f5b53b56 (bug 1456115) Backed out changeset e48268ffa4d8 (bug 1456115) Backed out changeset bffecfd92808 (bug 1456115)
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraph.h
dom/media/MediaStreamGraphImpl.h
dom/media/MediaStreamListener.h
media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
media/webrtc/trunk/webrtc/audio/audio_receive_stream.cc
media/webrtc/trunk/webrtc/common_types.h
media/webrtc/trunk/webrtc/modules/audio_coding/acm2/acm_receiver.cc
media/webrtc/trunk/webrtc/modules/audio_coding/acm2/acm_receiver.h
media/webrtc/trunk/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
media/webrtc/trunk/webrtc/modules/audio_coding/include/audio_coding_module.h
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_impl.cc
media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_impl.h
media/webrtc/trunk/webrtc/voice_engine/channel.cc
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -1154,19 +1154,31 @@ MediaStreamGraphImpl::UpdateGraph(GraphT
   // means the driver would have been blocking indefinitly, but the graph has
   // been woken up right after having been to sleep.
   MOZ_ASSERT(aEndBlockingDecisions >= mStateComputedTime);
 
   UpdateStreamOrder();
 
   bool ensureNextIteration = false;
 
+  // Grab pending stream input and compute blocking time
+  AutoTArray<RefPtr<SourceMediaStream::NotifyPullPromise>, 64> promises;
   for (MediaStream* stream : mStreams) {
     if (SourceMediaStream* is = stream->AsSourceStream()) {
-      ensureNextIteration |= is->PullNewData(aEndBlockingDecisions);
+      ensureNextIteration |= is->PullNewData(aEndBlockingDecisions, promises);
+    }
+  }
+
+  // Wait until all PullEnabled stream's listeners have completed.
+  if (!promises.IsEmpty()) {
+    AwaitAll(do_AddRef(mThreadPool), promises);
+  }
+
+  for (MediaStream* stream : mStreams) {
+    if (SourceMediaStream* is = stream->AsSourceStream()) {
       is->ExtractPendingInput();
     }
     if (stream->mFinished) {
       // The stream's not suspended, and since it's finished, underruns won't
       // stop it playing out. So there's no blocking other than what we impose
       // here.
       GraphTime endTime = stream->GetStreamTracks().GetAllTracksEnd() +
           stream->mTracksStartTime;
@@ -1473,16 +1485,20 @@ public:
     // objects owning streams, or for expiration of mGraph->mShutdownTimer,
     // which won't otherwise release its reference on the graph until
     // nsTimerImpl::Shutdown(), which runs after xpcom-shutdown-threads.
     {
       MonitorAutoLock mon(mGraph->mMonitor);
       mGraph->SetCurrentDriver(nullptr);
     }
 
+    // Do not hold on our threadpool, global shutdown will hang otherwise as
+    // it waits for all thread pools to shutdown.
+    mGraph->mThreadPool = nullptr;
+
     // Safe to access these without the monitor since the graph isn't running.
     // We may be one of several graphs. Drop ticket to eventually unblock shutdown.
     if (mGraph->mShutdownTimer && !mGraph->mForceShutdownTicket) {
       MOZ_ASSERT(false,
         "AudioCallbackDriver took too long to shut down and we let shutdown"
         " continue - freezing and leaking");
 
       // The timer fired, so we may be deeper in shutdown now.  Block any further
@@ -2752,17 +2768,19 @@ SourceMediaStream::SetPullEnabled(bool a
     }
     SourceMediaStream* mStream;
     bool mEnabled;
   };
   GraphImpl()->AppendMessage(MakeUnique<Message>(this, aEnabled));
 }
 
 bool
-SourceMediaStream::PullNewData(StreamTime aDesiredUpToTime)
+SourceMediaStream::PullNewData(
+  StreamTime aDesiredUpToTime,
+  nsTArray<RefPtr<SourceMediaStream::NotifyPullPromise>>& aPromises)
 {
   TRACE_AUDIO_CALLBACK();
   MutexAutoLock lock(mMutex);
   if (!mPullEnabled || mFinished) {
     return false;
   }
   // Compute how much stream time we'll need assuming we don't block
   // the stream at all.
@@ -2775,17 +2793,17 @@ SourceMediaStream::PullNewData(StreamTim
         GraphImpl()->MediaTimeToSeconds(current)));
   if (t <= current) {
     return false;
   }
   for (uint32_t j = 0; j < mListeners.Length(); ++j) {
     MediaStreamListener* l = mListeners[j];
     {
       MutexAutoUnlock unlock(mMutex);
-      l->NotifyPull(GraphImpl(), t);
+      aPromises.AppendElement(l->AsyncNotifyPull(GraphImpl(), t));
     }
   }
   return true;
 }
 
 void
 SourceMediaStream::ExtractPendingInput()
 {
@@ -3590,16 +3608,17 @@ MediaStreamGraphImpl::MediaStreamGraphIm
   , mPostedRunInStableStateEvent(false)
   , mDetectedNotRunning(false)
   , mPostedRunInStableState(false)
   , mRealtime(aDriverRequested != OFFLINE_THREAD_DRIVER)
   , mNonRealtimeProcessing(false)
   , mStreamOrderDirty(false)
   , mLatencyLog(AsyncLatencyLogger::Get())
   , mAbstractMainThread(aMainThread)
+  , mThreadPool(GetMediaThreadPool(MediaThreadType::MSG_CONTROL))
   , mSelfRef(this)
   , mOutputChannels(std::min<uint32_t>(8, CubebUtils::MaxNumberOfChannels()))
 #ifdef DEBUG
   , mCanRunMessagesSynchronously(false)
 #endif
 {
   if (mRealtime) {
     if (aDriverRequested == AUDIO_THREAD_DRIVER) {
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -7,16 +7,17 @@
 #define MOZILLA_MEDIASTREAMGRAPH_H_
 
 #include "AudioStream.h"
 #include "MainThreadUtils.h"
 #include "MediaStreamTypes.h"
 #include "StreamTracks.h"
 #include "VideoSegment.h"
 #include "mozilla/LinkedList.h"
+#include "mozilla/MozPromise.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/TaskQueue.h"
 #include "nsAutoPtr.h"
 #include "nsAutoRef.h"
 #include "nsIRunnable.h"
 #include "nsTArray.h"
 #include <speex/speex_resampler.h>
 
@@ -711,20 +712,23 @@ public:
   // MediaStreamGraph thread only
   void DestroyImpl() override;
 
   // Call these on any thread.
   /**
    * Call all MediaStreamListeners to request new data via the NotifyPull API
    * (if enabled).
    * aDesiredUpToTime (in): end time of new data requested.
+   * aPromises (out): NotifyPullPromises if async API is enabled.
    *
    * Returns true if new data is about to be added.
    */
-  bool PullNewData(StreamTime aDesiredUpToTime);
+  typedef MozPromise<bool, bool, true /* is exclusive */ > NotifyPullPromise;
+  bool PullNewData(StreamTime aDesiredUpToTime,
+                   nsTArray<RefPtr<NotifyPullPromise>>& aPromises);
 
   /**
    * Extract any state updates pending in the stream, and apply them.
    */
   void ExtractPendingInput();
 
   /**
    * These add/remove DirectListeners, which allow bypassing the graph and any
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -814,16 +814,17 @@ public:
    */
   bool mStreamOrderDirty;
   /**
    * Hold a ref to the Latency logger
    */
   RefPtr<AsyncLatencyLogger> mLatencyLog;
   AudioMixer mMixer;
   const RefPtr<AbstractThread> mAbstractMainThread;
+  RefPtr<SharedThreadPool> mThreadPool;
 
   // used to limit graph shutdown time
   // Only accessed on the main thread.
   nsCOMPtr<nsITimer> mShutdownTimer;
 
 private:
   virtual ~MediaStreamGraphImpl();
 
--- a/dom/media/MediaStreamListener.h
+++ b/dom/media/MediaStreamListener.h
@@ -56,16 +56,24 @@ public:
    * calls to add or remove MediaStreamListeners. It is not allowed to block
    * for any length of time.
    * aDesiredTime is the stream time we would like to get data up to. Data
    * beyond this point will not be played until NotifyPull runs again, so there's
    * not much point in providing it. Note that if the stream is blocked for
    * some reason, then data before aDesiredTime may not be played immediately.
    */
   virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) {}
+  virtual RefPtr<SourceMediaStream::NotifyPullPromise> AsyncNotifyPull(
+    MediaStreamGraph* aGraph,
+    StreamTime aDesiredTime)
+  {
+    NotifyPull(aGraph, aDesiredTime);
+    return SourceMediaStream::NotifyPullPromise::CreateAndResolve(true,
+                                                                  __func__);
+  }
 
   enum Blocking {
     BLOCKED,
     UNBLOCKED
   };
   /**
    * Notify that the blocking status of the stream changed. The initial state
    * is assumed to be BLOCKED.
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -2211,16 +2211,28 @@ public:
 
   // Implement MediaStreamListener
   void NotifyPull(MediaStreamGraph* aGraph,
                   StreamTime aDesiredTime) override
   {
     NotifyPullImpl(aDesiredTime);
   }
 
+  RefPtr<SourceMediaStream::NotifyPullPromise> AsyncNotifyPull(
+    MediaStreamGraph* aGraph,
+    StreamTime aDesiredTime) override
+  {
+    RefPtr<PipelineListener> self = this;
+    return InvokeAsync(mTaskQueue, __func__, [self, aDesiredTime]() {
+      self->NotifyPullImpl(aDesiredTime);
+      return SourceMediaStream::NotifyPullPromise::CreateAndResolve(true,
+                                                                    __func__);
+    });
+  }
+
 private:
   ~PipelineListener()
   {
     NS_ReleaseOnMainThreadSystemGroup("MediaPipeline::mConduit",
                                       mConduit.forget());
   }
 
   void NotifyPullImpl(StreamTime aDesiredTime)
--- a/media/webrtc/trunk/webrtc/audio/audio_receive_stream.cc
+++ b/media/webrtc/trunk/webrtc/audio/audio_receive_stream.cc
@@ -198,17 +198,17 @@ webrtc::AudioReceiveStream::Stats AudioR
   stats.jitter_buffer_ms = ns.currentBufferSize;
   stats.jitter_buffer_preferred_ms = ns.preferredBufferSize;
   stats.expand_rate = Q14ToFloat(ns.currentExpandRate);
   stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate);
   stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate);
   stats.accelerate_rate = Q14ToFloat(ns.currentAccelerateRate);
   stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
 
-  auto ds(channel_proxy_->GetDecodingCallStatistics());
+  auto ds = channel_proxy_->GetDecodingCallStatistics();
   stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
   stats.decoding_calls_to_neteq = ds.calls_to_neteq;
   stats.decoding_normal = ds.decoded_normal;
   stats.decoding_plc = ds.decoded_plc;
   stats.decoding_cng = ds.decoded_cng;
   stats.decoding_plc_cng = ds.decoded_plc_cng;
   stats.decoding_muted_output = ds.decoded_muted_output;
 
--- a/media/webrtc/trunk/webrtc/common_types.h
+++ b/media/webrtc/trunk/webrtc/common_types.h
@@ -9,17 +9,16 @@
  */
 
 #ifndef WEBRTC_COMMON_TYPES_H_
 #define WEBRTC_COMMON_TYPES_H_
 
 #include <stddef.h>
 #include <string.h>
 
-#include <atomic>
 #include <ostream>
 #include <string>
 #include <vector>
 
 #include "webrtc/api/video/video_rotation.h"
 #include "webrtc/base/checks.h"
 #include "webrtc/base/optional.h"
 #include "webrtc/typedefs.h"
@@ -404,47 +403,24 @@ struct AudioDecodingCallStats {
       : calls_to_silence_generator(0),
         calls_to_neteq(0),
         decoded_normal(0),
         decoded_plc(0),
         decoded_cng(0),
         decoded_plc_cng(0),
         decoded_muted_output(0) {}
 
-  AudioDecodingCallStats(const AudioDecodingCallStats& other)
-  {
-    calls_to_silence_generator = other.calls_to_silence_generator.load();
-    calls_to_neteq = other.calls_to_neteq.load();
-    decoded_normal = other.decoded_normal.load();
-    decoded_plc = other.decoded_plc.load();
-    decoded_cng = other.decoded_cng.load();
-    decoded_plc_cng = other.decoded_plc_cng.load();
-    decoded_muted_output = other.decoded_muted_output.load();
-  }
-
-  AudioDecodingCallStats& operator=(const AudioDecodingCallStats& other)
-  {
-    calls_to_silence_generator = other.calls_to_silence_generator.load();
-    calls_to_neteq = other.calls_to_neteq.load();
-    decoded_normal = other.decoded_normal.load();
-    decoded_plc = other.decoded_plc.load();
-    decoded_cng = other.decoded_cng.load();
-    decoded_plc_cng = other.decoded_plc_cng.load();
-    decoded_muted_output = other.decoded_muted_output.load();
-    return *this;
-  }
-
-  std::atomic<int> calls_to_silence_generator;  // Number of calls where silence generated,
+  int calls_to_silence_generator;  // Number of calls where silence generated,
                                    // and NetEq was disengaged from decoding.
-  std::atomic<int> calls_to_neteq;              // Number of calls to NetEq.
-  std::atomic<int> decoded_normal;  // Number of calls where audio RTP packet decoded.
-  std::atomic<int> decoded_plc;     // Number of calls resulted in PLC.
-  std::atomic<int> decoded_cng;  // Number of calls where comfort noise generated due to DTX.
-  std::atomic<int> decoded_plc_cng;  // Number of calls resulted where PLC faded to CNG.
-  std::atomic<int> decoded_muted_output;  // Number of calls returning a muted state output.
+  int calls_to_neteq;              // Number of calls to NetEq.
+  int decoded_normal;  // Number of calls where audio RTP packet decoded.
+  int decoded_plc;     // Number of calls resulted in PLC.
+  int decoded_cng;  // Number of calls where comfort noise generated due to DTX.
+  int decoded_plc_cng;  // Number of calls resulted where PLC faded to CNG.
+  int decoded_muted_output;  // Number of calls returning a muted state output.
 };
 
 // Type of Noise Suppression.
 enum NsModes {
   kNsUnchanged = 0,   // previously set mode
   kNsDefault,         // platform default
   kNsConference,      // conferencing default
   kNsLowSuppression,  // lowest suppression
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/acm2/acm_receiver.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/acm2/acm_receiver.cc
@@ -94,17 +94,16 @@ int AcmReceiver::InsertPacket(const WebR
       if (last_audio_decoder_ && last_audio_decoder_->channels > 1) {
         // This is a CNG and the audio codec is not mono, so skip pushing in
         // packets into NetEq.
         return 0;
       }
     } else {
       last_audio_decoder_ = ci;
       last_audio_format_ = neteq_->GetDecoderFormat(ci->pltype);
-      last_audio_format_clockrate_hz_ = last_audio_format_->clockrate_hz;
       RTC_DCHECK(last_audio_format_);
       last_packet_sample_rate_hz_ = rtc::Optional<int>(ci->plfreq);
     }
   }  // |crit_sect_| is released.
 
   if (neteq_->InsertPacket(rtp_header, incoming_payload, receive_timestamp) <
       0) {
     LOG(LERROR) << "AcmReceiver::InsertPacket "
@@ -114,16 +113,19 @@ int AcmReceiver::InsertPacket(const WebR
   }
   return 0;
 }
 
 int AcmReceiver::GetAudio(int desired_freq_hz,
                           AudioFrame* audio_frame,
                           bool* muted) {
   RTC_DCHECK(muted);
+  // Accessing members, take the lock.
+  rtc::CritScope lock(&crit_sect_);
+
   if (neteq_->GetAudio(audio_frame, muted) != NetEq::kOK) {
     LOG(LERROR) << "AcmReceiver::GetAudio - NetEq Failed.";
     return -1;
   }
 
   const int current_sample_rate_hz = neteq_->last_output_sample_rate_hz();
 
   // Update if resampling is required.
@@ -298,20 +300,16 @@ int AcmReceiver::LastAudioCodec(CodecIns
   return 0;
 }
 
 rtc::Optional<SdpAudioFormat> AcmReceiver::LastAudioFormat() const {
   rtc::CritScope lock(&crit_sect_);
   return last_audio_format_;
 }
 
-int AcmReceiver::LastAudioSampleRate() const {
-  return last_audio_format_clockrate_hz_;
-}
-
 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);
 
   acm_stat->currentBufferSize = neteq_stat.current_buffer_size_ms;
   acm_stat->preferredBufferSize = neteq_stat.preferred_buffer_size_ms;
   acm_stat->jitterPeaksFound = neteq_stat.jitter_peaks_found ? true : false;
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/acm2/acm_receiver.h
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/acm2/acm_receiver.h
@@ -10,17 +10,16 @@
 
 #ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_RECEIVER_H_
 #define WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_RECEIVER_H_
 
 #include <map>
 #include <memory>
 #include <string>
 #include <vector>
-#include <atomic>
 
 #include "webrtc/base/array_view.h"
 #include "webrtc/base/criticalsection.h"
 #include "webrtc/base/optional.h"
 #include "webrtc/base/thread_annotations.h"
 #include "webrtc/common_audio/vad/include/webrtc_vad.h"
 #include "webrtc/modules/audio_coding/acm2/acm_resampler.h"
 #include "webrtc/modules/audio_coding/acm2/call_statistics.h"
@@ -205,17 +204,16 @@ class AcmReceiver {
   //
   // Get the audio codec associated with the last non-CNG/non-DTMF received
   // payload. If no non-CNG/non-DTMF packet is received -1 is returned,
   // otherwise return 0.
   //
   int LastAudioCodec(CodecInst* codec) const;
 
   rtc::Optional<SdpAudioFormat> LastAudioFormat() const;
-  int LastAudioSampleRate() const;
 
   //
   // Get a decoder given its registered payload-type.
   //
   // Input:
   //    -payload_type         : the payload-type of the codec to be retrieved.
   //
   // Output:
@@ -273,24 +271,21 @@ class AcmReceiver {
       uint8_t first_payload_byte) const EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
 
   uint32_t NowInTimestamp(int decoder_sampling_rate) const;
 
   rtc::CriticalSection crit_sect_;
   rtc::Optional<CodecInst> last_audio_decoder_ GUARDED_BY(crit_sect_);
   rtc::Optional<SdpAudioFormat> last_audio_format_ GUARDED_BY(crit_sect_);
   ACMResampler resampler_ GUARDED_BY(crit_sect_);
-  // After construction, this is only ever touched on the thread that calls
-  // AcmReceiver::GetAudio, and only modified in this method.
-  std::unique_ptr<int16_t[]> last_audio_buffer_;
+  std::unique_ptr<int16_t[]> last_audio_buffer_ GUARDED_BY(crit_sect_);
   CallStatistics call_stats_ GUARDED_BY(crit_sect_);
-  NetEq* const neteq_;
+  NetEq* neteq_;
   Clock* clock_;  // TODO(henrik.lundin) Make const if possible.
-  std::atomic<bool> resampled_last_output_frame_;
+  bool resampled_last_output_frame_ GUARDED_BY(crit_sect_);
   rtc::Optional<int> last_packet_sample_rate_hz_ GUARDED_BY(crit_sect_);
-  std::atomic<int> last_audio_format_clockrate_hz_;
 };
 
 }  // namespace acm2
 
 }  // namespace webrtc
 
 #endif  // WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_RECEIVER_H_
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/acm2/audio_coding_module.cc
@@ -134,17 +134,16 @@ class AudioCodingModuleImpl final : publ
                                    int sample_rate_hz,
                                    int num_channels,
                                    const std::string& name) override;
 
   // Get current received codec.
   int ReceiveCodec(CodecInst* current_codec) const override;
 
   rtc::Optional<SdpAudioFormat> ReceiveFormat() const override;
-  int ReceiveSampleRate() const override;
 
   // Incoming packet from network parsed and ready for decode.
   int IncomingPacket(const uint8_t* incoming_payload,
                      const size_t payload_length,
                      const WebRtcRTPHeader& rtp_info) override;
 
   // Incoming payloads, without rtp-info, the rtp-info will be created in ACM.
   // One usage for this API is when pre-encoded files are pushed in ACM.
@@ -1085,20 +1084,16 @@ int AudioCodingModuleImpl::ReceiveCodec(
   return receiver_.LastAudioCodec(current_codec);
 }
 
 rtc::Optional<SdpAudioFormat> AudioCodingModuleImpl::ReceiveFormat() const {
   rtc::CritScope lock(&acm_crit_sect_);
   return receiver_.LastAudioFormat();
 }
 
-int AudioCodingModuleImpl::ReceiveSampleRate() const {
-  return receiver_.LastAudioSampleRate();
-}
-
 // Incoming packet from network parsed and ready for decode.
 int AudioCodingModuleImpl::IncomingPacket(const uint8_t* incoming_payload,
                                           const size_t payload_length,
                                           const WebRtcRTPHeader& rtp_header) {
   return receiver_.InsertPacket(
       rtp_header,
       rtc::ArrayView<const uint8_t>(incoming_payload, payload_length));
 }
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/include/audio_coding_module.h
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/include/audio_coding_module.h
@@ -559,27 +559,16 @@ class AudioCodingModule {
   // Return value:
   //    An SdpAudioFormat describing the format associated with the last
   //    received payload.
   //    An empty Optional if no payload has yet been received.
   //
   virtual rtc::Optional<SdpAudioFormat> ReceiveFormat() const = 0;
 
   ///////////////////////////////////////////////////////////////////////////
-  // int ReceiveSampleRate()
-  //
-  // Mozilla extension.
-  // Return the sample-rate of the inbound audio stream.
-  //
-  // Return value:
-  // 0 if no audio has been received, the sample-rate of the inbound audio
-  // otherwise.
-  virtual int ReceiveSampleRate() const = 0;
-
-  ///////////////////////////////////////////////////////////////////////////
   // int32_t IncomingPacket()
   // Call this function to insert a parsed RTP packet into ACM.
   //
   // Inputs:
   //   -incoming_payload   : received payload.
   //   -payload_len_bytes  : the length of payload in bytes.
   //   -rtp_info           : the relevant information retrieved from RTP
   //                         header.
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_impl.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_impl.cc
@@ -456,16 +456,17 @@ rtc::Optional<uint32_t> NetEqImpl::GetPl
     // which is indicated by returning an empty value.
     return rtc::Optional<uint32_t>();
   }
   return rtc::Optional<uint32_t>(
       timestamp_scaler_->ToExternal(playout_timestamp_));
 }
 
 int NetEqImpl::last_output_sample_rate_hz() const {
+  rtc::CritScope lock(&crit_sect_);
   return last_output_sample_rate_hz_;
 }
 
 rtc::Optional<CodecInst> NetEqImpl::GetDecoder(int payload_type) const {
   rtc::CritScope lock(&crit_sect_);
   const DecoderDatabase::DecoderInfo* di =
       decoder_database_->GetDecoderInfo(payload_type);
   if (!di) {
--- a/media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_impl.h
+++ b/media/webrtc/trunk/webrtc/modules/audio_coding/neteq/neteq_impl.h
@@ -378,17 +378,17 @@ class NetEqImpl : public webrtc::NetEq {
   std::unique_ptr<Accelerate> accelerate_ GUARDED_BY(crit_sect_);
   std::unique_ptr<PreemptiveExpand> preemptive_expand_ GUARDED_BY(crit_sect_);
   RandomVector random_vector_ GUARDED_BY(crit_sect_);
   std::unique_ptr<ComfortNoise> comfort_noise_ GUARDED_BY(crit_sect_);
   Rtcp rtcp_ GUARDED_BY(crit_sect_);
   StatisticsCalculator stats_ GUARDED_BY(crit_sect_);
   int fs_hz_ GUARDED_BY(crit_sect_);
   int fs_mult_ GUARDED_BY(crit_sect_);
-  std::atomic<int> last_output_sample_rate_hz_;
+  int last_output_sample_rate_hz_ GUARDED_BY(crit_sect_);
   size_t output_size_samples_ GUARDED_BY(crit_sect_);
   size_t decoder_frame_length_ GUARDED_BY(crit_sect_);
   Modes last_mode_ GUARDED_BY(crit_sect_);
   Operations last_operation_ GUARDED_BY(crit_sect_);
   std::unique_ptr<int16_t[]> mute_factor_array_ GUARDED_BY(crit_sect_);
   size_t decoded_buffer_length_ GUARDED_BY(crit_sect_);
   std::unique_ptr<int16_t[]> decoded_buffer_ GUARDED_BY(crit_sect_);
   uint32_t playout_timestamp_ GUARDED_BY(crit_sect_);
--- a/media/webrtc/trunk/webrtc/voice_engine/channel.cc
+++ b/media/webrtc/trunk/webrtc/voice_engine/channel.cc
@@ -3490,22 +3490,23 @@ int Channel::SetSendRtpHeaderExtension(b
   _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
   if (enable) {
     error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id);
   }
   return error;
 }
 
 int Channel::GetRtpTimestampRateHz() const {
-  int sampleRate = audio_coding_->ReceiveSampleRate();
+  const auto format = audio_coding_->ReceiveFormat();
   // Default to the playout frequency if we've not gotten any packets yet.
   // TODO(ossu): Zero clockrate can only happen if we've added an external
   // decoder for a format we don't support internally. Remove once that way of
   // adding decoders is gone!
-  return sampleRate != 0 ? sampleRate
+  return (format && format->clockrate_hz != 0)
+             ? format->clockrate_hz
              : audio_coding_->PlayoutFrequency();
 }
 
 int64_t Channel::GetRTT(bool allow_associate_channel) const {
   RtcpMode method = _rtpRtcpModule->RTCP();
   if (method == RtcpMode::kOff) {
     return 0;
   }