34 uint32_t original_size, uint32_t compressed_size) {
39 SET_ERRNO(ERROR_NETWORK_SIZE,
"Frame size exceeds maximum: %s (max %d MB)", size_str,
45 char *frame_data = SAFE_MALLOC(original_size + 1,
char *);
47 SET_ERRNO(ERROR_MEMORY,
"Failed to allocate %u bytes for frame decode", original_size);
53 if (frame_data_len != compressed_size) {
54 SET_ERRNO(ERROR_NETWORK_SIZE,
"Compressed frame size mismatch: expected %u, got %zu", compressed_size,
56 SAFE_FREE(frame_data);
61 asciichat_error_t decompress_result =
decompress_data(frame_data_ptr, frame_data_len, frame_data, original_size);
63 if (decompress_result != ASCIICHAT_OK) {
64 SET_ERRNO(ERROR_COMPRESSION,
"Decompression failed for expected size %u: %s", original_size,
65 asciichat_error_string(decompress_result));
66 SAFE_FREE(frame_data);
70 log_debug(
"Decompressed frame: %zu -> %u bytes", frame_data_len, original_size);
73 if (frame_data_len != original_size) {
74 log_error(
"Uncompressed frame size mismatch: expected %u, got %zu", original_size, frame_data_len);
75 SAFE_FREE(frame_data);
80 size_t copy_size = (frame_data_len > original_size) ? original_size : frame_data_len;
81 memcpy(frame_data, frame_data_ptr, copy_size);
85 frame_data[original_size] =
'\0';
90 void *output_buffer,
size_t output_size, uint32_t original_size,
91 uint32_t compressed_size) {
92 if (!frame_data_ptr || !output_buffer) {
93 return SET_ERRNO(ERROR_INVALID_PARAM,
"NULL pointer in frame decode");
96 if (output_size < original_size) {
97 return SET_ERRNO(ERROR_BUFFER_FULL,
"Output buffer too small: %zu < %u", output_size, original_size);
102 if (frame_data_len != compressed_size) {
103 return SET_ERRNO(ERROR_NETWORK_SIZE,
"Compressed frame size mismatch: expected %u, got %zu", compressed_size,
108 asciichat_error_t decompress_result =
decompress_data(frame_data_ptr, frame_data_len, output_buffer, original_size);
110 if (decompress_result != ASCIICHAT_OK) {
111 return SET_ERRNO(ERROR_COMPRESSION,
"Decompression failed for expected size %u: %s", original_size,
112 asciichat_error_string(decompress_result));
115 log_debug(
"Decompressed frame to buffer: %zu -> %u bytes", frame_data_len, original_size);
118 if (frame_data_len != original_size) {
119 return SET_ERRNO(ERROR_NETWORK_SIZE,
"Uncompressed frame size mismatch: expected %u, got %zu", original_size,
124 memcpy(output_buffer, frame_data_ptr, original_size);
132 return SET_ERRNO(ERROR_INVALID_PARAM,
"out_rgb_size pointer is NULL");
136 if (width == 0 || height == 0) {
137 return SET_ERRNO(ERROR_INVALID_STATE,
"Frame dimensions cannot be zero: %ux%u", width, height);
142 return SET_ERRNO(ERROR_INVALID_STATE,
"Frame dimensions exceed maximum: %ux%u (max %u)", width, height,
147 size_t pixel_count = 0;
148 if (safe_size_mul(width, height, &pixel_count) != 0) {
149 return SET_ERRNO(ERROR_MEMORY,
"Frame dimension multiplication overflow: %u * %u", width, height);
153 if (safe_size_mul(pixel_count, 3, &rgb_size) != 0) {
154 return SET_ERRNO(ERROR_MEMORY,
"RGB buffer size overflow: %zu * 3", pixel_count);
161 return SET_ERRNO(ERROR_MEMORY,
"Frame buffer size exceeds maximum: %s (max %d MB)", size_str,
165 *out_rgb_size = rgb_size;
174 size_t *out_opus_size,
const uint16_t **out_frame_sizes,
int *out_sample_rate,
175 int *out_frame_duration,
int *out_frame_count) {
176 if (!packet_data || !out_opus_data || !out_opus_size || !out_frame_sizes || !out_sample_rate || !out_frame_duration ||
178 return SET_ERRNO(ERROR_INVALID_PARAM,
"NULL parameter in Opus batch parsing");
182 const size_t header_size = 16;
183 if (packet_len < header_size) {
184 return SET_ERRNO(ERROR_NETWORK_PROTOCOL,
"Opus batch packet too small: %zu < %zu", packet_len, header_size);
188 const uint8_t *buf = (
const uint8_t *)packet_data;
191 memcpy(&fd, buf + 4, 4);
192 memcpy(&fc, buf + 8, 4);
193 *out_sample_rate = (int)NET_TO_HOST_U32(sr);
194 *out_frame_duration = (int)NET_TO_HOST_U32(fd);
195 int frame_count = (int)NET_TO_HOST_U32(fc);
196 *out_frame_count = frame_count;
199 if (frame_count < 0 || frame_count > 1000) {
200 return SET_ERRNO(ERROR_NETWORK_PROTOCOL,
"Invalid Opus frame count: %d (must be 0-1000)", frame_count);
204 size_t frame_sizes_bytes = (size_t)frame_count *
sizeof(uint16_t);
205 if (packet_len < header_size + frame_sizes_bytes) {
206 return SET_ERRNO(ERROR_NETWORK_PROTOCOL,
"Opus batch packet too small for frame sizes: %zu < %zu", packet_len,
207 header_size + frame_sizes_bytes);
210 *out_frame_sizes = (
const uint16_t *)(buf + header_size);
213 *out_opus_data = buf + header_size + frame_sizes_bytes;
214 *out_opus_size = packet_len - header_size - frame_sizes_bytes;
asciichat_error_t packet_parse_opus_batch(const void *packet_data, size_t packet_len, const uint8_t **out_opus_data, size_t *out_opus_size, const uint16_t **out_frame_sizes, int *out_sample_rate, int *out_frame_duration, int *out_frame_count)
asciichat_error_t packet_decode_frame_data_buffer(const char *frame_data_ptr, size_t frame_data_len, bool is_compressed, void *output_buffer, size_t output_size, uint32_t original_size, uint32_t compressed_size)