Ensure the AudioCodingModule is reset when sending is stopped.

Bug: webrtc:42226041
Change-Id: Ife3548bda3042a7447b7c50f48f023a2bc0bc443
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/362103
Commit-Queue: Lionel Koenig <lionelk@webrtc.org>
Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org>
Reviewed-by: Jakob Ivarsson‎ <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43017}
This commit is contained in:
Lionel Koenig 2024-09-12 15:50:46 +02:00 committed by WebRTC LUCI CQ
parent 6aab4ccf42
commit ec38238af7
5 changed files with 62 additions and 2 deletions

View File

@ -562,7 +562,7 @@ void ChannelSend::StopSend() {
rtc::Event flush; rtc::Event flush;
encoder_queue_->PostTask([this, &flush]() { encoder_queue_->PostTask([this, &flush]() {
RTC_DCHECK_RUN_ON(&encoder_queue_checker_); RTC_DCHECK_RUN_ON(&encoder_queue_checker_);
CallEncoder([](AudioEncoder* encoder) { encoder->Reset(); }); audio_coding_->Reset();
flush.Set(); flush.Set();
}); });
flush.Wait(rtc::Event::kForever); flush.Wait(rtc::Event::kForever);

View File

@ -140,6 +140,7 @@ TEST_F(ChannelSendTest, StopSendShouldResetEncoder) {
ProcessNextFrame(); ProcessNextFrame();
// StopSend should clear the previous audio frame stored in the encoder. // StopSend should clear the previous audio frame stored in the encoder.
channel_->StopSend(); channel_->StopSend();
channel_->StartSend(); channel_->StartSend();
// The following frame should not trigger a new packet since the encoder // The following frame should not trigger a new packet since the encoder
// needs 20 ms audio. // needs 20 ms audio.

View File

@ -43,6 +43,8 @@ class AudioCodingModuleImpl final : public AudioCodingModule {
explicit AudioCodingModuleImpl(); explicit AudioCodingModuleImpl();
~AudioCodingModuleImpl() override; ~AudioCodingModuleImpl() override;
void Reset() override;
///////////////////////////////////////// /////////////////////////////////////////
// Sender // Sender
// //
@ -280,7 +282,7 @@ int32_t AudioCodingModuleImpl::Encode(
absolute_capture_timestamp_ms_.value_or(-1)); absolute_capture_timestamp_ms_.value_or(-1));
} }
} }
absolute_capture_timestamp_ms_ = std::nullopt; absolute_capture_timestamp_ms_.reset();
previous_pltype_ = encoded_info.payload_type; previous_pltype_ = encoded_info.payload_type;
return static_cast<int32_t>(encode_buffer_.size()); return static_cast<int32_t>(encode_buffer_.size());
} }
@ -289,6 +291,14 @@ int32_t AudioCodingModuleImpl::Encode(
// Sender // Sender
// //
void AudioCodingModuleImpl::Reset() {
MutexLock lock(&acm_mutex_);
absolute_capture_timestamp_ms_.reset();
if (HaveValidEncoder("Reset")) {
encoder_stack_->Reset();
}
}
void AudioCodingModuleImpl::ModifyEncoder( void AudioCodingModuleImpl::ModifyEncoder(
rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) { rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) {
MutexLock lock(&acm_mutex_); MutexLock lock(&acm_mutex_);

View File

@ -522,6 +522,17 @@ class AudioPacketizationCallbackMock : public AudioPacketizationCallback {
(override)); (override));
}; };
TEST(AudioCodingModule, DoesResetEncoder) {
std::unique_ptr<AudioCodingModule> acm = AudioCodingModule::Create();
auto encoder = std::make_unique<MockAudioEncoder>();
MockAudioEncoder* encoder_mock = encoder.get();
acm->SetEncoder(std::move(encoder));
EXPECT_CALL(*encoder_mock, Reset()).Times(1);
acm->Reset();
}
class AcmAbsoluteCaptureTimestamp : public ::testing::Test { class AcmAbsoluteCaptureTimestamp : public ::testing::Test {
public: public:
AcmAbsoluteCaptureTimestamp() : audio_frame_(kSampleRateHz, kNumChannels) {} AcmAbsoluteCaptureTimestamp() : audio_frame_(kSampleRateHz, kNumChannels) {}
@ -587,6 +598,40 @@ TEST_F(AcmAbsoluteCaptureTimestamp, HaveBeginningOfFrameCaptureTime) {
} }
} }
TEST_F(AcmAbsoluteCaptureTimestamp, DoesResetWhenAudioCodingModuleDo) {
constexpr int64_t first_absolute_capture_timestamp_ms = 123456789;
int64_t absolute_capture_timestamp_ms = first_absolute_capture_timestamp_ms;
EXPECT_CALL(transport_,
SendData(_, _, _, _, _, first_absolute_capture_timestamp_ms))
.Times(1);
EXPECT_CALL(
transport_,
SendData(_, _, _, _, _, first_absolute_capture_timestamp_ms + kPTimeMs))
.Times(1);
for (int k = 0; k < 5; ++k) {
acm_->Add10MsData(
GetAudioWithAbsoluteCaptureTimestamp(absolute_capture_timestamp_ms));
absolute_capture_timestamp_ms += 10;
}
acm_->Reset();
constexpr int64_t after_reset_absolute_capture_timestamp_ms = 523456789;
EXPECT_CALL(transport_, SendData(_, _, _, _, _,
after_reset_absolute_capture_timestamp_ms))
.Times(1);
EXPECT_CALL(transport_,
SendData(_, _, _, _, _,
after_reset_absolute_capture_timestamp_ms + kPTimeMs))
.Times(1);
absolute_capture_timestamp_ms = after_reset_absolute_capture_timestamp_ms;
for (int k = 0; k < 5; ++k) {
acm_->Add10MsData(
GetAudioWithAbsoluteCaptureTimestamp(absolute_capture_timestamp_ms));
absolute_capture_timestamp_ms += 10;
}
}
// Disabling all of these tests on iOS until file support has been added. // Disabling all of these tests on iOS until file support has been added.
// See https://code.google.com/p/webrtc/issues/detail?id=4752 for details. // See https://code.google.com/p/webrtc/issues/detail?id=4752 for details.
#if !defined(WEBRTC_IOS) #if !defined(WEBRTC_IOS)

View File

@ -78,6 +78,10 @@ class AudioCodingModule {
}); });
} }
// Reset encoder and audio coding module. This throws away any audio passed
// and starts fresh.
virtual void Reset() = 0;
// int32_t RegisterTransportCallback() // int32_t RegisterTransportCallback()
// Register a transport callback which will be called to deliver // Register a transport callback which will be called to deliver
// the encoded buffers whenever Process() is called and a // the encoded buffers whenever Process() is called and a