ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
src/session/h265/server.c
Go to the documentation of this file.
1
5
6/* Existing buffer budgets in bytes, including NUL for text storage. */
7#define H265_ASCII_SCRATCH_COLUMNS 256
8#define H265_ASCII_SCRATCH_ROWS 64
9
10#include "server.h"
12#include <ascii-chat/common.h>
15#include <string.h>
16#include <stdlib.h>
17
27
40
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}
56
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}
68
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}
104
106 size_t packet_size, uint8_t *output_rgba, uint16_t *output_width,
107 uint16_t *output_height, size_t *output_size) {
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}
148
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}
166
168 uint16_t *last_width, uint16_t *last_height) {
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}
#define SET_ERRNO(code,...)
Application limits and constraints.
⚙️ Common definitions, error codes, macros, and types shared throughout the application
Named object registry for debugging — log identifiable resource names.
unsigned short uint16_t
Definition common.h:61
unsigned int uint32_t
Definition common.h:62
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
unsigned long long uint64_t
Definition common.h:63
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
@ ERROR_MEMORY
Definition error_codes.h:51
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_NETWORK_SIZE
Definition error_codes.h:77
@ ERROR_MEDIA_INIT
Definition error_codes.h:65
@ ERROR_INTERNAL
Definition error_codes.h:87
#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
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:595
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)
h265_server_context_t * h265_server_context_create(void)
void h265_server_context_destroy(h265_server_context_t *ctx)
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...
void h265_server_remove_client(h265_server_context_t *ctx, uint32_t client_id)
#define H265_ASCII_SCRATCH_ROWS
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)
#define H265_ASCII_SCRATCH_COLUMNS
h265_server_client_t * h265_server_get_client_decoder(h265_server_context_t *ctx, uint32_t client_id)
Server-side H.265 decoding pipeline for multi-client streams.
struct h265_server_client h265_server_client_t
🔤 String Manipulation and Shell Escaping Utilities
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]
void h265_decoder_destroy(h265_decoder_t *decoder)
struct h265_decoder h265_decoder_t
h265_decoder_t * h265_decoder_create(void)
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)
void h265_decoder_get_stats(h265_decoder_t *decoder, uint64_t *total_frames, uint64_t *keyframes, uint16_t *last_width, uint16_t *last_height)
HEVC/H.265 decoder for ASCII art frames using libde265.