#ifndef CAPTURETHREAD_H
#define CAPTURETHREAD_H
#include <QApplication>
#include <QScreen>
#include <QPixmap>
#include <QThread>
#include <QElapsedTimer>
#include <QTimer>
#include <QMutex>
#include <QDebug>
#include <QFile>
// 捕获线程
class CaptureThread : public QThread
{
Q_OBJECT
public:
explicit CaptureThread(QObject *parent = nullptr)
: QThread(parent), m_running(false), m_fps(30)
{
}
void startCapture(const QRect &captureRect)
{
m_captureRect = captureRect;
m_running = true;
start();
}
void stopCapture()
{
m_running = false;
wait();
}
void setFps(int fps)
{
m_fps = qBound(1, fps, 240); // ������1-60fps֮��
}
signals:
void frameCaptured(const QPixmap &frame, int frames);
protected:
void run() override
{
const qint64 targetInterval = 1000000 / m_fps; // ʹ����Ϊ��λ
QElapsedTimer timer, frameTimer;
timer.start();
qint64 nextFrameTime = timer.nsecsElapsed() / 1000; // ת��Ϊ��
qint64 lastFpsUpdate = 0;
int frames = 0;
int oldFrames = 0;
while (m_running)
{
frameTimer.start();
// 1. ��ȷ˯�ߵ���һ֡ʱ��
qint64 currentTime = timer.nsecsElapsed() / 1000;
qint64 sleepTime = nextFrameTime - currentTime;
if (sleepTime > 1000)
{ // ֻ����Ҫ�ȴ��ϳ�ʱ��ʱ��˯��
QThread::usleep(sleepTime - 500); // ��ǰ500us���Ѵ���ϵͳ�����ӳ�
}
// 2. æ�ȴ�ȷ����ȷͬ��
while ((timer.nsecsElapsed() / 1000) < nextFrameTime)
{
QThread::yieldCurrentThread();
}
// 3. ����֡
QPixmap frame = QGuiApplication::primaryScreen()->grabWindow(
0,
m_captureRect.x(),
m_captureRect.y(),
m_captureRect.width(),
m_captureRect.height());
// 4. ���㴦����ʱ
qint64 processTime = frameTimer.nsecsElapsed() / 1000;
emit frameCaptured(frame, oldFrames);
// 5. ������һ֡ʱ�䣨�̶����������ۻ���
nextFrameTime += targetInterval;
// 6. FPS����
frames++;
currentTime = timer.nsecsElapsed() / 1000;
if (currentTime - lastFpsUpdate >= 1000000)
{
oldFrames = frames;
qDebug() << "Actual FPS:" << frames
<< "| Drift:" << (currentTime - (lastFpsUpdate + 1000000)) << "us";
frames = 0;
lastFpsUpdate = currentTime;
}
}
}
private:
QRect m_captureRect;
bool m_running;
int m_fps;
QMutex m_mutex;
};
#endif // CAPTURETHREAD_H
#include "CaptureRGB.h"
#include <QGuiApplication>
#include <QScreen>
#include <QVBoxLayout>
#include <QPushButton>
#include "QtVulkanWidget.h"
CaptureRGB::CaptureRGB(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
setAttribute(Qt::WA_PaintOnScreen);
// 设置抓取区域(示例:屏幕中心400x300区域)
QScreen *screen = QGuiApplication::primaryScreen();
QRect screenRect = screen->geometry();
m_captureRect = QRect(
screenRect.center().x() - CAPTURE_WIDTH / 2,
screenRect.center().y() - CAPTURE_HEIGHT / 2,
CAPTURE_WIDTH, CAPTURE_HEIGHT);
// 初始化线程
m_captureThread = new CaptureThread(this);
m_captureThread->setFps(60); // 30fps
connect(m_captureThread, &CaptureThread::frameCaptured, ui.m_window, &QtVulkanWidget::handleFrame);
// 控制按钮
connect(ui.m_startBtn, &QPushButton::clicked, [this]()
{ m_captureThread->startCapture(m_captureRect); });
connect(ui.m_stopBtn, &QPushButton::clicked, [this]()
{ m_captureThread->stopCapture(); });
}
CaptureRGB::~CaptureRGB()
{
m_captureThread->stopCapture();
}
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_CaptureRGB.h"
#include <QTimer>
#include <QMessageBox>
#include <QPixmap>
#include <QPainter>
#include <QDateTime>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QVector>
#include "CaptureThread.h"
class CaptureRGB : public QMainWindow
{
Q_OBJECT
public:
CaptureRGB(QWidget *parent = nullptr);
~CaptureRGB();
private:
Ui::CaptureRGBClass ui;
private:
CaptureThread* m_captureThread;
QRect m_captureRect;
};