feat: add screenshot

This commit is contained in:
rankun 2020-01-31 20:47:49 +08:00
parent 5abff3f573
commit 9f5f432316
9 changed files with 107 additions and 20 deletions

View file

@ -12,7 +12,7 @@ AVFrameConvert::~AVFrameConvert()
}
void AVFrameConvert::setSrcFrameInfo(quint32 srcWidth, quint32 srcHeight, AVPixelFormat srcFormat)
void AVFrameConvert::setSrcFrameInfo(int srcWidth, int srcHeight, AVPixelFormat srcFormat)
{
m_srcWidth = srcWidth;
m_srcHeight = srcHeight;
@ -20,21 +20,21 @@ void AVFrameConvert::setSrcFrameInfo(quint32 srcWidth, quint32 srcHeight, AVPixe
qDebug() << "Convert::src frame info " << srcWidth << "x" << srcHeight;
}
void AVFrameConvert::getSrcFrameInfo(quint32& srcWidth, quint32& srcHeight, AVPixelFormat& srcFormat)
void AVFrameConvert::getSrcFrameInfo(int& srcWidth, int& srcHeight, AVPixelFormat& srcFormat)
{
srcWidth = m_srcWidth;
srcHeight = m_srcHeight;
srcFormat = m_srcFormat;
}
void AVFrameConvert::setDstFrameInfo(quint32 dstWidth, quint32 dstHeight, AVPixelFormat dstFormat)
void AVFrameConvert::setDstFrameInfo(int dstWidth, int dstHeight, AVPixelFormat dstFormat)
{
m_dstWidth = dstWidth;
m_dstHeight = dstHeight;
m_dstFormat = dstFormat;
}
void AVFrameConvert::getDstFrameInfo(quint32& dstWidth, quint32& dstHeight, AVPixelFormat& dstFormat)
void AVFrameConvert::getDstFrameInfo(int& dstWidth, int& dstHeight, AVPixelFormat& dstFormat)
{
dstWidth = m_dstWidth;
dstHeight = m_dstHeight;
@ -67,12 +67,15 @@ void AVFrameConvert::deInit()
}
}
bool AVFrameConvert::convert(AVFrame* srcFrame, AVFrame* dstFrame)
bool AVFrameConvert::convert(const AVFrame* srcFrame, AVFrame* dstFrame)
{
if(!m_convertCtx || !srcFrame || !dstFrame) {
return false;
}
qint32 ret = sws_scale(m_convertCtx, (const uint8_t* const*)srcFrame->data, srcFrame->linesize, 0, m_srcHeight, dstFrame->data, dstFrame->linesize);
qint32 ret = sws_scale(m_convertCtx,
static_cast<const uint8_t* const*>(srcFrame->data),
srcFrame->linesize, 0, m_srcHeight, dstFrame->data,
dstFrame->linesize);
if (0 == ret) {
return false;
}

View file

@ -16,22 +16,22 @@ public:
virtual ~AVFrameConvert();
public:
void setSrcFrameInfo(quint32 srcWidth, quint32 srcHeight, AVPixelFormat srcFormat);
void getSrcFrameInfo(quint32& srcWidth, quint32& srcHeight, AVPixelFormat& srcFormat);
void setDstFrameInfo(quint32 dstWidth, quint32 dstHeight, AVPixelFormat dstFormat);
void getDstFrameInfo(quint32& dstWidth, quint32& dstHeight, AVPixelFormat& dstFormat);
void setSrcFrameInfo(int srcWidth, int srcHeight, AVPixelFormat srcFormat);
void getSrcFrameInfo(int& srcWidth, int& srcHeight, AVPixelFormat& srcFormat);
void setDstFrameInfo(int dstWidth, int dstHeight, AVPixelFormat dstFormat);
void getDstFrameInfo(int& dstWidth, int& dstHeight, AVPixelFormat& dstFormat);
bool init();
bool isInit();
void deInit();
bool convert(AVFrame* srcFrame, AVFrame* dstFrame);
bool convert(const AVFrame* srcFrame, AVFrame* dstFrame);
private:
quint32 m_srcWidth = 0;
quint32 m_srcHeight = 0;
int m_srcWidth = 0;
int m_srcHeight = 0;
AVPixelFormat m_srcFormat = AV_PIX_FMT_NONE;
quint32 m_dstWidth = 0;
quint32 m_dstHeight = 0;
int m_dstWidth = 0;
int m_dstHeight = 0;
AVPixelFormat m_dstFormat = AV_PIX_FMT_NONE;
struct SwsContext *m_convertCtx = Q_NULLPTR;

View file

@ -1,5 +1,6 @@
#include <QTimer>
#include <QMessageBox>
#include <QDir>
#include "device.h"
#include "recorder.h"
@ -11,6 +12,11 @@
#include "videoform.h"
#include "controller.h"
#include "config.h"
#include "avframeconvert.h"
extern "C"
{
#include "libavutil/imgutils.h"
}
Device::Device(DeviceParams params, QObject *parent)
: QObject(parent)
@ -97,10 +103,16 @@ void Device::updateScript(QString script)
}
}
void Device::onScreenshot()
{
m_screenshot = true;
}
void Device::initSignals()
{
if (m_controller && m_videoForm) {
connect(m_controller, &Controller::grabCursor, m_videoForm, &VideoForm::onGrabCursor);
connect(m_videoForm, &VideoForm::screenshot, this, &Device::onScreenshot);
}
if (m_videoForm) {
connect(m_videoForm, &VideoForm::destroyed, this, [this](QObject *obj){
@ -138,7 +150,7 @@ void Device::initSignals()
});
connect(m_server, &Server::connectToResult, this, [this](bool success, const QString &deviceName, const QSize &size){
if (success) {
float diff = m_startTimeCount.elapsed() / 1000.0f;
double diff = m_startTimeCount.elapsed() / 1000.0;
qInfo(QString("server start finish in %1s").arg(diff).toStdString().c_str());
// update ui
@ -189,6 +201,12 @@ void Device::initSignals()
if (m_videoForm) {
m_videoForm->updateRender(frame);
}
// screenshot
if (m_screenshot) {
saveFrame(frame);
m_screenshot = false;
}
m_vb->unLock();
},Qt::QueuedConnection);
}
@ -216,3 +234,56 @@ void Device::startServer()
m_server->start(params);
});
}
bool Device::saveFrame(const AVFrame* frame)
{
if (!frame) {
return false;
}
// create buffer
QImage rgbImage(frame->width, frame->height, QImage::Format_RGB32);
AVFrame* rgbFrame = av_frame_alloc();
if (!rgbFrame) {
return false;
}
// bind buffer to AVFrame
av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize, rgbImage.bits(), AV_PIX_FMT_RGB32, frame->width, frame->height, 4);
// convert
AVFrameConvert convert;
convert.setSrcFrameInfo(frame->width, frame->height, AV_PIX_FMT_YUV420P);
convert.setDstFrameInfo(frame->width, frame->height, AV_PIX_FMT_RGB32);
bool ret = false;
ret = convert.init();
if (!ret) {
return false;
}
ret = convert.convert(frame, rgbFrame);
if (!ret) {
return false;
}
convert.deInit();
av_free(rgbFrame);
// save
QString absFilePath;
QString fileDir(Config::getInstance().getRecordPath());
if (fileDir.isEmpty()) {
qWarning() << "please select record path!!!";
return false;
}
QDateTime dateTime = QDateTime::currentDateTime();
QString fileName = dateTime.toString("_yyyyMMdd_hhmmss_zzz");
fileName = Config::getInstance().getTitle() + fileName + ".jpg";
QDir dir(fileDir);
absFilePath = dir.absoluteFilePath(fileName);
ret = rgbImage.save(absFilePath);
if (!ret) {
return false;
}
qInfo() << "screenshot save to " << absFilePath;
return true;
}

View file

@ -12,6 +12,7 @@ class FileHandler;
class Stream;
class VideoForm;
class Controller;
struct AVFrame;
class Device : public QObject
{
Q_OBJECT
@ -40,9 +41,13 @@ public:
signals:
void deviceDisconnect(QString serial);
public slots:
void onScreenshot();
private:
void initSignals();
void startServer();
bool saveFrame(const AVFrame* frame);
private:
// server relevant
@ -59,6 +64,8 @@ private:
QTime m_startTimeCount;
DeviceParams m_params;
bool m_screenshot = false;
};
#endif // DEVICE_H

View file

@ -20,9 +20,6 @@ ToolForm::ToolForm(QWidget* adsorbWidget, AdsorbPositions adsorbPos)
m_videoForm = dynamic_cast<VideoForm*>(adsorbWidget);
initStyle();
// TODO
ui->screenShotBtn->hide();
}
ToolForm::~ToolForm()
@ -123,7 +120,7 @@ void ToolForm::on_powerBtn_clicked()
void ToolForm::on_screenShotBtn_clicked()
{
// TODO
emit screenshot();
}
void ToolForm::on_volumeUpBtn_clicked()

View file

@ -27,6 +27,9 @@ protected:
void showEvent(QShowEvent *event);
void hideEvent(QHideEvent *event);
signals:
void screenshot();
private slots:
void on_fullScreenBtn_clicked();

View file

@ -93,6 +93,8 @@ void VideoForm::showToolForm(bool show)
if (!m_toolForm) {
m_toolForm = new ToolForm(this, ToolForm::AP_OUTSIDE_RIGHT);
m_toolForm->move(pos().x() + geometry().width(), pos().y() + 30);
connect(m_toolForm, &ToolForm::screenshot, this, &VideoForm::screenshot);
}
m_toolForm->setVisible(show);
}

View file

@ -29,6 +29,9 @@ public:
void setFileHandler(FileHandler *fileHandler);
void setSerial(const QString &serial);
signals:
void screenshot();
public slots:
void onGrabCursor(bool grab);

View file

@ -51,6 +51,7 @@ private slots:
void on_stopAllServerBtn_clicked();
void on_refreshGameScriptBtn_clicked();
void on_applyScriptBtn_clicked();
private: