Bug 1456115 - Stop locking when getting the sampling rate from the channel in acm_receiver.cc. r?dminor draft
authorPaul Adenot <paul@paul.cx>
Mon, 09 Apr 2018 13:52:08 +0200
changeset 787245 6059cc975097bdbd46679f013ab7ef08caf28114
parent 786478 dfb15917c057f17e5143f7d7c6e1972ba53efc49
child 787246 910254a18841b98287e6f8986601279f4e2f945d
push id107695
push userpaul@paul.cx
push dateTue, 24 Apr 2018 16:04:50 +0000
reviewersdminor
bugs1456115
milestone61.0a1
Bug 1456115 - Stop locking when getting the sampling rate from the channel in acm_receiver.cc. r?dminor This accounts for half of our audio dropouts, there is very high contention on this piece of data. MozReview-Commit-ID: 2HSfqZHT2MK
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/voice_engine/channel.cc
--- 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,16 +94,17 @@ 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 "
@@ -300,16 +301,20 @@ 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,16 +10,17 @@
 
 #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"
@@ -204,16 +205,17 @@ 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:
@@ -277,15 +279,16 @@ class AcmReceiver {
   rtc::Optional<SdpAudioFormat> last_audio_format_ GUARDED_BY(crit_sect_);
   ACMResampler resampler_ GUARDED_BY(crit_sect_);
   std::unique_ptr<int16_t[]> last_audio_buffer_ GUARDED_BY(crit_sect_);
   CallStatistics call_stats_ GUARDED_BY(crit_sect_);
   NetEq* neteq_;
   Clock* clock_;  // TODO(henrik.lundin) Make const if possible.
   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,16 +134,17 @@ 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.
@@ -1084,16 +1085,20 @@ 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,16 +559,27 @@ 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/voice_engine/channel.cc
+++ b/media/webrtc/trunk/webrtc/voice_engine/channel.cc
@@ -3490,23 +3490,22 @@ int Channel::SetSendRtpHeaderExtension(b
   _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
   if (enable) {
     error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id);
   }
   return error;
 }
 
 int Channel::GetRtpTimestampRateHz() const {
-  const auto format = audio_coding_->ReceiveFormat();
+  int sampleRate = audio_coding_->ReceiveSampleRate();
   // 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 (format && format->clockrate_hz != 0)
-             ? format->clockrate_hz
+  return sampleRate != 0 ? sampleRate
              : audio_coding_->PlayoutFrequency();
 }
 
 int64_t Channel::GetRTT(bool allow_associate_channel) const {
   RtcpMode method = _rtpRtcpModule->RTCP();
   if (method == RtcpMode::kOff) {
     return 0;
   }