chatgui: нативный move/resize (Wayland) + фикс замирания видео при перемотке
- окно: startSystemMove/startSystemResize вместо ручного move/setGeometry (Wayland игнорирует позицию окна) — драг и resize за левый/верхний край работают - пропорции: снэп к videoAspect после нативного resize (дебаунс 150мс) - перемотка: backpressure по m_buffered (декод не убегает вперёд и воркер живёт для seek), seek через av_seek_frame(-1, us), пропуск кадров с AV_NOPTS_VALUE - SeekSlider: клик по шкале = прыжок к позиции - крестик закрытия справа вверху; курсор контролов — стрелка - test_video_engine: проверка seek
This commit is contained in:
1 parent
f2b34459c3
commit
645591bb64
5 files changed
+139
-122
No files matched your search
@@ -7,15 +7,23 @@
|
||||
#include <QDebug>
|
||||
#include <cstdio>
|
||||
|
||||
extern "C" {
|
||||
#include "../../lib/debug_config.h"
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
debug_config_init();
|
||||
debug_set_level(DEBUG_LEVEL_TRACE);
|
||||
debug_enable_console(1);
|
||||
QApplication app(argc, argv);
|
||||
if (argc < 2) { qCritical("usage: test_video_engine <video.mp4>"); return 2; }
|
||||
QString path = argv[1];
|
||||
|
||||
VideoPlayerEngine eng;
|
||||
int frames = 0, opened = 0, errors = 0, finished = 0;
|
||||
qint64 lastPos = -1;
|
||||
qint64 lastPos = -1, posAfterSeek = -1;
|
||||
int width = 0, height = 0; qint64 dur = 0; bool hasAudio = false;
|
||||
int framesAfterSeek = 0;
|
||||
|
||||
QObject::connect(&eng, &VideoPlayerEngine::opened,
|
||||
[&](int w, int h, qint64 d, bool a) { opened++; width = w; height = h; dur = d; hasAudio = a; });
|
||||
@@ -26,22 +34,38 @@ int main(int argc, char** argv) {
|
||||
|
||||
eng.open(path);
|
||||
|
||||
/* через 1с — seek к середине */
|
||||
int framesBeforeSeek = 0;
|
||||
QTimer seekTimer;
|
||||
seekTimer.setSingleShot(true);
|
||||
QObject::connect(&seekTimer, &QTimer::timeout, [&]() {
|
||||
framesBeforeSeek = frames;
|
||||
eng.seekMs(eng.durationMs() / 2);
|
||||
QTimer::singleShot(1000, &eng, [&]() {
|
||||
framesAfterSeek = frames - framesBeforeSeek;
|
||||
posAfterSeek = eng.positionMs();
|
||||
});
|
||||
});
|
||||
seekTimer.start(1000);
|
||||
|
||||
QEventLoop loop;
|
||||
QTimer timer;
|
||||
timer.setSingleShot(true);
|
||||
QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
|
||||
timer.start(5000);
|
||||
timer.start(6000);
|
||||
loop.exec();
|
||||
|
||||
eng.close();
|
||||
|
||||
qInfo("opened=%d (%dx%d dur=%lldms audio=%d) frames=%d finished=%d errors=%d lastPos=%lldms",
|
||||
opened, width, height, (long long)dur, hasAudio ? 1 : 0, frames, finished, errors, (long long)lastPos);
|
||||
qInfo("opened=%d (%dx%d dur=%lldms audio=%d) frames=%d finished=%d errors=%d lastPos=%lldms posAfterSeek=%lldms framesAfterSeek=%d",
|
||||
opened, width, height, (long long)dur, hasAudio ? 1 : 0, frames, finished, errors,
|
||||
(long long)lastPos, (long long)posAfterSeek, framesAfterSeek);
|
||||
|
||||
int rc = 0;
|
||||
if (opened != 1) { qCritical("FAIL: opened != 1"); rc = 1; }
|
||||
if (frames <= 0) { qCritical("FAIL: no frames presented"); rc = 1; }
|
||||
if (errors > 0) { qCritical("FAIL: errors present"); rc = 1; }
|
||||
if (posAfterSeek <= 0 || framesAfterSeek <= 0) { qCritical("FAIL: no frames/position after seek"); rc = 1; }
|
||||
qInfo(rc == 0 ? "PASS" : "FAIL");
|
||||
return rc;
|
||||
}
|
||||
Reference in new issue
Block a user