diff --git a/AGENTS.md b/AGENTS.md index 9e0d9c7d..636f7e1e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -235,6 +235,71 @@ with the same library loaded elsewhere in the host process. - Use `LK_LOG_WARN` for non-fatal unexpected conditions. - Use `Result` for operations that can fail with typed errors (e.g., data track publish/subscribe). +### Public API Documentation (Doxygen) + +The public API (`include/livekit/*.h`) is what consumers read first and is also +published as a Doxygen site (`docs/Doxyfile`, `.github/workflows/publish-docs.yml`). +Every doc comment in `include/livekit/` must use the rules below, and PRs that +add or modify public symbols are gated on these rules during review. + +#### Comment style + +- Use triple-slash `///` Doxygen comments. Do **not** use `/** ... */` Javadoc + blocks or `/* ... */` block comments for documentation. +- Apache license headers stay as `/* ... */` block comments — they are not + documentation. +- Section organization comments (e.g. `// ---- Accessors ----`, + `// Read-only properties`) may stay as `//` since they do not document a + specific symbol. +- Implementation comments inside `.cpp` files (non-Doxygen) may use `//` + freely. +- Use Doxygen `@`-prefixed commands (`@param`, `@return`, `@throws`, `@note`, + `@brief`, `@deprecated`, `@ref`, `@p`, `@c`). Do not use the equivalent + `\`-prefixed forms in new code. + +#### Required tags + +- Document parameters using `@param name Description.` +- Document non-void return values using `@return Description.` +- Document thrown exceptions using `@throws ExceptionType When/why it's + thrown.` Operations that can fail without throwing should return + `Result` (see Error Handling above) and the variants should be + documented in the doc block. +- Free-text "Parameters:", "Returns:", "Throws:" sections in legacy comments + must be converted to the corresponding `@param` / `@return` / `@throws` + tags when the comment is touched. + +#### Example + +```cpp +/// Publish a local track to the room. +/// +/// Blocks until the FFI publish response arrives. +/// +/// @param track Track to publish. Must be non-null. +/// @param options Publish options (codec, simulcast, etc.). +/// @throws std::runtime_error if the FFI reports an error. +void publishTrack(const std::shared_ptr& track, const TrackPublishOptions& options); +``` + +#### Deprecation comments + +When superseding a public API, every retained back-compat shim must carry a +Doxygen `/// @deprecated Use () instead.` line so the generated docs +render a deprecation callout (see "Deprecating a public API" above). + +#### Verifying locally + +Run Doxygen from the repository root to regenerate the HTML docs: + +```bash +doxygen docs/Doxyfile +``` + +The output lands in `docs/html/`. Doxygen warnings about "is not documented" +indicate undocumented public symbols — adding documentation to them is +encouraged but not strictly required by these rules. + ### Integer Types - Prefer fixed-width integer types from `` (`std::int32_t`, `std::uint64_t`, etc.) over raw primitive integer types when size or signedness matters. diff --git a/include/livekit/audio_frame.h b/include/livekit/audio_frame.h index 78bb87c5..80678903 100644 --- a/include/livekit/audio_frame.h +++ b/include/livekit/audio_frame.h @@ -29,38 +29,30 @@ class AudioFrameBufferInfo; class OwnedAudioFrameBuffer; } // namespace proto -/** - * @brief Represents a raw PCM audio frame with interleaved int16 samples. - * - * AudioFrame holds decoded audio data along with metadata such as sample rate, - * number of channels, and samples per channel. It is used for capturing and - * processing audio in the LiveKit SDK. - */ +/// @brief Represents a raw PCM audio frame with interleaved int16 samples. +/// +/// AudioFrame holds decoded audio data along with metadata such as sample rate, +/// number of channels, and samples per channel. It is used for capturing and +/// processing audio in the LiveKit SDK. class LIVEKIT_API AudioFrame { public: - /** - * Construct an AudioFrame from raw PCM samples. - * - * @param data Interleaved PCM samples (int16). - * @param sample_rate Sample rate (Hz). - * @param num_channels Number of channels. - * @param samples_per_channel Number of samples per channel. - * - * Throws std::invalid_argument if the data size is inconsistent with - * num_channels * samples_per_channel. - */ + /// Construct an AudioFrame from raw PCM samples. + /// + /// @param data Interleaved PCM samples (int16). + /// @param sample_rate Sample rate (Hz). + /// @param num_channels Number of channels. + /// @param samples_per_channel Number of samples per channel. + /// + /// @throws std::invalid_argument if the data size is inconsistent with + /// num_channels * samples_per_channel. AudioFrame(std::vector data, int sample_rate, int num_channels, int samples_per_channel); AudioFrame(); // Default constructor virtual ~AudioFrame() = default; - /** - * Create a new zero-initialized AudioFrame instance. - */ + /// Create a new zero-initialized AudioFrame instance. static AudioFrame create(int sample_rate, int num_channels, int samples_per_channel); - /** - * Construct an AudioFrame by copying data out of an OwnedAudioFrameBuffer. - */ + /// Construct an AudioFrame by copying data out of an OwnedAudioFrameBuffer. static AudioFrame fromOwnedInfo(const proto::OwnedAudioFrameBuffer& owned); // ---- Accessors ---- diff --git a/include/livekit/audio_processing_module.h b/include/livekit/audio_processing_module.h index 2d141ceb..8e8f96af 100644 --- a/include/livekit/audio_processing_module.h +++ b/include/livekit/audio_processing_module.h @@ -24,29 +24,25 @@ namespace livekit { -/** - * @brief WebRTC Audio Processing Module (APM) for real-time audio enhancement. - * - * AudioProcessingModule exposes WebRTC's built-in audio processing capabilities - * including echo cancellation, noise suppression, automatic gain control, and - * high-pass filtering. - * - * This class is designed for scenarios where you need explicit control over - * audio processing, separate from the built-in processing in AudioSource. - * - * Typical usage pattern for echo cancellation: - * 1. Create an APM with desired features enabled - * 2. Call processReverseStream() with speaker/playback audio (reference signal) - * 3. Call processStream() with microphone audio (near-end signal) - * 4. The processed microphone audio will have echo removed - * - * Note: Audio frames must be exactly 10ms in duration. - */ +/// @brief WebRTC Audio Processing Module (APM) for real-time audio enhancement. +/// +/// AudioProcessingModule exposes WebRTC's built-in audio processing capabilities +/// including echo cancellation, noise suppression, automatic gain control, and +/// high-pass filtering. +/// +/// This class is designed for scenarios where you need explicit control over +/// audio processing, separate from the built-in processing in AudioSource. +/// +/// Typical usage pattern for echo cancellation: +/// 1. Create an APM with desired features enabled +/// 2. Call processReverseStream() with speaker/playback audio (reference signal) +/// 3. Call processStream() with microphone audio (near-end signal) +/// 4. The processed microphone audio will have echo removed +/// +/// @note Audio frames must be exactly 10ms in duration. class LIVEKIT_API AudioProcessingModule { public: - /** - * @brief Configuration options for the Audio Processing Module. - */ + /// @brief Configuration options for the Audio Processing Module. struct Options { /// Enable acoustic echo cancellation (AEC3). /// Removes acoustic echo in two-way communication scenarios. @@ -68,20 +64,16 @@ class LIVEKIT_API AudioProcessingModule { Options() = default; }; - /** - * @brief Create a new Audio Processing Module with default options (all - * disabled). - * - * @throws std::runtime_error if the APM could not be created. - */ + /// @brief Create a new Audio Processing Module with default options (all + /// disabled). + /// + /// @throws std::runtime_error if the APM could not be created. AudioProcessingModule(); - /** - * @brief Create a new Audio Processing Module with the specified options. - * - * @param options Configuration for which processing features to enable. - * @throws std::runtime_error if the APM could not be created. - */ + /// @brief Create a new Audio Processing Module with the specified options. + /// + /// @param options Configuration for which processing features to enable. + /// @throws std::runtime_error if the APM could not be created. explicit AudioProcessingModule(const Options& options); virtual ~AudioProcessingModule() = default; @@ -94,65 +86,59 @@ class LIVEKIT_API AudioProcessingModule { AudioProcessingModule(AudioProcessingModule&&) noexcept = default; AudioProcessingModule& operator=(AudioProcessingModule&&) noexcept = default; - /** - * @brief Process the forward (near-end/microphone) audio stream. - * - * This method processes audio captured from the local microphone. It applies - * the enabled processing features (noise suppression, gain control, etc.) - * and removes echo based on the reference signal provided via - * processReverseStream(). - * - * The audio data is modified in-place. - * - * @param frame The audio frame to process (modified in-place). - * - * @throws std::runtime_error if processing fails. - * - * @note The frame must contain exactly 10ms of audio. - */ + /// @brief Process the forward (near-end/microphone) audio stream. + /// + /// This method processes audio captured from the local microphone. It applies + /// the enabled processing features (noise suppression, gain control, etc.) + /// and removes echo based on the reference signal provided via + /// processReverseStream(). + /// + /// The audio data is modified in-place. + /// + /// @param frame The audio frame to process (modified in-place). + /// + /// @throws std::runtime_error if processing fails. + /// + /// @note The frame must contain exactly 10ms of audio. void processStream(AudioFrame& frame); - /** - * @brief Process the reverse (far-end/speaker) audio stream. - * - * This method provides the reference signal for echo cancellation. Call this - * with the audio that is being played through the speakers, so the APM can - * learn the acoustic characteristics and remove the echo from the microphone - * signal. - * - * The audio data is modified in-place. - * - * @param frame The audio frame to process (modified in-place). - * - * @throws std::runtime_error if processing fails. - * - * @note The frame must contain exactly 10ms of audio. - */ + /// @brief Process the reverse (far-end/speaker) audio stream. + /// + /// This method provides the reference signal for echo cancellation. Call this + /// with the audio that is being played through the speakers, so the APM can + /// learn the acoustic characteristics and remove the echo from the microphone + /// signal. + /// + /// The audio data is modified in-place. + /// + /// @param frame The audio frame to process (modified in-place). + /// + /// @throws std::runtime_error if processing fails. + /// + /// @note The frame must contain exactly 10ms of audio. void processReverseStream(AudioFrame& frame); - /** - * @brief Set the estimated delay between the reverse and forward streams. - * - * This must be called if and only if echo processing is enabled. - * - * Sets the delay in ms between processReverseStream() receiving a far-end - * frame and processStream() receiving a near-end frame containing the - * corresponding echo. On the client-side this can be expressed as: - * - * delay = (t_render - t_analyze) + (t_process - t_capture) - * - * where: - * - t_analyze is the time a frame is passed to processReverseStream() and - * t_render is the time the first sample of the same frame is rendered by - * the audio hardware. - * - t_capture is the time the first sample of a frame is captured by the - * audio hardware and t_process is the time the same frame is passed to - * processStream(). - * - * @param delay_ms Delay in milliseconds. - * - * @throws std::runtime_error if setting the delay fails. - */ + /// @brief Set the estimated delay between the reverse and forward streams. + /// + /// This must be called if and only if echo processing is enabled. + /// + /// Sets the delay in ms between processReverseStream() receiving a far-end + /// frame and processStream() receiving a near-end frame containing the + /// corresponding echo. On the client-side this can be expressed as: + /// + /// delay = (t_render - t_analyze) + (t_process - t_capture) + /// + /// where: + /// - t_analyze is the time a frame is passed to processReverseStream() and + /// t_render is the time the first sample of the same frame is rendered by + /// the audio hardware. + /// - t_capture is the time the first sample of a frame is captured by the + /// audio hardware and t_process is the time the same frame is passed to + /// processStream(). + /// + /// @param delay_ms Delay in milliseconds. + /// + /// @throws std::runtime_error if setting the delay fails. void setStreamDelayMs(int delay_ms); private: diff --git a/include/livekit/audio_source.h b/include/livekit/audio_source.h index c2a16ed2..5c149dd0 100644 --- a/include/livekit/audio_source.h +++ b/include/livekit/audio_source.h @@ -31,44 +31,40 @@ class FfiResponse; class FfiClient; -/** - * Represents a real-time audio source with an internal audio queue. - */ +/// Represents a real-time audio source with an internal audio queue. class LIVEKIT_API AudioSource { public: - /** - * Create a new native audio source. - * - * @param sample_rate Sample rate in Hz. - * @param num_channels Number of channels. - * @param queue_size_ms Max buffer duration for the internal queue in ms. - * - * Buffering behavior: - * ------------------- - * - queue_size_ms == 0 (recommended for real-time capture): - * Disables internal buffering entirely. Audio frames are forwarded - * directly to WebRTC sinks and consumed synchronously. - * - * This mode is optimized for real-time audio capture driven by hardware - * media callbacks (e.g. microphone capture). The caller is expected to - * provide fixed-size real-time frames (typically 10 ms per call). - * - * Because the native side consumes frames immediately, this mode - * minimizes latency and jitter and is the best choice for live capture - * scenarios. - * - * - queue_size_ms > 0 (buffered / blocking mode): - * Enables an internal queue that buffers audio up to the specified - * duration. Frames are accumulated and flushed asynchronously once the buffer - * reaches its threshold. - * - * This mode is intended for non-real-time producers (e.g. TTS engines, - * file-based audio, or agents generating audio faster or slower than - * real-time). The buffering layer smooths timing and allows the audio to - * be streamed out in real time even if the producer is bursty. - * - * queue_size_ms must be a multiple of 10. - */ + /// Create a new native audio source. + /// + /// @param sample_rate Sample rate in Hz. + /// @param num_channels Number of channels. + /// @param queue_size_ms Max buffer duration for the internal queue in ms. + /// + /// Buffering behavior: + /// ------------------- + /// - queue_size_ms == 0 (recommended for real-time capture): + /// Disables internal buffering entirely. Audio frames are forwarded + /// directly to WebRTC sinks and consumed synchronously. + /// + /// This mode is optimized for real-time audio capture driven by hardware + /// media callbacks (e.g. microphone capture). The caller is expected to + /// provide fixed-size real-time frames (typically 10 ms per call). + /// + /// Because the native side consumes frames immediately, this mode + /// minimizes latency and jitter and is the best choice for live capture + /// scenarios. + /// + /// - queue_size_ms > 0 (buffered / blocking mode): + /// Enables an internal queue that buffers audio up to the specified + /// duration. Frames are accumulated and flushed asynchronously once the buffer + /// reaches its threshold. + /// + /// This mode is intended for non-real-time producers (e.g. TTS engines, + /// file-based audio, or agents generating audio faster or slower than + /// real-time). The buffering layer smooths timing and allows the audio to + /// be streamed out in real time even if the producer is bursty. + /// + /// queue_size_ms must be a multiple of 10. AudioSource(int sample_rate, int num_channels, int queue_size_ms = 0); virtual ~AudioSource() = default; @@ -107,55 +103,49 @@ class LIVEKIT_API AudioSource { /// Current duration of queued audio (in seconds). double queuedDuration() const noexcept; - /** - * Clears the internal audio queue on the native side and resets local - * queue tracking. - */ + /// Clears the internal audio queue on the native side and resets local + /// queue tracking. void clearQueue(); - /** - * Push an AudioFrame into the audio source and BLOCK until the FFI callback - * confirms that the native side has finished processing (consuming) the - * frame. Safe usage: The frame's internal buffer must remain valid only until - * this function returns. Because this call blocks until the corresponding FFI - * callback arrives, the caller may safely destroy or reuse the frame - * afterward. - * @param frame The audio frame to send. No-op if the frame contains - * zero samples. - * @param timeout_ms Maximum time to wait for the FFI callback. - * - If timeout_ms > 0: block up to this duration. - * A timeout will cause std::runtime_error. - * - If timeout_ms == 0: wait indefinitely until the - * callback arrives (recommended for production unless the caller needs - * explicit timeout control). - * - * Blocking semantics: - * The blocking behavior of this call depends on the buffering mode selected - * at construction time: - * - * - queue_size_ms == 0 (real-time capture mode): - * Frames are consumed synchronously by the native layer. The FFI callback - * is invoked immediately as part of the capture call, so this function - * returns quickly. - * - * This mode relies on the caller being paced by a real-time media - * callback (e.g. audio hardware interrupt / capture thread). It provides the - * lowest possible latency and is ideal for live microphone capture. - * - * - queue_size_ms > 0 (buffered / non-real-time mode): - * Frames are queued internally and flushed asynchronously. This function - * will block until the buffered audio corresponding to this frame has - * been consumed by the native side and the FFI callback fires. - * - * This mode is best suited for non-real-time audio producers (such as TTS - * engines or agents) that generate audio independently of real-time - * pacing, while still streaming audio out in real time. - * - * Safety notes: - * May throw std::runtime_error if: - * - the FFI reports an error - * - a timeout occurs in bounded-wait mode - */ + /// Push an AudioFrame into the audio source and BLOCK until the FFI callback + /// confirms that the native side has finished processing (consuming) the + /// frame. Safe usage: The frame's internal buffer must remain valid only until + /// this function returns. Because this call blocks until the corresponding FFI + /// callback arrives, the caller may safely destroy or reuse the frame + /// afterward. + /// @param frame The audio frame to send. No-op if the frame contains + /// zero samples. + /// @param timeout_ms Maximum time to wait for the FFI callback. + /// - If timeout_ms > 0: block up to this duration. + /// A timeout will cause std::runtime_error. + /// - If timeout_ms == 0: wait indefinitely until the + /// callback arrives (recommended for production unless the caller needs + /// explicit timeout control). + /// + /// Blocking semantics: + /// The blocking behavior of this call depends on the buffering mode selected + /// at construction time: + /// + /// - queue_size_ms == 0 (real-time capture mode): + /// Frames are consumed synchronously by the native layer. The FFI callback + /// is invoked immediately as part of the capture call, so this function + /// returns quickly. + /// + /// This mode relies on the caller being paced by a real-time media + /// callback (e.g. audio hardware interrupt / capture thread). It provides the + /// lowest possible latency and is ideal for live microphone capture. + /// + /// - queue_size_ms > 0 (buffered / non-real-time mode): + /// Frames are queued internally and flushed asynchronously. This function + /// will block until the buffered audio corresponding to this frame has + /// been consumed by the native side and the FFI callback fires. + /// + /// This mode is best suited for non-real-time audio producers (such as TTS + /// engines or agents) that generate audio independently of real-time + /// pacing, while still streaming audio out in real time. + /// + /// @throws std::runtime_error if the FFI reports an error or a timeout + /// occurs in bounded-wait mode. void captureFrame(const AudioFrame& frame, int timeout_ms = 20); private: diff --git a/include/livekit/audio_stream.h b/include/livekit/audio_stream.h index 57be0a89..2cfa2501 100644 --- a/include/livekit/audio_stream.h +++ b/include/livekit/audio_stream.h @@ -36,12 +36,10 @@ namespace proto { class FfiEvent; } -/** - * @brief Event containing an audio frame received from an AudioStream. - * - * This struct wraps an AudioFrame and is used as the output type when - * reading from an AudioStream. - */ +/// @brief Event containing an audio frame received from an AudioStream. +/// +/// This struct wraps an AudioFrame and is used as the output type when +/// reading from an AudioStream. // NOLINTBEGIN(bugprone-exception-escape) // AudioFrame can throw in various places monitored by bugprone-exception-escape // Suppressing for now, would require significant refactor to fix @@ -50,22 +48,20 @@ struct AudioFrameEvent { }; // NOLINTEND(bugprone-exception-escape) -/** - * Represents a pull-based stream of decoded PCM audio frames coming from - * a remote (or local) LiveKit track. Similar to VideoStream, but for audio. - * - * Typical usage: - * - * AudioStream::Options opts; - * auto stream = AudioStream::fromTrack(remoteAudioTrack, opts); - * - * AudioFrameEvent ev; - * while (stream->read(ev)) { - * // ev.frame contains interleaved int16 PCM samples - * } - * - * stream->close(); // optional, called automatically in destructor - */ +/// Represents a pull-based stream of decoded PCM audio frames coming from +/// a remote (or local) LiveKit track. Similar to VideoStream, but for audio. +/// +/// Typical usage: +/// +/// AudioStream::Options opts; +/// auto stream = AudioStream::fromTrack(remoteAudioTrack, opts); +/// +/// AudioFrameEvent ev; +/// while (stream->read(ev)) { +/// // ev.frame contains interleaved int16 PCM samples +/// } +/// +/// stream->close(); // optional, called automatically in destructor class LIVEKIT_API AudioStream { public: /// Configuration options for AudioStream creation. @@ -105,8 +101,8 @@ class LIVEKIT_API AudioStream { /// Blocking read: waits until there is an AudioFrameEvent available in the /// internal queue, or the stream reaches EOS / is closed. /// - /// \param out_event On success, filled with the next audio frame. - /// \return true if a frame was delivered; false if the stream ended + /// @param out_event On success, filled with the next audio frame. + /// @return true if a frame was delivered; false if the stream ended /// (end-of-stream or close()) and no more data is available. bool read(AudioFrameEvent& out_event); diff --git a/include/livekit/data_stream.h b/include/livekit/data_stream.h index ed81cf83..318a29ff 100644 --- a/include/livekit/data_stream.h +++ b/include/livekit/data_stream.h @@ -33,9 +33,9 @@ namespace livekit { class LocalParticipant; -// Chunk size for data streams (matches Python STREAM_CHUNK_SIZE). -// Chosen to balance throughput and latency, and to work well with WebRTC data -// channels. +/// Chunk size for data streams (matches Python STREAM_CHUNK_SIZE). +/// Chosen to balance throughput and latency, and to work well with WebRTC data +/// channels. constexpr std::size_t kStreamChunkSize = 15'000; // 15 KB /// Base metadata for any stream (text or bytes). @@ -261,21 +261,19 @@ class LIVEKIT_API ByteStreamWriter : public BaseStreamWriter { std::mutex write_mutex_; }; -/* Callback invoked when a new incoming text stream is opened. - * - * The TextStreamReader is provided as a shared_ptr to ensure it remains - * alive for the duration of asynchronous reads (for example, when the - * user spawns a background thread to consume the stream). - */ +/// Callback invoked when a new incoming text stream is opened. +/// +/// The TextStreamReader is provided as a shared_ptr to ensure it remains +/// alive for the duration of asynchronous reads (for example, when the +/// user spawns a background thread to consume the stream). using TextStreamHandler = std::function, const std::string& participant_identity)>; -/* Callback invoked when a new incoming byte stream is opened. - * - * The ByteStreamReader is provided as a shared_ptr to ensure it remains - * alive for the duration of asynchronous reads (for example, file writes - * or background processing). - */ +/// Callback invoked when a new incoming byte stream is opened. +/// +/// The ByteStreamReader is provided as a shared_ptr to ensure it remains +/// alive for the duration of asynchronous reads (for example, file writes +/// or background processing). using ByteStreamHandler = std::function, const std::string& participant_identity)>; diff --git a/include/livekit/data_track_frame.h b/include/livekit/data_track_frame.h index 1e82ac5a..a93199a6 100644 --- a/include/livekit/data_track_frame.h +++ b/include/livekit/data_track_frame.h @@ -28,23 +28,19 @@ namespace proto { class DataTrackFrame; } // namespace proto -/** - * A single frame of data published or received on a data track. - * - * Carries an arbitrary binary payload and an optional user-specified - * timestamp. The unit is application-defined; the SDK examples use - * microseconds since the Unix epoch (system_clock). - */ +/// A single frame of data published or received on a data track. +/// +/// Carries an arbitrary binary payload and an optional user-specified +/// timestamp. The unit is application-defined; the SDK examples use +/// microseconds since the Unix epoch (system_clock). struct DataTrackFrame { - /** Arbitrary binary payload (the frame contents). */ + /// Arbitrary binary payload (the frame contents). std::vector payload; - /** - * Optional application-defined timestamp. - * - * The proto field is a bare uint64 with no prescribed unit. - * By convention the SDK examples use microseconds since the Unix epoch. - */ + /// Optional application-defined timestamp. + /// + /// The proto field is a bare uint64 with no prescribed unit. + /// By convention the SDK examples use microseconds since the Unix epoch. std::optional user_timestamp; DataTrackFrame() = default; DataTrackFrame(const DataTrackFrame&) = default; @@ -55,13 +51,11 @@ struct DataTrackFrame { explicit DataTrackFrame(std::vector&& p, std::optional ts = std::nullopt) noexcept : payload(std::move(p)), user_timestamp(ts) {} - /** - * @brief This is a private method used by the SDK to create a DataTrackFrame - * from a proto::DataTrackFrame. - * - * @param owned The proto::DataTrackFrame to create a DataTrackFrame from. - * @return The created DataTrackFrame. - */ + /// @brief This is a private method used by the SDK to create a DataTrackFrame + /// from a proto::DataTrackFrame. + /// + /// @param owned The proto::DataTrackFrame to create a DataTrackFrame from. + /// @return The created DataTrackFrame. LIVEKIT_API static DataTrackFrame fromOwnedInfo(const proto::DataTrackFrame& owned); }; diff --git a/include/livekit/data_track_info.h b/include/livekit/data_track_info.h index 45c4fc5f..27310269 100644 --- a/include/livekit/data_track_info.h +++ b/include/livekit/data_track_info.h @@ -20,20 +20,18 @@ namespace livekit { -/** - * Metadata about a published data track. - * - * Unlike audio/video tracks, data tracks are not part of the Track class - * hierarchy. They carry their own lightweight info struct. - */ +/// Metadata about a published data track. +/// +/// Unlike audio/video tracks, data tracks are not part of the Track class +/// hierarchy. They carry their own lightweight info struct. struct DataTrackInfo { - /** Publisher-assigned track name (unique per publisher). */ + /// Publisher-assigned track name (unique per publisher). std::string name; - /** SFU-assigned track identifier. */ + /// SFU-assigned track identifier. std::string sid; - /** Whether frames on this track use end-to-end encryption. */ + /// Whether frames on this track use end-to-end encryption. bool uses_e2ee = false; }; diff --git a/include/livekit/data_track_stream.h b/include/livekit/data_track_stream.h index 6328d152..466677c8 100644 --- a/include/livekit/data_track_stream.h +++ b/include/livekit/data_track_stream.h @@ -33,26 +33,24 @@ class FfiEvent; class DataTrackStreamReadResponse; } // namespace proto -/** - * Represents a pull-based stream of frames from a remote data track. - * - * Provides a blocking read() interface similar to AudioStream / VideoStream. - * Frames are delivered via FfiEvent callbacks and stored internally. - * - * Destroying the stream automatically unsubscribes from the remote track by - * releasing the underlying FFI handle. - * - * Typical usage: - * - * auto sub_result = remoteDataTrack->subscribe(); - * if (sub_result) { - * auto sub = sub_result.value(); - * DataTrackFrame frame; - * while (sub->read(frame)) { - * // process frame.payload - * } - * } - */ +/// Represents a pull-based stream of frames from a remote data track. +/// +/// Provides a blocking read() interface similar to AudioStream / VideoStream. +/// Frames are delivered via FfiEvent callbacks and stored internally. +/// +/// Destroying the stream automatically unsubscribes from the remote track by +/// releasing the underlying FFI handle. +/// +/// Typical usage: +/// +/// auto sub_result = remoteDataTrack->subscribe(); +/// if (sub_result) { +/// auto sub = sub_result.value(); +/// DataTrackFrame frame; +/// while (sub->read(frame)) { +/// // process frame.payload +/// } +/// } class LIVEKIT_API DataTrackStream { public: struct Options { @@ -71,30 +69,24 @@ class LIVEKIT_API DataTrackStream { // support is not required by the current API. DataTrackStream& operator=(DataTrackStream&&) noexcept = delete; - /** - * Blocking read: waits until a DataTrackFrame is available, or the - * stream reaches EOS / is closed. - * - * @param out On success, filled with the next data frame. - * @return true if a frame was delivered; false if the stream ended. - */ + /// Blocking read: waits until a DataTrackFrame is available, or the + /// stream reaches EOS / is closed. + /// + /// @param out On success, filled with the next data frame. + /// @return true if a frame was delivered; false if the stream ended. bool read(DataTrackFrame& out); - /** - * Returns the terminal subscription error reported by the FFI stream. - * - * This is set when read() returns false because subscription establishment - * failed before any frames were emitted. It remains empty for normal EOS or - * when close() ends the stream locally. - */ + /// Returns the terminal subscription error reported by the FFI stream. + /// + /// This is set when read() returns false because subscription establishment + /// failed before any frames were emitted. It remains empty for normal EOS or + /// when close() ends the stream locally. std::optional terminalError() const; - /** - * End the stream early. - * - * Releases the FFI handle (which unsubscribes from the remote track), - * unregisters the event listener, and wakes any blocking read(). - */ + /// End the stream early. + /// + /// Releases the FFI handle (which unsubscribes from the remote track), + /// unregisters the event listener, and wakes any blocking read(). void close(); private: @@ -122,32 +114,30 @@ class LIVEKIT_API DataTrackStream { /// Push an end-of-stream signal (EOS). void pushEos(std::optional error = std::nullopt); - /** Protects all mutable state below. */ + /// Protects all mutable state below. mutable std::mutex mutex_; - /** Signalled when a frame is pushed or the subscription ends. */ + /// Signalled when a frame is pushed or the subscription ends. std::condition_variable cv_; - /** - * Received frame awaiting read(). - * NOTE: the Rust side handles buffering, so we should only really ever have - * one item. - */ + /// Received frame awaiting read(). + /// NOTE: the Rust side handles buffering, so we should only really ever have + /// one item. std::optional frame_; - /** True once the remote side signals end-of-stream. */ + /// True once the remote side signals end-of-stream. bool eof_{false}; - /** True after close() has been called by the consumer. */ + /// True after close() has been called by the consumer. bool closed_{false}; - /** Typed terminal error reported with EOS, if subscription setup failed. */ + /// Typed terminal error reported with EOS, if subscription setup failed. std::optional terminal_error_; - /** RAII handle for the Rust-owned subscription resource. */ + /// RAII handle for the Rust-owned subscription resource. FfiHandle subscription_handle_; - /** FfiClient listener id for routing FfiEvent callbacks to this object. */ + /// FfiClient listener id for routing FfiEvent callbacks to this object. std::int32_t listener_id_{-1}; }; diff --git a/include/livekit/e2ee.h b/include/livekit/e2ee.h index fe087c38..295a68ab 100644 --- a/include/livekit/e2ee.h +++ b/include/livekit/e2ee.h @@ -26,36 +26,34 @@ namespace livekit { -/* Encryption algorithm type used by the underlying stack. - * Keep this aligned with your proto enum values. */ +/// Encryption algorithm type used by the underlying stack. +/// Keep this aligned with your proto enum values. enum class EncryptionType { NONE = 0, GCM = 1, CUSTOM = 2, }; -/* Key derivation algorithm used by the key provider. */ +/// Key derivation algorithm used by the key provider. enum class KeyDerivationFunction { PBKDF2 = 0, HKDF = 1, }; -/* Defaults (match Rust KeyProviderOptions::default()). */ +/// Defaults (match Rust KeyProviderOptions::default()). inline constexpr const char* kDefaultRatchetSalt = "LKFrameEncryptionKey"; inline constexpr int kDefaultRatchetWindowSize = 16; inline constexpr int kDefaultFailureTolerance = -1; inline constexpr int kDefaultKeyRingSize = 16; inline constexpr KeyDerivationFunction kDefaultKeyDerivationFunction = KeyDerivationFunction::PBKDF2; -/** - * Options for configuring the key provider used by E2EE. - * - * Notes: - * - `shared_key` is optional. If omitted, the application may set keys later - * (e.g. via KeyProvider::setSharedKey / per-participant keys). - * - `ratchet_salt` may be empty to indicate "use implementation default". - * - Other key provider fields use SDK defaults unless overridden. - */ +/// Options for configuring the key provider used by E2EE. +/// +/// Notes: +/// - `shared_key` is optional. If omitted, the application may set keys later +/// (e.g. via KeyProvider::setSharedKey / per-participant keys). +/// - `ratchet_salt` may be empty to indicate "use implementation default". +/// - Other key provider fields use SDK defaults unless overridden. struct KeyProviderOptions { /// Shared static key for "shared-key E2EE" (optional). /// @@ -85,49 +83,44 @@ struct KeyProviderOptions { KeyDerivationFunction key_derivation_function = kDefaultKeyDerivationFunction; }; -/** - * End-to-end encryption (E2EE) configuration for a room. - * - * Provide this in RoomOptions to initialize E2EE support. - * - * IMPORTANT: - * - Providing E2EEOptions means "E2EE support is configured for this room". - * - Whether encryption is actively applied can still be toggled at runtime via - * E2EEManager::setEnabled(). - * - A room can be configured for E2EE even if no shared key is provided yet. - * In that case, the app must supply keys later via KeyProvider (shared-key or - * per-participant). - */ +/// End-to-end encryption (E2EE) configuration for a room. +/// +/// Provide this in RoomOptions to initialize E2EE support. +/// +/// IMPORTANT: +/// - Providing E2EEOptions means "E2EE support is configured for this room". +/// - Whether encryption is actively applied can still be toggled at runtime via +/// E2EEManager::setEnabled(). +/// - A room can be configured for E2EE even if no shared key is provided yet. +/// In that case, the app must supply keys later via KeyProvider (shared-key or +/// per-participant). struct E2EEOptions { KeyProviderOptions key_provider_options{}; EncryptionType encryption_type = EncryptionType::GCM; // default & recommended }; -/** - * E2EE manager for a connected room. - * - * Lifetime: - * - Owned by Room. Applications must not construct E2EEManager directly. - * - * Enablement model: - * - If the Room was created with `RoomOptions.e2ee` set, the room will expose - * a non-null E2EEManager via Room::E2eeManager(). - * - If the Room was created without E2EE options, Room::E2eeManager() may be - * null. - * - * Key model: - * - Keys are managed via KeyProvider (shared-key or per-participant). - * - Providing a shared key up-front is convenient for shared-key E2EE, but is - * not required by the API shape (keys may be supplied later). - */ +/// E2EE manager for a connected room. +/// +/// Lifetime: +/// - Owned by Room. Applications must not construct E2EEManager directly. +/// +/// Enablement model: +/// - If the Room was created with `RoomOptions.e2ee` set, the room will expose +/// a non-null E2EEManager via Room::E2eeManager(). +/// - If the Room was created without E2EE options, Room::E2eeManager() may be +/// null. +/// +/// Key model: +/// - Keys are managed via KeyProvider (shared-key or per-participant). +/// - Providing a shared key up-front is convenient for shared-key E2EE, but is +/// not required by the API shape (keys may be supplied later). class LIVEKIT_API E2EEManager { public: - /** If your application requires key rotation during the lifetime of a single - * room or unique keys per participant (such as when implementing the MEGOLM - * or MLS protocol), you' can do it via key provider and frame cryptor. refer - * https://docs.livekit.io/home/client/encryption/#custom-key-provider doe - * details - * */ + /// If your application requires key rotation during the lifetime of a single + /// room or unique keys per participant (such as when implementing the MEGOLM + /// or MLS protocol), you' can do it via key provider and frame cryptor. refer + /// https://docs.livekit.io/home/client/encryption/#custom-key-provider doe + /// details class LIVEKIT_API KeyProvider { public: ~KeyProvider() = default; diff --git a/include/livekit/ffi_handle.h b/include/livekit/ffi_handle.h index 840aa384..c1b33a4a 100644 --- a/include/livekit/ffi_handle.h +++ b/include/livekit/ffi_handle.h @@ -22,12 +22,10 @@ namespace livekit { -/** - * @brief RAII wrapper for an FFI handle (uintptr_t) coming from Rust. - * - * Ensures that the handle is automatically released via - * livekit_ffi_drop_handle() when the object goes out of scope. - */ +/// @brief RAII wrapper for an FFI handle (uintptr_t) coming from Rust. +/// +/// Ensures that the handle is automatically released via +/// livekit_ffi_drop_handle() when the object goes out of scope. class LIVEKIT_API FfiHandle { public: explicit FfiHandle(uintptr_t h = 0) noexcept; @@ -41,19 +39,19 @@ class LIVEKIT_API FfiHandle { FfiHandle(FfiHandle&& other) noexcept; FfiHandle& operator=(FfiHandle&& other) noexcept; - // Replace the current handle with a new one, dropping the old if needed + /// Replace the current handle with a new one, dropping the old if needed void reset(uintptr_t new_handle = 0) noexcept; - // Release ownership of the handle without dropping it + /// Release ownership of the handle without dropping it [[nodiscard]] uintptr_t release() noexcept; - // Whether the handle is valid (non-zero) + /// Whether the handle is valid (non-zero) [[nodiscard]] bool valid() const noexcept; - // Get the raw handle value + /// Get the raw handle value [[nodiscard]] uintptr_t get() const noexcept; - // Allow `if (handle)` syntax + /// Allow `if (handle)` syntax explicit operator bool() const noexcept { return valid(); } private: diff --git a/include/livekit/local_audio_track.h b/include/livekit/local_audio_track.h index 268042e0..827ba4e7 100644 --- a/include/livekit/local_audio_track.h +++ b/include/livekit/local_audio_track.h @@ -32,26 +32,24 @@ class OwnedTrack; class AudioSource; -/** - * Represents a user-provided audio track sourced from the local device. - * - * `LocalAudioTrack` is used to publish microphone audio (or any custom - * audio source) to a LiveKit room. It wraps a platform-specific audio - * source and exposes simple controls such as `mute()` and `unmute()`. - * - * Typical usage: - * - * auto source = AudioSource::create(...); - * auto track = LocalAudioTrack::createLocalAudioTrack("mic", source); - * room->localParticipant()->publishTrack(track); - * - * Muting a local audio track stops transmitting audio to the room, but - * the underlying source may continue capturing depending on platform - * behavior. - * - * The track name provided during creation is visible to remote - * participants and can be used for debugging or UI display. - */ +/// Represents a user-provided audio track sourced from the local device. +/// +/// `LocalAudioTrack` is used to publish microphone audio (or any custom +/// audio source) to a LiveKit room. It wraps a platform-specific audio +/// source and exposes simple controls such as `mute()` and `unmute()`. +/// +/// Typical usage: +/// +/// auto source = AudioSource::create(...); +/// auto track = LocalAudioTrack::createLocalAudioTrack("mic", source); +/// room->localParticipant()->publishTrack(track); +/// +/// Muting a local audio track stops transmitting audio to the room, but +/// the underlying source may continue capturing depending on platform +/// behavior. +/// +/// The track name provided during creation is visible to remote +/// participants and can be used for debugging or UI display. class LIVEKIT_API LocalAudioTrack : public Track { public: /// Creates a new local audio track backed by the given `AudioSource`. diff --git a/include/livekit/local_data_track.h b/include/livekit/local_data_track.h index 642a18ed..80d57dac 100644 --- a/include/livekit/local_data_track.h +++ b/include/livekit/local_data_track.h @@ -35,27 +35,25 @@ namespace proto { class OwnedLocalDataTrack; } -/** - * Represents a locally published data track. - * - * Unlike audio/video tracks, data tracks do not extend the Track base class. - * They use a separate publish/unpublish lifecycle and carry arbitrary binary - * frames instead of media. - * - * Created via LocalParticipant::publishDataTrack(). - * - * Typical usage: - * - * auto lp = room->localParticipant(); - * auto result = lp->publishDataTrack("sensor-data"); - * if (result) { - * auto dt = result.value(); - * DataTrackFrame frame; - * frame.payload = {0x01, 0x02, 0x03}; - * (void)dt->tryPush(frame); - * dt->unpublishDataTrack(); - * } - */ +/// Represents a locally published data track. +/// +/// Unlike audio/video tracks, data tracks do not extend the Track base class. +/// They use a separate publish/unpublish lifecycle and carry arbitrary binary +/// frames instead of media. +/// +/// Created via LocalParticipant::publishDataTrack(). +/// +/// Typical usage: +/// +/// auto lp = room->localParticipant(); +/// auto result = lp->publishDataTrack("sensor-data"); +/// if (result) { +/// auto dt = result.value(); +/// DataTrackFrame frame; +/// frame.payload = {0x01, 0x02, 0x03}; +/// (void)dt->tryPush(frame); +/// dt->unpublishDataTrack(); +/// } class LIVEKIT_API LocalDataTrack { public: ~LocalDataTrack() = default; @@ -66,31 +64,25 @@ class LIVEKIT_API LocalDataTrack { /// Metadata about this data track. const DataTrackInfo& info() const noexcept { return info_; } - /** - * Try to push a frame to all subscribers of this track. - * - * @return success on delivery acceptance, or a typed error describing why - * the frame could not be queued. - */ + /// Try to push a frame to all subscribers of this track. + /// + /// @return success on delivery acceptance, or a typed error describing why + /// the frame could not be queued. Result tryPush(const DataTrackFrame& frame); - /** - * Try to push a frame to all subscribers of this track. - * - * @return success on delivery acceptance, or a typed error describing why - * the frame could not be queued. - */ + /// Try to push a frame to all subscribers of this track. + /// + /// @return success on delivery acceptance, or a typed error describing why + /// the frame could not be queued. Result tryPush(std::vector&& payload, std::optional user_timestamp = std::nullopt); /// Whether the track is still published in the room. bool isPublished() const; - /** - * Unpublish this data track from the room. - * - * After this call, tryPush() fails and the track cannot be re-published. - */ + /// Unpublish this data track from the room. + /// + /// After this call, tryPush() fails and the track cannot be re-published. void unpublishDataTrack(); private: @@ -100,10 +92,10 @@ class LIVEKIT_API LocalDataTrack { uintptr_t ffiHandleId() const noexcept { return handle_.get(); } - /** RAII wrapper for the Rust-owned FFI resource. */ + /// RAII wrapper for the Rust-owned FFI resource. FfiHandle handle_; - /** Metadata snapshot taken at construction time. */ + /// Metadata snapshot taken at construction time. DataTrackInfo info_; }; diff --git a/include/livekit/local_participant.h b/include/livekit/local_participant.h index 3b3ae6c6..608e5692 100644 --- a/include/livekit/local_participant.h +++ b/include/livekit/local_participant.h @@ -50,240 +50,201 @@ struct RpcInvocationData { double response_timeout_sec; // seconds }; -/** - * Represents the local participant in a room. - * - * LocalParticipant, built on top of the participant.h base class. - */ +/// Represents the local participant in a room. +/// +/// LocalParticipant, built on top of the participant.h base class. class LIVEKIT_API LocalParticipant : public Participant { public: using PublicationMap = std::unordered_map>; using TrackMap = std::unordered_map>; - /** - * Type of callback used to handle incoming RPC method invocations. - * - * The handler receives an RpcInvocationData describing the incoming call - * and may return an optional response payload. To signal an error to the - * remote caller, throw an RpcError; it will be serialized and forwarded. - * - * Returning std::nullopt means "no payload" and results in an empty - * response body being sent back to the caller. - */ + /// Type of callback used to handle incoming RPC method invocations. + /// + /// The handler receives an RpcInvocationData describing the incoming call + /// and may return an optional response payload. To signal an error to the + /// remote caller, throw an RpcError; it will be serialized and forwarded. + /// + /// Returning std::nullopt means "no payload" and results in an empty + /// response body being sent back to the caller. using RpcHandler = std::function(const RpcInvocationData&)>; LocalParticipant(FfiHandle handle, std::string sid, std::string name, std::string identity, std::string metadata, std::unordered_map attributes, ParticipantKind kind, DisconnectReason reason); - /** - * Track publications for this participant, keyed by publication SID. - * - * Built on each call from published local tracks (see \ref publishTrack). - * Expired track handles are removed from the internal map while building. - */ + /// Track publications for this participant, keyed by publication SID. + /// + /// Built on each call from published local tracks (see @ref publishTrack). + /// Expired track handles are removed from the internal map while building. PublicationMap trackPublications() const; - /** - * Publish arbitrary data to the room. - * - * @param payload Raw bytes to send. - * @param reliable Whether to send reliably or not. - * @param destination_identities Optional list of participant identities. - * @param topic Optional topic string. - * - * Throws std::runtime_error if FFI reports an error (if you wire that up). - */ + /// Publish arbitrary data to the room. + /// + /// @param payload Raw bytes to send. + /// @param reliable Whether to send reliably or not. + /// @param destination_identities Optional list of participant identities. + /// @param topic Optional topic string. + /// + /// @throws std::runtime_error if FFI reports an error (if you wire that up). void publishData(const std::vector& payload, bool reliable = true, const std::vector& destination_identities = {}, const std::string& topic = {}); - /** - * Publish a SIP DTMF (phone keypad) tone into the room. - * - * Only meaningful when a SIP trunk is bridging a phone call into the - * room. See SipDtmfData for background on SIP and DTMF. - * - * @param code DTMF code (0-15). - * @param digit Human-readable digit string (e.g. "5", "#"). - */ + /// Publish a SIP DTMF (phone keypad) tone into the room. + /// + /// Only meaningful when a SIP trunk is bridging a phone call into the + /// room. See SipDtmfData for background on SIP and DTMF. + /// + /// @param code DTMF code (0-15). + /// @param digit Human-readable digit string (e.g. "5", "#"). void publishDtmf(int code, const std::string& digit); - /** - * Update this participant's metadata on the server. - * - * Sends an FFI request to the LiveKit server to change the metadata - * associated with the local participant. Other participants will be - * notified via \c onParticipantMetadataChanged. - * - * Note: this requires \c canUpdateOwnMetadata permission. - */ + /// Update this participant's metadata on the server. + /// + /// Sends an FFI request to the LiveKit server to change the metadata + /// associated with the local participant. Other participants will be + /// notified via @c onParticipantMetadataChanged. + /// + /// @note this requires @c canUpdateOwnMetadata permission. void setMetadata(const std::string& metadata); - /** - * Update this participant's display name on the server. - * - * Sends an FFI request to the LiveKit server to change the name - * associated with the local participant. Other participants will be - * notified via \c onParticipantNameChanged. - * - * Note: this requires \c canUpdateOwnMetadata permission. - */ + /// Update this participant's display name on the server. + /// + /// Sends an FFI request to the LiveKit server to change the name + /// associated with the local participant. Other participants will be + /// notified via @c onParticipantNameChanged. + /// + /// @note this requires @c canUpdateOwnMetadata permission. void setName(const std::string& name); - /** - * Update this participant's attributes on the server. - * - * Sends an FFI request to the LiveKit server to replace the attribute - * map for the local participant. Other participants will be notified - * via \c onParticipantAttributesChanged. - * - * Note: this requires \c canUpdateOwnMetadata permission. - */ + /// Update this participant's attributes on the server. + /// + /// Sends an FFI request to the LiveKit server to replace the attribute + /// map for the local participant. Other participants will be notified + /// via @c onParticipantAttributesChanged. + /// + /// @note this requires @c canUpdateOwnMetadata permission. void setAttributes(const std::unordered_map& attributes); - /** - * Set track subscription permissions for this participant. - * - * @param allow_all_participants If true, all participants may subscribe. - * @param participant_permissions Optional participant-specific permissions. - */ + /// Set track subscription permissions for this participant. + /// + /// @param allow_all_participants If true, all participants may subscribe. + /// @param participant_permissions Optional participant-specific permissions. void setTrackSubscriptionPermissions(bool allow_all_participants, const std::vector& participant_permissions = {}); - /** - * Publish a local track to the room. - * - * Throws std::runtime_error on error (e.g. publish failure). - */ + /// Publish a local track to the room. + /// + /// @throws std::runtime_error on error (e.g. publish failure). void publishTrack(const std::shared_ptr& track, const TrackPublishOptions& options); - /** - * Create a \ref LocalVideoTrack backed by the given \ref VideoSource, - * publish it, and return the track. - * - * The caller retains ownership of \p source and should use it directly - * for frame capture on the video thread. - */ + /// Create a @ref LocalVideoTrack backed by the given @ref VideoSource, + /// publish it, and return the track. + /// + /// The caller retains ownership of @p source and should use it directly + /// for frame capture on the video thread. std::shared_ptr publishVideoTrack(const std::string& name, const std::shared_ptr& source, TrackSource track_source); - /** - * Create a \ref LocalAudioTrack backed by the given \ref AudioSource, - * publish it, and return the track. - * - * The caller retains ownership of \p source and should use it directly - * for frame capture on the audio thread. - */ + /// Create a @ref LocalAudioTrack backed by the given @ref AudioSource, + /// publish it, and return the track. + /// + /// The caller retains ownership of @p source and should use it directly + /// for frame capture on the audio thread. std::shared_ptr publishAudioTrack(const std::string& name, const std::shared_ptr& source, TrackSource track_source); - /** - * Unpublish a track from the room by SID. - * - * If the publication exists in the local map, it is removed. - */ + /// Unpublish a track from the room by SID. + /// + /// If the publication exists in the local map, it is removed. void unpublishTrack(const std::string& track_sid); - /** - * Publish a data track to the room. - * - * Data tracks carry arbitrary binary frames and are independent of the - * audio/video track hierarchy. The returned LocalDataTrack can push - * frames via tryPush() and be unpublished via - * LocalDataTrack::unpublishDataTrack() or - * LocalParticipant::unpublishDataTrack(). - * - * @param name Unique track name visible to other participants. - * @return The published track on success, or a typed error describing why - * publication failed. - */ + /// Publish a data track to the room. + /// + /// Data tracks carry arbitrary binary frames and are independent of the + /// audio/video track hierarchy. The returned LocalDataTrack can push + /// frames via tryPush() and be unpublished via + /// LocalDataTrack::unpublishDataTrack() or + /// LocalParticipant::unpublishDataTrack(). + /// + /// @param name Unique track name visible to other participants. + /// @return The published track on success, or a typed error describing why + /// publication failed. Result, PublishDataTrackError> publishDataTrack(const std::string& name); - /** - * Unpublish a data track from the room. - * - * Delegates to LocalDataTrack::unpublishDataTrack(). After this call, - * tryPush() on the track will fail and the track cannot be re-published. - * - * @param track The data track to unpublish. Null is ignored. - */ + /// Unpublish a data track from the room. + /// + /// Delegates to LocalDataTrack::unpublishDataTrack(). After this call, + /// tryPush() on the track will fail and the track cannot be re-published. + /// + /// @param track The data track to unpublish. Null is ignored. void unpublishDataTrack(const std::shared_ptr& track); - /** - * Initiate an RPC call to a remote participant. - * - * @param destination_identity Identity of the destination participant. - * @param method Name of the RPC method to invoke. - * @param payload Request payload to send to the remote handler. - * @param response_timeout Optional timeout in seconds for receiving - * a response. If not set, the server default - * timeout (15 seconds) is used. - * - * @return The response payload returned by the remote handler. - * - * @throws RpcError If the remote side returns an RPC error, times out, - * or rejects the request. - * @throws std::runtime_error If the underlying FFI handle is invalid or - * the FFI call fails unexpectedly. - */ + /// Initiate an RPC call to a remote participant. + /// + /// @param destination_identity Identity of the destination participant. + /// @param method Name of the RPC method to invoke. + /// @param payload Request payload to send to the remote handler. + /// @param response_timeout Optional timeout in seconds for receiving + /// a response. If not set, the server default + /// timeout (15 seconds) is used. + /// + /// @return The response payload returned by the remote handler. + /// + /// @throws RpcError If the remote side returns an RPC error, times out, + /// or rejects the request. + /// @throws std::runtime_error If the underlying FFI handle is invalid or + /// the FFI call fails unexpectedly. std::string performRpc(const std::string& destination_identity, const std::string& method, const std::string& payload, const std::optional& response_timeout = std::nullopt); - /** - * Register a handler for an incoming RPC method. - * - * Once registered, the provided handler will be invoked whenever a remote - * participant calls the given method name on this LocalParticipant. - * - * @param method_name Name of the RPC method to handle. This must match - * the method name used by remote callers. - * @param handler Callback to execute when an invocation is received. - * The handler may return an optional response payload - * or throw an RpcError to signal failure. - * - * If a handler is already registered for the same method_name, it will be - * replaced by the new handler. - */ - + /// Register a handler for an incoming RPC method. + /// + /// Once registered, the provided handler will be invoked whenever a remote + /// participant calls the given method name on this LocalParticipant. + /// + /// @param method_name Name of the RPC method to handle. This must match + /// the method name used by remote callers. + /// @param handler Callback to execute when an invocation is received. + /// The handler may return an optional response payload + /// or throw an RpcError to signal failure. + /// + /// If a handler is already registered for the same method_name, it will be + /// replaced by the new handler. void registerRpcMethod(const std::string& method_name, RpcHandler handler); - /** - * Unregister a previously registered RPC method handler. - * - * After this call, invocations for the given method_name will no longer - * be dispatched to a local handler and will instead result in an - * "unsupported method" error being returned to the caller. - * - * @param method_name Name of the RPC method to unregister. - * If no handler is registered for this name, the call - * is a no-op. - */ + /// Unregister a previously registered RPC method handler. + /// + /// After this call, invocations for the given method_name will no longer + /// be dispatched to a local handler and will instead result in an + /// "unsupported method" error being returned to the caller. + /// + /// @param method_name Name of the RPC method to unregister. + /// If no handler is registered for this name, the call + /// is a no-op. void unregisterRpcMethod(const std::string& method_name); protected: - /** - * Shutdown the local participant, cleaning up all resources. - * - * This unregisters all RPC handlers and prepares the participant for - * destruction. Called by Room during its destruction sequence. - */ + /// Shutdown the local participant, cleaning up all resources. + /// + /// This unregisters all RPC handlers and prepares the participant for + /// destruction. Called by Room during its destruction sequence. void shutdown(); - // Called by Room when an rpc_method_invocation event is received from the - // SFU. This is internal plumbing and not intended to be called directly by - // SDK users. + /// Called by Room when an rpc_method_invocation event is received from the + /// SFU. This is internal plumbing and not intended to be called directly by + /// SDK users. void handleRpcMethodInvocation(std::uint64_t invocation_id, const std::string& method, const std::string& request_id, const std::string& caller_identity, const std::string& payload, double response_timeout); - // Called by Room events like kTrackMuted. + /// Called by Room events like kTrackMuted. std::shared_ptr findTrackPublication(const std::string& sid) const override; friend class Room; private: - /// Publication SID → local track (\ref unpublishTrack clears the track’s - /// cached publication). \c mutable so \ref trackPublications() const can - /// prune expired \c weak_ptr entries. + /// Publication SID → local track (@ref unpublishTrack clears the track’s + /// cached publication). @c mutable so @ref trackPublications() const can + /// prune expired @c weak_ptr entries. mutable TrackMap published_tracks_by_sid_; std::unordered_map rpc_handlers_; diff --git a/include/livekit/local_video_track.h b/include/livekit/local_video_track.h index 63183c75..7b8da0ef 100644 --- a/include/livekit/local_video_track.h +++ b/include/livekit/local_video_track.h @@ -31,27 +31,25 @@ class OwnedTrack; class VideoSource; -/** - * Represents a user-provided video track sourced from the local device. - * - * `LocalVideoTrack` is used to publish camera video (or any custom - * video source) to a LiveKit room. It wraps a platform-specific video - * source and exposes simple controls such as `mute()` and `unmute()`. - * - * Typical usage: - * - * auto source = std::make_shared(1280, 720); - * auto track = LocalVideoTrack::createLocalVideoTrack("cam", source); - * room->localParticipant()->publishTrack(track); - * // Capture frames on the video thread via `source`, not via the track. - * - * Muting a local video track stops transmitting video to the room, but - * the underlying source may continue capturing depending on platform - * behavior. - * - * The track name provided during creation is visible to remote - * participants and can be used for debugging or UI display. - */ +/// Represents a user-provided video track sourced from the local device. +/// +/// `LocalVideoTrack` is used to publish camera video (or any custom +/// video source) to a LiveKit room. It wraps a platform-specific video +/// source and exposes simple controls such as `mute()` and `unmute()`. +/// +/// Typical usage: +/// +/// auto source = std::make_shared(1280, 720); +/// auto track = LocalVideoTrack::createLocalVideoTrack("cam", source); +/// room->localParticipant()->publishTrack(track); +/// // Capture frames on the video thread via `source`, not via the track. +/// +/// Muting a local video track stops transmitting video to the room, but +/// the underlying source may continue capturing depending on platform +/// behavior. +/// +/// The track name provided during creation is visible to remote +/// participants and can be used for debugging or UI display. class LIVEKIT_API LocalVideoTrack : public Track { public: /// Creates a new local video track backed by the given `VideoSource`. diff --git a/include/livekit/remote_audio_track.h b/include/livekit/remote_audio_track.h index 9b3c1079..837e0262 100644 --- a/include/livekit/remote_audio_track.h +++ b/include/livekit/remote_audio_track.h @@ -30,18 +30,16 @@ class OwnedTrack; class AudioSource; -/** - * Represents an audio track published by a remote participant and - * subscribed to by the local participant. - * - * `RemoteAudioTrack` instances are created internally when the SDK receives a - * `kTrackSubscribed` event. Each instance is owned by its associated - * `RemoteParticipant` and delivered to the application via - * `TrackSubscribedEvent`. - * - * Applications generally interact with `RemoteAudioTrack` through events and - * `RemoteTrackPublication`, not through direct construction. - */ +/// Represents an audio track published by a remote participant and +/// subscribed to by the local participant. +/// +/// `RemoteAudioTrack` instances are created internally when the SDK receives a +/// `kTrackSubscribed` event. Each instance is owned by its associated +/// `RemoteParticipant` and delivered to the application via +/// `TrackSubscribedEvent`. +/// +/// Applications generally interact with `RemoteAudioTrack` through events and +/// `RemoteTrackPublication`, not through direct construction. class LIVEKIT_API RemoteAudioTrack : public Track { public: /// Constructs a `RemoteAudioTrack` from an internal protocol-level diff --git a/include/livekit/remote_data_track.h b/include/livekit/remote_data_track.h index 40bbf65d..e74fd936 100644 --- a/include/livekit/remote_data_track.h +++ b/include/livekit/remote_data_track.h @@ -32,25 +32,23 @@ namespace proto { class OwnedRemoteDataTrack; } -/** - * Represents a data track published by a remote participant. - * - * Discovered via the DataTrackPublishedEvent room event. Unlike - * audio/video tracks, remote data tracks require an explicit subscribe() - * call to begin receiving frames. - * - * Typical usage: - * - * // In RoomDelegate::onDataTrackPublished callback: - * auto sub_result = remoteDataTrack->subscribe(); - * if (sub_result) { - * auto sub = sub_result.value(); - * DataTrackFrame frame; - * while (sub->read(frame)) { - * // process frame - * } - * } - */ +/// Represents a data track published by a remote participant. +/// +/// Discovered via the DataTrackPublishedEvent room event. Unlike +/// audio/video tracks, remote data tracks require an explicit subscribe() +/// call to begin receiving frames. +/// +/// Typical usage: +/// +/// // In RoomDelegate::onDataTrackPublished callback: +/// auto sub_result = remoteDataTrack->subscribe(); +/// if (sub_result) { +/// auto sub = sub_result.value(); +/// DataTrackFrame frame; +/// while (sub->read(frame)) { +/// // process frame +/// } +/// } class RemoteDataTrack { public: ~RemoteDataTrack() = default; @@ -72,12 +70,10 @@ class RemoteDataTrack { uintptr_t testFfiHandleId() const noexcept { return ffiHandleId(); } #endif - /** - * Subscribe to this remote data track. - * - * Returns a DataTrackStream that delivers frames via blocking - * read(). Destroy the stream to unsubscribe. - */ + /// Subscribe to this remote data track. + /// + /// Returns a DataTrackStream that delivers frames via blocking + /// read(). Destroy the stream to unsubscribe. LIVEKIT_API Result, SubscribeDataTrackError> subscribe( const DataTrackStream::Options& options = {}); @@ -87,13 +83,13 @@ class RemoteDataTrack { explicit RemoteDataTrack(const proto::OwnedRemoteDataTrack& owned); uintptr_t ffiHandleId() const noexcept { return handle_.get(); } - /** RAII wrapper for the Rust-owned FFI resource. */ + /// RAII wrapper for the Rust-owned FFI resource. FfiHandle handle_; - /** Metadata snapshot taken at construction time. */ + /// Metadata snapshot taken at construction time. DataTrackInfo info_; - /** Identity string of the remote participant who published this track. */ + /// Identity string of the remote participant who published this track. std::string publisher_identity_; }; diff --git a/include/livekit/remote_participant.h b/include/livekit/remote_participant.h index ef33407b..f354b36b 100644 --- a/include/livekit/remote_participant.h +++ b/include/livekit/remote_participant.h @@ -35,10 +35,10 @@ class LIVEKIT_API RemoteParticipant : public Participant { std::unordered_map attributes, ParticipantKind kind, DisconnectReason reason); - // A dictionary of track publications associated with the participant. + /// A dictionary of track publications associated with the participant. const PublicationMap& trackPublications() const noexcept { return track_publications_; } - // Optional: non-const access if you want to mutate in-place. + /// Optional: non-const access if you want to mutate in-place. PublicationMap& mutableTrackPublications() noexcept { return track_publications_; } std::string toString() const; @@ -50,8 +50,8 @@ class LIVEKIT_API RemoteParticipant : public Participant { // NOLINTEND(readability-identifier-naming) protected: - // Called by Room events like kTrackMuted. This is internal plumbing and not - // intended to be called directly by SDK users. + /// Called by Room events like kTrackMuted. This is internal plumbing and not + /// intended to be called directly by SDK users. std::shared_ptr findTrackPublication(const std::string& sid) const override; friend class Room; @@ -59,7 +59,7 @@ class LIVEKIT_API RemoteParticipant : public Participant { PublicationMap track_publications_; }; -// Convenience for logging / streaming +/// Convenience for logging / streaming LIVEKIT_API std::ostream& operator<<(std::ostream& os, const RemoteParticipant& participant); } // namespace livekit diff --git a/include/livekit/remote_video_track.h b/include/livekit/remote_video_track.h index 69af3075..0f2054ac 100644 --- a/include/livekit/remote_video_track.h +++ b/include/livekit/remote_video_track.h @@ -30,18 +30,16 @@ class OwnedTrack; class VideoSource; -/** - * Represents an video track published by a remote participant and - * subscribed to by the local participant. - * - * `RemoteVideoTrack` instances are created internally when the SDK receives a - * `kTrackSubscribed` event. Each instance is owned by its associated - * `RemoteParticipant` and delivered to the application via - * `TrackSubscribedEvent`. - * - * Applications generally interact with `RemoteVideoTrack` through events and - * `RemoteTrackPublication`, not through direct construction. - */ +/// Represents an video track published by a remote participant and +/// subscribed to by the local participant. +/// +/// `RemoteVideoTrack` instances are created internally when the SDK receives a +/// `kTrackSubscribed` event. Each instance is owned by its associated +/// `RemoteParticipant` and delivered to the application via +/// `TrackSubscribedEvent`. +/// +/// Applications generally interact with `RemoteVideoTrack` through events and +/// `RemoteTrackPublication`, not through direct construction. class LIVEKIT_API RemoteVideoTrack : public Track { public: /// Constructs a `RemoteVideoTrack` from an internal protocol-level diff --git a/include/livekit/result.h b/include/livekit/result.h index 362be938..6155fe92 100644 --- a/include/livekit/result.h +++ b/include/livekit/result.h @@ -24,20 +24,18 @@ namespace livekit { -/** - * Lightweight success-or-error return type for non-exceptional API failures. - * - * This is intended for SDK operations where callers are expected to branch on - * success vs. failure, such as back-pressure or an unpublished track. - * - * `Result` stores either: - * - a success value of type `T`, or - * - an error value of type `E` - * - * Accessors validate their preconditions before returning. Calling `value()` - * on an error result, or `error()` on a success result, throws `std::logic_error`. - * Avoid this by checking `ok()` / `hasError()` / if (result) before calling `value()` or `error()`. - */ +/// Lightweight success-or-error return type for non-exceptional API failures. +/// +/// This is intended for SDK operations where callers are expected to branch on +/// success vs. failure, such as back-pressure or an unpublished track. +/// +/// `Result` stores either: +/// - a success value of type `T`, or +/// - an error value of type `E` +/// +/// Accessors validate their preconditions before returning. Calling `value()` +/// on an error result, or `error()` on a success result, throws `std::logic_error`. +/// Avoid this by checking `ok()` / `hasError()` / if (result) before calling `value()` or `error()`. template class [[nodiscard]] Result { public: @@ -154,12 +152,10 @@ class [[nodiscard]] Result { std::variant storage_; }; -/** - * `void` specialization for operations that only report success or failure. - * - * This keeps the same calling style as `Result` without forcing callers - * to invent a dummy success payload. - */ +/// `void` specialization for operations that only report success or failure. +/// +/// This keeps the same calling style as `Result` without forcing callers +/// to invent a dummy success payload. template class [[nodiscard]] Result { public: diff --git a/include/livekit/room.h b/include/livekit/room.h index 33839158..cd08be0a 100644 --- a/include/livekit/room.h +++ b/include/livekit/room.h @@ -40,51 +40,51 @@ class E2EEManager; class LocalParticipant; class RemoteParticipant; -// Represents a single ICE server configuration. +/// Represents a single ICE server configuration. struct IceServer { - // TURN/STUN server URL (e.g. "stun:stun.l.google.com:19302"). + /// TURN/STUN server URL (e.g. "stun:stun.l.google.com:19302"). std::string url; - // Optional username for TURN authentication. + /// Optional username for TURN authentication. std::string username; - // Optional credential (password) for TURN authentication. + /// Optional credential (password) for TURN authentication. std::string credential; }; -// WebRTC configuration (ICE, transport, etc.). +/// WebRTC configuration (ICE, transport, etc.). struct RtcConfig { - // ICE transport type (e.g., ALL, RELAY). Maps to proto::IceTransportType. + /// ICE transport type (e.g., ALL, RELAY). Maps to proto::IceTransportType. int ice_transport_type = 0; - // Continuous or single ICE gathering. Maps to - // proto::ContinualGatheringPolicy. + /// Continuous or single ICE gathering. Maps to + /// proto::ContinualGatheringPolicy. int continual_gathering_policy = 0; - // List of STUN/TURN servers for ICE candidate generation. + /// List of STUN/TURN servers for ICE candidate generation. std::vector ice_servers; }; -// Top-level room connection options. +/// Top-level room connection options. struct RoomOptions { - // If true (default), automatically subscribe to all remote tracks. - // This is CRITICAL. Without auto_subscribe, you will never receive: - // - `track_subscribed` events - // - remote audio/video frames + /// If true (default), automatically subscribe to all remote tracks. + /// This is CRITICAL. Without auto_subscribe, you will never receive: + /// - `track_subscribed` events + /// - remote audio/video frames bool auto_subscribe = true; - // Enable dynacast (server sends optimal layers depending on subscribers). + /// Enable dynacast (server sends optimal layers depending on subscribers). bool dynacast = false; - // Enable single peer connection mode. When true, uses one RTCPeerConnection - // for both publishing and subscribing instead of two separate connections. - // Falls back to dual peer connection if the server doesn't support single PC. + /// Enable single peer connection mode. When true, uses one RTCPeerConnection + /// for both publishing and subscribing instead of two separate connections. + /// Falls back to dual peer connection if the server doesn't support single PC. bool single_peer_connection = true; - // Optional WebRTC configuration (ICE policy, servers, etc.) + /// Optional WebRTC configuration (ICE policy, servers, etc.) std::optional rtc_config; - // Optional end-to-end encryption settings. + /// Optional end-to-end encryption settings. std::optional encryption; }; @@ -99,38 +99,35 @@ class LIVEKIT_API Room { Room(); ~Room(); - /* Assign a RoomDelegate that receives room lifecycle callbacks. - * - * The delegate must remain valid for the lifetime of the Room or until a - * different delegate is assigned. The Room does not take ownership. - * Typical usage: - * class MyDelegate : public RoomDelegate { ... }; - * MyDelegate del; - * Room room; - * room.setDelegate(&del); - */ + /// Assign a RoomDelegate that receives room lifecycle callbacks. + /// + /// The delegate must remain valid for the lifetime of the Room or until a + /// different delegate is assigned. The Room does not take ownership. + /// Typical usage: + /// class MyDelegate : public RoomDelegate { ... }; + /// MyDelegate del; + /// Room room; + /// room.setDelegate(&del); void setDelegate(RoomDelegate* delegate); - /* Connect to a LiveKit room using the given URL and token, applying the - * supplied connection options. - * - * Parameters: - * url — WebSocket URL of the LiveKit server. - * token — Access token for authentication. - * options — Connection options controlling auto-subscribe, - * dynacast, E2EE, and WebRTC configuration. - * Behavior: - * - Registers an FFI event listener *before* sending the connect request. - * - Sends a proto::FfiRequest::Connect with the URL, token, - * and the provided RoomOptions. - * - Blocks until the FFI connect response arrives. - * - Initializes local participant and remote participants. - * - Emits room/participant/track events to the delegate. - * IMPORTANT: - * RoomOptions defaults auto_subscribe = true. - * Without auto_subscribe enabled, remote tracks will NOT be subscribed - * automatically, and no remote audio/video will ever arrive. - */ + /// Connect to a LiveKit room using the given URL and token, applying the + /// supplied connection options. + /// + /// @param url WebSocket URL of the LiveKit server. + /// @param token Access token for authentication. + /// @param options Connection options controlling auto-subscribe, + /// dynacast, E2EE, and WebRTC configuration. + /// Behavior: + /// - Registers an FFI event listener *before* sending the connect request. + /// - Sends a proto::FfiRequest::Connect with the URL, token, + /// and the provided RoomOptions. + /// - Blocks until the FFI connect response arrives. + /// - Initializes local participant and remote participants. + /// - Emits room/participant/track events to the delegate. + /// IMPORTANT: + /// RoomOptions defaults auto_subscribe = true. + /// Without auto_subscribe enabled, remote tracks will NOT be subscribed + /// automatically, and no remote audio/video will ever arrive. bool connect(const std::string& url, const std::string& token, const RoomOptions& options); /// @deprecated Use connect() instead. @@ -141,14 +138,13 @@ class LIVEKIT_API Room { // Accessors - /* Retrieve static metadata about the room. - * This contains fields such as: - * - SID - * - room name - * - metadata - * - participant counts - * - creation timestamp - */ + /// Retrieve static metadata about the room. + /// This contains fields such as: + /// - SID + /// - room name + /// - metadata + /// - participant counts + /// - creation timestamp RoomInfoData roomInfo() const; /// @deprecated Use roomInfo() instead. @@ -157,28 +153,23 @@ class LIVEKIT_API Room { RoomInfoData room_info() const; // NOLINTEND(readability-identifier-naming) - /* Get the local participant. - * - * This object represents the current user, including: - * - published tracks (audio/video/screen) - * - identity, SID, metadata - * - publishing/unpublishing operations - * Return value: - * Non-null pointer after successful Connect(). - */ + /// Get the local participant. + /// + /// This object represents the current user, including: + /// - published tracks (audio/video/screen) + /// - identity, SID, metadata + /// - publishing/unpublishing operations + /// @return Non-null pointer after successful connect(). LocalParticipant* localParticipant() const; - /* Look up a remote participant by identity. - * - * Parameters: - * identity — The participant’s identity string (not SID) - * Return value: - * Pointer to RemoteParticipant if present, otherwise nullptr. - * RemoteParticipant contains: - * - identity/name/metadata - * - track publications - * - callbacks for track subscribed/unsubscribed, muted/unmuted - */ + /// Look up a remote participant by identity. + /// + /// @param identity The participant’s identity string (not SID) + /// @return Pointer to RemoteParticipant if present, otherwise nullptr. + /// RemoteParticipant contains: + /// - identity/name/metadata + /// - track publications + /// - callbacks for track subscribed/unsubscribed, muted/unmuted RemoteParticipant* remoteParticipant(const std::string& identity) const; /// Returns a snapshot of all current remote participants. @@ -187,130 +178,100 @@ class LIVEKIT_API Room { /// Returns the current connection state of the room. ConnectionState connectionState() const; - /* Register a handler for incoming text streams on a specific topic. - * - * When a remote participant opens a text stream with the given topic, - * the handler is invoked with: - * - a shared_ptr for consuming the stream - * - the identity of the participant who sent the stream - * - * Notes: - * - Only one handler may be registered per topic. - * - If no handler is registered for a topic, incoming streams with that - * topic are ignored. - * - The handler is invoked on the Room event thread. The handler must - * not block; spawn a background thread if synchronous reading is - * required. - * - * Throws: - * std::runtime_error if a handler is already registered for the topic. - */ + /// Register a handler for incoming text streams on a specific topic. + /// + /// When a remote participant opens a text stream with the given topic, + /// the handler is invoked with: + /// - a shared_ptr for consuming the stream + /// - the identity of the participant who sent the stream + /// + /// Notes: + /// - Only one handler may be registered per topic. + /// - If no handler is registered for a topic, incoming streams with that + /// topic are ignored. + /// - The handler is invoked on the Room event thread. The handler must + /// not block; spawn a background thread if synchronous reading is + /// required. + /// + /// @throws std::runtime_error if a handler is already registered for the topic. void registerTextStreamHandler(const std::string& topic, TextStreamHandler handler); - /* Unregister the text stream handler for the given topic. - * - * If no handler exists for the topic, this function is a no-op. - */ + /// Unregister the text stream handler for the given topic. + /// + /// If no handler exists for the topic, this function is a no-op. void unregisterTextStreamHandler(const std::string& topic); - /* Register a handler for incoming byte streams on a specific topic. - * - * When a remote participant opens a byte stream with the given topic, - * the handler is invoked with: - * - a shared_ptr for consuming the stream - * - the identity of the participant who sent the stream - * - * Notes: - * - Only one handler may be registered per topic. - * - If no handler is registered for a topic, incoming streams with that - * topic are ignored. - * - The ByteStreamReader remains valid as long as the shared_ptr is held, - * preventing lifetime-related crashes when reading asynchronously. - * - * Throws: - * std::runtime_error if a handler is already registered for the topic. - */ + /// Register a handler for incoming byte streams on a specific topic. + /// + /// When a remote participant opens a byte stream with the given topic, + /// the handler is invoked with: + /// - a shared_ptr for consuming the stream + /// - the identity of the participant who sent the stream + /// + /// Notes: + /// - Only one handler may be registered per topic. + /// - If no handler is registered for a topic, incoming streams with that + /// topic are ignored. + /// - The ByteStreamReader remains valid as long as the shared_ptr is held, + /// preventing lifetime-related crashes when reading asynchronously. + /// + /// @throws std::runtime_error if a handler is already registered for the topic. void registerByteStreamHandler(const std::string& topic, ByteStreamHandler handler); - /* Unregister the byte stream handler for the given topic. - * - * If no handler exists for the topic, this function is a no-op. - */ + /// Unregister the byte stream handler for the given topic. + /// + /// If no handler exists for the topic, this function is a no-op. void unregisterByteStreamHandler(const std::string& topic); - /** - * Returns the room's E2EE manager, or nullptr if E2EE was not enabled at - * connect time. - * - * Notes: - * - The manager is created after a successful Connect(). - * - If E2EE was not configured in RoomOptions, this will return nullptr. - */ + /// Returns the room's E2EE manager, or nullptr if E2EE was not enabled at + /// connect time. + /// + /// Notes: + /// - The manager is created after a successful connect(). + /// - If E2EE was not configured in RoomOptions, this will return nullptr. E2EEManager* e2eeManager() const; // --------------------------------------------------------------- // Frame callbacks // --------------------------------------------------------------- - /** - * @brief Sets the audio frame callback via SubscriptionThreadDispatcher. - */ + /// @brief Sets the audio frame callback via SubscriptionThreadDispatcher. void setOnAudioFrameCallback(const std::string& participant_identity, TrackSource source, AudioFrameCallback callback, const AudioStream::Options& opts = {}); - /** - * @brief Sets the audio frame callback via SubscriptionThreadDispatcher. - */ + /// @brief Sets the audio frame callback via SubscriptionThreadDispatcher. 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. - */ + /// @brief Sets the video frame callback via SubscriptionThreadDispatcher. void setOnVideoFrameCallback(const std::string& participant_identity, TrackSource source, VideoFrameCallback callback, const VideoStream::Options& opts = {}); - /** - * @brief Sets the video frame callback via SubscriptionThreadDispatcher. - */ + /// @brief Sets the video frame callback via SubscriptionThreadDispatcher. 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. - */ + /// @brief Sets the video frame event callback via + /// SubscriptionThreadDispatcher. void setOnVideoFrameEventCallback(const std::string& participant_identity, const std::string& track_name, VideoFrameEventCallback callback, const VideoStream::Options& opts = {}); - /** - * @brief Clears the audio frame callback via SubscriptionThreadDispatcher. - */ + /// @brief Clears the audio frame callback via SubscriptionThreadDispatcher. void clearOnAudioFrameCallback(const std::string& participant_identity, TrackSource source); - /** - * @brief Clears the audio frame callback via SubscriptionThreadDispatcher. - */ + /// @brief Clears the audio frame callback via SubscriptionThreadDispatcher. void clearOnAudioFrameCallback(const std::string& participant_identity, const std::string& track_name); - /** - * @brief Clears the video frame callback via SubscriptionThreadDispatcher. - */ + /// @brief Clears the video frame callback via SubscriptionThreadDispatcher. void clearOnVideoFrameCallback(const std::string& participant_identity, TrackSource source); - /** - * @brief Clears the video frame callback via SubscriptionThreadDispatcher. - */ + /// @brief Clears the video frame callback via SubscriptionThreadDispatcher. void clearOnVideoFrameCallback(const std::string& participant_identity, const std::string& track_name); - /** - * @brief Adds a data frame callback via SubscriptionThreadDispatcher. - */ + /// @brief Adds a data frame callback via SubscriptionThreadDispatcher. DataFrameCallbackId addOnDataFrameCallback(const std::string& participant_identity, const std::string& track_name, DataFrameCallback callback); - /** - * @brief Removes the data frame callback via SubscriptionThreadDispatcher. - */ + /// @brief Removes the data frame callback via SubscriptionThreadDispatcher. void removeOnDataFrameCallback(DataFrameCallbackId id); private: diff --git a/include/livekit/room_delegate.h b/include/livekit/room_delegate.h index 79c484aa..7902ad09 100644 --- a/include/livekit/room_delegate.h +++ b/include/livekit/room_delegate.h @@ -23,15 +23,13 @@ namespace livekit { class Room; -/** - * Interface for receiving room-level events. - * - * Implement this class and pass an instance to Room::setDelegate() - * to be notified about participants, tracks, data, and connection changes. - * - * All methods provide default no-op implementations so you can override - * only the callbacks you care about. - */ +/// Interface for receiving room-level events. +/// +/// Implement this class and pass an instance to Room::setDelegate() +/// to be notified about participants, tracks, data, and connection changes. +/// +/// All methods provide default no-op implementations so you can override +/// only the callbacks you care about. class LIVEKIT_API RoomDelegate { public: virtual ~RoomDelegate() = default; @@ -40,215 +38,147 @@ class LIVEKIT_API RoomDelegate { // Participant lifecycle // ------------------------------------------------------------------ - /** - * Called when a new remote participant joins the room. - */ + /// Called when a new remote participant joins the room. virtual void onParticipantConnected(Room&, const ParticipantConnectedEvent&) {} - /** - * Called when a remote participant leaves the room. - */ + /// Called when a remote participant leaves the room. virtual void onParticipantDisconnected(Room&, const ParticipantDisconnectedEvent&) {} // ------------------------------------------------------------------ // Local track publication events // ------------------------------------------------------------------ - /** - * Called when a local track is successfully published. - */ + /// Called when a local track is successfully published. virtual void onLocalTrackPublished(Room&, const LocalTrackPublishedEvent&) {} - /** - * Called when a local track is unpublished. - */ + /// Called when a local track is unpublished. virtual void onLocalTrackUnpublished(Room&, const LocalTrackUnpublishedEvent&) {} - /** - * Called when a local track gains its first subscriber. - */ + /// Called when a local track gains its first subscriber. virtual void onLocalTrackSubscribed(Room&, const LocalTrackSubscribedEvent&) {} // ------------------------------------------------------------------ // Remote track publication/subscription // ------------------------------------------------------------------ - /** - * Called when a remote participant publishes a track. - */ + /// Called when a remote participant publishes a track. virtual void onTrackPublished(Room&, const TrackPublishedEvent&) {} - /** - * Called when a remote participant unpublishes a track. - */ + /// Called when a remote participant unpublishes a track. virtual void onTrackUnpublished(Room&, const TrackUnpublishedEvent&) {} - /** - * Called when a remote track is successfully subscribed. - */ + /// Called when a remote track is successfully subscribed. virtual void onTrackSubscribed(Room&, const TrackSubscribedEvent&) {} - /** - * Called when a remote track is unsubscribed. - */ + /// Called when a remote track is unsubscribed. virtual void onTrackUnsubscribed(Room&, const TrackUnsubscribedEvent&) {} - /** - * Called when subscribing to a remote track fails. - */ + /// Called when subscribing to a remote track fails. virtual void onTrackSubscriptionFailed(Room&, const TrackSubscriptionFailedEvent&) {} - /** - * Called when a track is muted. - */ + /// Called when a track is muted. virtual void onTrackMuted(Room&, const TrackMutedEvent&) {} - /** - * Called when a track is unmuted. - */ + /// Called when a track is unmuted. virtual void onTrackUnmuted(Room&, const TrackUnmutedEvent&) {} // ------------------------------------------------------------------ // Active speakers // ------------------------------------------------------------------ - /** - * Called when the list of active speakers changes. - */ + /// Called when the list of active speakers changes. virtual void onActiveSpeakersChanged(Room&, const ActiveSpeakersChangedEvent&) {} // ------------------------------------------------------------------ // Room info / metadata // ------------------------------------------------------------------ - /** - * Called when the room's metadata changes. - */ + /// Called when the room's metadata changes. virtual void onRoomMetadataChanged(Room&, const RoomMetadataChangedEvent&) {} - /** - * Called when the room SID changes (e.g., after migration). - */ + /// Called when the room SID changes (e.g., after migration). virtual void onRoomSidChanged(Room&, const RoomSidChangedEvent&) {} - /** - * Called when any room info is updated. - */ + /// Called when any room info is updated. virtual void onRoomUpdated(Room&, const RoomUpdatedEvent&) {} - /** - * Called when the participant is moved to another room. - */ + /// Called when the participant is moved to another room. virtual void onRoomMoved(Room&, const RoomMovedEvent&) {} // ------------------------------------------------------------------ // Participant info changes // ------------------------------------------------------------------ - /** - * Called when a participant's metadata is updated. - */ + /// Called when a participant's metadata is updated. virtual void onParticipantMetadataChanged(Room&, const ParticipantMetadataChangedEvent&) {} - /** - * Called when a participant's name is changed. - */ + /// Called when a participant's name is changed. virtual void onParticipantNameChanged(Room&, const ParticipantNameChangedEvent&) {} - /** - * Called when a participant's attributes are updated. - */ + /// Called when a participant's attributes are updated. virtual void onParticipantAttributesChanged(Room&, const ParticipantAttributesChangedEvent&) {} - /** - * Called when a participant's encryption status changes. - */ + /// Called when a participant's encryption status changes. virtual void onParticipantEncryptionStatusChanged(Room&, const ParticipantEncryptionStatusChangedEvent&) {} // ------------------------------------------------------------------ // Connection quality / state // ------------------------------------------------------------------ - /** - * Called when a participant's connection quality changes. - */ + /// Called when a participant's connection quality changes. virtual void onConnectionQualityChanged(Room&, const ConnectionQualityChangedEvent&) {} - /** - * Called when the room's connection state changes. - */ + /// Called when the room's connection state changes. virtual void onConnectionStateChanged(Room&, const ConnectionStateChangedEvent&) {} - /** - * Called when the room is disconnected. - */ + /// Called when the room is disconnected. virtual void onDisconnected(Room&, const DisconnectedEvent&) {} - /** - * Called before the SDK attempts to reconnect. - */ + /// Called before the SDK attempts to reconnect. virtual void onReconnecting(Room&, const ReconnectingEvent&) {} - /** - * Called after the SDK successfully reconnects. - */ + /// Called after the SDK successfully reconnects. virtual void onReconnected(Room&, const ReconnectedEvent&) {} // ------------------------------------------------------------------ // E2EE // ------------------------------------------------------------------ - /** - * Called when a participant's end-to-end encryption state changes. - */ + /// Called when a participant's end-to-end encryption state changes. virtual void onE2eeStateChanged(Room&, const E2eeStateChangedEvent&) {} // ------------------------------------------------------------------ // EOS // ------------------------------------------------------------------ - /** - * Called when the room reaches end-of-stream and will not emit further - * events. - */ + /// Called when the room reaches end-of-stream and will not emit further + /// events. virtual void onRoomEos(Room&, const RoomEosEvent&) {} // ------------------------------------------------------------------ // Data / transcription / chat // ------------------------------------------------------------------ - /** - * Called when a user data packet (non-SIP) is received. - */ + /// Called when a user data packet (non-SIP) is received. virtual void onUserPacketReceived(Room&, const UserDataPacketEvent&) {} - /** - * Called when a SIP DTMF packet is received. - */ + /// Called when a SIP DTMF packet is received. virtual void onSipDtmfReceived(Room&, const SipDtmfReceivedEvent&) {} // ------------------------------------------------------------------ // Data streams // ------------------------------------------------------------------ - /** - * Called when a data stream header is received. - */ + /// Called when a data stream header is received. virtual void onDataStreamHeaderReceived(Room&, const DataStreamHeaderReceivedEvent&) {} - /** - * Called when a data stream chunk is received. - */ + /// Called when a data stream chunk is received. virtual void onDataStreamChunkReceived(Room&, const DataStreamChunkReceivedEvent&) {} - /** - * Called when a data stream trailer is received. - */ + /// Called when a data stream trailer is received. virtual void onDataStreamTrailerReceived(Room&, const DataStreamTrailerReceivedEvent&) {} - /** - * Called when a data channel's buffered amount falls below its low threshold. - */ + /// Called when a data channel's buffered amount falls below its low threshold. virtual void onDataChannelBufferedAmountLowThresholdChanged( Room&, const DataChannelBufferedAmountLowThresholdChangedEvent&) {} @@ -256,40 +186,30 @@ class LIVEKIT_API RoomDelegate { // High-level byte/text streams // ------------------------------------------------------------------ - /** - * Called when a high-level byte stream reader is opened. - */ + /// Called when a high-level byte stream reader is opened. virtual void onByteStreamOpened(Room&, const ByteStreamOpenedEvent&) {} - /** - * Called when a high-level text stream reader is opened. - */ + /// Called when a high-level text stream reader is opened. virtual void onTextStreamOpened(Room&, const TextStreamOpenedEvent&) {} // ------------------------------------------------------------------ // Data tracks // ------------------------------------------------------------------ - /** - * Called when a remote participant publishes a data track. - * - * Data tracks are independent of the audio/video track hierarchy and - * require an explicit subscribe() call to start receiving frames. - */ + /// Called when a remote participant publishes a data track. + /// + /// Data tracks are independent of the audio/video track hierarchy and + /// require an explicit subscribe() call to start receiving frames. virtual void onDataTrackPublished(Room&, const DataTrackPublishedEvent&) {} - /** - * Called when a remote participant unpublishes a data track. - */ + /// Called when a remote participant unpublishes a data track. virtual void onDataTrackUnpublished(Room&, const DataTrackUnpublishedEvent&) {} // ------------------------------------------------------------------ // Participants snapshot // ------------------------------------------------------------------ - /** - * Called when a snapshot of participants has been updated. - */ + /// Called when a snapshot of participants has been updated. virtual void onParticipantsUpdated(Room&, const ParticipantsUpdatedEvent&) {} }; diff --git a/include/livekit/room_event_types.h b/include/livekit/room_event_types.h index d30d925b..cb55f7b0 100644 --- a/include/livekit/room_event_types.h +++ b/include/livekit/room_event_types.h @@ -37,9 +37,7 @@ class TrackPublication; enum class VideoCodec; enum class TrackSource; -/** - * Overall quality of a participant's connection. - */ +/// Overall quality of a participant's connection. enum class ConnectionQuality { Poor = 0, Good, @@ -47,31 +45,25 @@ enum class ConnectionQuality { Lost, }; -/** - * Current connection state of the room. - */ +/// Current connection state of the room. enum class ConnectionState { Disconnected = 0, Connected, Reconnecting, }; -/** - * Type of data packet delivery semantics. - * - * - Lossy: unordered, unreliable (e.g. for real-time updates). - * - Reliable: ordered, reliable (e.g. for critical messages). - */ +/// Type of data packet delivery semantics. +/// +/// - Lossy: unordered, unreliable (e.g. for real-time updates). +/// - Reliable: ordered, reliable (e.g. for critical messages). enum class DataPacketKind { Lossy, Reliable, }; -/** - * End-to-end encryption state for a participant. - * - * These values mirror the proto::EncryptionState enum. - */ +/// End-to-end encryption state for a participant. +/// +/// These values mirror the proto::EncryptionState enum. enum class EncryptionState { New = 0, Ok, @@ -82,11 +74,9 @@ enum class EncryptionState { InternalError, }; -/** - * Reason why a participant or room was disconnected. - * - * These values mirror the server-side DisconnectReason enum. - */ +/// Reason why a participant or room was disconnected. +/// +/// These values mirror the server-side DisconnectReason enum. enum class DisconnectReason { Unknown = 0, ClientInitiated, @@ -106,85 +96,76 @@ enum class DisconnectReason { MediaFailure }; -/** - * Application-level user data carried in a data packet. - */ +/// Application-level user data carried in a data packet. struct UserPacketData { - /** Raw payload bytes. */ + /// Raw payload bytes. std::vector data; - /** Optional topic name associated with this payload. */ + /// Optional topic name associated with this payload. std::optional topic; }; -/** - * SIP (Session Initiation Protocol) DTMF payload carried via data packets. - * - * SIP is a signalling protocol used in VoIP telephony. LiveKit supports - * SIP trunking, which bridges traditional phone calls into LiveKit rooms. - * DTMF (Dual-Tone Multi-Frequency) tones are the signals generated when - * phone keypad buttons are pressed (0-9, *, #). This struct surfaces - * those tones so that applications handling SIP-bridged calls can react - * to caller input (e.g. IVR menu selection). - */ +/// SIP (Session Initiation Protocol) DTMF payload carried via data packets. +/// +/// SIP is a signalling protocol used in VoIP telephony. LiveKit supports +/// SIP trunking, which bridges traditional phone calls into LiveKit rooms. +/// DTMF (Dual-Tone Multi-Frequency) tones are the signals generated when +/// phone keypad buttons are pressed (0-9, *, #). This struct surfaces +/// those tones so that applications handling SIP-bridged calls can react +/// to caller input (e.g. IVR menu selection). struct SipDtmfData { - /** Numeric DTMF code (0-15, mapping to 0-9, *, #, A-D). */ + /// Numeric DTMF code (0-15, mapping to 0-9, *, #, A-D). std::uint32_t code = 0; - /** Human-readable digit representation (e.g. "1", "#"). */ + /// Human-readable digit representation (e.g. "1", "#"). std::optional digit; }; -/** - * Snapshot of core room information. - */ +/// Snapshot of core room information. struct RoomInfoData { - /** Room SID, if known. */ + /// Room SID, if known. std::optional sid; - /** Room name. */ + /// Room name. std::string name; - /** Arbitrary application metadata associated with the room. */ + /// Arbitrary application metadata associated with the room. std::string metadata; - /** Low-watermark threshold for lossy data channel buffer. */ + /// Low-watermark threshold for lossy data channel buffer. std::uint64_t lossy_dc_buffered_amount_low_threshold = 0; - /** Low-watermark threshold for reliable data channel buffer. */ + /// Low-watermark threshold for reliable data channel buffer. std::uint64_t reliable_dc_buffered_amount_low_threshold = 0; - /** Time (seconds) to keep room open if no participants join. */ + /// Time (seconds) to keep room open if no participants join. std::uint32_t empty_timeout = 0; - /** Time (seconds) to keep room open after last standard participant leaves. - */ + /// Time (seconds) to keep room open after last standard participant leaves. std::uint32_t departure_timeout = 0; - /** Maximum number of participants allowed in the room. */ + /// Maximum number of participants allowed in the room. std::uint32_t max_participants = 0; - /** Creation time of the room (ms since Unix epoch). */ + /// Creation time of the room (ms since Unix epoch). std::int64_t creation_time = 0; - /** Approximate number of participants (eventually consistent). */ + /// Approximate number of participants (eventually consistent). std::uint32_t num_participants = 0; - /** Approximate number of publishers (eventually consistent). */ + /// Approximate number of publishers (eventually consistent). std::uint32_t num_publishers = 0; - /** True if the room is currently being recorded. */ + /// True if the room is currently being recorded. bool active_recording = false; }; -/** - * Key/value pair for participant or room attributes. - */ +/// Key/value pair for participant or room attributes. struct AttributeEntry { - /** Attribute key. */ + /// Attribute key. std::string key; - /** Attribute value. */ + /// Attribute value. std::string value; AttributeEntry() = default; @@ -192,41 +173,35 @@ struct AttributeEntry { AttributeEntry(std::string k, std::string v) : key(std::move(k)), value(std::move(v)) {} }; -/** - * Header information for an incoming data stream. - * Represents proto_room.DataStream.Header in a C++-friendly form. - */ +/// Header information for an incoming data stream. +/// Represents proto_room.DataStream.Header in a C++-friendly form. struct DataStreamHeaderData { - /** Unique stream identifier. */ + /// Unique stream identifier. std::string stream_id; - /** Timestamp (ms since Unix epoch). */ + /// Timestamp (ms since Unix epoch). std::int64_t timestamp = 0; - /** MIME type of the content (e.g. "application/json"). */ + /// MIME type of the content (e.g. "application/json"). std::string mime_type; - /** Application-defined topic name. */ + /// Application-defined topic name. std::string topic; - /** Optional total length in bytes, if known. */ + /// Optional total length in bytes, if known. std::optional total_length; - /** Custom attributes associated with this stream. */ + /// Custom attributes associated with this stream. std::map attributes; - /** - * Content type carried by this stream. - */ + /// Content type carried by this stream. enum class ContentType { None, Text, Byte, } content_type = ContentType::None; - /** - * Operation type for text streams. - */ + /// Operation type for text streams. enum class OperationType { Create = 0, Update = 1, @@ -234,121 +209,109 @@ struct DataStreamHeaderData { Reaction = 3, }; - /** Optional operation type, for text content. */ + /// Optional operation type, for text content. std::optional operation_type; - /** Optional version number for the text stream. */ + /// Optional version number for the text stream. std::optional version; - /** Optional ID of the stream this one replies to. */ + /// Optional ID of the stream this one replies to. std::optional reply_to_stream_id; - /** IDs of streams attached to this one. */ + /// IDs of streams attached to this one. std::vector attached_stream_ids; - /** True if this stream was generated (e.g. by AI). */ + /// True if this stream was generated (e.g. by AI). std::optional generated; - /** Optional filename for byte streams. */ + /// Optional filename for byte streams. std::optional name; }; -/** - * One chunk of a data stream’s payload. - */ +/// One chunk of a data stream’s payload. struct DataStreamChunkData { - /** Stream identifier this chunk belongs to. */ + /// Stream identifier this chunk belongs to. std::string stream_id; - /** Zero-based index of this chunk. */ + /// Zero-based index of this chunk. std::uint64_t chunk_index = 0; - /** Raw chunk content. */ + /// Raw chunk content. std::vector content; - /** Optional version, mirroring header version if applicable. */ + /// Optional version, mirroring header version if applicable. std::optional version; - /** Optional initialization vector for encrypted payloads. */ + /// Optional initialization vector for encrypted payloads. std::vector iv; }; -/** - * Trailer metadata for a data stream, sent after all chunks. - */ +/// Trailer metadata for a data stream, sent after all chunks. struct DataStreamTrailerData { - /** Stream identifier. */ + /// Stream identifier. std::string stream_id; - /** Reason why the stream ended (empty if normal completion). */ + /// Reason why the stream ended (empty if normal completion). std::string reason; - /** Additional attributes describing the final state of the stream. */ + /// Additional attributes describing the final state of the stream. std::map attributes; }; -/** - * Video encoding configuration used when publishing a track. - */ +/// Video encoding configuration used when publishing a track. struct VideoEncodingOptions { - /** Maximum target bitrate in bps. */ + /// Maximum target bitrate in bps. std::uint64_t max_bitrate = 0; - /** Maximum frame rate in frames per second. */ + /// Maximum frame rate in frames per second. double max_framerate = 0.0; }; -/** - * Audio encoding configuration used when publishing a track. - */ +/// Audio encoding configuration used when publishing a track. struct AudioEncodingOptions { - /** Maximum target bitrate in bps. */ + /// Maximum target bitrate in bps. std::uint64_t max_bitrate = 0; }; -/** - * Optional RTP packet-trailer features for published video tracks. - */ +/// Optional RTP packet-trailer features for published video tracks. struct PacketTrailerFeatures { - /** Embed a user-supplied wall-clock timestamp. */ + /// Embed a user-supplied wall-clock timestamp. bool user_timestamp = false; - /** Embed a monotonically increasing frame identifier. */ + /// Embed a monotonically increasing frame identifier. bool frame_id = false; }; -/** - * Options for publishing a track to the room. - */ +/// Options for publishing a track to the room. struct TrackPublishOptions { - /** Optional video encoding parameters. */ + /// Optional video encoding parameters. std::optional video_encoding; - /** Optional audio encoding parameters. */ + /// Optional audio encoding parameters. std::optional audio_encoding; - /** Optional video codec to use. */ + /// Optional video codec to use. std::optional video_codec; - /** Enable or disable discontinuous transmission (DTX). */ + /// Enable or disable discontinuous transmission (DTX). std::optional dtx; - /** Enable or disable RED (redundant encoding). */ + /// Enable or disable RED (redundant encoding). std::optional red; - /** Enable or disable simulcast. */ + /// Enable or disable simulcast. std::optional simulcast; - /** Track source (camera, microphone, screen share, etc.). */ + /// Track source (camera, microphone, screen share, etc.). std::optional source; - /** Optional stream label/group for this track. */ + /// Optional stream label/group for this track. std::optional stream; - /** Enable pre-connect buffering for lower startup latency. */ + /// Enable pre-connect buffering for lower startup latency. std::optional preconnect_buffer; - /** Optional packet-trailer features to enable for published video. */ + /// Optional packet-trailer features to enable for published video. PacketTrailerFeatures packet_trailer_features{}; }; @@ -356,407 +319,329 @@ struct TrackPublishOptions { // Event structs – public representations of RoomEvent.* // --------------------------------------------------------- -/** - * Fired when a remote participant joins the room. - */ +/// Fired when a remote participant joins the room. struct ParticipantConnectedEvent { - /** The newly connected remote participant (owned by Room). */ + /// The newly connected remote participant (owned by Room). RemoteParticipant* participant = nullptr; }; -/** - * Fired when a remote participant leaves the room. - */ +/// Fired when a remote participant leaves the room. struct ParticipantDisconnectedEvent { - /** The participant that disconnected (owned by Room). */ + /// The participant that disconnected (owned by Room). RemoteParticipant* participant = nullptr; - /** Reason for the disconnect, if known. */ + /// Reason for the disconnect, if known. DisconnectReason reason = DisconnectReason::Unknown; }; -/** - * Fired when a local track is successfully published. - */ +/// Fired when a local track is successfully published. struct LocalTrackPublishedEvent { - /** Track publication for the local track. */ + /// Track publication for the local track. std::shared_ptr publication; - /** The published local track. */ + /// The published local track. std::shared_ptr track; }; -/** - * Fired when a local track is unpublished. - */ +/// Fired when a local track is unpublished. struct LocalTrackUnpublishedEvent { - /** Publication that was unpublished. */ + /// Publication that was unpublished. std::shared_ptr publication; }; -/** - * Fired when a local track gets its first subscriber. - */ +/// Fired when a local track gets its first subscriber. struct LocalTrackSubscribedEvent { - /** Subscribed local track. */ + /// Subscribed local track. std::shared_ptr track; }; -/** - * Fired when a remote participant publishes a track. - */ +/// Fired when a remote participant publishes a track. struct TrackPublishedEvent { - /** Remote track publication. */ + /// Remote track publication. std::shared_ptr publication; - /** Remote participant who owns this track (owned by Room). */ + /// Remote participant who owns this track (owned by Room). RemoteParticipant* participant = nullptr; }; -/** - * Fired when a remote participant unpublishes a track. - */ +/// Fired when a remote participant unpublishes a track. struct TrackUnpublishedEvent { - /** Remote track publication that was removed. */ + /// Remote track publication that was removed. std::shared_ptr publication; - /** Remote participant who owned this track (owned by Room). */ + /// Remote participant who owned this track (owned by Room). RemoteParticipant* participant = nullptr; }; -/** - * Fired when a remote track is successfully subscribed. - */ +/// Fired when a remote track is successfully subscribed. struct TrackSubscribedEvent { - /** Subscribed remote track. */ + /// Subscribed remote track. std::shared_ptr track; - /** Publication associated with the track. */ + /// Publication associated with the track. std::shared_ptr publication; - /** Remote participant who owns the track (owned by Room). */ + /// Remote participant who owns the track (owned by Room). RemoteParticipant* participant = nullptr; }; -/** - * Fired when a remote track is unsubscribed. - */ +/// Fired when a remote track is unsubscribed. struct TrackUnsubscribedEvent { - /** Track that was unsubscribed. */ + /// Track that was unsubscribed. std::shared_ptr track; - /** Publication associated with the track. */ + /// Publication associated with the track. std::shared_ptr publication; - /** Remote participant who owns the track (owned by Room). */ + /// Remote participant who owns the track (owned by Room). RemoteParticipant* participant = nullptr; }; -/** - * Fired when subscribing to a remote track fails. - */ +/// Fired when subscribing to a remote track fails. struct TrackSubscriptionFailedEvent { - /** Remote participant for which the subscription failed (owned by Room). */ + /// Remote participant for which the subscription failed (owned by Room). RemoteParticipant* participant = nullptr; - /** SID of the track that failed to subscribe. */ + /// SID of the track that failed to subscribe. std::string track_sid; - /** Error message describing the failure. */ + /// Error message describing the failure. std::string error; }; -/** - * Fired when a track is muted. - */ +/// Fired when a track is muted. struct TrackMutedEvent { - /** Local or remote participant who owns the track (owned by Room). */ + /// Local or remote participant who owns the track (owned by Room). Participant* participant = nullptr; - /** Publication that was muted. */ + /// Publication that was muted. std::shared_ptr publication; }; -/** - * Fired when a track is unmuted. - */ +/// Fired when a track is unmuted. struct TrackUnmutedEvent { - /** Local or remote participant who owns the track (owned by Room). */ + /// Local or remote participant who owns the track (owned by Room). Participant* participant = nullptr; - /** Publication that was unmuted. */ + /// Publication that was unmuted. std::shared_ptr publication; }; -/** - * Fired when the list of active speakers changes. - */ +/// Fired when the list of active speakers changes. struct ActiveSpeakersChangedEvent { - /** Participants currently considered active speakers (owned by Room). */ + /// Participants currently considered active speakers (owned by Room). std::vector speakers; }; -/** - * Fired when room metadata is updated. - */ +/// Fired when room metadata is updated. struct RoomMetadataChangedEvent { - /** Previous metadata value. */ + /// Previous metadata value. std::string old_metadata; - /** New metadata value. */ + /// New metadata value. std::string new_metadata; }; -/** - * Fired when the room SID changes (e.g., after migration). - */ +/// Fired when the room SID changes (e.g., after migration). struct RoomSidChangedEvent { - /** New room SID. */ + /// New room SID. std::string sid; }; -/** - * Fired when a participant's metadata is updated. - */ +/// Fired when a participant's metadata is updated. struct ParticipantMetadataChangedEvent { - /** Participant whose metadata changed (owned by Room). */ + /// Participant whose metadata changed (owned by Room). Participant* participant = nullptr; - /** Old metadata value. */ + /// Old metadata value. std::string old_metadata; - /** New metadata value. */ + /// New metadata value. std::string new_metadata; }; -/** - * Fired when a participant's name changes. - */ +/// Fired when a participant's name changes. struct ParticipantNameChangedEvent { - /** Participant whose name changed (owned by Room). */ + /// Participant whose name changed (owned by Room). Participant* participant = nullptr; - /** Previous name. */ + /// Previous name. std::string old_name; - /** New name. */ + /// New name. std::string new_name; }; -/** - * Fired when a participant's attributes change. - */ +/// Fired when a participant's attributes change. struct ParticipantAttributesChangedEvent { - /** Participant whose attributes changed (owned by Room). */ + /// Participant whose attributes changed (owned by Room). Participant* participant = nullptr; - /** Set of attributes that changed (key/value pairs). */ + /// Set of attributes that changed (key/value pairs). std::vector changed_attributes; }; -/** - * Fired when a participant's encryption status changes. - */ +/// Fired when a participant's encryption status changes. struct ParticipantEncryptionStatusChangedEvent { - /** Participant whose encryption status changed (owned by Room). */ + /// Participant whose encryption status changed (owned by Room). Participant* participant = nullptr; - /** True if the participant is now fully encrypted. */ + /// True if the participant is now fully encrypted. bool is_encrypted = false; }; -/** - * Fired when a participant's connection quality estimate changes. - */ +/// Fired when a participant's connection quality estimate changes. struct ConnectionQualityChangedEvent { - /** Participant whose connection quality changed (owned by Room). */ + /// Participant whose connection quality changed (owned by Room). Participant* participant = nullptr; - /** New connection quality. */ + /// New connection quality. ConnectionQuality quality = ConnectionQuality::Good; }; -/** - * Fired when a user data packet (non-SIP) is received. - */ +/// Fired when a user data packet (non-SIP) is received. struct UserDataPacketEvent { - /** Payload data. */ + /// Payload data. std::vector data; - /** Delivery kind (reliable or lossy). */ + /// Delivery kind (reliable or lossy). DataPacketKind kind = DataPacketKind::Reliable; - /** Remote participant that sent this packet, or nullptr if server (owned by - * Room). */ + /// Remote participant that sent this packet, or nullptr if server (owned by + /// Room). RemoteParticipant* participant = nullptr; - /** Optional topic associated with this data (may be empty). */ + /// Optional topic associated with this data (may be empty). std::string topic; }; -/** - * Fired when a SIP DTMF packet is received. - */ +/// Fired when a SIP DTMF packet is received. struct SipDtmfReceivedEvent { - /** DTMF code. */ + /// DTMF code. int code = 0; - /** Human-readable DTMF digit. */ + /// Human-readable DTMF digit. std::string digit; - /** Remote participant that sent the DTMF (owned by Room). */ + /// Remote participant that sent the DTMF (owned by Room). RemoteParticipant* participant = nullptr; }; -/** - * Fired when the room's connection state changes. - */ +/// Fired when the room's connection state changes. struct ConnectionStateChangedEvent { - /** New connection state. */ + /// New connection state. ConnectionState state = ConnectionState::Disconnected; }; -/** - * Fired when the room is disconnected. - */ +/// Fired when the room is disconnected. struct DisconnectedEvent { - /** Reason for disconnect, if known. */ + /// Reason for disconnect, if known. DisconnectReason reason = DisconnectReason::Unknown; }; -/** - * Fired just before attempting to reconnect. - */ +/// Fired just before attempting to reconnect. struct ReconnectingEvent {}; -/** - * Fired after successfully reconnecting. - */ +/// Fired after successfully reconnecting. struct ReconnectedEvent {}; -/** - * Fired when the room has reached end-of-stream (no more events). - */ +/// Fired when the room has reached end-of-stream (no more events). struct RoomEosEvent {}; -/** - * Fired when a data stream header is received. - */ +/// Fired when a data stream header is received. struct DataStreamHeaderReceivedEvent { - /** Identity of the participant that sent the stream. */ + /// Identity of the participant that sent the stream. std::string participant_identity; - /** Parsed header data. */ + /// Parsed header data. DataStreamHeaderData header; }; -/** - * Fired when a data stream chunk is received. - */ +/// Fired when a data stream chunk is received. struct DataStreamChunkReceivedEvent { - /** Identity of the participant that sent the stream. */ + /// Identity of the participant that sent the stream. std::string participant_identity; - /** Chunk payload and metadata. */ + /// Chunk payload and metadata. DataStreamChunkData chunk; }; -/** - * Fired when a data stream trailer is received. - */ +/// Fired when a data stream trailer is received. struct DataStreamTrailerReceivedEvent { - /** Identity of the participant that sent the stream. */ + /// Identity of the participant that sent the stream. std::string participant_identity; - /** Trailer metadata describing the stream termination. */ + /// Trailer metadata describing the stream termination. DataStreamTrailerData trailer; }; -/** - * Fired when a data channel's buffered amount falls below its low threshold. - */ +/// Fired when a data channel's buffered amount falls below its low threshold. struct DataChannelBufferedAmountLowThresholdChangedEvent { - /** Data channel kind (reliable or lossy). */ + /// Data channel kind (reliable or lossy). DataPacketKind kind = DataPacketKind::Reliable; - /** New threshold value in bytes. */ + /// New threshold value in bytes. std::uint64_t threshold = 0; }; -/** - * Fired when a high-level byte stream reader is opened. - */ +/// Fired when a high-level byte stream reader is opened. struct ByteStreamOpenedEvent { - /** Handle to the underlying byte stream reader. */ + /// Handle to the underlying byte stream reader. std::uint64_t reader_handle = 0; - /** Identity of the participant that opened the stream. */ + /// Identity of the participant that opened the stream. std::string participant_identity; }; -/** - * Fired when a high-level text stream reader is opened. - */ +/// Fired when a high-level text stream reader is opened. struct TextStreamOpenedEvent { - /** Handle to the underlying text stream reader. */ + /// Handle to the underlying text stream reader. std::uint64_t reader_handle = 0; - /** Identity of the participant that opened the stream. */ + /// Identity of the participant that opened the stream. std::string participant_identity; }; -/** - * Fired when the room's info is updated. - */ +/// Fired when the room's info is updated. struct RoomUpdatedEvent { - /** New room info snapshot. */ + /// New room info snapshot. RoomInfoData info; }; -/** - * Fired when the participant has been moved to another room. - */ +/// Fired when the participant has been moved to another room. struct RoomMovedEvent { - /** Info about the new room. */ + /// Info about the new room. RoomInfoData info; }; -/** - * Fired when a batch of participants has been updated. - */ +/// Fired when a batch of participants has been updated. struct ParticipantsUpdatedEvent { - /** Participants updated in this event (owned by Room). */ + /// Participants updated in this event (owned by Room). std::vector participants; }; -/** - * Fired when a participant's E2EE state changes. - */ +/// Fired when a participant's E2EE state changes. struct E2eeStateChangedEvent { - /** Local or remote participant whose state changed (owned by Room). */ + /// Local or remote participant whose state changed (owned by Room). Participant* participant = nullptr; - /** New encryption state. */ + /// New encryption state. EncryptionState state = EncryptionState::New; }; -/** - * Fired when a participant publishes a data track. - * - * Data tracks are independent of the audio/video track hierarchy. - * The application must call RemoteDataTrack::subscribe() to start - * receiving frames. - */ +/// Fired when a participant publishes a data track. +/// +/// Data tracks are independent of the audio/video track hierarchy. +/// The application must call RemoteDataTrack::subscribe() to start +/// receiving frames. struct DataTrackPublishedEvent { - /** The newly published remote data track. */ + /// The newly published remote data track. std::shared_ptr track; }; -/** - * Fired when a remote participant unpublishes a data track. - */ +/// Fired when a remote participant unpublishes a data track. struct DataTrackUnpublishedEvent { - /** SID of the track that was unpublished. */ + /// SID of the track that was unpublished. std::string sid; }; diff --git a/include/livekit/rpc_error.h b/include/livekit/rpc_error.h index 9e449644..95575649 100644 --- a/include/livekit/rpc_error.h +++ b/include/livekit/rpc_error.h @@ -28,22 +28,18 @@ namespace proto { class RpcError; } -/** - * Specialized error type for RPC methods. - * - * Instances of this type, when thrown in a method handler, will have their - * `code`, `message`, and optional `data` serialized into a proto::RpcError - * and sent across the wire. The caller will receive an equivalent error - * on the other side. - * - * Built-in errors are included (codes 1400–1999) but developers may use - * arbitrary codes as well. - */ +/// Specialized error type for RPC methods. +/// +/// Instances of this type, when thrown in a method handler, will have their +/// `code`, `message`, and optional `data` serialized into a proto::RpcError +/// and sent across the wire. The caller will receive an equivalent error +/// on the other side. +/// +/// Built-in errors are included (codes 1400–1999) but developers may use +/// arbitrary codes as well. class LIVEKIT_API RpcError : public std::runtime_error { public: - /** - * Built-in error codes - */ + /// Built-in error codes enum class ErrorCode : std::uint32_t { APPLICATION_ERROR = 1500, CONNECTION_TIMEOUT = 1501, @@ -59,51 +55,39 @@ class LIVEKIT_API RpcError : public std::runtime_error { UNSUPPORTED_VERSION = 1404, }; - /** - * Construct an RpcError with an explicit numeric code. - * - * @param code Error code value. Codes 1001–1999 are reserved for - * built-in errors (see ErrorCode). - * @param message Human-readable error message. - * @param data Optional extra data, e.g. JSON. Empty string means no data. - */ + /// Construct an RpcError with an explicit numeric code. + /// + /// @param code Error code value. Codes 1001–1999 are reserved for + /// built-in errors (see ErrorCode). + /// @param message Human-readable error message. + /// @param data Optional extra data, e.g. JSON. Empty string means no data. RpcError(std::uint32_t code, std::string message, std::string data = {}); - /** - * Construct an RpcError from a built-in ErrorCode. - * - * @param code Built-in error code. - * @param message Human-readable error message. - * @param data Optional extra data, e.g. JSON. Empty string means no data. - */ + /// Construct an RpcError from a built-in ErrorCode. + /// + /// @param code Built-in error code. + /// @param message Human-readable error message. + /// @param data Optional extra data, e.g. JSON. Empty string means no data. RpcError(ErrorCode code, std::string message, std::string data = {}); - /** - * Numeric error code. - * - * Codes 1001–1999 are reserved for built-in errors. For built-ins, this - * value matches the underlying ErrorCode enum value. - */ + /// Numeric error code. + /// + /// Codes 1001–1999 are reserved for built-in errors. For built-ins, this + /// value matches the underlying ErrorCode enum value. std::uint32_t code() const noexcept; - /** - * Human-readable error message. - */ + /// Human-readable error message. const std::string& message() const noexcept; - /** - * Optional extra data associated with the error (JSON recommended). - * May be an empty string if no data was provided. - */ + /// Optional extra data associated with the error (JSON recommended). + /// May be an empty string if no data was provided. const std::string& data() const noexcept; - /** - * Create a built-in RpcError using a predefined ErrorCode and default - * message text. - * - * @param code Built-in error code. - * @param data Optional extra data payload (JSON recommended). - */ + /// Create a built-in RpcError using a predefined ErrorCode and default + /// message text. + /// + /// @param code Built-in error code. + /// @param data Optional extra data payload (JSON recommended). static RpcError builtIn(ErrorCode code, const std::string& data = {}); protected: diff --git a/include/livekit/stats.h b/include/livekit/stats.h index 84674d8e..6755edde 100644 --- a/include/livekit/stats.h +++ b/include/livekit/stats.h @@ -295,12 +295,10 @@ struct VideoSourceStats { double frames_per_second; }; -/** - * @brief Statistics for audio playout performance. - * - * Contains metrics about audio sample synthesis and playout timing, - * useful for monitoring audio quality and detecting issues like underruns. - */ +/// @brief Statistics for audio playout performance. +/// +/// Contains metrics about audio sample synthesis and playout timing, +/// useful for monitoring audio quality and detecting issues like underruns. struct AudioPlayoutStats { std::string kind; ///< The type of media ("audio"). double synthesized_samples_duration; ///< Duration of synthesized samples in diff --git a/include/livekit/subscription_thread_dispatcher.h b/include/livekit/subscription_thread_dispatcher.h index d93e863e..934e669c 100644 --- a/include/livekit/subscription_thread_dispatcher.h +++ b/include/livekit/subscription_thread_dispatcher.h @@ -61,28 +61,26 @@ using DataFrameCallback = /// individual subscription via removeOnDataFrameCallback. using DataFrameCallbackId = std::uint64_t; -/** - * Owns subscription callback registration and per-subscription reader threads. - * - * `SubscriptionThreadDispatcher` is the low-level companion to \ref Room's - * remote track subscription flow. `Room` forwards user-facing callback - * registration requests here, and then calls \ref handleTrackSubscribed and - * \ref handleTrackUnsubscribed as room events arrive. - * - * For each registered `(participant identity, TrackSource)` pair, this class - * may create a dedicated \ref AudioStream or \ref VideoStream and a matching - * reader thread. That thread blocks on stream reads and invokes the - * registered callback with decoded frames. - * - * This type is intentionally independent from \ref RoomDelegate. High-level - * room events such as `RoomDelegate::onTrackSubscribed()` remain in \ref Room, - * while this dispatcher focuses only on callback registration, stream - * ownership, and reader-thread lifecycle. - * - * The design keeps track-type-specific startup isolated so additional track - * kinds can be added later without pushing more thread state back into - * \ref Room. - */ +/// Owns subscription callback registration and per-subscription reader threads. +/// +/// `SubscriptionThreadDispatcher` is the low-level companion to @ref Room's +/// remote track subscription flow. `Room` forwards user-facing callback +/// registration requests here, and then calls @ref handleTrackSubscribed and +/// @ref handleTrackUnsubscribed as room events arrive. +/// +/// For each registered `(participant identity, TrackSource)` pair, this class +/// may create a dedicated @ref AudioStream or @ref VideoStream and a matching +/// reader thread. That thread blocks on stream reads and invokes the +/// registered callback with decoded frames. +/// +/// This type is intentionally independent from @ref RoomDelegate. High-level +/// room events such as `RoomDelegate::onTrackSubscribed()` remain in @ref Room, +/// while this dispatcher focuses only on callback registration, stream +/// ownership, and reader-thread lifecycle. +/// +/// The design keeps track-type-specific startup isolated so additional track +/// kinds can be added later without pushing more thread state back into +/// @ref Room. class LIVEKIT_API SubscriptionThreadDispatcher { public: /// Constructs an empty dispatcher with no registered callbacks or readers. @@ -91,161 +89,139 @@ class LIVEKIT_API SubscriptionThreadDispatcher { /// Stops all active readers and clears all registered callbacks. ~SubscriptionThreadDispatcher(); - /** - * Register or replace an audio frame callback for a remote subscription. - * - * The callback is keyed by remote participant identity plus \p source. - * If the matching remote audio track is already subscribed, \ref Room may - * immediately call \ref handleTrackSubscribed to start a reader. - * - * @param participant_identity Identity of the remote participant. - * @param source Track source to match. - * @param callback Function invoked for each decoded audio frame. - * @param opts Options used when creating the backing - * \ref AudioStream. - */ + /// Register or replace an audio frame callback for a remote subscription. + /// + /// The callback is keyed by remote participant identity plus @p source. + /// If the matching remote audio track is already subscribed, @ref Room may + /// immediately call @ref handleTrackSubscribed to start a reader. + /// + /// @param participant_identity Identity of the remote participant. + /// @param source Track source to match. + /// @param callback Function invoked for each decoded audio frame. + /// @param opts Options used when creating the backing + /// @ref AudioStream. void setOnAudioFrameCallback(const std::string& participant_identity, TrackSource source, AudioFrameCallback callback, const AudioStream::Options& opts = {}); - /** - * Register or replace an audio frame callback for a remote subscription. - * - * The callback is keyed by remote participant identity plus \p track_name. - * If the matching remote audio track is already subscribed, \ref Room may - * immediately call \ref handleTrackSubscribed to start a reader. - * - * @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. - */ + /// Register or replace an audio frame callback for a remote subscription. + /// + /// The callback is keyed by remote participant identity plus @p track_name. + /// If the matching remote audio track is already subscribed, @ref Room may + /// immediately call @ref handleTrackSubscribed to start a reader. + /// + /// @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. void setOnAudioFrameCallback(const std::string& participant_identity, const std::string& track_name, AudioFrameCallback callback, const AudioStream::Options& opts = {}); - /** - * Register or replace a video frame callback for a remote subscription. - * - * The callback is keyed by remote participant identity plus \p source. - * If the matching remote video track is already subscribed, \ref Room may - * immediately call \ref handleTrackSubscribed to start a reader. - * - * @param participant_identity Identity of the remote participant. - * @param source Track source to match. - * @param callback Function invoked for each decoded video frame. - * @param opts Options used when creating the backing - * \ref VideoStream. - */ + /// Register or replace a video frame callback for a remote subscription. + /// + /// The callback is keyed by remote participant identity plus @p source. + /// If the matching remote video track is already subscribed, @ref Room may + /// immediately call @ref handleTrackSubscribed to start a reader. + /// + /// @param participant_identity Identity of the remote participant. + /// @param source Track source to match. + /// @param callback Function invoked for each decoded video frame. + /// @param opts Options used when creating the backing + /// @ref VideoStream. void setOnVideoFrameCallback(const std::string& participant_identity, TrackSource source, VideoFrameCallback callback, const VideoStream::Options& opts = {}); - /** - * Register or replace a video frame callback for a remote subscription. - * - * The callback is keyed by remote participant identity plus \p track_name. - * If the matching remote video track is already subscribed, \ref Room may - * immediately call \ref handleTrackSubscribed to start a reader. - * - * @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. - */ + /// Register or replace a video frame callback for a remote subscription. + /// + /// The callback is keyed by remote participant identity plus @p track_name. + /// If the matching remote video track is already subscribed, @ref Room may + /// immediately call @ref handleTrackSubscribed to start a reader. + /// + /// @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. void setOnVideoFrameCallback(const std::string& participant_identity, const std::string& track_name, VideoFrameCallback callback, const VideoStream::Options& opts = {}); - /** - * Register or replace a rich video frame event callback for a remote - * subscription. - * - * The callback is keyed by remote participant identity plus \p track_name. - * If the matching remote video track is already subscribed, \ref Room may - * immediately call \ref handleTrackSubscribed to start a reader. - * - * @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. - */ + /// Register or replace a rich video frame event callback for a remote + /// subscription. + /// + /// The callback is keyed by remote participant identity plus @p track_name. + /// If the matching remote video track is already subscribed, @ref Room may + /// immediately call @ref handleTrackSubscribed to start a reader. + /// + /// @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. void setOnVideoFrameEventCallback(const std::string& participant_identity, const std::string& track_name, VideoFrameEventCallback callback, const VideoStream::Options& opts = {}); - /** - * Remove an audio callback registration and stop any active reader. - * - * If an audio reader thread is active for the given key, its stream is - * closed and the thread is joined before this call returns. - * - * @param participant_identity Identity of the remote participant. - * @param source Track source to clear. - */ + /// Remove an audio callback registration and stop any active reader. + /// + /// If an audio reader thread is active for the given key, its stream is + /// closed and the thread is joined before this call returns. + /// + /// @param participant_identity Identity of the remote participant. + /// @param source Track source to clear. void clearOnAudioFrameCallback(const std::string& participant_identity, TrackSource source); - /** - * Remove an audio callback registration and stop any active reader. - * - * If an audio reader thread is active for the given key, its stream is - * closed and the thread is joined before this call returns. - * - * @param participant_identity Identity of the remote participant. - * @param track_name Track name to clear. - */ + /// Remove an audio callback registration and stop any active reader. + /// + /// If an audio reader thread is active for the given key, its stream is + /// closed and the thread is joined before this call returns. + /// + /// @param participant_identity Identity of the remote participant. + /// @param track_name Track name to clear. void clearOnAudioFrameCallback(const std::string& participant_identity, const std::string& track_name); - /** - * Remove a video callback registration and stop any active reader. - * - * If a video reader thread is active for the given key, its stream is - * closed and the thread is joined before this call returns. - * - * @param participant_identity Identity of the remote participant. - * @param source Track source to clear. - */ + /// Remove a video callback registration and stop any active reader. + /// + /// If a video reader thread is active for the given key, its stream is + /// closed and the thread is joined before this call returns. + /// + /// @param participant_identity Identity of the remote participant. + /// @param source Track source to clear. void clearOnVideoFrameCallback(const std::string& participant_identity, TrackSource source); - /** - * Remove a video callback registration and stop any active reader. - * - * If a video reader thread is active for the given key, its stream is - * closed and the thread is joined before this call returns. - * - * @param participant_identity Identity of the remote participant. - * @param track_name Track name to clear. - */ + /// Remove a video callback registration and stop any active reader. + /// + /// If a video reader thread is active for the given key, its stream is + /// closed and the thread is joined before this call returns. + /// + /// @param participant_identity Identity of the remote participant. + /// @param track_name Track name to clear. void clearOnVideoFrameCallback(const std::string& participant_identity, const std::string& track_name); - /** - * Start or restart reader dispatch for a newly subscribed remote track. - * - * \ref Room calls this after it has processed a track-subscription event and - * updated its publication state. If a matching callback registration exists, - * the dispatcher creates the appropriate stream type and launches a reader - * thread for the `(participant, source)` key. - * - * If no matching callback is registered, this is a no-op. - * - * @param participant_identity Identity of the remote participant. - * @param source Track source associated with the subscription. - * @param track Subscribed remote track to read from. - */ + /// Start or restart reader dispatch for a newly subscribed remote track. + /// + /// @ref Room calls this after it has processed a track-subscription event and + /// updated its publication state. If a matching callback registration exists, + /// the dispatcher creates the appropriate stream type and launches a reader + /// thread for the `(participant, source)` key. + /// + /// If no matching callback is registered, this is a no-op. + /// + /// @param participant_identity Identity of the remote participant. + /// @param source Track source associated with the subscription. + /// @param track Subscribed remote track to read from. void handleTrackSubscribed(const std::string& participant_identity, TrackSource source, const std::string& track_name, const std::shared_ptr& track); - /** - * Stop reader dispatch for an unsubscribed remote track. - * - * \ref Room calls this when a remote track is unsubscribed. Any active - * reader stream for the given `(participant, source)` key is closed and its - * thread is joined. Callback registration is preserved so future - * re-subscription can start dispatch again automatically. - * - * @param participant_identity Identity of the remote participant. - * @param source Track source associated with the subscription. - * @param track_name Track name associated with the subscription. - */ + /// Stop reader dispatch for an unsubscribed remote track. + /// + /// @ref Room calls this when a remote track is unsubscribed. Any active + /// reader stream for the given `(participant, source)` key is closed and its + /// thread is joined. Callback registration is preserved so future + /// re-subscription can start dispatch again automatically. + /// + /// @param participant_identity Identity of the remote participant. + /// @param source Track source associated with the subscription. + /// @param track_name Track name associated with the subscription. void handleTrackUnsubscribed(const std::string& participant_identity, TrackSource source, const std::string& track_name); @@ -253,63 +229,53 @@ class LIVEKIT_API SubscriptionThreadDispatcher { // Data track callbacks // --------------------------------------------------------------- - /** - * Add a callback for data frames from a specific remote participant's - * data track. - * - * Multiple callbacks may be registered for the same (participant, - * track_name) pair; each one creates an independent FFI subscription. - * - * The callback fires on a dedicated background thread. If the remote - * data track has not yet been published, the callback is stored and - * auto-wired when the track appears (via handleDataTrackPublished). - * - * @param participant_identity Identity of the remote participant. - * @param track_name Name of the remote data track. - * @param callback Function to invoke per data frame. - * @return An opaque ID that can later be passed to - * removeOnDataFrameCallback() to tear down this subscription. - */ + /// Add a callback for data frames from a specific remote participant's + /// data track. + /// + /// Multiple callbacks may be registered for the same (participant, + /// track_name) pair; each one creates an independent FFI subscription. + /// + /// The callback fires on a dedicated background thread. If the remote + /// data track has not yet been published, the callback is stored and + /// auto-wired when the track appears (via handleDataTrackPublished). + /// + /// @param participant_identity Identity of the remote participant. + /// @param track_name Name of the remote data track. + /// @param callback Function to invoke per data frame. + /// @return An opaque ID that can later be passed to + /// removeOnDataFrameCallback() to tear down this subscription. DataFrameCallbackId addOnDataFrameCallback(const std::string& participant_identity, const std::string& track_name, DataFrameCallback callback); - /** - * Remove a data frame callback previously registered via - * addOnDataFrameCallback(). Stops and joins the active reader thread - * for this subscription. - * No-op if the ID is not (or no longer) registered. - * - * @param id The identifier returned by addOnDataFrameCallback(). - */ + /// Remove a data frame callback previously registered via + /// addOnDataFrameCallback(). Stops and joins the active reader thread + /// for this subscription. + /// No-op if the ID is not (or no longer) registered. + /// + /// @param id The identifier returned by addOnDataFrameCallback(). void removeOnDataFrameCallback(DataFrameCallbackId id); - /** - * Notify the dispatcher that a remote data track has been published. - * - * \ref Room calls this when it receives a kDataTrackPublished event. - * For every registered callback whose (participant, track_name) matches, - * a reader thread is launched. - * - * @param track The newly published remote data track. - */ + /// Notify the dispatcher that a remote data track has been published. + /// + /// @ref Room calls this when it receives a kDataTrackPublished event. + /// For every registered callback whose (participant, track_name) matches, + /// a reader thread is launched. + /// + /// @param track The newly published remote data track. void handleDataTrackPublished(const std::shared_ptr& track); - /** - * Notify the dispatcher that a remote data track has been unpublished. - * - * \ref Room calls this when it receives a kDataTrackUnpublished event. - * Any active data reader threads for this track SID are closed and joined. - * - * @param sid The SID of the unpublished data track. - */ + /// Notify the dispatcher that a remote data track has been unpublished. + /// + /// @ref Room calls this when it receives a kDataTrackUnpublished event. + /// Any active data reader threads for this track SID are closed and joined. + /// + /// @param sid The SID of the unpublished data track. void handleDataTrackUnpublished(const std::string& sid); - /** - * Stop all readers and clear all callback registrations. - * - * This is used during room teardown or EOS handling to ensure no reader - * thread survives beyond the lifetime of the owning \ref Room. - */ + /// Stop all readers and clear all callback registrations. + /// + /// This is used during room teardown or EOS handling to ensure no reader + /// thread survives beyond the lifetime of the owning @ref Room. void stopAll(); private: @@ -328,7 +294,7 @@ class LIVEKIT_API SubscriptionThreadDispatcher { } }; - /// Hash function for \ref CallbackKey so it can be used in unordered maps. + /// Hash function for @ref CallbackKey so it can be used in unordered maps. struct CallbackKeyHash { std::size_t operator()(const CallbackKey& k) const { auto h1 = std::hash{}(k.participant_identity); @@ -355,7 +321,7 @@ class LIVEKIT_API SubscriptionThreadDispatcher { } }; - /// Hash function for \ref DataCallbackKey. + /// Hash function for @ref DataCallbackKey. struct DataCallbackKeyHash { std::size_t operator()(const DataCallbackKey& k) const { auto h1 = std::hash{}(k.participant_identity); @@ -391,54 +357,54 @@ class LIVEKIT_API SubscriptionThreadDispatcher { VideoStream::Options options; }; - /// Remove and close the active reader for \p key, returning its thread. + /// Remove and close the active reader for @p key, returning its thread. /// - /// Must be called with \ref lock_ held. The returned thread, if joinable, + /// Must be called with @ref lock_ held. The returned thread, if joinable, /// must be joined after releasing the lock. std::thread extractReaderThreadLocked(const CallbackKey& key); - /// Select the appropriate reader startup path for \p track. + /// Select the appropriate reader startup path for @p track. /// - /// Must be called with \ref lock_ held. + /// Must be called with @ref lock_ held. std::thread startReaderLocked(const CallbackKey& key, const std::shared_ptr& track); - /// Start an audio reader thread for \p key using \p track. + /// Start an audio reader thread for @p key using @p track. /// - /// Must be called with \ref lock_ held. Any previous reader for the same key + /// Must be called with @ref lock_ held. Any previous reader for the same key /// is extracted and returned to the caller for joining outside the lock. std::thread startAudioReaderLocked(const CallbackKey& key, const std::shared_ptr& track, const AudioFrameCallback& cb, const AudioStream::Options& opts); - /// Start a video reader thread for \p key using \p track. + /// Start a video reader thread for @p key using @p track. /// - /// Must be called with \ref lock_ held. Any previous reader for the same key + /// Must be called with @ref lock_ held. Any previous reader for the same key /// is extracted and returned to the caller for joining outside the lock. std::thread startVideoReaderLocked(const CallbackKey& key, const std::shared_ptr& track, const RegisteredVideoCallback& callback); /// Extract and close the data reader for a given callback ID, returning its - /// thread. Must be called with \ref lock_ held. + /// thread. Must be called with @ref lock_ held. std::thread extractDataReaderThreadLocked(DataFrameCallbackId id); /// Extract and close the data reader for a given (participant, track_name) - /// key, returning its thread. Must be called with \ref lock_ held. + /// key, returning its thread. Must be called with @ref lock_ held. std::thread extractDataReaderThreadLocked(const DataCallbackKey& key); /// Start a data reader thread for the given callback ID, key, and track. - /// Must be called with \ref lock_ held. + /// Must be called with @ref lock_ held. std::thread startDataReaderLocked(DataFrameCallbackId id, const DataCallbackKey& key, const std::shared_ptr& track, const DataFrameCallback& cb); /// Protects callback registration maps and active reader state. mutable std::mutex lock_; - /// Registered audio frame callbacks keyed by \ref CallbackKey. + /// Registered audio frame callbacks keyed by @ref CallbackKey. std::unordered_map audio_callbacks_; - /// Registered video frame callbacks keyed by \ref CallbackKey. + /// Registered video frame callbacks keyed by @ref CallbackKey. std::unordered_map video_callbacks_; - /// Active stream/thread state keyed by \ref CallbackKey. + /// Active stream/thread state keyed by @ref CallbackKey. std::unordered_map active_readers_; /// Next auto-increment ID for data frame callbacks. diff --git a/include/livekit/tracing.h b/include/livekit/tracing.h index a630ffe6..a6549224 100644 --- a/include/livekit/tracing.h +++ b/include/livekit/tracing.h @@ -23,35 +23,29 @@ namespace livekit { -/** - * Start tracing and write events to a file. - * - * Events are written to the file asynchronously by a background thread. - * The file is written in Chrome trace format (JSON), viewable in: - * - Chrome: chrome://tracing - * - Perfetto: https://ui.perfetto.dev - * - * @param trace_file_path Path to the output trace file (e.g., "trace.json") - * @param categories Categories to enable (empty = all categories). - * Supports wildcards: "livekit.*" matches all livekit - * categories. - * @return true if tracing was started, false if already running or file error - */ +/// Start tracing and write events to a file. +/// +/// Events are written to the file asynchronously by a background thread. +/// The file is written in Chrome trace format (JSON), viewable in: +/// - Chrome: chrome://tracing +/// - Perfetto: https://ui.perfetto.dev +/// +/// @param trace_file_path Path to the output trace file (e.g., "trace.json") +/// @param categories Categories to enable (empty = all categories). +/// Supports wildcards: "livekit.*" matches all livekit +/// categories. +/// @return true if tracing was started, false if already running or file error LIVEKIT_API bool startTracing(const std::string& trace_file_path, const std::vector& categories = {}); -/** - * Stop tracing and flush remaining events to file. - * - * This blocks until all pending events are written and the file is closed. - * After stopping, the trace file is complete and ready for analysis. - */ +/// Stop tracing and flush remaining events to file. +/// +/// This blocks until all pending events are written and the file is closed. +/// After stopping, the trace file is complete and ready for analysis. LIVEKIT_API void stopTracing(); -/** - * Check if tracing is currently active. - * - * @return true if tracing is running - */ +/// Check if tracing is currently active. +/// +/// @return true if tracing is running LIVEKIT_API bool isTracingEnabled(); } // namespace livekit diff --git a/include/livekit/track.h b/include/livekit/track.h index 04cb8d7a..00c2d744 100644 --- a/include/livekit/track.h +++ b/include/livekit/track.h @@ -129,7 +129,7 @@ class LIVEKIT_API Track { // Async get stats std::future> getStats() const; - /// After publishing a local track, associates the \ref LocalTrackPublication + /// After publishing a local track, associates the @ref LocalTrackPublication /// with this track. Default implementation is a no-op (e.g. remote tracks). virtual void setPublication(const std::shared_ptr& publication) noexcept { (void)publication; } diff --git a/include/livekit/track_publication.h b/include/livekit/track_publication.h index 7a8d9ead..1552b937 100644 --- a/include/livekit/track_publication.h +++ b/include/livekit/track_publication.h @@ -32,12 +32,10 @@ class Track; class LocalTrack; class RemoteTrack; -/** - * C++ TrackPublication. - * - * Wraps the immutable publication info plus an FFI handle, and - * holds a weak reference to the associated Track (if any). - */ +/// C++ TrackPublication. +/// +/// Wraps the immutable publication info plus an FFI handle, and +/// holds a weak reference to the associated Track (if any). class LIVEKIT_API TrackPublication { public: virtual ~TrackPublication() = default; diff --git a/include/livekit/video_frame.h b/include/livekit/video_frame.h index 4520aeed..79c2d016 100644 --- a/include/livekit/video_frame.h +++ b/include/livekit/video_frame.h @@ -25,27 +25,25 @@ namespace livekit { -// Mirror of WebRTC video buffer type +/// Mirror of WebRTC video buffer type enum class VideoBufferType { RGBA = 0, ABGR, ARGB, BGRA, RGB24, I420, I420A, I422, I444, I010, NV12 }; struct VideoPlaneInfo { - std::uintptr_t data_ptr; // pointer to plane data (for FFI) - std::uint32_t stride; // bytes per row - std::uint32_t size; // plane size in bytes + std::uintptr_t data_ptr; ///< pointer to plane data (for FFI) + std::uint32_t stride; ///< bytes per row + std::uint32_t size; ///< plane size in bytes }; namespace proto { class OwnedVideoBuffer; } -/** - * Public SDK representation of a video frame. - * - * - Owns its pixel buffer (std::vector). - * - Developers can allocate and fill frames in C++ and pass them to the SDK. - * - The SDK can expose the backing memory to Rust via data_ptr + layout for - * the duration of a blocking FFI call (similar to AudioFrame). - */ +/// Public SDK representation of a video frame. +/// +/// - Owns its pixel buffer (std::vector). +/// - Developers can allocate and fill frames in C++ and pass them to the SDK. +/// - The SDK can expose the backing memory to Rust via data_ptr + layout for +/// the duration of a blocking FFI call (similar to AudioFrame). class LIVEKIT_API VideoFrame { public: VideoFrame(); @@ -57,10 +55,8 @@ class LIVEKIT_API VideoFrame { VideoFrame(VideoFrame&&) noexcept = default; VideoFrame& operator=(VideoFrame&&) noexcept = default; - /** - * Allocate a new frame with the correct buffer size for the given format. - * Data is zero-initialized. - */ + /// Allocate a new frame with the correct buffer size for the given format. + /// Data is zero-initialized. static VideoFrame create(int width, int height, VideoBufferType type); // Basic properties @@ -72,39 +68,35 @@ class LIVEKIT_API VideoFrame { const std::uint8_t* data() const noexcept { return data_.data(); } std::size_t dataSize() const noexcept { return data_.size(); } - /** - * Compute plane layout for this frame (Y/U/V, UV, etc.), in terms of - * pointers & sizes relative to this frame's backing buffer. - * - * For packed formats (ARGB, RGB24) this will be either 1 plane or empty. - */ + /// Compute plane layout for this frame (Y/U/V, UV, etc.), in terms of + /// pointers & sizes relative to this frame's backing buffer. + /// + /// For packed formats (ARGB, RGB24) this will be either 1 plane or empty. std::vector planeInfos() const; - /** - * Convert this frame into another pixel format. - * - * This uses the underlying FFI `video_convert` pipeline to transform the - * current frame into a new `VideoFrame` with the requested - * `dst` buffer type (e.g. ARGB → I420, BGRA → RGB24, etc.). - * - * @param dst Desired output format (see VideoBufferType). - * @param flip_y If true, the converted frame will be vertically flipped. - * - * @return A new VideoFrame containing the converted image data. - * - * Notes: - * - This function allocates a new buffer and copies pixel data; it does - * not modify the original frame. - * - This function performs a full CPU-based pixel conversion**. Depending - * on resolution and format, this may involve substantial computation - * (e.g., color-space transforms, planar repacking, vertical flipping). - * Avoid calling this inside tight real-time loops unless necessary. - * - Throws std::runtime_error if the FFI conversion fails or if the - * format combination is unsupported. - * - * Typical usage: - * VideoFrame i420 = frame.convert(VideoBufferType::I420); - */ + /// Convert this frame into another pixel format. + /// + /// This uses the underlying FFI `video_convert` pipeline to transform the + /// current frame into a new `VideoFrame` with the requested + /// `dst` buffer type (e.g. ARGB → I420, BGRA → RGB24, etc.). + /// + /// @param dst Desired output format (see VideoBufferType). + /// @param flip_y If true, the converted frame will be vertically flipped. + /// + /// @return A new VideoFrame containing the converted image data. + /// + /// Notes: + /// - This function allocates a new buffer and copies pixel data; it does + /// not modify the original frame. + /// - This function performs a full CPU-based pixel conversion**. Depending + /// on resolution and format, this may involve substantial computation + /// (e.g., color-space transforms, planar repacking, vertical flipping). + /// Avoid calling this inside tight real-time loops unless necessary. + /// - Throws std::runtime_error if the FFI conversion fails or if the + /// format combination is unsupported. + /// + /// Typical usage: + /// VideoFrame i420 = frame.convert(VideoBufferType::I420); VideoFrame convert(VideoBufferType dst, bool flip_y = false) const; protected: diff --git a/include/livekit/video_source.h b/include/livekit/video_source.h index bdbbb593..03af3fed 100644 --- a/include/livekit/video_source.h +++ b/include/livekit/video_source.h @@ -26,11 +26,9 @@ namespace livekit { class VideoFrame; -/** - * Rotation of a video frame. - * - * Mirrors proto_video.VideoRotation but kept as a public SDK enum. - */ +/// Rotation of a video frame. +/// +/// Mirrors proto_video.VideoRotation but kept as a public SDK enum. enum class VideoRotation { VIDEO_ROTATION_0 = 0, VIDEO_ROTATION_90 = 90, @@ -38,42 +36,34 @@ enum class VideoRotation { VIDEO_ROTATION_270 = 270, }; -/** - * Optional packet-trailer metadata carried alongside a video frame. - * - * Each field is independently optional because the corresponding transport - * feature can be negotiated separately. - */ +/// Optional packet-trailer metadata carried alongside a video frame. +/// +/// Each field is independently optional because the corresponding transport +/// feature can be negotiated separately. struct VideoFrameMetadata { std::optional user_timestamp_us; std::optional frame_id; }; -/** - * Capture options for a single outbound video frame. - */ +/// Capture options for a single outbound video frame. struct VideoCaptureOptions { std::int64_t timestamp_us = 0; VideoRotation rotation = VideoRotation::VIDEO_ROTATION_0; - // Populate meta data when you want to send user timestamps or frame IDs. + /// Populate meta data when you want to send user timestamps or frame IDs. std::optional metadata; }; -/** - * Represents a real-time video source that can accept frames from the - * application and feed them into the LiveKit core. - */ +/// Represents a real-time video source that can accept frames from the +/// application and feed them into the LiveKit core. class LIVEKIT_API VideoSource { public: - /** - * Create a new native video source with a fixed resolution. - * - * @param width Width in pixels. - * @param height Height in pixels. - * - * Throws std::runtime_error if the FFI call fails or the response - * does not contain the expected new_video_source field. - */ + /// Create a new native video source with a fixed resolution. + /// + /// @param width Width in pixels. + /// @param height Height in pixels. + /// + /// @throws std::runtime_error if the FFI call fails or the response + /// does not contain the expected new_video_source field. VideoSource(int width, int height); virtual ~VideoSource() = default; @@ -95,17 +85,13 @@ class LIVEKIT_API VideoSource { return ffiHandleId(); } - /** - * Push a VideoFrame into the FFI video source. - * - * @param frame Video frame to send. - * @param options Timestamp, rotation, and optional metadata for this frame. - */ + /// Push a VideoFrame into the FFI video source. + /// + /// @param frame Video frame to send. + /// @param options Timestamp, rotation, and optional metadata for this frame. void captureFrame(const VideoFrame& frame, const VideoCaptureOptions& options); - /** - * Backward-compatible convenience overload for timestamp + rotation only. - */ + /// Backward-compatible convenience overload for timestamp + rotation only. void captureFrame(const VideoFrame& frame, std::int64_t timestamp_us = 0, VideoRotation rotation = VideoRotation::VIDEO_ROTATION_0); diff --git a/include/livekit/video_stream.h b/include/livekit/video_stream.h index dcc11645..5ed03c78 100644 --- a/include/livekit/video_stream.h +++ b/include/livekit/video_stream.h @@ -33,13 +33,13 @@ namespace livekit { -// A single video frame event delivered by VideoStream::read(). +/// A single video frame event delivered by VideoStream::read(). struct VideoFrameEvent { VideoFrame frame; - // WebRTC frame timestamp in microseconds. - // This may be translated onto WebRTC's internal capture-time timeline and - // should not be expected to match application-provided metadata such as - // VideoFrameMetadata::user_timestamp_us exactly. + /// WebRTC frame timestamp in microseconds. + /// This may be translated onto WebRTC's internal capture-time timeline and + /// should not be expected to match application-provided metadata such as + /// VideoFrameMetadata::user_timestamp_us exactly. std::int64_t timestamp_us; VideoRotation rotation; std::optional metadata; @@ -49,40 +49,39 @@ namespace proto { class FfiEvent; } -// Represents a pull-based stream of decoded video frames coming from -// a remote (or local) LiveKit track. Similar to AudioStream, but for video. -// -// Typical usage: -// -// VideoStream::Options opts; -// auto stream = VideoStream::fromTrack(remoteVideoTrack, opts); -// -// VideoFrameEvent ev; -// while (stream->read(ev)) { -// // ev.frame contains the decoded video buffer -// } -// -// stream->close(); // optional, called automatically in destructor -// +/// Represents a pull-based stream of decoded video frames coming from +/// a remote (or local) LiveKit track. Similar to AudioStream, but for video. +/// +/// Typical usage: +/// +/// VideoStream::Options opts; +/// auto stream = VideoStream::fromTrack(remoteVideoTrack, opts); +/// +/// VideoFrameEvent ev; +/// while (stream->read(ev)) { +/// // ev.frame contains the decoded video buffer +/// } +/// +/// stream->close(); // optional, called automatically in destructor class LIVEKIT_API VideoStream { public: struct Options { - // Maximum number of VideoFrameEvent items buffered in the internal queue. - // 0 means "unbounded" (the queue can grow without limit). - // - // With a non-zero capacity, the queue behaves like a ring-buffer: if it - // is full, the oldest frame is dropped when a new one arrives. + /// Maximum number of VideoFrameEvent items buffered in the internal queue. + /// 0 means "unbounded" (the queue can grow without limit). + /// + /// With a non-zero capacity, the queue behaves like a ring-buffer: if it + /// is full, the oldest frame is dropped when a new one arrives. std::size_t capacity{0}; - // Preferred pixel format for frames delivered by read(). The FFI layer - // converts into this format if supported (e.g., RGBA, BGRA, I420, ...). + /// Preferred pixel format for frames delivered by read(). The FFI layer + /// converts into this format if supported (e.g., RGBA, BGRA, I420, ...). VideoBufferType format{VideoBufferType::RGBA}; }; - // Factory: create a VideoStream bound to a specific Track + /// Factory: create a VideoStream bound to a specific Track static std::shared_ptr fromTrack(const std::shared_ptr& track, const Options& options); - // Factory: create a VideoStream from a Participant + TrackSource + /// Factory: create a VideoStream from a Participant + TrackSource static std::shared_ptr fromParticipant(Participant& participant, TrackSource track_source, const Options& options); @@ -96,8 +95,8 @@ class LIVEKIT_API VideoStream { /// Blocking read: waits until a VideoFrameEvent is available in the internal /// queue, or the stream reaches EOS / is closed. /// - /// \param out On success, filled with the next video frame event. - /// \return true if a frame was delivered; false if the stream ended + /// @param out On success, filled with the next video frame event. + /// @return true if a frame was delivered; false if the stream ended /// (end-of-stream or close()) and no more data is available. bool read(VideoFrameEvent& out); diff --git a/src/tests/integration/test_late_join_track_publication.cpp b/src/tests/integration/test_late_join_track_publication.cpp index 1e832e83..89e84392 100644 --- a/src/tests/integration/test_late_join_track_publication.cpp +++ b/src/tests/integration/test_late_join_track_publication.cpp @@ -363,7 +363,7 @@ TEST_P(LateJoinTrackPublicationIntegrationTest, ConsumerReceivesAlreadyPublished options.single_peer_connection = single_peer_connection; Room publisher_room; - ASSERT_TRUE(publisher_room.Connect(config_.url, config_.token_a, options)) << "Publisher failed to connect"; + ASSERT_TRUE(publisher_room.connect(config_.url, config_.token_a, options)) << "Publisher failed to connect"; ASSERT_NE(publisher_room.localParticipant(), nullptr); const std::string publisher_identity = publisher_room.localParticipant()->identity(); @@ -397,7 +397,7 @@ TEST_P(LateJoinTrackPublicationIntegrationTest, ConsumerReceivesAlreadyPublished Room consumer_room; consumer_room.setDelegate(&delegate); - ASSERT_TRUE(consumer_room.Connect(config_.url, config_.token_b, options)) << "Consumer failed to connect"; + ASSERT_TRUE(consumer_room.connect(config_.url, config_.token_b, options)) << "Consumer failed to connect"; ASSERT_NE(consumer_room.localParticipant(), nullptr); ASSERT_TRUE(waitForParticipant(&consumer_room, publisher_identity, 10s)) << "Publisher not visible to late-joining consumer"; @@ -467,7 +467,7 @@ TEST_P(LateJoinTrackPublicationIntegrationTest, ConsumerReceivesAlreadyPublished options.single_peer_connection = single_peer_connection; Room publisher_room; - ASSERT_TRUE(publisher_room.Connect(config_.url, config_.token_a, options)) << "Publisher failed to connect"; + ASSERT_TRUE(publisher_room.connect(config_.url, config_.token_a, options)) << "Publisher failed to connect"; ASSERT_NE(publisher_room.localParticipant(), nullptr); const std::string publisher_identity = publisher_room.localParticipant()->identity(); @@ -502,7 +502,7 @@ TEST_P(LateJoinTrackPublicationIntegrationTest, ConsumerReceivesAlreadyPublished Room consumer_room; consumer_room.setDelegate(&delegate); - ASSERT_TRUE(consumer_room.Connect(config_.url, config_.token_b, options)) << "Consumer failed to connect"; + ASSERT_TRUE(consumer_room.connect(config_.url, config_.token_b, options)) << "Consumer failed to connect"; ASSERT_NE(consumer_room.localParticipant(), nullptr); ASSERT_TRUE(waitForParticipant(&consumer_room, publisher_identity, 10s)) << "Publisher not visible to late-joining consumer"; @@ -572,7 +572,7 @@ TEST_P(LateJoinTrackPublicationIntegrationTest, ConsumerReceivesAlreadyPublished options.single_peer_connection = single_peer_connection; Room publisher_room; - ASSERT_TRUE(publisher_room.Connect(config_.url, config_.token_a, options)) << "Publisher failed to connect"; + ASSERT_TRUE(publisher_room.connect(config_.url, config_.token_a, options)) << "Publisher failed to connect"; ASSERT_NE(publisher_room.localParticipant(), nullptr); const std::string publisher_identity = publisher_room.localParticipant()->identity(); @@ -601,7 +601,7 @@ TEST_P(LateJoinTrackPublicationIntegrationTest, ConsumerReceivesAlreadyPublished Room consumer_room; consumer_room.setDelegate(&delegate); - ASSERT_TRUE(consumer_room.Connect(config_.url, config_.token_b, options)) << "Consumer failed to connect"; + ASSERT_TRUE(consumer_room.connect(config_.url, config_.token_b, options)) << "Consumer failed to connect"; ASSERT_NE(consumer_room.localParticipant(), nullptr); ASSERT_TRUE(waitForParticipant(&consumer_room, publisher_identity, 10s)) << "Publisher not visible to late-joining consumer"; diff --git a/src/tests/integration/test_room_listener_cleanup.cpp b/src/tests/integration/test_room_listener_cleanup.cpp index f225b929..912df3b0 100644 --- a/src/tests/integration/test_room_listener_cleanup.cpp +++ b/src/tests/integration/test_room_listener_cleanup.cpp @@ -83,13 +83,13 @@ void expectFailedConnectDoesNotDuplicateParticipantCallbacks(const TestConfig& c Room observed_room; observed_room.setDelegate(&counter); - EXPECT_FALSE(observed_room.Connect(failed_url, failed_token, options)) << "Initial failing Connect() should fail"; + EXPECT_FALSE(observed_room.connect(failed_url, failed_token, options)) << "Initial failing connect() should fail"; - ASSERT_TRUE(observed_room.Connect(config.url, config.token_a, options)) << "Reconnect after failed Connect() failed"; + ASSERT_TRUE(observed_room.connect(config.url, config.token_a, options)) << "Reconnect after failed connect() failed"; ASSERT_NE(observed_room.localParticipant(), nullptr); Room peer_room; - ASSERT_TRUE(peer_room.Connect(config.url, config.token_b, options)) << "Peer failed to connect"; + ASSERT_TRUE(peer_room.connect(config.url, config.token_b, options)) << "Peer failed to connect"; ASSERT_NE(peer_room.localParticipant(), nullptr); const std::string peer_identity = peer_room.localParticipant()->identity(); ASSERT_FALSE(peer_identity.empty()); @@ -129,13 +129,13 @@ TEST_F(RoomListenerCleanupIntegrationTest, AlreadyConnectedConnectDoesNotReplace Room observed_room; observed_room.setDelegate(&counter); - ASSERT_TRUE(observed_room.Connect(config_.url, config_.token_a, options)) << "Initial Connect() failed"; + ASSERT_TRUE(observed_room.connect(config_.url, config_.token_a, options)) << "Initial connect() failed"; ASSERT_NE(observed_room.localParticipant(), nullptr); - EXPECT_THROW((void)observed_room.Connect(config_.url, config_.token_a, options), std::runtime_error); + EXPECT_THROW((void)observed_room.connect(config_.url, config_.token_a, options), std::runtime_error); Room peer_room; - ASSERT_TRUE(peer_room.Connect(config_.url, config_.token_b, options)) << "Peer failed to connect"; + ASSERT_TRUE(peer_room.connect(config_.url, config_.token_b, options)) << "Peer failed to connect"; ASSERT_NE(peer_room.localParticipant(), nullptr); const std::string peer_identity = peer_room.localParticipant()->identity(); ASSERT_FALSE(peer_identity.empty()); diff --git a/src/tests/stress/test_room_listener_race_stress.cpp b/src/tests/stress/test_room_listener_race_stress.cpp index 4b35f257..51dee819 100644 --- a/src/tests/stress/test_room_listener_race_stress.cpp +++ b/src/tests/stress/test_room_listener_race_stress.cpp @@ -81,14 +81,14 @@ TEST_F(RoomListenerRaceStressTest, ConnectFailDestroyReconnectAndPublishDataTrac { Room failed_room; - if (failed_room.Connect("ws://127.0.0.1:9", tokens[publisher_index], options)) { + if (failed_room.connect("ws://127.0.0.1:9", tokens[publisher_index], options)) { addStressError(errors, errors_mutex, "unexpected successful failed connect"); return; } } Room room; - if (!room.Connect(config_.url, tokens[publisher_index], options)) { + if (!room.connect(config_.url, tokens[publisher_index], options)) { addStressError(errors, errors_mutex, "valid connect failed"); return; }