From b6046aece2a2c04a0c16ea5b9fced208a3c0daa8 Mon Sep 17 00:00:00 2001 From: Jakob Ivarsson Date: Tue, 27 Aug 2024 14:31:41 +0000 Subject: [PATCH] Add NetEq API to get info about the current decoder. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is currenly tracked in both AcmReceiver and NetEq. Adding this API enables us to have it in just one place. Bug: None Change-Id: Ia537f87f36b0aedf19c00a57bd6cec4425a49df1 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/360743 Commit-Queue: Jakob Ivarsson‎ Reviewed-by: Tomas Lundqvist Cr-Commit-Position: refs/heads/main@{#42872} --- api/neteq/neteq.h | 6 ++++ modules/audio_coding/neteq/neteq_impl.cc | 32 +++++++++++++------ modules/audio_coding/neteq/neteq_impl.h | 5 +++ .../audio_coding/neteq/neteq_impl_unittest.cc | 13 +++++++- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/api/neteq/neteq.h b/api/neteq/neteq.h index 77ccb31576..9e71afcc86 100644 --- a/api/neteq/neteq.h +++ b/api/neteq/neteq.h @@ -176,6 +176,7 @@ class NetEq { // Return type for GetDecoderFormat. struct DecoderFormat { + int payload_type; int sample_rate_hz; int num_channels; SdpAudioFormat sdp_format; @@ -300,6 +301,11 @@ class NetEq { virtual absl::optional GetDecoderFormat( int payload_type) const = 0; + // Returns info for the most recently used decoder. + virtual absl::optional GetCurrentDecoderFormat() const { + return absl::nullopt; + } + // Flushes both the packet buffer and the sync buffer. virtual void FlushBuffers() = 0; diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc index f4d01f570a..7ef4832cca 100644 --- a/modules/audio_coding/neteq/neteq_impl.cc +++ b/modules/audio_coding/neteq/neteq_impl.cc @@ -377,20 +377,34 @@ int NetEqImpl::last_output_sample_rate_hz() const { absl::optional NetEqImpl::GetDecoderFormat( int payload_type) const { MutexLock lock(&mutex_); + return GetDecoderFormatInternal(payload_type); +} + +absl::optional NetEqImpl::GetDecoderFormatInternal( + int payload_type) const { const DecoderDatabase::DecoderInfo* const di = decoder_database_->GetDecoderInfo(payload_type); - if (di) { - const AudioDecoder* const decoder = di->GetDecoder(); - // TODO(kwiberg): Why the special case for RED? - return DecoderFormat{ - /*sample_rate_hz=*/di->IsRed() ? 8000 : di->SampleRateHz(), - /*num_channels=*/ - decoder ? rtc::dchecked_cast(decoder->Channels()) : 1, - /*sdp_format=*/di->GetFormat()}; - } else { + if (di == nullptr) { // Payload type not registered. return absl::nullopt; } + const AudioDecoder* const decoder = di->GetDecoder(); + // TODO(kwiberg): Why the special case for RED? + return DecoderFormat{ + /*payload_type=*/payload_type, + /*sample_rate_hz=*/di->IsRed() ? 8000 : di->SampleRateHz(), + /*num_channels=*/ + decoder ? rtc::dchecked_cast(decoder->Channels()) : 1, + /*sdp_format=*/di->GetFormat()}; +} + +absl::optional NetEqImpl::GetCurrentDecoderFormat() + const { + MutexLock lock(&mutex_); + if (!current_rtp_payload_type_.has_value()) { + return absl::nullopt; + } + return GetDecoderFormatInternal(*current_rtp_payload_type_); } void NetEqImpl::FlushBuffers() { diff --git a/modules/audio_coding/neteq/neteq_impl.h b/modules/audio_coding/neteq/neteq_impl.h index 73d2920407..1b2e12d6c6 100644 --- a/modules/audio_coding/neteq/neteq_impl.h +++ b/modules/audio_coding/neteq/neteq_impl.h @@ -180,6 +180,8 @@ class NetEqImpl : public webrtc::NetEq { absl::optional GetDecoderFormat( int payload_type) const override; + absl::optional GetCurrentDecoderFormat() const override; + // Flushes both the packet buffer and the sync buffer. void FlushBuffers() override; @@ -340,6 +342,9 @@ class NetEqImpl : public webrtc::NetEq { NetEqController::PacketArrivedInfo ToPacketArrivedInfo( const Packet& packet) const RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + absl::optional GetDecoderFormatInternal(int payload_type) const + RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + const Environment env_; mutable Mutex mutex_; diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc index 1e4cc9c2a5..561a10ead7 100644 --- a/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -1734,16 +1734,28 @@ TEST_F(NetEqImplTest, InsertPacketChangePayloadType) { header.timestamp = 1234; uint8_t payload[160] = {0}; + absl::optional decoder = + neteq_->GetCurrentDecoderFormat(); + EXPECT_FALSE(decoder.has_value()); + EXPECT_EQ(neteq_->InsertPacket(header, payload, /*receive_time=*/clock_.CurrentTime()), NetEq::kOK); EXPECT_EQ(neteq_->GetLifetimeStatistics().packets_discarded, 0u); + decoder = neteq_->GetCurrentDecoderFormat(); + ASSERT_TRUE(decoder.has_value()); + EXPECT_EQ(decoder->payload_type, kPcmuPayloadType); + EXPECT_EQ(decoder->sdp_format.name, "pcmu"); header.payloadType = kPcmaPayloadType; header.timestamp += 80; EXPECT_EQ(neteq_->InsertPacket(header, payload, /*receive_time=*/clock_.CurrentTime()), NetEq::kOK); + decoder = neteq_->GetCurrentDecoderFormat(); + ASSERT_TRUE(decoder.has_value()); + EXPECT_EQ(decoder->payload_type, kPcmaPayloadType); + EXPECT_EQ(decoder->sdp_format.name, "pcma"); // The previous packet should be discarded since the codec changed. EXPECT_EQ(neteq_->GetLifetimeStatistics().packets_discarded, 1u); @@ -1753,7 +1765,6 @@ TEST_F(NetEqImplTest, InsertPacketChangePayloadType) { EXPECT_EQ(neteq_->GetAudio(&audio_frame, &muted), NetEq::kOK); EXPECT_EQ(audio_frame.sample_rate_hz(), 8000); EXPECT_EQ(audio_frame.speech_type_, AudioFrame::SpeechType::kNormalSpeech); - // TODO(jakobi): check active decoder. } class Decoder120ms : public AudioDecoder {