#include "av_test_support.hh" #include #include #include #include "../toxcore/os_memory.h" // Mock Time uint64_t mock_time_cb(void *ud) { return static_cast(ud)->t; } // RTP Mock int RtpMock::send_packet(void *user_data, const uint8_t *data, uint16_t length) { auto *self = static_cast(user_data); if (self->capture_packets) { if (self->store_last_packet_only) { if (self->captured_packets.empty()) { self->captured_packets.emplace_back(data, data + length); } else { self->captured_packets[0].assign(data, data + length); } } else { self->captured_packets.push_back(std::vector(data, data + length)); } } if (self->auto_forward && self->recv_session) { rtp_receive_packet(self->recv_session, data, length); } return 0; } int RtpMock::audio_cb(const Mono_Time *mono_time, void *cs, RTPMessage *msg) { return ac_queue_message(mono_time, cs, msg); } int RtpMock::video_cb(const Mono_Time *mono_time, void *cs, RTPMessage *msg) { return vc_queue_message(mono_time, cs, msg); } int RtpMock::noop_cb(const Mono_Time * /*mono_time*/, void * /*cs*/, RTPMessage *msg) { std::free(msg); return 0; } // Audio Helpers void fill_audio_frame(uint32_t sampling_rate, uint8_t channels, int frame_index, size_t sample_count, std::vector &pcm) { const double pi = std::acos(-1.0); double amplitude = 10000.0; for (size_t i = 0; i < sample_count; ++i) { double t = static_cast(frame_index * sample_count + i) / sampling_rate; // Linear frequency sweep from 50Hz to 440Hz over 1 second (50 frames) // f(t) = 50 + 390t // phi(t) = 2*pi * (50t + 195t^2) double phi = 2.0 * pi * (50.0 * t + 195.0 * t * t); int16_t val = static_cast(std::sin(phi) * amplitude); for (uint8_t c = 0; c < channels; ++c) { pcm[i * channels + c] = val; } } } void fill_silent_frame(uint8_t channels, size_t sample_count, std::vector &pcm) { for (size_t i = 0; i < sample_count * channels; ++i) { // Very low amplitude white noise (simulating silence with background hiss) pcm[i] = (std::rand() % 21) - 10; } } AudioTestData::AudioTestData() = default; AudioTestData::~AudioTestData() = default; void AudioTestData::receive_frame(uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, void *user_data) { auto *self = static_cast(user_data); self->friend_number = friend_number; self->last_pcm.assign(pcm, pcm + sample_count * channels); self->sample_count = sample_count; self->channels = channels; self->sampling_rate = sampling_rate; } // Video Helpers void fill_video_frame(uint16_t width, uint16_t height, int frame_index, std::vector &y, std::vector &u, std::vector &v) { // Background (dark gray) std::fill(y.begin(), y.end(), 32); std::fill(u.begin(), u.end(), 128); std::fill(v.begin(), v.end(), 128); // Moving square (light gray) int sq_size = height / 4; if (sq_size < 16) sq_size = 16; int x0 = (frame_index * 8) % (width - sq_size); int y0 = (frame_index * 4) % (height - sq_size); for (int r = 0; r < sq_size; ++r) { for (int c = 0; c < sq_size; ++c) { y[(y0 + r) * width + (x0 + c)] = 200; } } } double calculate_video_mse(uint16_t width, uint16_t height, int32_t ystride, const std::vector &y_recv, const std::vector &y_orig) { if (y_recv.empty() || y_orig.size() != static_cast(width) * height) { return 1e10; } double mse = 0; for (int r = 0; r < height; ++r) { for (int c = 0; c < width; ++c) { int diff = static_cast(y_orig[r * width + c]) - y_recv[r * std::abs(ystride) + c]; mse += diff * diff; } } return mse / (static_cast(width) * height); } // Video Test Data Helper VideoTestData::VideoTestData() = default; VideoTestData::~VideoTestData() = default; void VideoTestData::receive_frame(uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, int32_t ystride, int32_t ustride, int32_t vstride, void *user_data) { auto *self = static_cast(user_data); self->friend_number = friend_number; self->width = width; self->height = height; self->ystride = ystride; self->ustride = ustride; self->vstride = vstride; self->y.assign(y, y + static_cast(std::abs(ystride)) * height); self->u.assign(u, u + static_cast(std::abs(ustride)) * (height / 2)); self->v.assign(v, v + static_cast(std::abs(vstride)) * (height / 2)); } double VideoTestData::calculate_mse(const std::vector &y_orig) const { return calculate_video_mse(width, height, ystride, y, y_orig); } // Common Test Fixture void AvTest::SetUp() { const Memory *mem = os_memory(); log = logger_new(mem); tm.t = 1000; mono_time = mono_time_new(mem, mock_time_cb, &tm); mono_time_update(mono_time); } void AvTest::TearDown() { const Memory *mem = os_memory(); mono_time_free(mem, mono_time); logger_kill(log); }