// Exercise the real local seek/decode/presentation loop without worker races. #include "../Sources/Core/player.cpp" #include #include static void require(bool condition, const char *message) { if (!condition) { std::fprintf(stderr, "FAIL: %s\n", message); std::exit(1); } } static std::vector pixels(const AVFrame *frame) { const auto format = static_cast(frame->format); const int size = av_image_get_buffer_size(format, frame->width, frame->height, 1); require(size > 0, "preview has readable pixels"); std::vector bytes(size); require(av_image_copy_to_buffer(bytes.data(), size, frame->data, frame->linesize, format, frame->width, frame->height, 1) == size, "copy preview pixels"); return bytes; } int main(int argc, char **argv) { require(argc > 1, "provide local media fixtures"); for (int i = 1; i < argc; ++i) { av_log_set_level(AV_LOG_ERROR); Player player; player.shutdown(); player.stopping.store(false); player.activeEpoch = player.requestedEpoch.load(); player.open(Command{Action::Open, argv[i]}); require(player.tracks[1].codec && player.canSeek, "seekable local video"); player.output.set_volume(0); for (bool playing : {false, true}) { for (double fraction : {.01, .79, .21, .59}) { const double target = player.duration * fraction; // Full reference decoding supplies an independent expected picture, // including disposable B-frames at or immediately after the target. player.seek(target, false); VideoFrame expected{}; const auto referenceStart = Clock::now(); while (!expected.frame && Clock::now() - referenceStart < std::chrono::seconds(5)) { player.decodeOne(true); while (!player.video.empty()) { auto frame = std::move(player.video.front()); player.videoBytes -= frame.bytes; player.video.pop_front(); if (frame.pts + sampleTime * .5 >= target) { expected = std::move(frame); break; } } } require(bool(expected.frame), "full decode supplies reference picture"); const auto start = Clock::now(); player.seek(target, playing); while ((!player.presented.frame || player.presented.pts < target - .002) && Clock::now() - start < std::chrono::seconds(5)) player.tick(); const double elapsed = std::chrono::duration(Clock::now() - start).count(); std::printf("local-seek fixture=%s playing=%d target=%.3f preview=%.3f latency_ms=%.3f\n", argv[i], playing, target, player.presented.pts, elapsed); require(player.presented.frame && player.presented.pts == expected.pts && pixels(player.presented.frame.get()) == pixels(expected.frame.get()), "seek presents the exact fully decoded picture, including B-frame targets"); require(player.status == (playing ? PLAYER_PLAYING : PLAYER_PAUSED), "seek preserves playback intent"); } } } }