ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches

📹 Unified media capture implementation More...

Go to the source code of this file.

Data Structures

struct  session_capture_ctx
 Runtime state for media loading, frame timing, and source switching. More...

Macros

#define SESSION_CAPTURE_LOAD_PATH_BUFFER_SIZE   8192
#define SESSION_CAPTURE_LOAD_ERROR_BUFFER_SIZE   512
#define SESSION_CAPTURE_WEBCAM_INDEX_BUFFER_SIZE   32
#define SESSION_CAPTURE_ERROR_BUFFER_SIZE   512
#define SESSION_CAPTURE_PATH_BUFFER_SIZE   8192
#define SESSION_CAPTURE_FAILURE_BUFFER_SIZE   512
#define CAPTURE_TRACKER_NAME_BUFFER_SIZE   32
#define SESSION_MAX_FRAME_WIDTH   320
 Maximum frame width for network transmission (bandwidth optimization).
#define SESSION_MAX_FRAME_HEIGHT   180
 Maximum frame height for network transmission (bandwidth optimization).

Functions

session_capture_ctx_t * session_mirror_capture_create (const session_capture_config_t *config)
 Create a new session capture context.
session_capture_ctx_t * session_network_capture_create (uint32_t target_fps)
 Create network mode capture context without media source.
session_capture_ctx_t * session_capture_create (const session_capture_config_t *config)
 Legacy function - creates either mirror or network capture based on options.
void session_capture_destroy (session_capture_ctx_t *ctx)
 Destroy session capture context and free resources.
bool session_capture_cancel_open (session_capture_ctx_t *ctx)
asciichat_error_t session_capture_open_media (session_capture_ctx_t *ctx, const char *path)
asciichat_error_t session_capture_open_playlist (session_capture_ctx_t *ctx, const char *text)
void session_capture_skip_media (session_capture_ctx_t *ctx, int direction)
void session_capture_lock_source (session_capture_ctx_t *ctx)
void session_capture_unlock_source (session_capture_ctx_t *ctx)
image_t * session_capture_read_frame (session_capture_ctx_t *ctx)
 Read the next video frame from the capture source.
asciichat_error_t session_capture_process_for_transmission_into (session_capture_ctx_t *ctx, image_t *frame, image_t **output)
image_t * session_capture_process_for_transmission (session_capture_ctx_t *ctx, image_t *frame)
 Process a frame for network transmission (resize if needed).
void session_capture_sleep_for_fps (session_capture_ctx_t *ctx)
 Sleep to maintain target frame rate.
bool session_capture_at_end (session_capture_ctx_t *ctx)
 Check if capture source has reached end of stream.
bool session_capture_is_valid (session_capture_ctx_t *ctx)
 Check if capture context is initialized and valid.
double session_capture_get_current_fps (session_capture_ctx_t *ctx)
 Get the current FPS being achieved by the capture source.
uint32_t session_capture_get_target_fps (session_capture_ctx_t *ctx)
 Get the target FPS configured for this capture context.
bool session_capture_has_audio (session_capture_ctx_t *ctx)
 Check if capture source has audio available.
size_t session_capture_read_audio (session_capture_ctx_t *ctx, float *buffer, size_t num_samples)
 Read audio samples from capture source.
bool session_capture_using_file_audio (session_capture_ctx_t *ctx)
 Check if currently using file audio vs microphone fallback.
void * session_capture_get_media_source (session_capture_ctx_t *ctx)
 Get the underlying media source from capture context.
void * session_capture_get_audio_context (session_capture_ctx_t *ctx)
 Get the audio context for playback control.
void session_capture_set_audio_updater (session_capture_ctx_t *ctx, session_capture_audio_update_fn update, void *user_data)
void session_capture_set_audio_context (session_capture_ctx_t *ctx, void *audio_ctx)
 Set the audio context for playback control.
void session_capture_toggle_media (session_capture_ctx_t *ctx)
bool session_capture_media_active (session_capture_ctx_t *ctx)
void session_capture_redraw_media (session_capture_ctx_t *ctx)
uint64_t session_capture_source_epoch (session_capture_ctx_t *ctx)
uint64_t session_capture_frame_serial (session_capture_ctx_t *ctx)
void session_capture_complete_open (session_capture_ctx_t *ctx, uint64_t epoch)

Detailed Description

📹 Unified media capture implementation

Implements the session capture abstraction layer for unified media source handling across client, mirror, and discovery modes.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

Definition in file common/session/capture.c.

Macro Definition Documentation

◆ CAPTURE_TRACKER_NAME_BUFFER_SIZE

#define CAPTURE_TRACKER_NAME_BUFFER_SIZE   32

◆ SESSION_CAPTURE_ERROR_BUFFER_SIZE

#define SESSION_CAPTURE_ERROR_BUFFER_SIZE   512

Definition at line 6 of file common/session/capture.c.

◆ SESSION_CAPTURE_FAILURE_BUFFER_SIZE

#define SESSION_CAPTURE_FAILURE_BUFFER_SIZE   512

Definition at line 8 of file common/session/capture.c.

◆ SESSION_CAPTURE_LOAD_ERROR_BUFFER_SIZE

#define SESSION_CAPTURE_LOAD_ERROR_BUFFER_SIZE   512

Definition at line 4 of file common/session/capture.c.

◆ SESSION_CAPTURE_LOAD_PATH_BUFFER_SIZE

#define SESSION_CAPTURE_LOAD_PATH_BUFFER_SIZE   8192

Definition at line 3 of file common/session/capture.c.

◆ SESSION_CAPTURE_PATH_BUFFER_SIZE

#define SESSION_CAPTURE_PATH_BUFFER_SIZE   8192

Definition at line 7 of file common/session/capture.c.

◆ SESSION_CAPTURE_WEBCAM_INDEX_BUFFER_SIZE

#define SESSION_CAPTURE_WEBCAM_INDEX_BUFFER_SIZE   32

Definition at line 5 of file common/session/capture.c.

Referenced by session_capture_create().

◆ SESSION_MAX_FRAME_HEIGHT

#define SESSION_MAX_FRAME_HEIGHT   180

Maximum frame height for network transmission (bandwidth optimization).

Definition at line 65 of file common/session/capture.c.

Referenced by session_capture_process_for_transmission_into().

◆ SESSION_MAX_FRAME_WIDTH

#define SESSION_MAX_FRAME_WIDTH   320

Maximum frame width for network transmission (bandwidth optimization).

Definition at line 62 of file common/session/capture.c.

Referenced by session_capture_process_for_transmission_into().

Function Documentation

◆ session_capture_cancel_open()

bool session_capture_cancel_open ( session_capture_ctx_t * ctx)

Definition at line 603 of file common/session/capture.c.

603 {
604 if (!ctx || !ctx->media_locks_ready)
605 return false;
606 mutex_lock(&ctx->load_mutex);
607 bool busy = ctx->loader_created;
608 if (busy)
609 atomic_store_bool(&ctx->load_cancel, true);
610 mutex_unlock(&ctx->load_mutex);
611 if (busy)
613 return busy;
614}
void ui_controller_remove(ui_screen_t screen)
@ UI_SCREEN_RENDER_PROGRESS

References session_capture_ctx::load_cancel, session_capture_ctx::load_mutex, session_capture_ctx::loader_created, session_capture_ctx::media_locks_ready, ui_controller_remove(), and UI_SCREEN_RENDER_PROGRESS.

Referenced by session_handle_keyboard_input().

◆ session_capture_complete_open()

void session_capture_complete_open ( session_capture_ctx_t * ctx,
uint64_t epoch )

Reveal the committed source after its first frame has been published or transmitted.

Definition at line 1264 of file common/session/capture.c.

1264 {
1265 if (!ctx || !atomic_load_bool(&ctx->awaiting_presentation))
1266 return;
1267 mutex_lock(&ctx->load_mutex);
1268 if (epoch == session_capture_source_epoch(ctx) && atomic_exchange_bool(&ctx->awaiting_presentation, false))
1270 mutex_unlock(&ctx->load_mutex);
1271}
uint64_t session_capture_source_epoch(session_capture_ctx_t *ctx)

References session_capture_ctx::awaiting_presentation, session_capture_ctx::load_mutex, session_capture_source_epoch(), ui_controller_remove(), and UI_SCREEN_RENDER_PROGRESS.

Referenced by session_pipeline_run_main().

◆ session_capture_frame_serial()

uint64_t session_capture_frame_serial ( session_capture_ctx_t * ctx)

Definition at line 1261 of file common/session/capture.c.

1261 {
1262 return ctx ? atomic_load_u64(&ctx->frame_serial) : 0;
1263}

References session_capture_ctx::frame_serial.

◆ session_capture_get_audio_context()

void * session_capture_get_audio_context ( session_capture_ctx_t * ctx)

Get the audio context for playback control.

Parameters
ctxCapture context
Returns
Audio context pointer (borrowed, not owned) or NULL

Definition at line 1204 of file common/session/capture.c.

1204 {
1205 if (!ctx || !ctx->initialized) {
1206 return NULL;
1207 }
1208 return atomic_ptr_load(&ctx->audio_ctx);
1209}
bool initialized
Context has been successfully initialized.
atomic_ptr_t audio_ctx
Main audio context for playback (borrowed, not owned).

References session_capture_ctx::audio_ctx, and session_capture_ctx::initialized.

◆ session_capture_lock_source()

void session_capture_lock_source ( session_capture_ctx_t * ctx)

Serialize decoder controls with capture-owner replacement.

Definition at line 835 of file common/session/capture.c.

835 {
836 if (ctx && ctx->media_locks_ready)
837 mutex_lock(&ctx->source_mutex);
838}

References session_capture_ctx::media_locks_ready, and session_capture_ctx::source_mutex.

Referenced by session_capture_read_audio(), session_capture_read_frame(), session_capture_set_audio_context(), and session_handle_keyboard_input().

◆ session_capture_media_active()

bool session_capture_media_active ( session_capture_ctx_t * ctx)

Definition at line 1249 of file common/session/capture.c.

1249 {
1250 return ctx && !atomic_load_bool(&ctx->non_media_active);
1251}

References session_capture_ctx::non_media_active.

◆ session_capture_open_media()

asciichat_error_t session_capture_open_media ( session_capture_ctx_t * ctx,
const char * path )

Definition at line 651 of file common/session/capture.c.

651 {
652 ASCII_OTEL_SCOPE(SESSION_CAPTURE_OPEN_MEDIA);
653 media_playlist_t list = {0};
654 asciichat_error_t result = media_playlist_append(&list, path, path && strstr(path, "://") != NULL);
655 return result == ASCIICHAT_OK ? capture_load_playlist(ctx, &list, 0, false) : result;
656}
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ASCIICHAT_OK
Definition error_codes.h:46
#define ASCII_OTEL_SCOPE(id)
Definition otel.h:72
asciichat_error_t media_playlist_append(media_playlist_t *list, const char *path, bool url)
Definition playlist.c:7

References ASCII_OTEL_SCOPE, ASCIICHAT_OK, and media_playlist_append().

◆ session_capture_open_playlist()

asciichat_error_t session_capture_open_playlist ( session_capture_ctx_t * ctx,
const char * text )

Replace the current playlist with quoted paths or URLs.

Definition at line 657 of file common/session/capture.c.

657 {
658 ASCII_OTEL_SCOPE(SESSION_CAPTURE_OPEN_PLAYLIST);
659 media_playlist_t list = {0};
660 asciichat_error_t result = media_playlist_parse(text, &list);
661 return result == ASCIICHAT_OK ? capture_load_playlist(ctx, &list, 0, false) : result;
662}
asciichat_error_t media_playlist_parse(const char *text, media_playlist_t *list)
Definition playlist.c:32

References ASCII_OTEL_SCOPE, ASCIICHAT_OK, and media_playlist_parse().

Referenced by session_handle_keyboard_input().

◆ session_capture_process_for_transmission_into()

asciichat_error_t session_capture_process_for_transmission_into ( session_capture_ctx_t * ctx,
image_t * frame,
image_t ** output )

Reuse capture-worker-owned storage; preserves it on allocation failure. The caller destroys *output after capture joins. Input may equal *output.

Definition at line 1058 of file common/session/capture.c.

1059 {
1060 ASCII_OTEL_SCOPE(SESSION_CAPTURE_PROCESS_FOR_TRANSMISSION_INTO);
1061 if (!ctx || !frame || !output)
1062 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing transmission frame or workspace");
1063 ssize_t width = frame->w, height = frame->h;
1064 if (ctx->resize_for_network)
1065 calculate_optimal_dimensions(frame->w, frame->h, SESSION_MAX_FRAME_WIDTH, SESSION_MAX_FRAME_HEIGHT, &width,
1066 &height);
1067 if (!*output || (*output)->w != width || (*output)->h != height) {
1068 image_t *replacement = image_new(width, height);
1069 if (!replacement)
1070 return SET_ERRNO(ERROR_MEMORY, "Cannot reserve transmission image workspace");
1071 image_destroy(*output);
1072 *output = replacement;
1073 }
1074 if (frame != *output) {
1075 if (frame->w == width && frame->h == height)
1076 memcpy((*output)->pixels, frame->pixels, (size_t)width * (size_t)height * sizeof(rgb_pixel_t));
1077 else
1078 image_resize(frame, *output);
1079 }
1080 return ASCIICHAT_OK;
1081}
#define SET_ERRNO(code,...)
#define SESSION_MAX_FRAME_WIDTH
Maximum frame width for network transmission (bandwidth optimization).
#define SESSION_MAX_FRAME_HEIGHT
Maximum frame height for network transmission (bandwidth optimization).
unsigned int height
Definition fft.c:23
unsigned int width
Definition fft.c:23
@ ERROR_MEMORY
Definition error_codes.h:51
@ ERROR_INVALID_PARAM
void image_resize(const image_t *s, image_t *d)
Resize image using nearest-neighbor interpolation.
void image_destroy(image_t *image)
Destroy an image allocated with image_new().
image_t * image_new(size_t width, size_t height)
Create a new image with standard allocation.
SIMD-friendly storage for one RGB pixel. r, g, and b hold the color channels and padding keeps the la...
int w
Image width in pixels (must be > 0).
int h
Image height in pixels (must be > 0).
rgb_pixel_t * pixels
Pixel data array (width * height RGB pixels, row-major order).
bool resize_for_network
Whether to resize frames for network transmission.

References ASCII_OTEL_SCOPE, ASCIICHAT_OK, ERROR_INVALID_PARAM, ERROR_MEMORY, image_t::h, height, image_destroy(), image_new(), image_resize(), image_t::pixels, session_capture_ctx::resize_for_network, SESSION_MAX_FRAME_HEIGHT, SESSION_MAX_FRAME_WIDTH, SET_ERRNO, image_t::w, and width.

Referenced by session_capture_process_for_transmission().

◆ session_capture_redraw_media()

void session_capture_redraw_media ( session_capture_ctx_t * ctx)

Definition at line 1253 of file common/session/capture.c.

1253 {
1254 if (ctx)
1255 atomic_store_bool(&ctx->redraw_media, true);
1256}

References session_capture_ctx::redraw_media.

◆ session_capture_set_audio_context()

void session_capture_set_audio_context ( session_capture_ctx_t * ctx,
void * audio_ctx )

Set the audio context for playback control.

Parameters
ctxCapture context (must not be NULL)
audio_ctxAudio context pointer (borrowed, not owned)

Definition at line 1219 of file common/session/capture.c.

1219 {
1220 if (ctx) {
1222 atomic_ptr_store(&ctx->audio_ctx, audio_ctx);
1224 }
1225}
void session_capture_lock_source(session_capture_ctx_t *ctx)
void session_capture_unlock_source(session_capture_ctx_t *ctx)

References session_capture_ctx::audio_ctx, session_capture_lock_source(), and session_capture_unlock_source().

Referenced by client_protocol_start(), session_participant_start_audio(), and session_participant_stop_audio().

◆ session_capture_set_audio_updater()

void session_capture_set_audio_updater ( session_capture_ctx_t * ctx,
session_capture_audio_update_fn update,
void * user_data )

Definition at line 1211 of file common/session/capture.c.

1212 {
1213 if (ctx) {
1214 ctx->audio_update = update;
1215 ctx->audio_update_data = user_data;
1216 }
1217}
session_capture_audio_update_fn audio_update

References session_capture_ctx::audio_update, and session_capture_ctx::audio_update_data.

◆ session_capture_skip_media()

void session_capture_skip_media ( session_capture_ctx_t * ctx,
int direction )

Queue a relative playlist change on the capture owner.

Definition at line 663 of file common/session/capture.c.

663 {
664 ASCII_OTEL_SCOPE(SESSION_CAPTURE_SKIP_MEDIA);
665 if (ctx && (direction == -1 || direction == 1))
666 atomic_store_u64(&ctx->playlist_skip, direction > 0 ? 1 : 2);
667}

References ASCII_OTEL_SCOPE, and session_capture_ctx::playlist_skip.

Referenced by session_handle_keyboard_input().

◆ session_capture_source_epoch()

uint64_t session_capture_source_epoch ( session_capture_ctx_t * ctx)

Source identity and successful acquisition count; retained redraws do not advance the serial.

Definition at line 1258 of file common/session/capture.c.

1258 {
1259 return ctx ? atomic_load_u64(&ctx->source_epoch) : 0;
1260}

References session_capture_ctx::source_epoch.

Referenced by session_capture_complete_open(), and session_pipeline_run_main().

◆ session_capture_toggle_media()

void session_capture_toggle_media ( session_capture_ctx_t * ctx)

Request a source change on the capture thread.

Definition at line 1227 of file common/session/capture.c.

1227 {
1228 if (!ctx || !ctx->source || media_source_get_type(ctx->source) != MEDIA_SOURCE_FILE)
1229 return;
1230 // Swap UI preferences in input order so a following animation key applies to
1231 // the newly selected mode even before the capture thread switches devices.
1233 options_set_bool("media_input", !ctx->non_media_requested);
1234 if (ctx->non_media_requested) {
1235 options_set_bool("matrix_rain", ctx->saved_matrix);
1236 options_set_bool("waveform", ctx->saved_waveform);
1237 options_set_bool("fft", ctx->saved_fft);
1238 } else {
1239 ctx->saved_matrix = GET_OPTION(matrix_rain);
1240 ctx->saved_waveform = GET_OPTION(waveform);
1241 ctx->saved_fft = GET_OPTION(fft);
1242 options_set_bool("matrix_rain", false);
1243 options_set_bool("waveform", false);
1244 options_set_bool("fft", false);
1245 }
1246 atomic_fetch_add_u64(&ctx->toggle_media, 1);
1247}
media_source_type_t media_source_get_type(media_source_t *source)
Get media source type.
Definition source.c:999
@ MEDIA_SOURCE_FILE
Media file (video/audio).
Definition source.h:99
#define GET_OPTION(field)
Safely get a specific option field (lock-free read).
Definition options.h:1336
asciichat_error_t options_set_bool(const char *name, bool value)
Definition rcu.c:902
media_source_t * source
Underlying media source (webcam, file, stdin, test).

References GET_OPTION, MEDIA_SOURCE_FILE, media_source_get_type(), session_capture_ctx::non_media_requested, options_set_bool(), session_capture_ctx::saved_fft, session_capture_ctx::saved_matrix, session_capture_ctx::saved_waveform, session_capture_ctx::source, and session_capture_ctx::toggle_media.

◆ session_capture_unlock_source()

void session_capture_unlock_source ( session_capture_ctx_t * ctx)