ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
server.c File Reference

Server-side H.265 decoding pipeline. More...

Go to the source code of this file.

Data Structures

struct  h265_client_decoder_t
 
struct  h265_server_context
 

Typedefs

typedef struct h265_server_context h265_server_context_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.

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

Typedef Documentation

◆ h265_server_context_t

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 153 of file src/session/h265/server.c.

154 {
155 if (!client)
156 return;
157
158 h265_client_decoder_t *client_dec = (h265_client_decoder_t *)client;
159 if (!client_dec->decoder)
160 return;
161
162 h265_decoder_get_stats(client_dec->decoder, total_frames, keyframes, last_width, last_height);
163}
void h265_decoder_get_stats(h265_decoder_t *decoder, uint64_t *total_frames, uint64_t *keyframes, uint16_t *last_width, uint16_t *last_height)
Definition decoder.c:187

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 27 of file src/session/h265/server.c.

27 {
29 if (!ctx) {
30 SET_ERRNO(ERROR_MEMORY, "Failed to allocate server context");
31 return NULL;
32 }
33
34 for (int i = 0; i < MAX_CLIENTS; i++) {
35 ctx->clients[i].in_use = false;
36 }
37 ctx->active_client_count = 0;
38
39 log_info("H.265 server context created (max %d clients)", MAX_CLIENTS);
40 return ctx;
41}
#define SAFE_CALLOC(count, size, cast)
Definition common.h:274
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
@ ERROR_MEMORY
Definition error_codes.h:56
#define MAX_CLIENTS
Maximum possible clients (static array size) - actual runtime limit set by –max-clients (1-32)
Definition limits.h:26
#define log_info(...)
Log an INFO message.
Definition log/log.h:561
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 43 of file src/session/h265/server.c.

43 {
44 if (!ctx)
45 return;
46
47 for (int i = 0; i < MAX_CLIENTS; i++) {
48 if (ctx->clients[i].in_use && ctx->clients[i].decoder) {
50 }
51 }
52 SAFE_FREE(ctx);
53}
void h265_decoder_destroy(h265_decoder_t *decoder)
Definition decoder.c:90
#define SAFE_FREE(ptr)
Definition common.h:376

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 91 of file src/session/h265/server.c.

93 {
94 if (!client || !h265_packet || !output_rgba || !output_width || !output_height || !output_size) {
95 return SET_ERRNO(ERROR_INTERNAL, "Invalid arguments to decode_and_convert");
96 }
97
98 h265_client_decoder_t *client_dec = (h265_client_decoder_t *)client;
99 if (!client_dec->decoder || !client_dec->in_use) {
100 return SET_ERRNO(ERROR_INTERNAL, "Invalid client decoder state");
101 }
102
103 uint8_t ascii_buf[256 * 64];
104 size_t ascii_size = sizeof(ascii_buf);
105
106 asciichat_error_t result =
107 h265_decode(client_dec->decoder, h265_packet, packet_size, output_width, output_height, ascii_buf, &ascii_size);
108
109 if (result != ASCIICHAT_OK) {
110 return result;
111 }
112
113 size_t required_rgba_size = (size_t)(*output_width) * (*output_height) * 4;
114 if (*output_size < required_rgba_size) {
115 *output_size = required_rgba_size;
116 return SET_ERRNO(ERROR_NETWORK_SIZE, "Output buffer too small: need %zu, have %zu", required_rgba_size,
117 *output_size);
118 }
119
120 for (size_t i = 0; i < ascii_size && i < (size_t)(*output_width) * (*output_height); i++) {
121 uint8_t val = ascii_buf[i];
122 output_rgba[i * 4 + 0] = val;
123 output_rgba[i * 4 + 1] = val;
124 output_rgba[i * 4 + 2] = val;
125 output_rgba[i * 4 + 3] = 255;
126 }
127
128 *output_size = required_rgba_size;
129 client_dec->last_width = *output_width;
130 client_dec->last_height = *output_height;
131
132 return ASCIICHAT_OK;
133}
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)
Definition decoder.c:109
unsigned char uint8_t
Definition common.h:56
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_NETWORK_SIZE
Definition error_codes.h:82
@ ERROR_INTERNAL
Definition error_codes.h:92

References ASCIICHAT_OK, h265_client_decoder_t::decoder, ERROR_INTERNAL, ERROR_NETWORK_SIZE, 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 55 of file src/session/h265/server.c.

55 {
56 if (!ctx) {
57 SET_ERRNO(ERROR_INTERNAL, "Invalid server context");
58 return NULL;
59 }
60
61 for (int i = 0; i < MAX_CLIENTS; i++) {
62 if (ctx->clients[i].in_use && ctx->clients[i].client_id == client_id) {
63 return (h265_server_client_t *)&ctx->clients[i];
64 }
65 }
66
67 for (int i = 0; i < MAX_CLIENTS; i++) {
68 if (!ctx->clients[i].in_use) {
70 if (!decoder) {
71 SET_ERRNO(ERROR_MEDIA_INIT, "Failed to create decoder for client %u", client_id);
72 return NULL;
73 }
74
75 ctx->clients[i].client_id = client_id;
76 ctx->clients[i].decoder = decoder;
77 ctx->clients[i].in_use = true;
78 ctx->clients[i].last_width = 0;
79 ctx->clients[i].last_height = 0;
81
82 log_debug("Created H.265 decoder for client %u", client_id);
83 return (h265_server_client_t *)&ctx->clients[i];
84 }
85 }
86
87 SET_ERRNO(ERROR_INTERNAL, "No free decoder slots (max %d clients)", MAX_CLIENTS);
88 return NULL;
89}
h265_decoder_t * h265_decoder_create(void)
Definition decoder.c:31
@ ERROR_MEDIA_INIT
Definition error_codes.h:70
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
struct h265_server_client h265_server_client_t

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 135 of file src/session/h265/server.c.

135 {
136 if (!ctx)
137 return;
138
139 for (int i = 0; i < MAX_CLIENTS; i++) {
140 if (ctx->clients[i].in_use && ctx->clients[i].client_id == client_id) {
141 if (ctx->clients[i].decoder) {
143 ctx->clients[i].decoder = NULL;
144 }
145 ctx->clients[i].in_use = false;
146 ctx->active_client_count--;
147 log_debug("Removed H.265 decoder for client %u", client_id);
148 return;
149 }
150 }
151}

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.