From e788e467de02ca4795095a4e2e512216f78abc30 Mon Sep 17 00:00:00 2001
From: dpt <1013505110@qq.com>
Date: 星期四, 20 二月 2025 11:52:14 +0800
Subject: [PATCH] 2.19更新

---
 Client/董澎韬/code/main.cpp            |   11 +
 Client/董澎韬/code/rtspthread.cpp      |   13 +
 Client/董澎韬/code/qffmpeg.cpp         |  113 ++++++++++++
 Client/董澎韬/log/日志_董澎韬_0219.doc      |    0 
 Client/董澎韬/log/日志_董澎韬_0218.doc      |    0 
 Client/董澎韬/code/rtspthread.h        |   22 ++
 Client/董澎韬/code/facexmainwindow.cpp |  204 ++++++++++++++++++++++
 Client/董澎韬/code/qffmpeg.h           |   63 +++++++
 Client/董澎韬/code/facexmainwindow.h   |   82 +++++++++
 9 files changed, 508 insertions(+), 0 deletions(-)

diff --git "a/Client/\350\221\243\346\276\216\351\237\254/code/facexmainwindow.cpp" "b/Client/\350\221\243\346\276\216\351\237\254/code/facexmainwindow.cpp"
new file mode 100644
index 0000000..4d398d3
--- /dev/null
+++ "b/Client/\350\221\243\346\276\216\351\237\254/code/facexmainwindow.cpp"
@@ -0,0 +1,204 @@
+#include "facexmainwindow.h"
+#include "ui_facexmainwindow.h"
+
+#include <QMessageBox>
+#include <QStringList>
+#include <QFileDialog>
+#include <QGuiApplication>
+#include <QScreen>
+#include <QException>
+#include <QThread>
+
+FaceXMainWindow::FaceXMainWindow(QWidget *parent) :
+    QMainWindow(parent),
+    ui(new Ui::FaceXMainWindow),
+    m_player(new QMediaPlayer),
+    m_playerlist(new QMediaPlaylist),
+    m_videowidget(new QVideoWidget(this)),
+    m_ffmpeg(new QFFmpeg(this)),
+    m_rtspThread(nullptr)
+{
+    ui->setupUi(this);
+    //璁剧疆鍙Щ鍔ㄥ尯鍩�
+    dragArea = QRect(0, 0, width(), 40);
+    setWindowFlags(Qt::FramelessWindowHint);//闅愯棌杈规
+    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
+    // 璁剧疆鎾斁鎸夐挳鍥炬爣涓烘挱鏀惧浘鏍�
+    ui->btn_play->setStyleSheet("border-image: url(:/image/start.png)");
+
+    //璁剧疆鎾斁鍣ㄦ挱鏀鹃槦鍒�
+    m_player->setPlaylist(m_playerlist);
+    //璁剧疆鎾斁鍣ㄦ樉绀虹獥鍙�
+    m_player->setVideoOutput(m_videowidget);
+    // 璁剧疆鎾斁鍣ㄦ樉绀虹獥鍙�
+    m_videowidget->resize(ui->label_video->size());
+    m_videowidget->move(ui->label_video->pos());
+    m_videowidget->show();
+    ui->label_video->show();
+
+    // 杩炴帴 QFFmpeg 鐨勪俊鍙�
+    connect(m_ffmpeg, &QFFmpeg::GetImage, this, &FaceXMainWindow::SetImage, Qt::QueuedConnection);
+
+    // 杩炴帴鎾斁鍣ㄧ殑閿欒淇″彿
+    connect(m_player, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), this, [this](QMediaPlayer::Error error) {
+        QMessageBox::critical(this, "鎾斁閿欒", m_player->errorString());
+    });
+
+
+}
+
+FaceXMainWindow::~FaceXMainWindow()
+{
+    if (m_rtspThread && m_rtspThread->isRunning()) {
+        m_rtspThread->quit();
+        m_rtspThread->wait();
+    }
+    delete ui;
+}
+
+void FaceXMainWindow::mousePressEvent(QMouseEvent *event)
+{
+    if (dragArea.contains(event->pos())) {
+        offset = event->globalPos() - pos();
+        isDragging = true;
+    }
+}
+
+void FaceXMainWindow::mouseMoveEvent(QMouseEvent *event)
+{
+    if (isDragging && dragArea.contains(event->pos())) {
+        move(event->globalPos() - offset);
+    }
+}
+
+void FaceXMainWindow::mouseReleaseEvent(QMouseEvent *event)
+{
+    isDragging = false;
+}
+
+//鏌ヨ鎸夐挳
+void FaceXMainWindow::on_btnSelect_clicked()
+{
+    QDate dateStart = ui->dateStart->date();
+    QDate dateEnd = ui->dateEnd->date();
+
+    if (dateStart > dateEnd) {
+        QMessageBox::critical(nullptr, "閿欒", "寮�濮嬫椂闂翠笉鑳藉ぇ浜庣粨鏉熸椂闂�!");
+        return;
+    }
+
+    //灏嗘棩鏈熻浆鎹负鏃ユ湡鏃堕棿璁$畻鐩稿樊鐨勫ぉ鏁�,瓒呰繃60澶╁垯鎻愮ず涓嶇敤缁х画
+    QDateTime dateTimeStart = ui->dateStart->dateTime();
+    QDateTime dateTimeEnd = ui->dateEnd->dateTime();
+    if (dateTimeStart.daysTo(dateTimeEnd) >= 60) {
+        QMessageBox::critical(nullptr, "閿欒", "姣忔鏈�澶у彧鑳芥煡璇�60澶╁唴!");
+        return;
+    }
+
+    QStringList fileNames = QFileDialog::getOpenFileNames(this, "閫夋嫨鏂囦欢", "D:/", "瑙嗛鏂囦欢 (*.mp4 *.avi *.mov);;鎵�鏈夋枃浠� (*.*)");
+    if (!fileNames.isEmpty()) {
+        m_playerlist->clear();
+        m_ffmpeg->SetUrl(fileNames.first());
+        if (m_ffmpeg->Init()) {
+            if (m_rtspThread && m_rtspThread->isRunning()) {
+                m_rtspThread->quit();
+                m_rtspThread->wait();
+            }
+            m_rtspThread = new RtspThread(m_ffmpeg, this);
+            m_rtspThread->start();
+        }
+        QMessageBox::information(this, "鎴愬姛", "鏂囦欢宸叉坊鍔犲埌鎾斁鍒楄〃");
+    } else {
+        QMessageBox::information(this, "鎻愮ず", "鏈�夋嫨浠讳綍鏂囦欢");
+    }
+}
+
+//闅愯棌绐楀彛鎸夐挳
+void FaceXMainWindow::on_toolButton_clicked()
+{
+    hide();
+}
+
+//鏈�灏忓寲鎸夐挳
+void FaceXMainWindow::on_toolButton_3_clicked()
+{
+    showMinimized();
+}
+
+//鏈�澶у寲鎸夐挳
+void FaceXMainWindow::on_toolButton_2_clicked()
+{
+    if(windowState() != Qt::WindowMaximized)
+    {
+        this->showMaximized();
+    }
+    else
+    {
+        this->showNormal();
+    }
+}
+
+//榧犳爣鍙屽嚮鏈�澶у寲
+void FaceXMainWindow::mouseDoubleClickEvent(QMouseEvent *event)
+{
+    if(windowState() != Qt::WindowMaximized)
+    {
+        this->showMaximized();
+    }
+    else
+    {
+        this->showNormal();
+    }
+}
+
+void FaceXMainWindow::setPlayButtonIcon(bool isPlaying)
+{
+    if (isPlaying) {
+        ui->btn_play->setStyleSheet("border-image: url(:/image/pause.png)");
+    } else {
+        ui->btn_play->setStyleSheet("border-image: url(:/image/start.png)");
+    }
+}
+
+//鎾斁鎸夐挳
+void FaceXMainWindow::on_btn_play_clicked()
+{
+    if (m_ffmpeg) {
+        if (!m_rtspThread || !m_rtspThread->isRunning()) {
+            if (m_ffmpeg->Init()) {
+                m_rtspThread = new RtspThread(m_ffmpeg, this);
+                m_rtspThread->start();
+            }
+        }
+    } else {
+        QMessageBox::critical(this, "閿欒", "鎾斁鍣ㄦ湭鍒濆鍖�");
+    }
+}
+
+//鎴浘鎸夐挳
+void FaceXMainWindow::on_btn_cut_clicked()
+{
+    QScreen *screen = QGuiApplication::primaryScreen();
+    if (screen) {
+        QPixmap screenshot = screen->grabWindow(this->winId());
+        screenshot.save("screenshot.png");
+        QMessageBox::information(this, "鎻愮ず", "鎴浘宸蹭繚瀛樹负 screenshot.png");
+    }
+}
+
+void FaceXMainWindow::SetImage(const QImage &image)
+{
+    qDebug() << "鍥惧儚灏哄: " << image.width() << "x" << image.height();
+    qDebug() << "鍥惧儚鏍煎紡: " << image.format();
+    qDebug() << "鎺ユ敹鍒板浘鍍忎俊鍙�";
+    if (!image.isNull()) {
+        ui->label_video->setScaledContents(true); // 璁剧疆鍥惧儚鑷姩缂╂斁
+        ui->label_video->setPixmap(QPixmap::fromImage(image));
+        ui->label_video->adjustSize();
+        ui->label_video->update();
+        qDebug() << "鍥惧儚宸叉洿鏂�";
+    } else {
+        qDebug() << "鎺ユ敹鍒扮殑鍥惧儚涓虹┖";
+    }
+}
diff --git "a/Client/\350\221\243\346\276\216\351\237\254/code/facexmainwindow.h" "b/Client/\350\221\243\346\276\216\351\237\254/code/facexmainwindow.h"
new file mode 100644
index 0000000..71a4542
--- /dev/null
+++ "b/Client/\350\221\243\346\276\216\351\237\254/code/facexmainwindow.h"
@@ -0,0 +1,82 @@
+#ifndef FACEXMAINWINDOW_H
+#define FACEXMAINWINDOW_H
+
+#include <QMainWindow>
+#include <QMouseEvent>
+#include <QRect>
+#include <QMediaPlayer>     //鎾斁鍣�
+#include <QMediaPlaylist>   //鎾斁闃熷垪
+#include <QVideoWidget>     //瑙嗛鏄剧ず绐楀彛
+#include "qffmpeg.h"
+#include "rtspthread.h"
+
+//蹇呴』鍔犱互涓嬪唴瀹�,鍚﹀垯缂栬瘧涓嶈兘閫氳繃,涓轰簡鍏煎C鍜孋99鏍囧噯
+#ifndef INT64_C
+#define INT64_C
+#define UINT64_C
+#endif
+
+//鍥犱负#include <libavcodec/avcodec.h>鏄疌鏂囦欢锛屾墍浠ラ渶瑕佺敤extern
+extern "C"
+{
+#include <libavcodec/avcodec.h>     //瀹炵幇闊宠棰戠殑缂栬В鐮佸姛鑳�
+#include <libavformat/avformat.h>   //瀹炵幇闊宠棰戞枃浠剁殑璇诲彇鍜屽啓鍏ュ姛鑳斤紝鏀寔澶氱闊宠棰戞牸寮�
+#include <libavfilter/avfilter.h>
+#include <libswscale/swscale.h>
+#include <libavutil/frame.h>
+}
+
+QT_BEGIN_NAMESPACE
+namespace Ui {
+class FaceXMainWindow;
+}
+QT_END_NAMESPACE
+
+class FaceXMainWindow : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    explicit FaceXMainWindow(QWidget *parent = 0);
+    ~FaceXMainWindow();
+
+    void mousePressEvent(QMouseEvent *event)override;
+    void mouseMoveEvent(QMouseEvent *event)override;
+    void mouseReleaseEvent(QMouseEvent *event)override;
+    void mouseDoubleClickEvent(QMouseEvent *event)override;
+
+
+private slots:
+    void on_btnSelect_clicked();
+
+    void on_toolButton_clicked();
+
+    void on_toolButton_3_clicked();
+
+    void on_toolButton_2_clicked();
+
+    void on_btn_play_clicked();
+
+    void on_btn_cut_clicked();
+
+    void SetImage(const QImage &image);
+
+
+private:
+    Ui::FaceXMainWindow *ui;
+    QPoint offset;
+
+    QRect dragArea;
+    bool isDragging;
+
+    QMediaPlayer *m_player;
+    QMediaPlaylist *m_playerlist;
+    QVideoWidget *m_videowidget;
+
+    QFFmpeg *m_ffmpeg;
+    RtspThread *m_rtspThread;
+
+    void setPlayButtonIcon(bool isPlaying);
+};
+
+#endif // FACEXMAINWINDOW_H
diff --git "a/Client/\350\221\243\346\276\216\351\237\254/code/main.cpp" "b/Client/\350\221\243\346\276\216\351\237\254/code/main.cpp"
new file mode 100644
index 0000000..168202d
--- /dev/null
+++ "b/Client/\350\221\243\346\276\216\351\237\254/code/main.cpp"
@@ -0,0 +1,11 @@
+#include "facexmainwindow.h"
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+    FaceXMainWindow w;
+    w.show();
+
+    return a.exec();
+}
diff --git "a/Client/\350\221\243\346\276\216\351\237\254/code/qffmpeg.cpp" "b/Client/\350\221\243\346\276\216\351\237\254/code/qffmpeg.cpp"
new file mode 100644
index 0000000..756314e
--- /dev/null
+++ "b/Client/\350\221\243\346\276\216\351\237\254/code/qffmpeg.cpp"
@@ -0,0 +1,113 @@
+#include "qffmpeg.h"
+#include <QDateTime>
+#include <QDebug>
+
+QFFmpeg::QFFmpeg(QObject *parent) :
+    QObject(parent)
+{
+    videoStreamIndex=-1;
+    av_register_all();//娉ㄥ唽搴撲腑鎵�鏈夊彲鐢ㄧ殑鏂囦欢鏍煎紡鍜岃В鐮佸櫒
+    avformat_network_init();//鍒濆鍖栫綉缁滄祦鏍煎紡,浣跨敤RTSP缃戠粶娴佹椂蹇呴』鍏堟墽琛�
+    pAVFormatContext = avformat_alloc_context();//鐢宠涓�涓狝VFormatContext缁撴瀯鐨勫唴瀛�,骞惰繘琛岀畝鍗曞垵濮嬪寲
+    pAVFrame=av_frame_alloc();
+}
+
+QFFmpeg::~QFFmpeg()
+{
+    if (pAVFormatContext) {
+        avformat_close_input(&pAVFormatContext);
+        avformat_free_context(pAVFormatContext);
+    }
+    if (pAVFrame) {
+        av_frame_free(&pAVFrame);
+    }
+    if (pSwsContext) {
+        sws_freeContext(pSwsContext);
+    }
+    avpicture_free(&pAVPicture);
+}
+
+bool QFFmpeg::Init()
+{
+    //鎵撳紑瑙嗛娴�
+    int result=avformat_open_input(&pAVFormatContext, url.toStdString().c_str(),NULL,NULL);
+    if (result<0){
+        qDebug()<<"鎵撳紑瑙嗛娴佸け璐�";
+        return false;
+    }
+
+    //鑾峰彇瑙嗛娴佷俊鎭�
+    result=avformat_find_stream_info(pAVFormatContext,NULL);
+    if (result<0){
+        qDebug()<<"鑾峰彇瑙嗛娴佷俊鎭け璐�";
+        avformat_close_input(&pAVFormatContext);
+        return false;
+    }
+
+    //鑾峰彇瑙嗛娴佺储寮�
+    videoStreamIndex = -1;
+//    qDebug()<<"nb:"<<pAVFormatContext->nb_streams;
+//    qDebug()<<"type:"<<pAVFormatContext->streams[0]->codec->codec_type;
+//    qDebug()<<"AVMEDIA_TYPE_VIDEO:"<<AVMEDIA_TYPE_VIDEO;
+    for (uint i = 0; i < pAVFormatContext->nb_streams; i++) {
+        if (pAVFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+            videoStreamIndex = i;
+            break;
+        }
+    }
+
+    if (videoStreamIndex==-1){
+        qDebug()<<"鑾峰彇瑙嗛娴佺储寮曞け璐�";
+        avformat_close_input(&pAVFormatContext);
+        return false;
+    }
+
+    //鑾峰彇瑙嗛娴佺殑鍒嗚鲸鐜囧ぇ灏�
+    pAVCodecContext = pAVFormatContext->streams[videoStreamIndex]->codec;
+    videoWidth=pAVCodecContext->width;
+    videoHeight=pAVCodecContext->height;
+
+    avpicture_alloc(&pAVPicture,AV_PIX_FMT_RGB24,videoWidth,videoHeight);
+
+    AVCodec *pAVCodec;
+
+    //鑾峰彇瑙嗛娴佽В鐮佸櫒
+    pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id);
+    pSwsContext = sws_getContext(videoWidth,videoHeight,AV_PIX_FMT_YUV420P,videoWidth,videoHeight,AV_PIX_FMT_RGB24,SWS_BICUBIC,0,0,0);
+
+    //鎵撳紑瀵瑰簲瑙g爜鍣�
+    result=avcodec_open2(pAVCodecContext,pAVCodec,NULL);
+    if (result<0){
+        qDebug()<<"鎵撳紑瑙g爜鍣ㄥけ璐�";
+        avpicture_free(&pAVPicture);
+        sws_freeContext(pSwsContext);
+        avformat_close_input(&pAVFormatContext);
+        return false;
+    }
+
+    qDebug()<<"鍒濆鍖栬棰戞祦鎴愬姛";
+    return true;
+}
+
+void QFFmpeg::Play()
+{
+    //涓�甯т竴甯ц鍙栬棰�
+    int frameFinished = 0;
+    while (av_read_frame(pAVFormatContext, &pAVPacket) >= 0) {
+        if (pAVPacket.stream_index == videoStreamIndex) {
+            qDebug() << "寮�濮嬭В鐮�" << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
+            avcodec_decode_video2(pAVCodecContext, pAVFrame, &frameFinished, &pAVPacket);
+            if (frameFinished) {
+                mutex.lock();
+                sws_scale(pSwsContext, (const uint8_t* const *)pAVFrame->data, pAVFrame->linesize, 0, videoHeight, pAVPicture.data, pAVPicture.linesize);
+                QImage image(pAVPicture.data[0], videoWidth, videoHeight, QImage::Format_RGB888);
+                QImage copyImage = image.copy(); // 娣辨嫹璐�
+                emit GetImage(copyImage, this->index);
+                qDebug() << "瑙g爜鎴愬姛锛屽彂閫佸浘鍍忎俊鍙�";
+                mutex.unlock();
+            }
+        }
+        av_packet_unref(&pAVPacket);
+    }
+    avformat_close_input(&pAVFormatContext);
+}
diff --git "a/Client/\350\221\243\346\276\216\351\237\254/code/qffmpeg.h" "b/Client/\350\221\243\346\276\216\351\237\254/code/qffmpeg.h"
new file mode 100644
index 0000000..9085958
--- /dev/null
+++ "b/Client/\350\221\243\346\276\216\351\237\254/code/qffmpeg.h"
@@ -0,0 +1,63 @@
+#ifndef QFFMPEG_H
+#define QFFMPEG_H
+
+//蹇呴』鍔犱互涓嬪唴瀹�,鍚﹀垯缂栬瘧涓嶈兘閫氳繃,涓轰簡鍏煎C鍜孋99鏍囧噯
+#ifndef INT64_C
+#define INT64_C
+#define UINT64_C
+#endif
+
+//寮曞叆ffmpeg澶存枃浠�
+extern "C"
+{
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+#include <libavfilter/avfilter.h>
+#include <libswscale/swscale.h>
+#include <libavutil/frame.h>
+}
+
+#include <QObject>
+#include <QMutex>
+#include <QImage>
+
+class QFFmpeg : public QObject
+{
+    Q_OBJECT
+public:
+    explicit QFFmpeg(QObject *parent = 0);
+    ~QFFmpeg();
+
+    bool Init();        // 鍒濆鍖�
+    void Play();        // 鎾斁
+
+    void SetUrl(QString url){this->url=url;}    // 璁剧疆瑙嗛婧�
+
+    QString Url()const{return url;}
+    int VideoWidth()const{return videoWidth;}
+    int VideoHeight()const{return videoHeight;}
+    void SetIndex(int x){this->index=x;}
+
+private:
+    QMutex mutex;
+    AVPicture  pAVPicture;
+    AVFormatContext *pAVFormatContext;
+    AVCodecContext *pAVCodecContext;
+    AVFrame *pAVFrame;
+    SwsContext * pSwsContext;
+    AVPacket pAVPacket;
+
+    QString url;
+    int videoWidth;
+    int videoHeight;
+    int videoStreamIndex;
+    int index;
+
+signals:
+    void GetImage(const QImage &image,int x);    // 鍙戦�佽В鐮佸悗鐨勫浘鍍忎俊鍙�
+
+public slots:
+
+};
+
+#endif // QFFMPEG_H
diff --git "a/Client/\350\221\243\346\276\216\351\237\254/code/rtspthread.cpp" "b/Client/\350\221\243\346\276\216\351\237\254/code/rtspthread.cpp"
new file mode 100644
index 0000000..0420869
--- /dev/null
+++ "b/Client/\350\221\243\346\276\216\351\237\254/code/rtspthread.cpp"
@@ -0,0 +1,13 @@
+#include "rtspthread.h"
+
+RtspThread::RtspThread(QFFmpeg *ffmpeg,QObject *parent) :
+    QThread(parent), ffmpeg(ffmpeg)
+{
+}
+
+void RtspThread::run()
+{
+    if (ffmpeg) {
+        ffmpeg->Play();
+    }
+}
diff --git "a/Client/\350\221\243\346\276\216\351\237\254/code/rtspthread.h" "b/Client/\350\221\243\346\276\216\351\237\254/code/rtspthread.h"
new file mode 100644
index 0000000..3232a8b
--- /dev/null
+++ "b/Client/\350\221\243\346\276\216\351\237\254/code/rtspthread.h"
@@ -0,0 +1,22 @@
+#ifndef RTSPTHREAD_H
+#define RTSPTHREAD_H
+
+
+#include <QThread>
+#include "qffmpeg.h"
+
+class RtspThread : public QThread
+{
+    Q_OBJECT
+public:
+    explicit RtspThread(QFFmpeg *ffmpeg,QObject *parent = 0);
+
+protected:
+    void run()override;
+
+private:
+    QFFmpeg * ffmpeg;
+
+};
+
+#endif // RTSPTHREAD_H
diff --git "a/Client/\350\221\243\346\276\216\351\237\254/log/\346\227\245\345\277\227_\350\221\243\346\276\216\351\237\254_\346\227\245\346\234\237.doc" "b/Client/\350\221\243\346\276\216\351\237\254/log/\346\227\245\345\277\227_\350\221\243\346\276\216\351\237\254_0218.doc"
similarity index 100%
rename from "Client/\350\221\243\346\276\216\351\237\254/log/\346\227\245\345\277\227_\350\221\243\346\276\216\351\237\254_\346\227\245\346\234\237.doc"
rename to "Client/\350\221\243\346\276\216\351\237\254/log/\346\227\245\345\277\227_\350\221\243\346\276\216\351\237\254_0218.doc"
Binary files differ
diff --git "a/Client/\350\221\243\346\276\216\351\237\254/log/\346\227\245\345\277\227_\350\221\243\346\276\216\351\237\254_0219.doc" "b/Client/\350\221\243\346\276\216\351\237\254/log/\346\227\245\345\277\227_\350\221\243\346\276\216\351\237\254_0219.doc"
new file mode 100644
index 0000000..37c4831
--- /dev/null
+++ "b/Client/\350\221\243\346\276\216\351\237\254/log/\346\227\245\345\277\227_\350\221\243\346\276\216\351\237\254_0219.doc"
Binary files differ

--
Gitblit v1.8.0