diff --git a/QtScrcpy/device/decoder/avframeconvert.cpp b/QtScrcpy/device/decoder/avframeconvert.cpp index 837497f..31930d1 100644 --- a/QtScrcpy/device/decoder/avframeconvert.cpp +++ b/QtScrcpy/device/decoder/avframeconvert.cpp @@ -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(srcFrame->data), + srcFrame->linesize, 0, m_srcHeight, dstFrame->data, + dstFrame->linesize); if (0 == ret) { return false; } diff --git a/QtScrcpy/device/decoder/avframeconvert.h b/QtScrcpy/device/decoder/avframeconvert.h index 105221c..d32338e 100644 --- a/QtScrcpy/device/decoder/avframeconvert.h +++ b/QtScrcpy/device/decoder/avframeconvert.h @@ -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; diff --git a/QtScrcpy/device/device.cpp b/QtScrcpy/device/device.cpp index 19548bc..1532438 100644 --- a/QtScrcpy/device/device.cpp +++ b/QtScrcpy/device/device.cpp @@ -1,5 +1,6 @@ #include #include +#include #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; +} diff --git a/QtScrcpy/device/device.h b/QtScrcpy/device/device.h index b7573ee..424ddfd 100644 --- a/QtScrcpy/device/device.h +++ b/QtScrcpy/device/device.h @@ -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 diff --git a/QtScrcpy/device/ui/toolform.cpp b/QtScrcpy/device/ui/toolform.cpp index c0aeb07..a95763c 100644 --- a/QtScrcpy/device/ui/toolform.cpp +++ b/QtScrcpy/device/ui/toolform.cpp @@ -20,9 +20,6 @@ ToolForm::ToolForm(QWidget* adsorbWidget, AdsorbPositions adsorbPos) m_videoForm = dynamic_cast(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() diff --git a/QtScrcpy/device/ui/toolform.h b/QtScrcpy/device/ui/toolform.h index 01e18bf..0f3deca 100644 --- a/QtScrcpy/device/ui/toolform.h +++ b/QtScrcpy/device/ui/toolform.h @@ -27,6 +27,9 @@ protected: void showEvent(QShowEvent *event); void hideEvent(QHideEvent *event); +signals: + void screenshot(); + private slots: void on_fullScreenBtn_clicked(); diff --git a/QtScrcpy/device/ui/videoform.cpp b/QtScrcpy/device/ui/videoform.cpp index 3f6bbc9..ba990b0 100644 --- a/QtScrcpy/device/ui/videoform.cpp +++ b/QtScrcpy/device/ui/videoform.cpp @@ -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); } diff --git a/QtScrcpy/device/ui/videoform.h b/QtScrcpy/device/ui/videoform.h index 31229d8..0ffa4be 100644 --- a/QtScrcpy/device/ui/videoform.h +++ b/QtScrcpy/device/ui/videoform.h @@ -29,6 +29,9 @@ public: void setFileHandler(FileHandler *fileHandler); void setSerial(const QString &serial); +signals: + void screenshot(); + public slots: void onGrabCursor(bool grab); diff --git a/QtScrcpy/dialog.h b/QtScrcpy/dialog.h index 31bf7d8..2f036de 100644 --- a/QtScrcpy/dialog.h +++ b/QtScrcpy/dialog.h @@ -51,6 +51,7 @@ private slots: void on_stopAllServerBtn_clicked(); void on_refreshGameScriptBtn_clicked(); + void on_applyScriptBtn_clicked(); private: