diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/acm2/acm_receiver.cc index 0b19310b84..73518b84fc 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.cc +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.cc @@ -98,6 +98,8 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header, } } else { last_audio_decoder_ = ci; + last_audio_format_ = neteq_->GetDecoderFormat(ci->pltype); + RTC_DCHECK(last_audio_format_); last_packet_sample_rate_hz_ = rtc::Optional(ci->plfreq); } @@ -263,6 +265,7 @@ void AcmReceiver::RemoveAllCodecs() { rtc::CritScope lock(&crit_sect_); neteq_->RemoveAllPayloadTypes(); last_audio_decoder_ = rtc::Optional(); + last_audio_format_ = rtc::Optional(); last_packet_sample_rate_hz_ = rtc::Optional(); } @@ -275,6 +278,7 @@ int AcmReceiver::RemoveCodec(uint8_t payload_type) { } if (last_audio_decoder_ && payload_type == last_audio_decoder_->pltype) { last_audio_decoder_ = rtc::Optional(); + last_audio_format_ = rtc::Optional(); last_packet_sample_rate_hz_ = rtc::Optional(); } return 0; @@ -297,6 +301,11 @@ int AcmReceiver::LastAudioCodec(CodecInst* codec) const { return 0; } +rtc::Optional AcmReceiver::LastAudioFormat() const { + rtc::CritScope lock(&crit_sect_); + return last_audio_format_; +} + void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) { NetEqNetworkStatistics neteq_stat; // NetEq function always returns zero, so we don't check the return value. diff --git a/webrtc/modules/audio_coding/acm2/acm_receiver.h b/webrtc/modules/audio_coding/acm2/acm_receiver.h index a9550fbf41..64150744e3 100644 --- a/webrtc/modules/audio_coding/acm2/acm_receiver.h +++ b/webrtc/modules/audio_coding/acm2/acm_receiver.h @@ -209,6 +209,8 @@ class AcmReceiver { // int LastAudioCodec(CodecInst* codec) const; + rtc::Optional LastAudioFormat() const; + // // Get a decoder given its registered payload-type. // @@ -273,6 +275,7 @@ class AcmReceiver { rtc::CriticalSection crit_sect_; rtc::Optional last_audio_decoder_ GUARDED_BY(crit_sect_); + rtc::Optional last_audio_format_ GUARDED_BY(crit_sect_); ACMResampler resampler_ GUARDED_BY(crit_sect_); std::unique_ptr last_audio_buffer_ GUARDED_BY(crit_sect_); CallStatistics call_stats_ GUARDED_BY(crit_sect_); diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module.cc b/webrtc/modules/audio_coding/acm2/audio_coding_module.cc index a845c017d1..ee1034b75a 100644 --- a/webrtc/modules/audio_coding/acm2/audio_coding_module.cc +++ b/webrtc/modules/audio_coding/acm2/audio_coding_module.cc @@ -138,6 +138,8 @@ class AudioCodingModuleImpl final : public AudioCodingModule { // Get current received codec. int ReceiveCodec(CodecInst* current_codec) const override; + rtc::Optional ReceiveFormat() const override; + // Incoming packet from network parsed and ready for decode. int IncomingPacket(const uint8_t* incoming_payload, const size_t payload_length, @@ -1087,6 +1089,11 @@ int AudioCodingModuleImpl::ReceiveCodec(CodecInst* current_codec) const { return receiver_.LastAudioCodec(current_codec); } +rtc::Optional AudioCodingModuleImpl::ReceiveFormat() const { + rtc::CritScope lock(&acm_crit_sect_); + return receiver_.LastAudioFormat(); +} + // Incoming packet from network parsed and ready for decode. int AudioCodingModuleImpl::IncomingPacket(const uint8_t* incoming_payload, const size_t payload_length, diff --git a/webrtc/modules/audio_coding/include/audio_coding_module.h b/webrtc/modules/audio_coding/include/audio_coding_module.h index e62bbd70f9..a0dafec022 100644 --- a/webrtc/modules/audio_coding/include/audio_coding_module.h +++ b/webrtc/modules/audio_coding/include/audio_coding_module.h @@ -552,6 +552,17 @@ class AudioCodingModule { // virtual int32_t ReceiveCodec(CodecInst* curr_receive_codec) const = 0; + /////////////////////////////////////////////////////////////////////////// + // rtc::Optional ReceiveFormat() + // Get the format associated with last received payload. + // + // 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 ReceiveFormat() const = 0; + /////////////////////////////////////////////////////////////////////////// // int32_t IncomingPacket() // Call this function to insert a parsed RTP packet into ACM. diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc index 0965963fdd..6dcef5fb4b 100644 --- a/webrtc/voice_engine/channel.cc +++ b/webrtc/voice_engine/channel.cc @@ -718,7 +718,7 @@ MixerParticipant::AudioFrameInfo Channel::GetAudioFrameWithMuted( rtp_ts_wraparound_handler_->Unwrap(audioFrame->timestamp_); audioFrame->elapsed_time_ms_ = (unwrap_timestamp - capture_start_rtp_time_stamp_) / - (GetPlayoutFrequency() / 1000); + (GetRtpTimestampRateHz() / 1000); { rtc::CritScope lock(&ts_stats_lock_); @@ -3162,7 +3162,7 @@ void Channel::UpdatePlayoutTimestamp(bool rtcp) { uint32_t playout_timestamp = *jitter_buffer_playout_timestamp_; // Remove the playout delay. - playout_timestamp -= (delay_ms * (GetPlayoutFrequency() / 1000)); + playout_timestamp -= (delay_ms * (GetRtpTimestampRateHz() / 1000)); WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId), "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu", @@ -3222,25 +3222,15 @@ int Channel::SetSendRtpHeaderExtension(bool enable, return error; } -int32_t Channel::GetPlayoutFrequency() const { - int32_t playout_frequency = audio_coding_->PlayoutFrequency(); - CodecInst current_recive_codec; - if (audio_coding_->ReceiveCodec(¤t_recive_codec) == 0) { - if (STR_CASE_CMP("G722", current_recive_codec.plname) == 0) { - // Even though the actual sampling rate for G.722 audio is - // 16,000 Hz, the RTP clock rate for the G722 payload format is - // 8,000 Hz because that value was erroneously assigned in - // RFC 1890 and must remain unchanged for backward compatibility. - playout_frequency = 8000; - } else if (STR_CASE_CMP("opus", current_recive_codec.plname) == 0) { - // We are resampling Opus internally to 32,000 Hz until all our - // DSP routines can operate at 48,000 Hz, but the RTP clock - // rate for the Opus payload format is standardized to 48,000 Hz, - // because that is the maximum supported decoding sampling rate. - playout_frequency = 48000; - } - } - return playout_frequency; +int Channel::GetRtpTimestampRateHz() const { + 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 (format && format->clockrate_hz != 0) + ? format->clockrate_hz + : audio_coding_->PlayoutFrequency(); } int64_t Channel::GetRTT(bool allow_associate_channel) const { diff --git a/webrtc/voice_engine/channel.h b/webrtc/voice_engine/channel.h index fc123e384f..bf279d870e 100644 --- a/webrtc/voice_engine/channel.h +++ b/webrtc/voice_engine/channel.h @@ -446,7 +446,7 @@ class Channel RTPExtensionType type, unsigned char id); - int32_t GetPlayoutFrequency() const; + int GetRtpTimestampRateHz() const; int64_t GetRTT(bool allow_associate_channel) const; rtc::CriticalSection _fileCritSect;