Skip to content

Commit bb97879

Browse files
tests
1 parent 8635411 commit bb97879

2 files changed

Lines changed: 78 additions & 1 deletion

File tree

src/tests/integration/test_platform_audio.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <chrono>
1818
#include <condition_variable>
19+
#include <cstdint>
1920
#include <memory>
2021
#include <mutex>
2122
#include <set>
@@ -218,4 +219,80 @@ TEST_F(PlatformAudioIntegrationTest, MultipleSourcesFromOneManagerPublish) {
218219
EXPECT_TRUE(both_subscribed) << "Receiver did not subscribe to both platform audio tracks";
219220
}
220221

222+
// Audio captured by the platform Audio Device Module must actually stream to a
223+
// remote participant as decoded frames, not merely produce a subscribed track.
224+
// PlatformAudioSource captures the real microphone (silence on headless
225+
// runners), so this verifies frames *flow* end-to-end without asserting on
226+
// their content.
227+
TEST_F(PlatformAudioIntegrationTest, PlatformAudioFramesReachRemote) {
228+
EXPECT_TRUE(config_.available) << "Missing integration configuration";
229+
230+
std::unique_ptr<PlatformAudio> platform_audio;
231+
EXPECT_NO_THROW(platform_audio = std::make_unique<PlatformAudio>());
232+
233+
RoomOptions options;
234+
options.auto_subscribe = true;
235+
236+
PlatformTrackState receiver_state;
237+
PlatformTrackCollectorDelegate receiver_delegate(receiver_state);
238+
239+
auto receiver_room = std::make_unique<Room>();
240+
receiver_room->setDelegate(&receiver_delegate);
241+
ASSERT_TRUE(receiver_room->connect(config_.url, config_.token_b, options)) << "Receiver failed to connect";
242+
243+
auto sender_room = std::make_unique<Room>();
244+
ASSERT_TRUE(sender_room->connect(config_.url, config_.token_a, options)) << "Sender failed to connect";
245+
246+
const std::string sender_identity = lockLocalParticipant(*sender_room)->identity();
247+
248+
const auto source = platform_audio->createAudioSource();
249+
ASSERT_NE(source, nullptr);
250+
251+
const std::string track_name = "platform-mic-frames";
252+
const auto track = LocalAudioTrack::createLocalAudioTrack(track_name, source);
253+
ASSERT_NE(track, nullptr);
254+
255+
// A few hundred ms of audio (10ms frames) is plenty to confirm the media path
256+
// is live without making the test slow.
257+
constexpr int kRequiredFrames = 10;
258+
constexpr auto kFrameTimeout = 20s;
259+
260+
std::mutex frame_mutex;
261+
std::condition_variable frame_cv;
262+
int received_frames = 0;
263+
264+
// The reader thread is only started when the subscription event fires and a
265+
// matching callback is already registered, so register before publishing.
266+
receiver_room->setOnAudioFrameCallback(sender_identity, track_name, [&](const AudioFrame& frame) {
267+
if (frame.totalSamples() == 0) {
268+
return;
269+
}
270+
{
271+
std::lock_guard<std::mutex> lock(frame_mutex);
272+
++received_frames;
273+
}
274+
frame_cv.notify_all();
275+
});
276+
277+
TrackPublishOptions publish_options;
278+
publish_options.source = TrackSource::SOURCE_MICROPHONE;
279+
lockLocalParticipant(*sender_room)->publishTrack(track, publish_options);
280+
281+
{
282+
std::unique_lock<std::mutex> lock(receiver_state.mutex);
283+
ASSERT_TRUE(receiver_state.cv.wait_for(lock, kSubscriptionTimeout, [&]() {
284+
return receiver_state.subscribed_audio_names.count(track_name) > 0;
285+
})) << "Receiver never subscribed to the platform audio track";
286+
}
287+
288+
bool frames_received = false;
289+
{
290+
std::unique_lock<std::mutex> lock(frame_mutex);
291+
frames_received = frame_cv.wait_for(lock, kFrameTimeout, [&]() { return received_frames >= kRequiredFrames; });
292+
}
293+
EXPECT_TRUE(frames_received) << "Receiver did not get platform audio frames from the remote";
294+
295+
receiver_room->clearOnAudioFrameCallback(sender_identity, track_name);
296+
}
297+
221298
} // namespace livekit::test

0 commit comments

Comments
 (0)