diff options
Diffstat (limited to 'third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc')
-rw-r--r-- | third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc | 185 |
1 files changed, 107 insertions, 78 deletions
diff --git a/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc b/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc index 52e8cbad3a..e5c8bf6c08 100644 --- a/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/third_party/libwebrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -70,6 +70,62 @@ std::unique_ptr<NetEqController> CreateNetEqController( return controller_factory.CreateNetEqController(config); } +void SetAudioFrameActivityAndType(bool vad_enabled, + NetEqImpl::OutputType type, + AudioFrame::VADActivity last_vad_activity, + AudioFrame* audio_frame) { + switch (type) { + case NetEqImpl::OutputType::kNormalSpeech: { + audio_frame->speech_type_ = AudioFrame::kNormalSpeech; + audio_frame->vad_activity_ = AudioFrame::kVadActive; + break; + } + case NetEqImpl::OutputType::kVadPassive: { + // This should only be reached if the VAD is enabled. + RTC_DCHECK(vad_enabled); + audio_frame->speech_type_ = AudioFrame::kNormalSpeech; + audio_frame->vad_activity_ = AudioFrame::kVadPassive; + break; + } + case NetEqImpl::OutputType::kCNG: { + audio_frame->speech_type_ = AudioFrame::kCNG; + audio_frame->vad_activity_ = AudioFrame::kVadPassive; + break; + } + case NetEqImpl::OutputType::kPLC: { + audio_frame->speech_type_ = AudioFrame::kPLC; + audio_frame->vad_activity_ = last_vad_activity; + break; + } + case NetEqImpl::OutputType::kPLCCNG: { + audio_frame->speech_type_ = AudioFrame::kPLCCNG; + audio_frame->vad_activity_ = AudioFrame::kVadPassive; + break; + } + case NetEqImpl::OutputType::kCodecPLC: { + audio_frame->speech_type_ = AudioFrame::kCodecPLC; + audio_frame->vad_activity_ = last_vad_activity; + break; + } + default: + RTC_DCHECK_NOTREACHED(); + } + if (!vad_enabled) { + // Always set kVadUnknown when receive VAD is inactive. + audio_frame->vad_activity_ = AudioFrame::kVadUnknown; + } +} + +// Returns true if both payload types are known to the decoder database, and +// have the same sample rate. +bool EqualSampleRates(uint8_t pt1, + uint8_t pt2, + const DecoderDatabase& decoder_database) { + auto* di1 = decoder_database.GetDecoderInfo(pt1); + auto* di2 = decoder_database.GetDecoderInfo(pt2); + return di1 && di2 && di1->SampleRateHz() == di2->SampleRateHz(); +} + } // namespace NetEqImpl::Dependencies::Dependencies( @@ -84,8 +140,9 @@ NetEqImpl::Dependencies::Dependencies( new DecoderDatabase(decoder_factory, config.codec_pair_id)), dtmf_buffer(new DtmfBuffer(config.sample_rate_hz)), dtmf_tone_generator(new DtmfToneGenerator), - packet_buffer( - new PacketBuffer(config.max_packets_in_buffer, tick_timer.get())), + packet_buffer(new PacketBuffer(config.max_packets_in_buffer, + tick_timer.get(), + stats.get())), neteq_controller( CreateNetEqController(controller_factory, config.min_delay_ms, @@ -182,54 +239,6 @@ void NetEqImpl::InsertEmptyPacket(const RTPHeader& rtp_header) { controller_->RegisterEmptyPacket(); } -namespace { -void SetAudioFrameActivityAndType(bool vad_enabled, - NetEqImpl::OutputType type, - AudioFrame::VADActivity last_vad_activity, - AudioFrame* audio_frame) { - switch (type) { - case NetEqImpl::OutputType::kNormalSpeech: { - audio_frame->speech_type_ = AudioFrame::kNormalSpeech; - audio_frame->vad_activity_ = AudioFrame::kVadActive; - break; - } - case NetEqImpl::OutputType::kVadPassive: { - // This should only be reached if the VAD is enabled. - RTC_DCHECK(vad_enabled); - audio_frame->speech_type_ = AudioFrame::kNormalSpeech; - audio_frame->vad_activity_ = AudioFrame::kVadPassive; - break; - } - case NetEqImpl::OutputType::kCNG: { - audio_frame->speech_type_ = AudioFrame::kCNG; - audio_frame->vad_activity_ = AudioFrame::kVadPassive; - break; - } - case NetEqImpl::OutputType::kPLC: { - audio_frame->speech_type_ = AudioFrame::kPLC; - audio_frame->vad_activity_ = last_vad_activity; - break; - } - case NetEqImpl::OutputType::kPLCCNG: { - audio_frame->speech_type_ = AudioFrame::kPLCCNG; - audio_frame->vad_activity_ = AudioFrame::kVadPassive; - break; - } - case NetEqImpl::OutputType::kCodecPLC: { - audio_frame->speech_type_ = AudioFrame::kCodecPLC; - audio_frame->vad_activity_ = last_vad_activity; - break; - } - default: - RTC_DCHECK_NOTREACHED(); - } - if (!vad_enabled) { - // Always set kVadUnknown when receive VAD is inactive. - audio_frame->vad_activity_ = AudioFrame::kVadUnknown; - } -} -} // namespace - int NetEqImpl::GetAudio(AudioFrame* audio_frame, bool* muted, int* current_sample_rate_hz, @@ -265,7 +274,7 @@ void NetEqImpl::SetCodecs(const std::map<int, SdpAudioFormat>& codecs) { const std::vector<int> changed_payload_types = decoder_database_->SetCodecs(codecs); for (const int pt : changed_payload_types) { - packet_buffer_->DiscardPacketsWithPayloadType(pt, stats_.get()); + packet_buffer_->DiscardPacketsWithPayloadType(pt); } } @@ -283,8 +292,7 @@ int NetEqImpl::RemovePayloadType(uint8_t rtp_payload_type) { MutexLock lock(&mutex_); int ret = decoder_database_->Remove(rtp_payload_type); if (ret == DecoderDatabase::kOK || ret == DecoderDatabase::kDecoderNotFound) { - packet_buffer_->DiscardPacketsWithPayloadType(rtp_payload_type, - stats_.get()); + packet_buffer_->DiscardPacketsWithPayloadType(rtp_payload_type); return kOK; } return kFail; @@ -441,7 +449,7 @@ absl::optional<NetEq::DecoderFormat> NetEqImpl::GetDecoderFormat( void NetEqImpl::FlushBuffers() { MutexLock lock(&mutex_); RTC_LOG(LS_VERBOSE) << "FlushBuffers"; - packet_buffer_->Flush(stats_.get()); + packet_buffer_->Flush(); RTC_DCHECK(sync_buffer_.get()); RTC_DCHECK(expand_.get()); sync_buffer_->Flush(); @@ -542,7 +550,7 @@ int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header, // the packet has been successfully inserted into the packet buffer. // Flush the packet buffer and DTMF buffer. - packet_buffer_->Flush(stats_.get()); + packet_buffer_->Flush(); dtmf_buffer_->Flush(); // Update audio buffer timestamp. @@ -681,26 +689,25 @@ int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header, number_of_primary_packets); } - // Insert packets in buffer. - const int target_level_ms = controller_->TargetLevelMs(); - const int ret = packet_buffer_->InsertPacketList( - &parsed_packet_list, *decoder_database_, ¤t_rtp_payload_type_, - ¤t_cng_rtp_payload_type_, stats_.get(), decoder_frame_length_, - last_output_sample_rate_hz_, target_level_ms); bool buffer_flush_occured = false; - if (ret == PacketBuffer::kFlushed) { + for (Packet& packet : parsed_packet_list) { + if (MaybeChangePayloadType(packet.payload_type)) { + packet_buffer_->Flush(); + buffer_flush_occured = true; + } + int return_val = packet_buffer_->InsertPacket(std::move(packet)); + if (return_val == PacketBuffer::kFlushed) { + buffer_flush_occured = true; + } else if (return_val != PacketBuffer::kOK) { + // An error occurred. + return kOtherError; + } + } + + if (buffer_flush_occured) { // Reset DSP timestamp etc. if packet buffer flushed. new_codec_ = true; update_sample_rate_and_channels = true; - buffer_flush_occured = true; - } else if (ret == PacketBuffer::kPartialFlush) { - // Forward sync buffer timestamp - timestamp_ = packet_buffer_->PeekNextPacket()->timestamp; - sync_buffer_->IncreaseEndTimestamp(timestamp_ - - sync_buffer_->end_timestamp()); - buffer_flush_occured = true; - } else if (ret != PacketBuffer::kOK) { - return kOtherError; } if (first_packet_) { @@ -767,6 +774,31 @@ int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header, return 0; } +bool NetEqImpl::MaybeChangePayloadType(uint8_t payload_type) { + bool changed = false; + if (decoder_database_->IsComfortNoise(payload_type)) { + if (current_cng_rtp_payload_type_ && + *current_cng_rtp_payload_type_ != payload_type) { + // New CNG payload type implies new codec type. + current_rtp_payload_type_ = absl::nullopt; + changed = true; + } + current_cng_rtp_payload_type_ = payload_type; + } else if (!decoder_database_->IsDtmf(payload_type)) { + // This must be speech. + if ((current_rtp_payload_type_ && + *current_rtp_payload_type_ != payload_type) || + (current_cng_rtp_payload_type_ && + !EqualSampleRates(payload_type, *current_cng_rtp_payload_type_, + *decoder_database_))) { + current_cng_rtp_payload_type_ = absl::nullopt; + changed = true; + } + current_rtp_payload_type_ = payload_type; + } + return changed; +} + int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame, bool* muted, absl::optional<Operation> action_override) { @@ -1037,8 +1069,7 @@ int NetEqImpl::GetDecision(Operation* operation, uint32_t end_timestamp = sync_buffer_->end_timestamp(); if (!new_codec_) { const uint32_t five_seconds_samples = 5 * fs_hz_; - packet_buffer_->DiscardOldPackets(end_timestamp, five_seconds_samples, - stats_.get()); + packet_buffer_->DiscardOldPackets(end_timestamp, five_seconds_samples); } const Packet* packet = packet_buffer_->PeekNextPacket(); @@ -1058,14 +1089,12 @@ int NetEqImpl::GetDecision(Operation* operation, (end_timestamp >= packet->timestamp || end_timestamp + generated_noise_samples > packet->timestamp)) { // Don't use this packet, discard it. - if (packet_buffer_->DiscardNextPacket(stats_.get()) != - PacketBuffer::kOK) { + if (packet_buffer_->DiscardNextPacket() != PacketBuffer::kOK) { RTC_DCHECK_NOTREACHED(); // Must be ok by design. } // Check buffer again. if (!new_codec_) { - packet_buffer_->DiscardOldPackets(end_timestamp, 5 * fs_hz_, - stats_.get()); + packet_buffer_->DiscardOldPackets(end_timestamp, 5 * fs_hz_); } packet = packet_buffer_->PeekNextPacket(); } @@ -2024,7 +2053,7 @@ int NetEqImpl::ExtractPackets(size_t required_samples, // we could end up in the situation where we never decode anything, since // all incoming packets are considered too old but the buffer will also // never be flooded and flushed. - packet_buffer_->DiscardAllOldPackets(timestamp_, stats_.get()); + packet_buffer_->DiscardAllOldPackets(timestamp_); } return rtc::dchecked_cast<int>(extracted_samples); |