blob: a4ee9ff2085208cd83f788a9e95bfb852fcc0004 [file] [log] [blame]
Marina Ciocead7197082020-05-04 15:50:381/*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "audio/channel_send_frame_transformer_delegate.h"
12
Harald Alvestrand6431a642024-06-04 21:29:1413#include <cstdint>
Marina Ciocead7197082020-05-04 15:50:3814#include <memory>
Florent Castelli8037fc62024-08-29 13:00:4015#include <optional>
Marina Ciocead7197082020-05-04 15:50:3816#include <utility>
Tony Herre5f3ac432023-12-07 11:39:4017#include <vector>
Marina Ciocead7197082020-05-04 15:50:3818
Tony Herre5f3ac432023-12-07 11:39:4019#include "absl/memory/memory.h"
Harald Alvestrand6431a642024-06-04 21:29:1420#include "api/array_view.h"
21#include "api/frame_transformer_interface.h"
22#include "api/make_ref_counted.h"
23#include "api/scoped_refptr.h"
Tony Herre9c6874602024-01-26 10:16:4524#include "api/test/mock_frame_transformer.h"
25#include "api/test/mock_transformable_audio_frame.h"
Harald Alvestrand6431a642024-06-04 21:29:1426#include "modules/audio_coding/include/audio_coding_module_typedefs.h"
Marina Ciocead7197082020-05-04 15:50:3827#include "rtc_base/task_queue_for_test.h"
28#include "test/gmock.h"
29#include "test/gtest.h"
Marina Ciocead7197082020-05-04 15:50:3830
31namespace webrtc {
32namespace {
33
Palak Agarwal14e5d4c2023-08-22 14:58:3334using ::testing::_;
35using ::testing::ElementsAre;
Tony Herre5f3ac432023-12-07 11:39:4036using ::testing::ElementsAreArray;
Marina Ciocead7197082020-05-04 15:50:3837using ::testing::NiceMock;
Tony Herre64437e82024-04-29 13:13:4838using ::testing::Optional;
Palak Agarwal14e5d4c2023-08-22 14:58:3339using ::testing::Return;
Marina Ciocead7197082020-05-04 15:50:3840using ::testing::SaveArg;
41
Tony Herre5f3ac432023-12-07 11:39:4042const uint8_t mock_data[] = {1, 2, 3, 4};
43
Marina Ciocead7197082020-05-04 15:50:3844class MockChannelSend {
45 public:
46 MockChannelSend() = default;
47 ~MockChannelSend() = default;
48
49 MOCK_METHOD(int32_t,
50 SendFrame,
51 (AudioFrameType frameType,
52 uint8_t payloadType,
53 uint32_t rtp_timestamp,
54 rtc::ArrayView<const uint8_t> payload,
Tony Herre5f3ac432023-12-07 11:39:4055 int64_t absolute_capture_timestamp_ms,
Tony Herre64437e82024-04-29 13:13:4856 rtc::ArrayView<const uint32_t> csrcs,
Florent Castelli8037fc62024-08-29 13:00:4057 std::optional<uint8_t> audio_level_dbov));
Marina Ciocead7197082020-05-04 15:50:3858
59 ChannelSendFrameTransformerDelegate::SendFrameCallback callback() {
60 return [this](AudioFrameType frameType, uint8_t payloadType,
61 uint32_t rtp_timestamp, rtc::ArrayView<const uint8_t> payload,
Tony Herre5f3ac432023-12-07 11:39:4062 int64_t absolute_capture_timestamp_ms,
Tony Herre64437e82024-04-29 13:13:4863 rtc::ArrayView<const uint32_t> csrcs,
Florent Castelli8037fc62024-08-29 13:00:4064 std::optional<uint8_t> audio_level_dbov) {
Marina Ciocead7197082020-05-04 15:50:3865 return SendFrame(frameType, payloadType, rtp_timestamp, payload,
Tony Herre64437e82024-04-29 13:13:4866 absolute_capture_timestamp_ms, csrcs, audio_level_dbov);
Marina Ciocead7197082020-05-04 15:50:3867 };
68 }
69};
70
Tony Herre5f3ac432023-12-07 11:39:4071std::unique_ptr<TransformableAudioFrameInterface> CreateMockReceiverFrame(
Tony Herre64437e82024-04-29 13:13:4872 const std::vector<uint32_t>& csrcs,
Florent Castelli8037fc62024-08-29 13:00:4073 std::optional<uint8_t> audio_level_dbov) {
Palak Agarwal14e5d4c2023-08-22 14:58:3374 std::unique_ptr<MockTransformableAudioFrame> mock_frame =
Tony Herre5f3ac432023-12-07 11:39:4075 std::make_unique<NiceMock<MockTransformableAudioFrame>>();
Palak Agarwal14e5d4c2023-08-22 14:58:3376 rtc::ArrayView<const uint8_t> payload(mock_data);
77 ON_CALL(*mock_frame, GetData).WillByDefault(Return(payload));
78 ON_CALL(*mock_frame, GetPayloadType).WillByDefault(Return(0));
79 ON_CALL(*mock_frame, GetDirection)
80 .WillByDefault(Return(TransformableFrameInterface::Direction::kReceiver));
Tony Herre5f3ac432023-12-07 11:39:4081 ON_CALL(*mock_frame, GetContributingSources).WillByDefault(Return(csrcs));
Tony Herre7aa79722024-01-29 07:31:1482 ON_CALL(*mock_frame, SequenceNumber).WillByDefault(Return(987654321));
Tony Herre64437e82024-04-29 13:13:4883 ON_CALL(*mock_frame, AudioLevel).WillByDefault(Return(audio_level_dbov));
Palak Agarwal14e5d4c2023-08-22 14:58:3384 return mock_frame;
85}
86
Tony Herre5f3ac432023-12-07 11:39:4087std::unique_ptr<TransformableAudioFrameInterface> CreateFrame() {
88 TaskQueueForTest channel_queue("channel_queue");
89 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
90 rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
91 MockChannelSend mock_channel;
92 rtc::scoped_refptr<ChannelSendFrameTransformerDelegate> delegate =
93 rtc::make_ref_counted<ChannelSendFrameTransformerDelegate>(
Danil Chapovalov0f1b9a92024-01-17 18:32:1594 mock_channel.callback(), mock_frame_transformer, channel_queue.Get());
Tony Herre5f3ac432023-12-07 11:39:4095
96 std::unique_ptr<TransformableFrameInterface> frame;
97 ON_CALL(*mock_frame_transformer, Transform)
98 .WillByDefault(
99 [&frame](
100 std::unique_ptr<TransformableFrameInterface> transform_frame) {
101 frame = std::move(transform_frame);
102 });
Tony Herre64437e82024-04-29 13:13:48103 delegate->Transform(
104 AudioFrameType::kEmptyFrame, 0, 0, mock_data, sizeof(mock_data), 0,
105 /*ssrc=*/0, /*mimeType=*/"audio/opus", /*audio_level_dbov=*/123);
Tony Herre5f3ac432023-12-07 11:39:40106 return absl::WrapUnique(
107 static_cast<webrtc::TransformableAudioFrameInterface*>(frame.release()));
108}
109
Marina Ciocead7197082020-05-04 15:50:38110// Test that the delegate registers itself with the frame transformer on Init().
111TEST(ChannelSendFrameTransformerDelegateTest,
112 RegisterTransformedFrameCallbackOnInit) {
113 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
Tomas Gunnarssonc1d58912021-04-22 17:21:43114 rtc::make_ref_counted<MockFrameTransformer>();
Marina Ciocead7197082020-05-04 15:50:38115 rtc::scoped_refptr<ChannelSendFrameTransformerDelegate> delegate =
Tomas Gunnarssonc1d58912021-04-22 17:21:43116 rtc::make_ref_counted<ChannelSendFrameTransformerDelegate>(
Marina Ciocead7197082020-05-04 15:50:38117 ChannelSendFrameTransformerDelegate::SendFrameCallback(),
118 mock_frame_transformer, nullptr);
119 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback);
120 delegate->Init();
121}
122
123// Test that the delegate unregisters itself from the frame transformer on
124// Reset().
125TEST(ChannelSendFrameTransformerDelegateTest,
126 UnregisterTransformedFrameCallbackOnReset) {
127 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
Tomas Gunnarssonc1d58912021-04-22 17:21:43128 rtc::make_ref_counted<MockFrameTransformer>();
Marina Ciocead7197082020-05-04 15:50:38129 rtc::scoped_refptr<ChannelSendFrameTransformerDelegate> delegate =
Tomas Gunnarssonc1d58912021-04-22 17:21:43130 rtc::make_ref_counted<ChannelSendFrameTransformerDelegate>(
Marina Ciocead7197082020-05-04 15:50:38131 ChannelSendFrameTransformerDelegate::SendFrameCallback(),
132 mock_frame_transformer, nullptr);
133 EXPECT_CALL(*mock_frame_transformer, UnregisterTransformedFrameCallback);
134 delegate->Reset();
135}
136
137// Test that when the delegate receives a transformed frame from the frame
138// transformer, it passes it to the channel using the SendFrameCallback.
139TEST(ChannelSendFrameTransformerDelegateTest,
140 TransformRunsChannelSendCallback) {
141 TaskQueueForTest channel_queue("channel_queue");
142 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
Tomas Gunnarssonc1d58912021-04-22 17:21:43143 rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
Marina Ciocead7197082020-05-04 15:50:38144 MockChannelSend mock_channel;
145 rtc::scoped_refptr<ChannelSendFrameTransformerDelegate> delegate =
Tomas Gunnarssonc1d58912021-04-22 17:21:43146 rtc::make_ref_counted<ChannelSendFrameTransformerDelegate>(
Danil Chapovalov0f1b9a92024-01-17 18:32:15147 mock_channel.callback(), mock_frame_transformer, channel_queue.Get());
Marina Ciocead7197082020-05-04 15:50:38148 rtc::scoped_refptr<TransformedFrameCallback> callback;
149 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback)
150 .WillOnce(SaveArg<0>(&callback));
151 delegate->Init();
152 ASSERT_TRUE(callback);
153
154 const uint8_t data[] = {1, 2, 3, 4};
155 EXPECT_CALL(mock_channel, SendFrame);
156 ON_CALL(*mock_frame_transformer, Transform)
157 .WillByDefault(
158 [&callback](std::unique_ptr<TransformableFrameInterface> frame) {
159 callback->OnTransformedFrame(std::move(frame));
160 });
Tony Herre36500ab2023-08-29 10:01:32161 delegate->Transform(AudioFrameType::kEmptyFrame, 0, 0, data, sizeof(data), 0,
Tony Herre64437e82024-04-29 13:13:48162 /*ssrc=*/0, /*mimeType=*/"audio/opus",
163 /*audio_level_dbov=*/31);
Marina Ciocead7197082020-05-04 15:50:38164 channel_queue.WaitForPreviouslyPostedTasks();
165}
166
Palak Agarwal14e5d4c2023-08-22 14:58:33167// Test that when the delegate receives a Incoming frame from the frame
168// transformer, it passes it to the channel using the SendFrameCallback.
169TEST(ChannelSendFrameTransformerDelegateTest,
170 TransformRunsChannelSendCallbackForIncomingFrame) {
171 TaskQueueForTest channel_queue("channel_queue");
172 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
173 rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
174 MockChannelSend mock_channel;
175 rtc::scoped_refptr<ChannelSendFrameTransformerDelegate> delegate =
176 rtc::make_ref_counted<ChannelSendFrameTransformerDelegate>(
Danil Chapovalov0f1b9a92024-01-17 18:32:15177 mock_channel.callback(), mock_frame_transformer, channel_queue.Get());
Palak Agarwal14e5d4c2023-08-22 14:58:33178 rtc::scoped_refptr<TransformedFrameCallback> callback;
179 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback)
180 .WillOnce(SaveArg<0>(&callback));
181 delegate->Init();
182 ASSERT_TRUE(callback);
183
Dor Hen3e613c22024-02-05 15:58:10184 const std::vector<uint32_t> csrcs = {123, 234, 345, 456};
Tony Herre64437e82024-04-29 13:13:48185 const uint8_t audio_level_dbov = 17;
Palak Agarwal14e5d4c2023-08-22 14:58:33186 EXPECT_CALL(mock_channel, SendFrame).Times(0);
Tony Herre64437e82024-04-29 13:13:48187 EXPECT_CALL(mock_channel,
188 SendFrame(_, 0, 0, ElementsAreArray(mock_data), _,
189 ElementsAreArray(csrcs), Optional(audio_level_dbov)));
Palak Agarwal14e5d4c2023-08-22 14:58:33190 ON_CALL(*mock_frame_transformer, Transform)
Tony Herre5f3ac432023-12-07 11:39:40191 .WillByDefault([&](std::unique_ptr<TransformableFrameInterface> frame) {
Tony Herre64437e82024-04-29 13:13:48192 callback->OnTransformedFrame(CreateMockReceiverFrame(
Florent Castelli8037fc62024-08-29 13:00:40193 csrcs, std::optional<uint8_t>(audio_level_dbov)));
Tony Herre5f3ac432023-12-07 11:39:40194 });
195 delegate->Transform(AudioFrameType::kEmptyFrame, 0, 0, mock_data,
196 sizeof(mock_data), 0,
Tony Herre64437e82024-04-29 13:13:48197 /*ssrc=*/0, /*mimeType=*/"audio/opus",
Florent Castelli8037fc62024-08-29 13:00:40198 /*audio_level_dbov=*/std::nullopt);
Palak Agarwal14e5d4c2023-08-22 14:58:33199 channel_queue.WaitForPreviouslyPostedTasks();
200}
201
Marina Ciocead7197082020-05-04 15:50:38202// Test that if the delegate receives a transformed frame after it has been
203// reset, it does not run the SendFrameCallback, as the channel is destroyed
204// after resetting the delegate.
205TEST(ChannelSendFrameTransformerDelegateTest,
206 OnTransformedDoesNotRunChannelSendCallbackAfterReset) {
207 TaskQueueForTest channel_queue("channel_queue");
208 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
Tomas Gunnarssonc1d58912021-04-22 17:21:43209 rtc::make_ref_counted<testing::NiceMock<MockFrameTransformer>>();
Marina Ciocead7197082020-05-04 15:50:38210 MockChannelSend mock_channel;
211 rtc::scoped_refptr<ChannelSendFrameTransformerDelegate> delegate =
Tomas Gunnarssonc1d58912021-04-22 17:21:43212 rtc::make_ref_counted<ChannelSendFrameTransformerDelegate>(
Danil Chapovalov0f1b9a92024-01-17 18:32:15213 mock_channel.callback(), mock_frame_transformer, channel_queue.Get());
Marina Ciocead7197082020-05-04 15:50:38214
215 delegate->Reset();
216 EXPECT_CALL(mock_channel, SendFrame).Times(0);
Palak Agarwal14e5d4c2023-08-22 14:58:33217 delegate->OnTransformedFrame(std::make_unique<MockTransformableAudioFrame>());
Marina Ciocead7197082020-05-04 15:50:38218 channel_queue.WaitForPreviouslyPostedTasks();
219}
220
Tony Herre6e956052023-11-16 13:59:54221TEST(ChannelSendFrameTransformerDelegateTest, ShortCircuitingSkipsTransform) {
222 TaskQueueForTest channel_queue("channel_queue");
223 rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
224 rtc::make_ref_counted<testing::NiceMock<MockFrameTransformer>>();
225 MockChannelSend mock_channel;
226 rtc::scoped_refptr<ChannelSendFrameTransformerDelegate> delegate =
227 rtc::make_ref_counted<ChannelSendFrameTransformerDelegate>(
Danil Chapovalov0f1b9a92024-01-17 18:32:15228 mock_channel.callback(), mock_frame_transformer, channel_queue.Get());
Tony Herre6e956052023-11-16 13:59:54229
230 delegate->StartShortCircuiting();
231
232 // Will not call the actual transformer.
233 EXPECT_CALL(*mock_frame_transformer, Transform).Times(0);
234 // Will pass the frame straight to the channel.
235 EXPECT_CALL(mock_channel, SendFrame);
236 const uint8_t data[] = {1, 2, 3, 4};
237 delegate->Transform(AudioFrameType::kEmptyFrame, 0, 0, data, sizeof(data), 0,
Tony Herre64437e82024-04-29 13:13:48238 /*ssrc=*/0, /*mimeType=*/"audio/opus",
Florent Castelli8037fc62024-08-29 13:00:40239 /*audio_level_dbov=*/std::nullopt);
Tony Herre6e956052023-11-16 13:59:54240}
241
Tony Herre5f3ac432023-12-07 11:39:40242TEST(ChannelSendFrameTransformerDelegateTest,
243 CloningSenderFramePreservesInformation) {
244 std::unique_ptr<TransformableAudioFrameInterface> frame = CreateFrame();
245 std::unique_ptr<TransformableAudioFrameInterface> cloned_frame =
246 CloneSenderAudioFrame(frame.get());
247
248 EXPECT_EQ(cloned_frame->GetTimestamp(), frame->GetTimestamp());
249 EXPECT_EQ(cloned_frame->GetSsrc(), frame->GetSsrc());
250 EXPECT_EQ(cloned_frame->Type(), frame->Type());
251 EXPECT_EQ(cloned_frame->GetPayloadType(), frame->GetPayloadType());
252 EXPECT_EQ(cloned_frame->GetMimeType(), frame->GetMimeType());
253 EXPECT_THAT(cloned_frame->GetContributingSources(),
254 ElementsAreArray(frame->GetContributingSources()));
Tony Herre64437e82024-04-29 13:13:48255 EXPECT_EQ(cloned_frame->AudioLevel(), frame->AudioLevel());
Tony Herre5f3ac432023-12-07 11:39:40256}
257
258TEST(ChannelSendFrameTransformerDelegateTest, CloningReceiverFrameWithCsrcs) {
259 std::unique_ptr<TransformableAudioFrameInterface> frame =
Tony Herre64437e82024-04-29 13:13:48260 CreateMockReceiverFrame(/*csrcs=*/{123, 234, 345},
Florent Castelli8037fc62024-08-29 13:00:40261 std::optional<uint8_t>(72));
Tony Herre5f3ac432023-12-07 11:39:40262 std::unique_ptr<TransformableAudioFrameInterface> cloned_frame =
263 CloneSenderAudioFrame(frame.get());
264
265 EXPECT_EQ(cloned_frame->GetTimestamp(), frame->GetTimestamp());
266 EXPECT_EQ(cloned_frame->GetSsrc(), frame->GetSsrc());
267 EXPECT_EQ(cloned_frame->Type(), frame->Type());
268 EXPECT_EQ(cloned_frame->GetPayloadType(), frame->GetPayloadType());
269 EXPECT_EQ(cloned_frame->GetMimeType(), frame->GetMimeType());
270 EXPECT_EQ(cloned_frame->AbsoluteCaptureTimestamp(),
271 frame->AbsoluteCaptureTimestamp());
272
273 ASSERT_NE(frame->GetContributingSources().size(), 0u);
274 EXPECT_THAT(cloned_frame->GetContributingSources(),
275 ElementsAreArray(frame->GetContributingSources()));
Tony Herre7aa79722024-01-29 07:31:14276 EXPECT_EQ(cloned_frame->SequenceNumber(), frame->SequenceNumber());
Tony Herre64437e82024-04-29 13:13:48277 EXPECT_EQ(cloned_frame->AudioLevel(), frame->AudioLevel());
Tony Herre5f3ac432023-12-07 11:39:40278}
279
Marina Ciocead7197082020-05-04 15:50:38280} // namespace
281} // namespace webrtc