Support sending IncomingFrames in audio

ChannelSendFrameTransformerDelegate::SendFrame() currently only
supports sending frames in a single direction. With this change, we
allow sending received audio frames.

Bug: chromium:1464847
Change-Id: I8113a3278dfce7b2ba709afecc672bc9af9c4a27
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/316600
Reviewed-by: Tony Herre <herre@google.com>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40643}
This commit is contained in:
Palak Agarwal 2023-08-22 16:58:33 +02:00 committed by WebRTC LUCI CQ
parent 93316a936f
commit 14e5d4ce5e
4 changed files with 65 additions and 9 deletions

View File

@ -146,7 +146,7 @@ TEST(ChannelReceiveFrameTransformerDelegateTest,
delegate->Reset();
EXPECT_CALL(mock_channel, ReceiveFrame).Times(0);
delegate->OnTransformedFrame(std::make_unique<MockTransformableFrame>());
delegate->OnTransformedFrame(std::make_unique<MockTransformableAudioFrame>());
rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
}

View File

@ -160,19 +160,25 @@ void ChannelSendFrameTransformerDelegate::SendFrame(
std::unique_ptr<TransformableFrameInterface> frame) const {
MutexLock lock(&send_lock_);
RTC_DCHECK_RUN_ON(encoder_queue_);
RTC_CHECK_EQ(frame->GetDirection(),
TransformableFrameInterface::Direction::kSender);
if (!send_frame_callback_)
return;
uint32_t rtp_start_timestamp = 0;
if (frame->GetDirection() ==
TransformableFrameInterface::Direction::kSender) {
auto* outgoing_frame =
static_cast<TransformableOutgoingAudioFrame*>(frame.get());
rtp_start_timestamp = outgoing_frame->GetStartTimestamp();
}
auto* transformed_frame =
static_cast<TransformableOutgoingAudioFrame*>(frame.get());
static_cast<TransformableAudioFrameInterface*>(frame.get());
send_frame_callback_(
InterfaceFrameTypeToInternalFrameType(transformed_frame->Type()),
transformed_frame->GetPayloadType(),
transformed_frame->GetTimestamp() -
transformed_frame->GetStartTimestamp(),
transformed_frame->GetTimestamp() - rtp_start_timestamp,
transformed_frame->GetData(),
*transformed_frame->AbsoluteCaptureTimestamp());
transformed_frame->AbsoluteCaptureTimestamp()
? *transformed_frame->AbsoluteCaptureTimestamp()
: 0);
}
std::unique_ptr<TransformableAudioFrameInterface> CloneSenderAudioFrame(

View File

@ -22,7 +22,10 @@
namespace webrtc {
namespace {
using ::testing::_;
using ::testing::ElementsAre;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SaveArg;
class MockChannelSend {
@ -48,6 +51,18 @@ class MockChannelSend {
}
};
std::unique_ptr<MockTransformableAudioFrame> CreateMockReceiverFrame() {
const uint8_t mock_data[] = {1, 2, 3, 4};
std::unique_ptr<MockTransformableAudioFrame> mock_frame =
std::make_unique<MockTransformableAudioFrame>();
rtc::ArrayView<const uint8_t> payload(mock_data);
ON_CALL(*mock_frame, GetData).WillByDefault(Return(payload));
ON_CALL(*mock_frame, GetPayloadType).WillByDefault(Return(0));
ON_CALL(*mock_frame, GetDirection)
.WillByDefault(Return(TransformableFrameInterface::Direction::kReceiver));
return mock_frame;
}
// Test that the delegate registers itself with the frame transformer on Init().
TEST(ChannelSendFrameTransformerDelegateTest,
RegisterTransformedFrameCallbackOnInit) {
@ -104,6 +119,36 @@ TEST(ChannelSendFrameTransformerDelegateTest,
channel_queue.WaitForPreviouslyPostedTasks();
}
// Test that when the delegate receives a Incoming frame from the frame
// transformer, it passes it to the channel using the SendFrameCallback.
TEST(ChannelSendFrameTransformerDelegateTest,
TransformRunsChannelSendCallbackForIncomingFrame) {
TaskQueueForTest channel_queue("channel_queue");
rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
MockChannelSend mock_channel;
rtc::scoped_refptr<ChannelSendFrameTransformerDelegate> delegate =
rtc::make_ref_counted<ChannelSendFrameTransformerDelegate>(
mock_channel.callback(), mock_frame_transformer, &channel_queue);
rtc::scoped_refptr<TransformedFrameCallback> callback;
EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback)
.WillOnce(SaveArg<0>(&callback));
delegate->Init();
ASSERT_TRUE(callback);
const uint8_t data[] = {1, 2, 3, 4};
EXPECT_CALL(mock_channel, SendFrame).Times(0);
EXPECT_CALL(mock_channel, SendFrame(_, 0, 0, ElementsAre(1, 2, 3, 4), _));
ON_CALL(*mock_frame_transformer, Transform)
.WillByDefault(
[&callback](std::unique_ptr<TransformableFrameInterface> frame) {
callback->OnTransformedFrame(CreateMockReceiverFrame());
});
delegate->Transform(AudioFrameType::kEmptyFrame, 0, 0, 0, data, sizeof(data),
0, 0);
channel_queue.WaitForPreviouslyPostedTasks();
}
// Test that if the delegate receives a transformed frame after it has been
// reset, it does not run the SendFrameCallback, as the channel is destroyed
// after resetting the delegate.
@ -119,7 +164,7 @@ TEST(ChannelSendFrameTransformerDelegateTest,
delegate->Reset();
EXPECT_CALL(mock_channel, SendFrame).Times(0);
delegate->OnTransformedFrame(std::make_unique<MockTransformableFrame>());
delegate->OnTransformedFrame(std::make_unique<MockTransformableAudioFrame>());
channel_queue.WaitForPreviouslyPostedTasks();
}

View File

@ -16,14 +16,19 @@
namespace webrtc {
class MockTransformableFrame : public TransformableFrameInterface {
class MockTransformableAudioFrame : public TransformableAudioFrameInterface {
public:
MOCK_METHOD(rtc::ArrayView<const uint8_t>, GetData, (), (const, override));
MOCK_METHOD(rtc::ArrayView<const uint32_t>,
GetContributingSources,
(),
(const, override));
MOCK_METHOD(void, SetData, (rtc::ArrayView<const uint8_t>), (override));
MOCK_METHOD(uint8_t, GetPayloadType, (), (const, override));
MOCK_METHOD(uint32_t, GetSsrc, (), (const, override));
MOCK_METHOD(uint32_t, GetTimestamp, (), (const, override));
MOCK_METHOD(void, SetRTPTimestamp, (uint32_t), (override));
MOCK_METHOD(Direction, GetDirection, (), (const, override));
};
} // namespace webrtc