using ::testing::Eq; using ::testing::IsTrue; using ::testing::NiceMock; using ::testing::Return; using ::testing::SaveArg;
constexpr int kRtcpIntervalMs = 1000;
constexpr int kSsrc = 333;
constexpr int kPayloadType = 1;
constexpr int kSampleRateHz = 48000;
constexpr int kRtpRateHz = 48000;
std::unique_ptr<AudioFrame> CreateAudioFrame(uint8_t data_init_value = 0) { auto frame = std::make_unique<AudioFrame>();
frame->sample_rate_hz_ = kSampleRateHz;
frame->samples_per_channel_ = kSampleRateHz / 100;
frame->num_channels_ = 1;
frame->set_absolute_capture_timestamp_ms(
time_controller_.GetClock()->TimeInMilliseconds());
int16_t* dest = frame->mutable_data();
for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_;
i++, dest++) {
*dest = data_init_value;
} return frame;
}
void ProcessNextFrame(std::unique_ptr<AudioFrame> audio_frame) {
channel_->ProcessAndEncodeAudio(std::move(audio_frame)); // Advance time to process the task queue.
time_controller_.AdvanceTime(TimeDelta::Millis(10));
}
TEST_F(ChannelSendTest, StopSendShouldResetEncoder) {
channel_->StartSend(); // Insert two frames which should trigger a new packet.
EXPECT_CALL(transport_, SendRtp).Times(1);
ProcessNextFrame();
ProcessNextFrame();
EXPECT_CALL(transport_, SendRtp).Times(0);
ProcessNextFrame(); // StopSend should clear the previous audio frame stored in the encoder.
channel_->StopSend();
channel_->StartSend(); // The following frame should not trigger a new packet since the encoder // needs 20 ms audio.
EXPECT_CALL(transport_, SendRtp).Times(0);
ProcessNextFrame();
}
channel_->StartSend();
int64_t transformable_frame_timestamp = -1;
EXPECT_CALL(*mock_frame_transformer, Transform)
.WillOnce([&](std::unique_ptr<TransformableFrameInterface> frame) {
transformable_frame_timestamp = frame->GetTimestamp();
callback->OnTransformedFrame(std::move(frame));
}); // Insert two frames which should trigger a new packet.
ProcessNextFrame();
ProcessNextFrame();
// Ensure the RTP timestamp on the frame passed to the transformer // includes the RTP offset and matches the actual RTP timestamp on the sent // packet.
EXPECT_THAT(
WaitUntil([&] { return0 + channel_->GetRtpRtcp()->StartTimestamp(); },
Eq(transformable_frame_timestamp)),
IsRtcOk());
EXPECT_THAT(WaitUntil([&] { return sent_timestamp; }, IsTrue()), IsRtcOk());
EXPECT_EQ(*sent_timestamp, transformable_frame_timestamp);
}
// Ensure that AudioLevel calculations are performed correctly per-packet even // if there's an async Encoded Frame Transform happening.
TEST_F(ChannelSendTest, AudioLevelsAttachedToCorrectTransformedFrame) {
channel_->SetSendAudioLevelIndicationStatus(true, /*id=*/1);
RtpPacketReceived::ExtensionManager extension_manager;
extension_manager.RegisterByType(1, kRtpExtensionAudioLevel);
// Insert two frames of 7s which should trigger a new packet.
ProcessNextFrame(CreateAudioFrame(/*data_init_value=*/7));
ProcessNextFrame(CreateAudioFrame(/*data_init_value=*/7));
// Insert two more frames of 3s, meaning a second packet is // prepared and sent to the transform before the first packet has // been sent.
ProcessNextFrame(CreateAudioFrame(/*data_init_value=*/3));
ProcessNextFrame(CreateAudioFrame(/*data_init_value=*/3));
// Wait for both packets to be encoded and sent to the transform.
EXPECT_THAT(WaitUntil([&] { return frames.size(); }, Eq(2ul)), IsRtcOk()); // Complete the transforms on both frames at the same time
callback->OnTransformedFrame(std::move(frames[0]));
callback->OnTransformedFrame(std::move(frames[1]));
// Allow things posted back to the encoder queue to run.
time_controller_.AdvanceTime(TimeDelta::Millis(10));
// Ensure the audio levels on both sent packets is present and // matches their contents.
EXPECT_THAT(WaitUntil([&] { return sent_audio_levels.size(); }, Eq(2ul)),
IsRtcOk()); // rms dbov of the packet with raw audio of 7s is 73.
EXPECT_EQ(sent_audio_levels[0], 73); // rms dbov of the second packet with raw audio of 3s is 81.
EXPECT_EQ(sent_audio_levels[1], 81);
}
// Ensure that AudioLevels are attached to frames injected into the // Encoded Frame transform.
TEST_F(ChannelSendTest, AudioLevelsAttachedToInsertedTransformedFrame) {
channel_->SetSendAudioLevelIndicationStatus(true, /*id=*/1);
RtpPacketReceived::ExtensionManager extension_manager;
extension_manager.RegisterByType(1, kRtpExtensionAudioLevel);
// Allow things posted back to the encoder queue to run.
time_controller_.AdvanceTime(TimeDelta::Millis(10));
// Ensure the audio levels is set on the sent packet.
EXPECT_THAT(WaitUntil([&] { return sent_audio_level; }, IsTrue()), IsRtcOk());
EXPECT_EQ(*sent_audio_level, audio_level);
}
// Ensure that GetUsedRate returns null if no frames are coded.
TEST_F(ChannelSendTest, NoUsedRateInitially) {
channel_->StartSend(); auto used_rate = channel_->GetUsedRate();
EXPECT_EQ(used_rate, std::nullopt);
}
// Ensure that GetUsedRate returns value with one coded frame.
TEST_F(ChannelSendTest, ValidUsedRateWithOneCodedFrame) {
channel_->StartSend();
EXPECT_CALL(transport_, SendRtp).Times(1);
ProcessNextFrame();
ProcessNextFrame(); auto used_rate = channel_->GetUsedRate();
EXPECT_GT(used_rate.value().bps(), 0);
}
// Ensure that GetUsedRate returns value with one coded frame.
TEST_F(ChannelSendTest, UsedRateIsLargerofLastTwoFrames) {
channel_->StartSend();
channel_->CallEncoder(
[&](AudioEncoder* encoder) { encoder->OnReceivedOverhead(72); });
DataRate lowrate = DataRate::BitsPerSec(40000);
DataRate highrate = DataRate::BitsPerSec(80000);
BitrateAllocationUpdate update;
update.bwe_period = TimeDelta::Millis(100);
update.target_bitrate = lowrate;
channel_->OnBitrateAllocation(update);
EXPECT_CALL(transport_, SendRtp).Times(1);
ProcessNextFrame();
ProcessNextFrame(); // Last two frames have rates [32kbps, -], yielding 32kbps. auto used_rate_1 = channel_->GetUsedRate();
update.target_bitrate = highrate;
channel_->OnBitrateAllocation(update);
EXPECT_CALL(transport_, SendRtp).Times(1);
ProcessNextFrame();
ProcessNextFrame(); // Last two frames have rates [54kbps, 32kbps], yielding 54kbps auto used_rate_2 = channel_->GetUsedRate();
update.target_bitrate = lowrate;
channel_->OnBitrateAllocation(update);
EXPECT_CALL(transport_, SendRtp).Times(1);
ProcessNextFrame();
ProcessNextFrame(); // Last two frames have rates [32kbps 54kbps], yielding 54kbps auto used_rate_3 = channel_->GetUsedRate();
// Test that we gracefully handle packets while the congestion control objects // are not configured. This can happen during calls // AudioSendStream::ConfigureStream
TEST_F(ChannelSendTest, EnqueuePacketsGracefullyHandlesNonInitializedPacer) {
EXPECT_CALL(transport_, SendRtp).Times(1);
channel_->StartSend();
channel_->ResetSenderCongestionControlObjects(); // This should trigger a packet, but congestion control is not configured // so it should be dropped
ProcessNextFrame();
ProcessNextFrame();
channel_->RegisterSenderCongestionControlObjects(&transport_controller_); // Now that we reconfigured the congestion control objects the new frame // should be processed
ProcessNextFrame();
ProcessNextFrame();
}
// Creates a frame with the given CSRCs where other values are copied from the // template.
std::unique_ptr<TransformableAudioFrameInterface> CreateMockFrameWithCsrcs( const TransformableAudioFrameInterface* frame_template, const std::vector<uint32_t>& csrcs) {
std::unique_ptr<MockTransformableAudioFrame> mock_frame =
std::make_unique<MockTransformableAudioFrame>();
EXPECT_CALL(*mock_frame, GetContributingSources)
.WillRepeatedly(Return(csrcs));
// Configure the mock frame transformer to return a frame with different CSRCs // than it is provided.
std::vector<uint32_t> csrcs_provided_to_frame_transformer;
std::vector<uint32_t> csrcs_output_by_frame_transformer = {1, 2, 3};
EXPECT_CALL(*mock_frame_transformer, Transform)
.WillRepeatedly(
[&](std::unique_ptr<TransformableFrameInterface> frame) { auto audio_frame = static_cast<TransformableAudioFrameInterface*>(frame.get());
csrcs_provided_to_frame_transformer.assign(
audio_frame->GetContributingSources().begin(),
audio_frame->GetContributingSources().end());
callback->OnTransformedFrame(CreateMockFrameWithCsrcs(
audio_frame, csrcs_output_by_frame_transformer));
});
EXPECT_EQ(csrcs_provided_to_frame_transformer, set_csrcs)
<< "The CSRCs configured in ChannelSend should be passed to the frame " "transformer.";
EXPECT_EQ(sent_csrcs, csrcs_output_by_frame_transformer)
<< "CSRCs provided by the frame transformer should propagate to the RTP " "packet.";
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.