Complete API documentation for RootStream's C library.
- Overview
- Data Types
- Initialization
- Cryptography
- Capture
- Encoding
- Decoding
- Network
- Audio
- Input
- Recording
- Utilities
Include the main header in your application:
#include <rootstream.h>Link with: -lrootstream (or compile source files directly)
- Most functions are not thread-safe
- Use a single
rootstream_ctx_tper thread - Network operations use internal locking
Main application context containing all state.
typedef struct {
keypair_t keypair; // Device identity
settings_t settings; // Configuration
display_info_t display; // Capture display info
frame_buffer_t current_frame;// Current video frame
encoder_ctx_t encoder; // Encoder state
peer_t peers[MAX_PEERS]; // Connected peers
int num_peers; // Peer count
recording_ctx_t recording; // Recording state
latency_stats_t latency; // Performance stats
bool running; // Main loop flag
} rootstream_ctx_t;Video frame data.
typedef struct {
uint8_t *data; // Pixel data (RGBA or encoded)
uint32_t size; // Data size in bytes
uint32_t width; // Frame width
uint32_t height; // Frame height
uint32_t pitch; // Bytes per row
uint32_t format; // Pixel format (DRM fourcc)
uint64_t timestamp; // Capture time (microseconds)
bool is_keyframe; // True for I-frames
} frame_buffer_t;Connected peer information.
typedef struct {
char rootstream_code[128]; // Peer's code
uint8_t public_key[32]; // Peer's public key
struct sockaddr_storage addr; // Network address
crypto_session_t session; // Encryption session
peer_state_t state; // Connection state
uint64_t last_seen; // Last packet time
char hostname[64]; // Peer hostname
bool is_streaming; // Stream active?
} peer_t;Video encoder configuration.
typedef struct {
encoder_type_t type; // ENCODER_VAAPI, ENCODER_NVENC
codec_type_t codec; // CODEC_H264, CODEC_H265
int device_fd; // Encoder device
void *hw_ctx; // Hardware context
uint32_t bitrate; // Target bitrate (bps)
uint32_t framerate; // Target FPS
uint8_t quality; // Quality level 0-100
bool low_latency; // Low-latency mode
bool force_keyframe; // Force next keyframe
} encoder_ctx_t;Initialize the RootStream context.
int rootstream_init(rootstream_ctx_t *ctx);Parameters:
ctx: Pointer to context structure (caller allocated)
Returns: 0 on success, -1 on error
Example:
rootstream_ctx_t ctx = {0};
if (rootstream_init(&ctx) < 0) {
fprintf(stderr, "Failed to initialize\n");
return 1;
}Clean up and release all resources.
void rootstream_cleanup(rootstream_ctx_t *ctx);Parameters:
ctx: Initialized context
Initialize the cryptographic subsystem.
int crypto_init(void);Returns: 0 on success, -1 on error
Note: Call once at program startup before other crypto functions.
Generate a new Ed25519 keypair.
int crypto_generate_keypair(keypair_t *kp, const char *hostname);Parameters:
kp: Output keypair structurehostname: Device hostname for identity
Returns: 0 on success, -1 on error
Load or save keypair to disk.
int crypto_load_keypair(keypair_t *kp, const char *config_dir);
int crypto_save_keypair(const keypair_t *kp, const char *config_dir);Parameters:
kp: Keypair structureconfig_dir: Configuration directory path
Create encrypted session with a peer.
int crypto_create_session(crypto_session_t *session,
const uint8_t *my_secret,
const uint8_t *peer_public);Parameters:
session: Output session structuremy_secret: Our 32-byte private keypeer_public: Peer's 32-byte public key
Returns: 0 on success, -1 on error
Encrypt or decrypt a packet.
int crypto_encrypt_packet(const crypto_session_t *session,
const void *plaintext, size_t plain_len,
void *ciphertext, size_t *cipher_len,
uint64_t nonce);
int crypto_decrypt_packet(const crypto_session_t *session,
const void *ciphertext, size_t cipher_len,
void *plaintext, size_t *plain_len,
uint64_t nonce);Parameters:
session: Established sessionplaintext/ciphertext: Data buffers*_len: Data lengthsnonce: Unique nonce (must never repeat)
Returns: 0 on success, -1 on error
Format a public key as a short fingerprint.
int crypto_format_fingerprint(const uint8_t *public_key, size_t key_len,
char *output, size_t output_len);Detect available displays.
int rootstream_detect_displays(display_info_t *displays, int max_displays);Returns: Number of displays found
Select a display for capture.
int rootstream_select_display(rootstream_ctx_t *ctx, int display_index);Initialize capture subsystem.
int rootstream_capture_init(rootstream_ctx_t *ctx);Capture a single frame.
int rootstream_capture_frame(rootstream_ctx_t *ctx, frame_buffer_t *frame);Parameters:
ctx: Context with display selectedframe: Output frame buffer
Returns: 0 on success, -1 on error
Clean up capture resources.
void rootstream_capture_cleanup(rootstream_ctx_t *ctx);Initialize hardware encoder.
int rootstream_encoder_init(rootstream_ctx_t *ctx,
encoder_type_t type,
codec_type_t codec);Parameters:
ctx: Contexttype:ENCODER_VAAPIorENCODER_NVENCcodec:CODEC_H264orCODEC_H265
Encode a captured frame.
int rootstream_encode_frame(rootstream_ctx_t *ctx, frame_buffer_t *in,
uint8_t *out, size_t *out_size);Parameters:
ctx: Initialized encoder contextin: Input RGBA frameout: Output buffer for encoded dataout_size: Output encoded size
Extended encode with keyframe detection.
int rootstream_encode_frame_ex(rootstream_ctx_t *ctx, frame_buffer_t *in,
uint8_t *out, size_t *out_size,
bool *is_keyframe);Additional Parameter:
is_keyframe: Output: true if encoded as keyframe
Clean up encoder.
void rootstream_encoder_cleanup(rootstream_ctx_t *ctx);Initialize hardware decoder.
int rootstream_decoder_init(rootstream_ctx_t *ctx);Decode an encoded frame.
int rootstream_decode_frame(rootstream_ctx_t *ctx,
const uint8_t *in, size_t in_size,
frame_buffer_t *out);Clean up decoder.
void rootstream_decoder_cleanup(rootstream_ctx_t *ctx);Initialize networking.
int rootstream_net_init(rootstream_ctx_t *ctx, uint16_t port);Send encrypted packet to peer.
int rootstream_net_send_encrypted(rootstream_ctx_t *ctx, peer_t *peer,
uint8_t type, const void *data,
size_t size);Packet Types:
PKT_VIDEO(0x02): Video framePKT_AUDIO(0x03): Audio framePKT_INPUT(0x04): Input eventsPKT_CONTROL(0x05): Control commands
Receive and process packets.
int rootstream_net_recv(rootstream_ctx_t *ctx, int timeout_ms);Parameters:
timeout_ms: Poll timeout (0 = non-blocking)
Connect to a peer by RootStream code.
int rootstream_connect_to_peer(rootstream_ctx_t *ctx, const char *code);int rootstream_send_control(rootstream_ctx_t *ctx, peer_t *peer,
control_cmd_t cmd, uint32_t value);
int rootstream_pause_stream(rootstream_ctx_t *ctx, peer_t *peer);
int rootstream_resume_stream(rootstream_ctx_t *ctx, peer_t *peer);
int rootstream_request_keyframe(rootstream_ctx_t *ctx, peer_t *peer);int rootstream_opus_encoder_init(rootstream_ctx_t *ctx);
int rootstream_opus_decoder_init(rootstream_ctx_t *ctx);
int rootstream_opus_encode(rootstream_ctx_t *ctx, const int16_t *pcm,
uint8_t *out, size_t *out_len);
int rootstream_opus_decode(rootstream_ctx_t *ctx, const uint8_t *in,
size_t in_len, int16_t *pcm, size_t *pcm_len);
void rootstream_opus_cleanup(rootstream_ctx_t *ctx);
int rootstream_opus_get_frame_size(void); // Returns 960
int rootstream_opus_get_sample_rate(void); // Returns 48000
int rootstream_opus_get_channels(void); // Returns 2int audio_capture_init(rootstream_ctx_t *ctx);
int audio_capture_frame(rootstream_ctx_t *ctx, int16_t *samples,
size_t *num_samples);
void audio_capture_cleanup(rootstream_ctx_t *ctx);int audio_playback_init(rootstream_ctx_t *ctx);
int audio_playback_write(rootstream_ctx_t *ctx, int16_t *samples,
size_t num_samples);
void audio_playback_cleanup(rootstream_ctx_t *ctx);Initialize virtual input devices.
int rootstream_input_init(rootstream_ctx_t *ctx);Process received input event.
int rootstream_input_process(rootstream_ctx_t *ctx, input_event_pkt_t *event);Clean up input devices.
void rootstream_input_cleanup(rootstream_ctx_t *ctx);Start recording to file.
int recording_init(rootstream_ctx_t *ctx, const char *filename);Write encoded frame to recording.
int recording_write_frame(rootstream_ctx_t *ctx, const uint8_t *data,
size_t size, bool is_keyframe);Close recording file.
void recording_cleanup(rootstream_ctx_t *ctx);uint64_t get_timestamp_ms(void); // Milliseconds (monotonic)
uint64_t get_timestamp_us(void); // Microseconds (monotonic)int latency_init(latency_stats_t *stats, size_t capacity,
uint64_t report_interval_ms, bool enabled);
void latency_cleanup(latency_stats_t *stats);
void latency_record(latency_stats_t *stats, const latency_sample_t *sample);const char* config_get_dir(void);
int config_load(rootstream_ctx_t *ctx);
int config_save(rootstream_ctx_t *ctx);
void config_add_peer_to_history(rootstream_ctx_t *ctx, const char *code);const char* rootstream_get_error(void); // Get last error message
void rootstream_print_stats(rootstream_ctx_t *ctx); // Print statistics#include <rootstream.h>
int main(void) {
rootstream_ctx_t ctx = {0};
// Initialize
crypto_init();
rootstream_init(&ctx);
rootstream_net_init(&ctx, 9876);
// Setup capture and encoding
rootstream_capture_init(&ctx);
rootstream_encoder_init(&ctx, ENCODER_VAAPI, CODEC_H264);
// Allocate encode buffer
uint8_t *enc_buf = malloc(ctx.display.width * ctx.display.height);
// Main loop
ctx.running = true;
while (ctx.running) {
// Capture
rootstream_capture_frame(&ctx, &ctx.current_frame);
// Encode
size_t enc_size = 0;
rootstream_encode_frame(&ctx, &ctx.current_frame, enc_buf, &enc_size);
// Send to peers
for (int i = 0; i < ctx.num_peers; i++) {
if (ctx.peers[i].is_streaming) {
rootstream_net_send_encrypted(&ctx, &ctx.peers[i],
PKT_VIDEO, enc_buf, enc_size);
}
}
// Process incoming
rootstream_net_recv(&ctx, 1);
}
// Cleanup
free(enc_buf);
rootstream_encoder_cleanup(&ctx);
rootstream_capture_cleanup(&ctx);
rootstream_cleanup(&ctx);
return 0;
}RootStream API Reference - Version 1.0