Skip to main content
This page covers creating and destroying SDK instances, joining and leaving channels, and every callback registration function. All functions are thread-safe.

Logging

rtc_set_log_level

Sets the global log level. It applies to the whole process; we recommend calling it before rtc_create.

Instance lifecycle

rtc_create

Creates an SDK instance and returns the instance handle. Every channel-related function afterward takes this handle. One handle corresponds to one channel connection. To connect to multiple channels at the same time, create multiple instances.

rtc_destroy

Destroys the instance and releases its resources. Starting with 0.0.11, rtc_destroy waits for all running callbacks to return before it returns. After it returns, no further callbacks fire for this instance, and you can safely free the context you passed to the callbacks.
  • You may call rtc_destroy from within one of this instance’s callbacks (including the disconnect callback). In that case it only waits for callbacks on other threads—don’t free the current callback’s context until that callback returns
  • If a callback does slow work (decoding, writing files), rtc_destroy waits correspondingly longer
  • Neither rtc_leave_channel nor replacing a callback with rtc_set_*_callback waits for running callbacks, so neither is a safe point to free context
0.0.10 and earlier don’t provide these guarantees: callbacks may still be running when rtc_destroy returns, and calling rtc_destroy from the disconnect callback deadlocks. With these older versions, don’t free context right after rtc_destroy, and don’t destroy the instance in the disconnect callback; we recommend upgrading to 0.0.11.
You must call rtc_destroy; otherwise the instance’s resources are not released. The handle can’t be used after it’s destroyed.

Joining and leaving a channel

rtc_join_channel

Joins a channel asynchronously and returns immediately. The actual connection result is reported through the connection state callback (rtc_set_connection_callback). Returns

rtc_join_channel_sync

Joins a channel synchronously, blocking until the connection succeeds, fails, or times out. Returns

rtc_get_last_error

Gets the error details of this instance’s most recent failed call (since 0.0.9). Call it after join, subscribe, publish, or similar functions return RTC_ERROR / RTC_TIMEOUT. Returns: The error code. 180xxx is an SDK error, ≥1000 is a server error code, -1 is an internal error with no specific code, and 0 means nothing was recorded.
Each instance keeps only the most recent error. When multiple threads call functions on the same instance concurrently, a later failure overwrites an earlier one.

rtc_leave_channel

Leaves the channel. The instance stays valid after leaving and can join again. When you’re done with it for good, you still need to call rtc_destroy. Returns: RTC_OK / RTC_INVALID_PARAM (invalid handle).

Auto-subscribe

rtc_set_auto_subscribe

Sets whether to automatically subscribe to remote tracks. When on, every already-published and newly published track of the corresponding type in the channel is subscribed automatically, and all data goes through the track data callback.
Must be called before joining the channel. Setting it after joining has no effect on existing tracks.
If a user wants to “hear everyone,” the right approach is rtc_set_auto_subscribe(rtc, 1, 0) to subscribe to everyone’s audio and then mix it yourself. Don’t subscribe to the audio composite stream—it includes your own voice and causes echo.

Callback registration

Every callback carries your context through the context parameter; the SDK passes it back unchanged without interpreting it.
context must be a real pointer (or NULL). Don’t cast small integers like 1 or 2 to pointers to use as IDs: the SDK stores it internally as a pointer, and a value below 4096 is treated as an invalid pointer and terminates the process immediately. If you need an ID, pass the address of memory that holds it.
Callbacks run on internal SDK threads. Keep three things in mind:
  1. Different callbacks can fire concurrently, so protect shared state yourself
  2. Don’t do slow work in callbacks, or you’ll block the SDK event loop; queue slow processing and hand it to your own threads
  3. Pointers in callback parameters (data, props, content_json, speakers, etc.) are only valid during the callback; copy them right away if you need to keep them

rtc_set_connection_callback

Connection state changes. state: 0=connecting, 1=connected, 2=disconnected, 3=reconnecting.

rtc_set_disconnected_callback

Fires once when the instance finally leaves the channel (at the same moment as state=2 in the connection state callback, and before it), with the disconnect reason (since 0.0.9).
Use it to decide whether to rejoin automatically: don’t rejoin automatically when removed from the channel (KICKED), replaced by another session with the same uid (REPLACE), or when the channel is destroyed (DESTROY); in cases such as a heartbeat timeout (TIMEOUT), you can rejoin with a newly issued token.

rtc_set_user_event_callback

Users joining and leaving the channel. event_type: 0=joined, 1=left.

rtc_set_track_event_callback

Remote tracks added, updated, or removed. event_type: 0=added, 1=updated, 2=removed. With manual subscription, use this callback to discover tracks you can subscribe to.

rtc_set_track_sample_callback

Media data for subscribed tracks. Every subscribed track (including composite streams) comes out of this single callback; use user_info->uid + track_info->track_id to tell the sources apart. data is a complete encoded frame (one frame for video, one encoded packet for audio). The pointer is only valid during the callback:

rtc_set_custom_msg_callback

In-channel custom messages; see Custom messages.

SeaStart-only callbacks

The following three callbacks only fire when the channel uses the SeaStart engine; with other engines they’re never called. See SeaStart advanced features.

Typical call order