You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
4.0 KiB
69 lines
4.0 KiB
/* Управляемое время: весь поток сохраняется при паузах сети/CPU и ускорении аудио. */ |
|
#include <stdlib.h> |
|
#include "../src/call/call_video_playout.h" |
|
#include "../lib/debug_config.h" |
|
|
|
#define CHECK(x) do { if (!(x)) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "playout test line=%d: %s", __LINE__, #x); exit(1); } } while (0) |
|
static const int64_t origin = 1000000; |
|
|
|
static void simulate(unsigned pause_ms, int cpu, int64_t quantum, int accelerated_audio) { |
|
struct call_video_playout p; call_video_playout_init(&p, 7); |
|
enum { COUNT = 240 }; |
|
struct call_video_playout_frame frames[COUNT]; |
|
for (int i = 0; i < COUNT; ++i) { |
|
int64_t arrival = origin + i * 33333ll; |
|
if (!cpu && arrival >= origin + 1000000 && arrival < origin + 1000000 + pause_ms * 1000ll) |
|
arrival = origin + 1000000 + pause_ms * 1000ll; |
|
frames[i] = (struct call_video_playout_frame){origin + i * 33333ll, arrival}; |
|
} |
|
unsigned shown = 0, accelerated = 0; |
|
int64_t last_show = 0, recovered_lag = INT64_MAX, audio_pts = origin; |
|
for (int64_t now = origin; now < origin + 12000000 && shown < COUNT; now += quantum) { |
|
uint32_t rate = accelerated_audio && now >= origin + 1500000 && now < origin + 2500000 ? 1100000 : 1000000; |
|
if (now > origin) audio_pts += quantum * rate / 1000000; |
|
if (cpu && now >= origin + 1000000 && now < origin + 1000000 + pause_ms * 1000ll) continue; |
|
struct call_clock_snapshot audio = {.pts_us = audio_pts, .rate_ppm = rate, |
|
.valid = !(now >= origin + 4000000 && now < origin + 4100000)}; |
|
struct call_video_playout_frame *f = frames + shown; |
|
int action = call_video_playout_poll(&p, f->received_us <= now ? f : NULL, NULL, now, &audio); |
|
if (action == CALL_VIDEO_PLAYOUT_WAIT) continue; |
|
CHECK(action == CALL_VIDEO_PLAYOUT_SHOW && audio.valid); |
|
CHECK(!last_show || now > last_show); |
|
CHECK(f->pts_us - audio.pts_us <= 40000); |
|
if (p.speed_ppm > 1050000) accelerated++; |
|
if (now >= origin + 6000000) recovered_lag = audio.pts_us - f->pts_us; |
|
last_show = now; shown++; |
|
// Даже готовая очередь после фриза не выдаётся целиком за один вызов worker. |
|
if (shown < COUNT && frames[shown].received_us <= now) |
|
CHECK(call_video_playout_poll(&p, frames + shown, NULL, now, &audio) == CALL_VIDEO_PLAYOUT_WAIT); |
|
} |
|
CHECK(shown == COUNT && accelerated && recovered_lag < 50000); |
|
DEBUG_INFO(DEBUG_CATEGORY_CALL, "PASS sequential recovery pause_ms=%u cpu=%d quantum_us=%lld audio_fast=%d shown=%u/%u lag_us=%lld", |
|
pause_ms, cpu, (long long)quantum, accelerated_audio, shown, COUNT, (long long)recovered_lag); |
|
} |
|
|
|
static void order_and_clock(void) { |
|
struct call_video_playout p; call_video_playout_init(&p, 9); |
|
struct call_video_playout_frame f = {origin, origin}; |
|
struct call_clock_snapshot audio = {.pts_us = origin, .rate_ppm = 1000000}; |
|
CHECK(call_video_playout_poll(&p, &f, NULL, origin, &audio) == CALL_VIDEO_PLAYOUT_WAIT); |
|
audio.valid = 1; |
|
CHECK(call_video_playout_poll(&p, &f, NULL, origin, &audio) == CALL_VIDEO_PLAYOUT_SHOW); |
|
CHECK(call_video_playout_poll(&p, &f, NULL, origin + 1000, &audio) == CALL_VIDEO_PLAYOUT_DROP_ORDER); |
|
f.pts_us += 33333; |
|
audio.valid = 0; |
|
CHECK(call_video_playout_poll(&p, &f, NULL, origin + 200000, &audio) == CALL_VIDEO_PLAYOUT_WAIT); |
|
audio.valid = 1; audio.pts_us += 200000; |
|
CHECK(call_video_playout_poll(&p, &f, NULL, origin + 200000, &audio) == CALL_VIDEO_PLAYOUT_SHOW); |
|
} |
|
|
|
int main(void) { |
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_INFO); |
|
const unsigned pauses[] = {50, 100, 200, 500}; |
|
for (unsigned i = 0; i < sizeof(pauses) / sizeof(pauses[0]); ++i) |
|
for (int cpu = 0; cpu <= 1; ++cpu) { |
|
simulate(pauses[i], cpu, 1000, 0); |
|
simulate(pauses[i], cpu, 15625, 1); |
|
} |
|
order_and_clock(); return 0; |
|
}
|
|
|