Support receiving cloned encoded audio frames

Bug: chromium:1464860
Change-Id: I01b2d768fcf5aef09b32304a8f9fe0b00ca32357
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/316320
Reviewed-by: Tony Herre <herre@google.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Palak Agarwal <agpalak@google.com>
Cr-Commit-Position: refs/heads/main@{#40583}
This commit is contained in:
Palak Agarwal 2023-08-18 14:09:53 +02:00 committed by WebRTC LUCI CQ
parent 2886da25da
commit f263e1eb03
2 changed files with 61 additions and 6 deletions

View File

@ -112,11 +112,30 @@ void ChannelReceiveFrameTransformerDelegate::ReceiveFrame(
RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_RUN_ON(&sequence_checker_);
if (!receive_frame_callback_) if (!receive_frame_callback_)
return; return;
RTC_CHECK_EQ(frame->GetDirection(),
TransformableFrameInterface::Direction::kReceiver); RTPHeader header;
auto* transformed_frame = if (frame->GetDirection() ==
static_cast<TransformableIncomingAudioFrame*>(frame.get()); TransformableFrameInterface::Direction::kSender) {
receive_frame_callback_(transformed_frame->GetData(), auto* transformed_frame =
transformed_frame->Header()); static_cast<TransformableAudioFrameInterface*>(frame.get());
header.payloadType = transformed_frame->GetPayloadType();
header.timestamp = transformed_frame->GetTimestamp();
header.ssrc = transformed_frame->GetSsrc();
if (transformed_frame->AbsoluteCaptureTimestamp().has_value()) {
header.extension.absolute_capture_time = AbsoluteCaptureTime();
header.extension.absolute_capture_time->absolute_capture_timestamp =
transformed_frame->AbsoluteCaptureTimestamp().value();
}
} else {
auto* transformed_frame =
static_cast<TransformableIncomingAudioFrame*>(frame.get());
header = transformed_frame->Header();
}
// TODO(crbug.com/1464860): Take an explicit struct with the required
// information rather than the RTPHeader to make it easier to
// construct the required information when injecting transformed frames not
// originally from this receiver.
receive_frame_callback_(frame->GetData(), header);
} }
} // namespace webrtc } // namespace webrtc

View File

@ -13,6 +13,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "audio/channel_send_frame_transformer_delegate.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
#include "test/mock_frame_transformer.h" #include "test/mock_frame_transformer.h"
@ -21,6 +22,8 @@
namespace webrtc { namespace webrtc {
namespace { namespace {
using ::testing::_;
using ::testing::ElementsAre;
using ::testing::NiceMock; using ::testing::NiceMock;
using ::testing::SaveArg; using ::testing::SaveArg;
@ -94,6 +97,39 @@ TEST(ChannelReceiveFrameTransformerDelegateTest,
rtc::ThreadManager::ProcessAllMessageQueuesForTesting(); rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
} }
// Test that when the delegate receives a Outgoing frame from the frame
// transformer, it passes it to the channel using the ReceiveFrameCallback.
TEST(ChannelReceiveFrameTransformerDelegateTest,
TransformRunsChannelReceiveCallbackForSenderFrame) {
rtc::AutoThread main_thread;
rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
MockChannelReceive mock_channel;
rtc::scoped_refptr<ChannelReceiveFrameTransformerDelegate> delegate =
rtc::make_ref_counted<ChannelReceiveFrameTransformerDelegate>(
mock_channel.callback(), mock_frame_transformer,
rtc::Thread::Current());
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};
rtc::ArrayView<const uint8_t> packet(data, sizeof(data));
RTPHeader header;
EXPECT_CALL(mock_channel, ReceiveFrame(ElementsAre(1, 2, 3, 4), _));
ON_CALL(*mock_frame_transformer, Transform)
.WillByDefault([&callback](
std::unique_ptr<TransformableFrameInterface> frame) {
auto* transformed_frame =
static_cast<TransformableAudioFrameInterface*>(frame.get());
callback->OnTransformedFrame(CloneSenderAudioFrame(transformed_frame));
});
delegate->Transform(packet, header, 1111 /*ssrc*/);
rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
}
// Test that if the delegate receives a transformed frame after it has been // Test that if the delegate receives a transformed frame after it has been
// reset, it does not run the ReceiveFrameCallback, as the channel is destroyed // reset, it does not run the ReceiveFrameCallback, as the channel is destroyed
// after resetting the delegate. // after resetting the delegate.