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

Server-side H.265 decoding pipeline for multi-client streams. More...

Go to the source code of this file.

Typedefs

typedef struct h265_server_client h265_server_client_t

Functions

h265_server_context_t * h265_server_context_create (void)
void h265_server_context_destroy (h265_server_context_t *ctx)
h265_server_client_t * h265_server_get_client_decoder (h265_server_context_t *ctx, uint32_t client_id)
asciichat_error_t h265_server_decode_and_convert (h265_server_client_t *client, const uint8_t *h265_packet, size_t packet_size, uint8_t *output_rgba, uint16_t *output_width, uint16_t *output_height, size_t *output_size)
void h265_server_remove_client (h265_server_context_t *ctx, uint32_t client_id)
void h265_server_client_get_stats (h265_server_client_t *client, uint64_t *total_frames, uint64_t *keyframes, uint16_t *last_width, uint16_t *last_height)

Detailed Description

Server-side H.265 decoding pipeline for multi-client streams.

The server maintains a separate H.265 decoder for each connected client. When a client sends an H.265-encoded frame, the server:

  1. Identifies the decoder for that client
  2. Decodes the H.265 frame to ASCII art
  3. Converts ASCII art to RGBA pixels for compositing
  4. Adds the RGBA frame to the compositing pipeline

Definition in file src/session/h265/server.h.

Typedef Documentation

◆ h265_server_client_t

typedef struct h265_server_client h265_server_client_t

Definition at line 20 of file src/session/h265/server.h.

Function Documentation

◆ h265_server_client_get_stats()

void h265_server_client_get_stats ( h265_server_client_t * client,
uint64_t * total_frames,
uint64_t * keyframes,
uint16_t * last_width,
uint16_t * last_height )

Get statistics for a client's decoder

Parameters
clientClient decoder
total_framesOutput: total frames decoded
keyframesOutput: total keyframes decoded
last_widthOutput: width of last decoded frame
last_heightOutput: height of last decoded frame

Definition at line 167 of file src/session/h265/server.c.

168 {
169 if (!client)
170 return;
171
172 h265_client_decoder_t *client_dec = (h265_client_decoder_t *)client;
173 if (!client_dec->decoder)
174 return;
175
176 h265_decoder_get_stats(client_dec->decoder, total_frames, keyframes, last_width, last_height);
177}
void h265_decoder_get_stats(h265_decoder_t *decoder, uint64_t *total_frames, uint64_t *keyframes, uint16_t *last_width, uint16_t *last_height)

References h265_client_decoder_t::decoder, and h265_decoder_get_stats().

◆ h265_server_context_create()

h265_server_context_t * h265_server_context_create ( void )

Create a server-side H.265 decoding context Manages decoders for all connected clients

Returns
Context handle, or NULL on error

Definition at line 41 of file src/session/h265/server.c.

41 {
43 if (!ctx) {
44 SET_ERRNO(ERROR_MEMORY, "Failed to allocate server context");
45 return NULL;
46 }
47
48 for (int i = 0; i < MAX_CLIENTS; i++) {
49 ctx->clients[i].in_use = false;
50 }
51 ctx->active_client_count = 0;
52
53 log_info("H.265 server context created (max %d clients)", MAX_CLIENTS);
54 return ctx;
55}
#define SET_ERRNO(code,...)
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
@ ERROR_MEMORY
Definition error_codes.h:51
#define MAX_CLIENTS
Maximum possible clients (static array size) - actual runtime limit set by –max-clients (1-128).
#define log_info(...)
Log an INFO message.
Definition log/log.h:608
struct h265_server_context h265_server_context_t
The useful part of h265 client decoder is in client_id, decoder, last_width, last_height: together th...
h265_client_decoder_t clients[MAX_CLIENTS]

References h265_server_context::active_client_count, h265_server_context::clients, ERROR_MEMORY, h265_client_decoder_t::in_use, log_info, MAX_CLIENTS, SAFE_CALLOC, and SET_ERRNO.

◆ h265_server_context_destroy()

void h265_server_context_destroy ( h265_server_context_t * ctx)

Destroy the server context and all client decoders

Parameters
ctxContext to destroy (may be NULL)

Definition at line 57 of file src/session/h265/server.c.

57 {
58 if (!ctx)
59 return;
60
61 for (int i = 0; i < MAX_CLIENTS; i++) {
62 if (ctx->clients[i].in_use && ctx->clients[i].decoder) {
64 }
65 }
66 SAFE_FREE(ctx);
67}
#define SAFE_FREE(ptr)
Definition common.h:377
void h265_decoder_destroy(h265_decoder_t *decoder)

References h265_server_context::clients, h265_client_decoder_t::decoder, h265_decoder_destroy(), h265_client_decoder_t::in_use, MAX_CLIENTS, and SAFE_FREE.

◆ h265_server_decode_and_convert()

asciichat_error_t h265_server_decode_and_convert ( h265_server_client_t * client,
const uint8_t * h265_packet,
size_t packet_size,
uint8_t * output_rgba,
uint16_t * output_width,
uint16_t * output_height,
size_t * output_size )

Decode an H.265 frame from a client and convert to RGBA

Parameters
clientClient decoder handle
h265_packetH.265 encoded packet data (with header)
packet_sizeSize of packet
output_rgbaOutput buffer for RGBA pixel data
output_widthOutput: frame width in pixels
output_heightOutput: frame height in pixels
output_sizeInput: buffer size, Output: actual RGBA size (width*height*4)
Returns
Error code (ASCIICHAT_OK on success)

RGBA conversion: Each ASCII character (0-255) becomes a grayscale pixel where pixel = (ascii_val, ascii_val, ascii_val, 255)

Definition at line 105 of file src/session/h265/server.c.

107 {
108 if (!client || !h265_packet || !output_rgba || !output_width || !output_height || !output_size) {
109 return SET_ERRNO(ERROR_INTERNAL, "Invalid arguments to decode_and_convert");
110 }
111
112 h265_client_decoder_t *client_dec = (h265_client_decoder_t *)client;
113 if (!client_dec->decoder || !client_dec->in_use) {
114 return SET_ERRNO(ERROR_INTERNAL, "Invalid client decoder state");
115 }
116
118 size_t ascii_size = sizeof(ascii_buf);
119
120 asciichat_error_t result =
121 h265_decode(client_dec->decoder, h265_packet, packet_size, output_width, output_height, ascii_buf, &ascii_size);
122
123 if (result != ASCIICHAT_OK) {
124 return result;
125 }
126
127 size_t required_rgba_size = (size_t)(*output_width) * (*output_height) * 4;
128 if (*output_size < required_rgba_size) {
129 *output_size = required_rgba_size;
130 return SET_ERRNO(ERROR_NETWORK_SIZE, "Output buffer too small: need %zu, have %zu", required_rgba_size,
131 *output_size);
132 }
133
134 for (size_t i = 0; i < ascii_size && i < (size_t)(*output_width) * (*output_height); i++) {
135 uint8_t val = ascii_buf[i];
136 output_rgba[i * 4 + 0] = val;
137 output_rgba[i * 4 + 1] = val;
138 output_rgba[i * 4 + 2] = val;
139 output_rgba[i * 4 + 3] = 255;
140 }
141
142 *output_size = required_rgba_size;
143 client_dec->last_width = *output_width;
144 client_dec->last_height = *output_height;
145
146 return ASCIICHAT_OK;
147}
unsigned char uint8_t
Definition common.h:60
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_NETWORK_SIZE
Definition error_codes.h:77
@ ERROR_INTERNAL
Definition error_codes.h:87
#define H265_ASCII_SCRATCH_ROWS
#define H265_ASCII_SCRATCH_COLUMNS
asciichat_error_t h265_decode(h265_decoder_t *decoder, const uint8_t *encoded_packet, size_t packet_size, uint16_t *output_width, uint16_t *output_height, uint8_t *output_buf, size_t *output_size)

References ASCIICHAT_OK, h265_client_decoder_t::decoder, ERROR_INTERNAL, ERROR_NETWORK_SIZE, H265_ASCII_SCRATCH_COLUMNS, H265_ASCII_SCRATCH_ROWS, h265_decode(), h265_client_decoder_t::in_use, h265_client_decoder_t::last_height, h265_client_decoder_t::last_width, and SET_ERRNO.

Referenced by handle_image_frame_h265_packet().

◆ h265_server_get_client_decoder()

h265_server_client_t * h265_server_get_client_decoder ( h265_server_context_t * ctx,
uint32_t client_id )

Get or create a client decoder within the server context Each client gets its own H.265 decoder instance

Parameters
ctxServer context
client_idUnique client identifier
Returns
Client decoder handle, or NULL on error

Definition at line 69 of file src/session/h265/server.c.

69 {
70 if (!ctx) {
71 SET_ERRNO(ERROR_INTERNAL, "Invalid server context");
72 return NULL;
73 }
74
75 for (int i = 0; i < MAX_CLIENTS; i++) {
76 if (ctx->clients[i].in_use && ctx->clients[i].client_id == client_id) {
77 return (h265_server_client_t *)&ctx->clients[i];
78 }
79 }
80
81 for (int i = 0; i < MAX_CLIENTS; i++) {
82 if (!ctx->clients[i].in_use) {
84 if (!decoder) {
85 SET_ERRNO(ERROR_MEDIA_INIT, "Failed to create decoder for client %u", client_id);
86 return NULL;
87 }
88
89 ctx->clients[i].client_id = client_id;
90 ctx->clients[i].decoder = decoder;
91 ctx->clients[i].in_use = true;
92 ctx->clients[i].last_width = 0;
93 ctx->clients[i].last_height = 0;
95
96 log_debug("Created H.265 decoder for client %u", client_id);
97 return (h265_server_client_t *)&ctx->clients[i];
98 }
99 }
100
101 SET_ERRNO(ERROR_INTERNAL, "No free decoder slots (max %d clients)", MAX_CLIENTS);
102 return NULL;
103}
@ ERROR_MEDIA_INIT
Definition error_codes.h:65
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:595
struct h265_server_client h265_server_client_t
struct h265_decoder h265_decoder_t
h265_decoder_t * h265_decoder_create(void)

References h265_server_context::active_client_count, h265_client_decoder_t::client_id, h265_server_context::clients, h265_client_decoder_t::decoder, ERROR_INTERNAL, ERROR_MEDIA_INIT, h265_decoder_create(), h265_client_decoder_t::in_use, h265_client_decoder_t::last_height, h265_client_decoder_t::last_width, log_debug, MAX_CLIENTS, and SET_ERRNO.

Referenced by handle_image_frame_h265_packet().

◆ h265_server_remove_client()

void h265_server_remove_client ( h265_server_context_t * ctx,
uint32_t client_id )

Remove a client decoder (when client disconnects)

Parameters
ctxServer context
client_idClient identifier

Definition at line 149 of file src/session/h265/server.c.

149 {
150 if (!ctx)
151 return;
152
153 for (int i = 0; i < MAX_CLIENTS; i++) {
154 if (ctx->clients[i].in_use && ctx->clients[i].client_id == client_id) {
155 if (ctx->clients[i].decoder) {
157 ctx->clients[i].decoder = NULL;
158 }
159 ctx->clients[i].in_use = false;
160 ctx->active_client_count--;
161 log_debug("Removed H.265 decoder for client %u", client_id);
162 return;
163 }
164 }
165}

References h265_server_context::active_client_count, h265_client_decoder_t::client_id, h265_server_context::clients, h265_client_decoder_t::decoder, h265_decoder_destroy(), h265_client_decoder_t::in_use, log_debug, and MAX_CLIENTS.