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

/* Управляемое время: весь поток сохраняется при паузах сети/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;
}