From cdfa8e35f97115bfb3f76b273ea71e0debeb6487 Mon Sep 17 00:00:00 2001 From: Alan George Date: Mon, 6 Jul 2026 21:45:36 -0500 Subject: [PATCH 1/3] Migrated over changes from existing branch, hardened AGENTS.md language for testing, added unit tests --- AGENTS.md | 12 +++++++++++- include/livekit/room_event_types.h | 17 +++++++++++++++++ src/room_proto_converter.cpp | 6 ++++++ src/tests/common/test_common.h | 4 +++- src/tests/unit/test_room_event_types.cpp | 1 + src/tests/unit/test_video_frame_metadata.cpp | 14 ++++++++++++++ 6 files changed, 52 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b18afe1b..39c09572 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -352,11 +352,21 @@ CI step will fail loudly if its symbols escape the public ABI of Tests are under `src/tests/` using Google Test: -``` +```bash +source .token_helpers/set_data_track_test_tokens.bash ./build.sh debug-tests cd build-debug && ctest ``` +Always source the test tokens before running tests, even for a targeted local +test run. The integration and stress suites require `LIVEKIT_URL`, +`LIVEKIT_TOKEN_A`, and `LIVEKIT_TOKEN_B`; use +`source .token_helpers/set_data_track_test_tokens.bash` from the repository +root so the current shell inherits them. Do not report an integration test as +verified just because it was skipped for missing tokens. If tokens cannot be +sourced or the LiveKit server is not available, say that the integration test +was not actually exercised. + Integration tests (`src/tests/integration/`) cover: room connections, callbacks, data tracks, RPC, logging, audio processing, and the subscription thread dispatcher. The token source HTTP/JSON wire contract (request serialization, response parsing, header passthrough, GET support, sandbox URL/header resolution) is covered by mocked unit tests in `src/tests/unit/test_token_source.cpp`, which inject a stub HTTP transport so no live server is needed. For a full end-to-end check, `TokenSourceEndpointConnectTest` connects a `Room` with a real JWT minted by the `livekit/token-server-action` token server pointed at the local dev `livekit-server`. The action exposes its `/createToken` endpoint as a `token-url` output; `tests.yml` passes that to the integration test step as `LIVEKIT_CREATE_TOKEN_URL`, which the test reads to locate the endpoint. The server is started in the `e2e-testing` jobs via the token server's reusable GitHub Action, pinned by SHA in `tests.yml`. When adding new client facing functionality, add a new test case to the existing test suite. diff --git a/include/livekit/room_event_types.h b/include/livekit/room_event_types.h index f688bbec..cc8d5146 100644 --- a/include/livekit/room_event_types.h +++ b/include/livekit/room_event_types.h @@ -273,6 +273,19 @@ struct AudioEncodingOptions { std::uint64_t max_bitrate = 0; }; +/// @brief Controls how the encoder degrades quality when bandwidth is constrained. +enum class DegradationPreference { + /// Balance between framerate and resolution degradation. + Balanced = 0, + /// Degrade resolution to maintain framerate (prioritize smooth motion). + MaintainFramerate = 1, + /// Degrade framerate to maintain resolution (prioritize image clarity). + MaintainResolution = 2, + /// Maintain both framerate and resolution. Frames may be dropped before + /// encoding if necessary to avoid overusing network and encoder resources. + MaintainFramerateAndResolution = 4, +}; + /// Optional frame metadata features for published video tracks. struct FrameMetadataFeatures { /// Embed a user-supplied wall-clock timestamp. @@ -324,6 +337,10 @@ struct TrackPublishOptions { /// @deprecated Use frame_metadata_features instead. [[deprecated("TrackPublishOptions::packet_trailer_features is deprecated; use frame_metadata_features instead")]] FrameMetadataFeatures packet_trailer_features{}; + + /// Controls how the encoder trades off between resolution and framerate + /// when bandwidth is constrained. Default is MaintainResolution. + std::optional degradation_preference; }; // --------------------------------------------------------- diff --git a/src/room_proto_converter.cpp b/src/room_proto_converter.cpp index 010aa545..6e2fdcd0 100644 --- a/src/room_proto_converter.cpp +++ b/src/room_proto_converter.cpp @@ -526,6 +526,9 @@ proto::TrackPublishOptions toProto(const TrackPublishOptions& in) { for (const proto::FrameMetadataFeature feature : toProto(mergedFrameMetadataFeatures(in))) { msg.add_frame_metadata_features(feature); } + if (in.degradation_preference) { + msg.set_degradation_preference(static_cast(*in.degradation_preference)); + } return msg; } @@ -563,6 +566,9 @@ TrackPublishOptions fromProto(const proto::TrackPublishOptions& in) { out.frame_metadata_features = frame_metadata_features; } out.packet_trailer_features = frame_metadata_features; + if (in.has_degradation_preference()) { + out.degradation_preference = static_cast(in.degradation_preference()); + } return out; } diff --git a/src/tests/common/test_common.h b/src/tests/common/test_common.h index 530fdb6b..53f6e736 100644 --- a/src/tests/common/test_common.h +++ b/src/tests/common/test_common.h @@ -548,7 +548,9 @@ class LiveKitTestBase : public ::testing::Test { /// Fail the test if the required environment variables are not set void failIfNotConfigured() { if (!config_.available) { - FAIL() << "LIVEKIT_URL, LIVEKIT_TOKEN_A, and LIVEKIT_TOKEN_B not set"; + throw std::runtime_error( + "LIVEKIT_URL, LIVEKIT_TOKEN_A, and LIVEKIT_TOKEN_B not set; source " + ".token_helpers/set_data_track_test_tokens.bash before running tests"); } } diff --git a/src/tests/unit/test_room_event_types.cpp b/src/tests/unit/test_room_event_types.cpp index 050e9776..c653aa10 100644 --- a/src/tests/unit/test_room_event_types.cpp +++ b/src/tests/unit/test_room_event_types.cpp @@ -49,6 +49,7 @@ TEST(RoomEventTypesTest, TrackPublishOptionsDefaults) { EXPECT_FALSE(options.packet_trailer_features.user_timestamp); EXPECT_FALSE(options.packet_trailer_features.frame_id); EXPECT_FALSE(options.packet_trailer_features.user_data); + EXPECT_FALSE(options.degradation_preference.has_value()); } TEST(RoomEventTypesTest, UserPacketDataDefaults) { diff --git a/src/tests/unit/test_video_frame_metadata.cpp b/src/tests/unit/test_video_frame_metadata.cpp index b87bbdab..5c683e84 100644 --- a/src/tests/unit/test_video_frame_metadata.cpp +++ b/src/tests/unit/test_video_frame_metadata.cpp @@ -138,6 +138,20 @@ TEST(TrackPublishOptionsTest, FrameMetadataFeaturesRoundTrip) { EXPECT_TRUE(round_trip.frame_metadata_features->user_data); } +TEST(TrackPublishOptionsTest, DegradationPreferenceRoundTrip) { + TrackPublishOptions options; + options.degradation_preference = DegradationPreference::MaintainFramerateAndResolution; + + proto::TrackPublishOptions proto_options = toProto(options); + ASSERT_TRUE(proto_options.has_degradation_preference()); + EXPECT_EQ(proto_options.degradation_preference(), + proto::DegradationPreference::DEGRADATION_PREFERENCE_MAINTAIN_FRAMERATE_AND_RESOLUTION); + + TrackPublishOptions round_trip = fromProto(proto_options); + ASSERT_TRUE(round_trip.degradation_preference.has_value()); + EXPECT_EQ(*round_trip.degradation_preference, DegradationPreference::MaintainFramerateAndResolution); +} + TEST(TrackPublishOptionsTest, DeprecatedPacketTrailerFeaturesAreMerged) { TrackPublishOptions options; From aa24f31e412be13d3dd8aaaa48ab29fb762859b9 Mon Sep 17 00:00:00 2001 From: Alan George Date: Mon, 6 Jul 2026 21:50:14 -0500 Subject: [PATCH 2/3] Cleanup AI comment --- src/tests/common/test_common.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tests/common/test_common.h b/src/tests/common/test_common.h index 53f6e736..9ec0e508 100644 --- a/src/tests/common/test_common.h +++ b/src/tests/common/test_common.h @@ -548,9 +548,7 @@ class LiveKitTestBase : public ::testing::Test { /// Fail the test if the required environment variables are not set void failIfNotConfigured() { if (!config_.available) { - throw std::runtime_error( - "LIVEKIT_URL, LIVEKIT_TOKEN_A, and LIVEKIT_TOKEN_B not set; source " - ".token_helpers/set_data_track_test_tokens.bash before running tests"); + throw std::runtime_error("LIVEKIT_URL, LIVEKIT_TOKEN_A, and LIVEKIT_TOKEN_B not set"); } } From bc76a4564675777f3da2cbec5cc51c2f8333799f Mon Sep 17 00:00:00 2001 From: alan-george-lk Date: Mon, 6 Jul 2026 21:06:20 -0600 Subject: [PATCH 3/3] Update include/livekit/room_event_types.h Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- include/livekit/room_event_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/livekit/room_event_types.h b/include/livekit/room_event_types.h index cc8d5146..11bad343 100644 --- a/include/livekit/room_event_types.h +++ b/include/livekit/room_event_types.h @@ -339,7 +339,7 @@ struct TrackPublishOptions { FrameMetadataFeatures packet_trailer_features{}; /// Controls how the encoder trades off between resolution and framerate - /// when bandwidth is constrained. Default is MaintainResolution. + /// when bandwidth is constrained. If not set, the server defaults apply. std::optional degradation_preference; };