-
Notifications
You must be signed in to change notification settings - Fork 32
subscription_thread_dispatcher: guard against duplicate room events #195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a04dc57
f1ff6e6
338f266
709a8ab
20e5d5b
6053b27
22991ec
1de44c8
4618ea9
d3ce7a9
ede1f20
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -303,16 +303,92 @@ class LIVEKIT_API Room { | |
| // Frame callbacks | ||
| // --------------------------------------------------------------- | ||
|
|
||
| /// @brief Sets the audio frame callback via SubscriptionThreadDispatcher. | ||
| /// Register an audio frame callback for a remote subscription. | ||
| /// | ||
| /// The callback is keyed by @p participant_identity and @p track_name. If the | ||
| /// matching remote audio track is already subscribed, a reader is started | ||
| /// immediately; otherwise the reader starts when the track is subscribed. | ||
| /// | ||
| /// To replace a callback whose reader is already running, call | ||
| /// @ref clearOnAudioFrameCallback first, then register again: | ||
| /// @code | ||
| /// room.clearOnAudioFrameCallback(identity, track_name); | ||
| /// if (!room.trySetOnAudioFrameCallback(identity, track_name, new_handler)) { | ||
| /// // registration was rejected (a reader is still active) | ||
| /// } | ||
| /// @endcode | ||
| /// | ||
| /// @param participant_identity Identity of the remote participant. | ||
| /// @param track_name Track name to match. | ||
| /// @param callback Function invoked for each decoded audio frame. | ||
| /// @param opts Options used when creating the backing | ||
| /// @ref AudioStream. | ||
| /// @return @c true if the callback was registered; @c false if a reader is | ||
| /// already active for the key (call @ref clearOnAudioFrameCallback | ||
| /// first) or the room has no dispatcher. | ||
| [[nodiscard]] bool trySetOnAudioFrameCallback(const std::string& participant_identity, const std::string& track_name, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From what I can tell, these new "try" methods have the same inputs as the deprecated prior ones, just a new return type (and name). This is actually a situation where I think maintaining the API and using exceptions is cleaner than deprecation/new API just to get the Thoughts on this? Could we not move the new implementations from
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isnt that still changing the public API though? maybe im wrong but i would think adding a throw to a function that previously didnt would require a major bump?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair point, technically speaking those methods were never marked |
||
| AudioFrameCallback callback, const AudioStream::Options& opts = {}); | ||
|
|
||
| /// Register a video frame callback for a remote subscription. | ||
| /// | ||
| /// The callback is keyed by @p participant_identity and @p track_name. If the | ||
| /// matching remote video track is already subscribed, a reader is started | ||
| /// immediately; otherwise the reader starts when the track is subscribed. | ||
| /// | ||
| /// To replace a callback whose reader is already running, call | ||
| /// @ref clearOnVideoFrameCallback first, then register again. | ||
| /// | ||
| /// @param participant_identity Identity of the remote participant. | ||
| /// @param track_name Track name to match. | ||
| /// @param callback Function invoked for each decoded video frame. | ||
| /// @param opts Options used when creating the backing | ||
| /// @ref VideoStream. | ||
| /// @return @c true if the callback was registered; @c false if a reader is | ||
| /// already active for the key (call @ref clearOnVideoFrameCallback | ||
| /// first) or the room has no dispatcher. | ||
| [[nodiscard]] bool trySetOnVideoFrameCallback(const std::string& participant_identity, const std::string& track_name, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess I didn't understand why these callback events need to be in the room ? And does this frame callbacks work on both local / remote participants ? |
||
| VideoFrameCallback callback, const VideoStream::Options& opts = {}); | ||
|
|
||
| /// Register a rich video frame event callback for a remote subscription. | ||
| /// | ||
| /// The callback is keyed by @p participant_identity and @p track_name. If the | ||
| /// matching remote video track is already subscribed, a reader is started | ||
| /// immediately; otherwise the reader starts when the track is subscribed. | ||
| /// | ||
| /// To replace a callback whose reader is already running, call | ||
| /// @ref clearOnVideoFrameCallback first, then register again. | ||
| /// | ||
| /// @param participant_identity Identity of the remote participant. | ||
| /// @param track_name Track name to match. | ||
| /// @param callback Function invoked for each decoded video frame | ||
| /// event, including optional metadata. | ||
| /// @param opts Options used when creating the backing | ||
| /// @ref VideoStream. | ||
| /// @return @c true if the callback was registered; @c false if a reader is | ||
| /// already active for the key (call @ref clearOnVideoFrameCallback | ||
| /// first) or the room has no dispatcher. | ||
| [[nodiscard]] bool trySetOnVideoFrameEventCallback(const std::string& participant_identity, | ||
| const std::string& track_name, VideoFrameEventCallback callback, | ||
| const VideoStream::Options& opts = {}); | ||
|
|
||
| /// @deprecated Use trySetOnAudioFrameCallback() instead. | ||
| /// | ||
| /// Forwards to @ref trySetOnAudioFrameCallback and discards the result. | ||
| [[deprecated("Room::setOnAudioFrameCallback is deprecated; use trySetOnAudioFrameCallback instead")]] | ||
| void setOnAudioFrameCallback(const std::string& participant_identity, const std::string& track_name, | ||
| AudioFrameCallback callback, const AudioStream::Options& opts = {}); | ||
|
|
||
| /// @brief Sets the video frame callback via SubscriptionThreadDispatcher. | ||
| /// @deprecated Use trySetOnVideoFrameCallback() instead. | ||
| /// | ||
| /// Forwards to @ref trySetOnVideoFrameCallback and discards the result. | ||
| [[deprecated("Room::setOnVideoFrameCallback is deprecated; use trySetOnVideoFrameCallback instead")]] | ||
| void setOnVideoFrameCallback(const std::string& participant_identity, const std::string& track_name, | ||
| VideoFrameCallback callback, const VideoStream::Options& opts = {}); | ||
|
|
||
| /// @brief Sets the video frame event callback via | ||
| /// SubscriptionThreadDispatcher. | ||
| /// @deprecated Use trySetOnVideoFrameEventCallback() instead. | ||
| /// | ||
| /// Forwards to @ref trySetOnVideoFrameEventCallback and discards the result. | ||
| [[deprecated("Room::setOnVideoFrameEventCallback is deprecated; use trySetOnVideoFrameEventCallback instead")]] | ||
| void setOnVideoFrameEventCallback(const std::string& participant_identity, const std::string& track_name, | ||
| VideoFrameEventCallback callback, const VideoStream::Options& opts = {}); | ||
|
|
||
|
|
@@ -354,6 +430,12 @@ class LIVEKIT_API Room { | |
| // FfiClient listener ID (0 means no listener registered) | ||
| int listener_id_{0}; | ||
|
|
||
| /// Find a currently subscribed remote track matching the given participant | ||
| /// identity and track name. Returns nullptr if no such subscribed track | ||
| /// exists. Acquires @ref lock_. | ||
| std::shared_ptr<Track> findSubscribedRemoteTrack(const std::string& participant_identity, | ||
| const std::string& track_name) const; | ||
|
|
||
| void onEvent(const proto::FfiEvent& event); | ||
| }; | ||
| } // namespace livekit | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if better or worse, but I typically use GTest's
FRIEND_TESTmacro so you can just give a single test suite/case access to what it needs. May break down a bit between unit and integration test binaries if they have different suite names (could unify name). Basically decays down to afriend class <blah>anyways, just looks a bit cleaner: https://google.github.io/googletest/reference/testing.html#FRIEND_TEST