Files
utun2/tests/test_call_video_port.c
T

83 lines
4.4 KiB
C

/* Реальные mailbox/mutex/post: частичная передача, повторная занятость, конкурентный producer и отмена. */
#define call_video_send_frame test_video_send
#define call_video_configure test_video_configure
#define call_session_find test_session_find
#define chat_setting_get test_setting_get
#include "../src/call/call_video_port.c"
#undef call_video_send_frame
#undef call_video_configure
#undef call_session_find
#undef chat_setting_get
#include <assert.h>
static struct call_session session;
static const struct call_video_ops *callbacks;
static void *callback_arg;
static unsigned accepted, allowance, offered;
static int concurrent;
static struct call_video_frame extra;
struct call_session *test_session_find(struct call_ctx *ctx, uint64_t id) {
return ctx == session.ctx && id == session.call_id ? &session : NULL;
}
const char *test_setting_get(struct UTUN_INSTANCE *inst, const char *name) {
(void)inst; (void)name; return "300:4000";
}
int test_video_configure(struct UTUN_INSTANCE *inst, uint64_t id, const struct call_video_caps *caps,
const struct call_video_ops *ops, void *arg) {
(void)inst; (void)id; (void)caps; callbacks = ops; callback_arg = arg; return 0;
}
int test_video_send(struct UTUN_INSTANCE *inst, const struct call_video_frame *f) {
(void)inst; offered++;
if (concurrent) { assert(call_video_port_send(&extra, 1) == 0); concurrent = 0; }
if (accepted == allowance) return 0;
assert(f->frame_id == accepted + 1 && f->pts_us == (int64_t)f->frame_id * 33333);
assert(f->size == 16);
for (unsigned i = 0; i < f->size; ++i) assert(f->data[i] == f->frame_id);
accepted++; return 1;
}
int main(void) {
debug_config_init(); debug_set_level(DEBUG_LEVEL_INFO);
struct UASYNC *ua = uasync_create(); assert(ua);
struct UTUN_INSTANCE inst = {.ua = ua}; struct call_ctx ctx = {.inst = &inst}; inst.call = &ctx;
session = (struct call_session){.ctx = &ctx, .call_id = 7, .state = CALL_ST_ACTIVE};
assert(!call_video_port_attach(&inst));
struct call_video_caps caps = {0};
assert(!call_video_port_open(7, &caps)); uasync_poll(ua, 0);
assert(callbacks && callbacks->writable); callbacks->writable(callback_arg, 1);
uint8_t data[8][16]; struct call_video_frame frames[8];
for (unsigned i = 0; i < 8; ++i) {
memset(data[i], i + 1, sizeof(data[i]));
frames[i] = (struct call_video_frame){.call_id = 7, .frame_id = i + 1, .pts_us = (i + 1) * 33333,
.format = {1, 640, 480, 30, 0, CALL_VIDEO_H264, 31, 4000000, CALL_VIDEO_BASELINE},
.size = 16, .length = 16, .data = data[i]};
}
extra = frames[7]; concurrent = 1; allowance = 2;
assert(call_video_port_send(frames, 8) == 1);
memset(data, 0, sizeof(data)); // Порт обязан владеть собственной копией.
uasync_poll(ua, 0);
assert(accepted == 2 && port.tx_count == 6 && !port.tx_processing && !port.pending);
unsigned before = offered; uasync_poll(ua, 0); assert(offered == before); // Нет busy loop.
struct call_video_port_status status;
assert(!call_video_port_status(7, &status) && !status.can_encode && !status.key_serial);
for (unsigned i = 0; i < 3; ++i) {
callbacks->writable(callback_arg, 0); uasync_poll(ua, 0);
assert(accepted == 2 && port.tx_count == 6 && !port.pending);
}
allowance = 8; callbacks->writable(callback_arg, 1); uasync_poll(ua, 0);
assert(accepted == 8 && !port.tx_count);
assert(!call_video_port_status(7, &status) && status.can_encode && !status.key_serial);
DEBUG_INFO(DEBUG_CATEGORY_CALL, "PASS video port: all 8 frames preserved across partial send and repeated busy; no KEY or spin");
for (unsigned i = 0; i < 8; ++i) { assert(callbacks->receive_ready(callback_arg, 16)); callbacks->frame(callback_arg, &frames[i]); }
assert(!callbacks->receive_ready(callback_arg, 16));
for (unsigned i = 0; i < 8; ++i) {
struct call_video_frame f; assert(call_video_port_pull(7, &f) == 1 && f.frame_id == i + 1); u_free((void *)f.data);
assert(callbacks->receive_ready(callback_arg, 16) == (i == 7));
}
DEBUG_INFO(DEBUG_CATEGORY_CALL, "PASS video port: full RX drains completely before resuming producer admission");
call_video_port_close(7); uasync_poll(ua, 0);
call_video_port_detach(&inst); uasync_poll(ua, 0);
uasync_destroy(ua, 0); return 0;
}