From 951695d8663403b5e291f6af395c5721d7a7ec56 Mon Sep 17 00:00:00 2001
From: wl <3569324431@QQ.com>
Date: 星期四, 20 二月 2025 12:15:32 +0800
Subject: [PATCH] Merge branch 'master' of ssh://115.28.86.8:29418/~admin/FaceX_AI_智能守卫

---
 Client/董澎韬/code/main.cpp                  |   11 
 Client/董佳琦/log/日志_董佳琦_0218.doc            |    0 
 Server/卢敏/log/日志_卢敏_2.18.doc              |    0 
 Server/冉凯/log/日志_冉凯_20250219.doc          |    0 
 Server/张敏丽/document/日志_姓名_日期.doc          |    0 
 Client/郭文强/document/新需求功能规格说明书 - 郭文强.docx |    0 
 Client/解来鑫/log/日志_姓名_日期.doc               |    0 
 Client/董澎韬/log/日志_董澎韬_0218.doc            |    0 
 Client/王雨阳/log/王雨阳_250218.doc             |    0 
 Client/董澎韬/code/rtspthread.h              |   22 +
 Server/卢敏/log/日志_卢敏_2.19.doc              |    0 
 Client/董澎韬/code/facexmainwindow.cpp       |  204 +++++++++++++++++
 Client/王雨阳/document/项目需求书2.0版.docx        |    0 
 Client/董澎韬/code/qffmpeg.h                 |   63 +++++
 Client/董澎韬/code/rtspthread.cpp            |   13 +
 Client/郭文强/log/郭文强_20250218.doc           |    0 
 ProjectInformation/1.2项目进度表.et            |    0 
 Client/董澎韬/code/qffmpeg.cpp               |  113 +++++++++
 Client/董澎韬/log/日志_董澎韬_0219.doc            |    0 
 Client/王雨阳/code/UI.html                   |  202 ++++++++++++++++
 Client/王雨阳/log/日志_王雨阳_250218.doc          |    0 
 Client/郭文强/log/郭文强_20250219.doc           |    0 
 Server/冉凯/document/日志_冉凯_20250218.doc     |    0 
 Client/董澎韬/code/facexmainwindow.h         |   82 ++++++
 24 files changed, 710 insertions(+), 0 deletions(-)

diff --git "a/Client/\347\216\213\351\233\250\351\230\263/code/UI.html" "b/Client/\347\216\213\351\233\250\351\230\263/code/UI.html"
new file mode 100644
index 0000000..473c500
--- /dev/null
+++ "b/Client/\347\216\213\351\233\250\351\230\263/code/UI.html"
@@ -0,0 +1,202 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>浜鸿劯璇嗗埆鑰冨嫟 - 浜鸿劯褰曞叆妯″潡</title>
+    <style>
+        body {
+            font-family: Arial, sans-serif;
+            margin: 20px;
+        }
+        .container {
+            max-width: 600px;
+            margin: auto;
+            padding: 20px;
+            border: 1px solid #ccc;
+            border-radius: 8px;
+            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+        }
+        h1 {
+            text-align: center;
+            color: #333;
+        }
+        .form-group {
+            margin-bottom: 15px;
+        }
+        label {
+            display: block;
+            margin-bottom: 5px;
+            font-weight: bold;
+        }
+        input[type="text"], button {
+            width: 100%;
+            padding: 10px;
+            font-size: 16px;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+        }
+        button {
+            background-color: #007bff;
+            color: white;
+            cursor: pointer;
+        }
+        button:hover {
+            background-color: #0056b3;
+        }
+        .camera-preview {
+            margin-top: 20px;
+            text-align: center;
+        }
+        .camera-preview video {
+            max-width: 100%;
+            height: auto;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+        }
+        .image-preview {
+            margin-top: 20px;
+            text-align: center;
+        }
+        .image-preview img {
+            max-width: 100%;
+            height: auto;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+        }
+        .status-message {
+            margin-top: 15px;
+            text-align: center;
+            font-size: 14px;
+            color: #555;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <h1>浜鸿劯璇嗗埆鑰冨嫟 - 浜鸿劯褰曞叆妯″潡</h1>
+
+        <!-- 宸ュ彿杈撳叆 -->
+        <div class="form-group">
+            <label for="employee-id">杈撳叆宸ュ彿:</label>
+            <input type="text" id="employee-id" placeholder="璇疯緭鍏ュ伐鍙�">
+        </div>
+
+        <!-- 鏌ヨ淇℃伅鎸夐挳 -->
+        <button onclick="searchUserInfo()">鏌ヨ淇℃伅</button>
+
+        <!-- 鐢ㄦ埛淇℃伅灞曠ず -->
+        <div class="form-group" id="user-info" style="display: none;">
+            <label>鐢ㄦ埛淇℃伅:</label>
+            <p id="user-details"></p>
+        </div>
+
+        <!-- 妯℃嫙鎽勫儚澶存姄鍙栧浘鐗� -->
+        <div class="camera-preview" id="camera-preview" style="display: none;">
+            <video id="camera-video" autoplay playsinline></video>
+            <div>
+                <button onclick="captureImage('front')">鎶撳彇姝h劯</button>
+                <button onclick="captureImage('left')">鎶撳彇宸︿晶鑴�</button>
+                <button onclick="captureImage('right')">鎶撳彇鍙充晶鑴�</button>
+            </div>
+        </div>
+
+        <!-- 鍥剧墖棰勮 -->
+        <div class="image-preview" id="image-preview" style="display: none;">
+            <h3>鎶撳彇鐨勫浘鐗囬瑙�</h3>
+            <div id="captured-images">
+                <img id="front-image" src="" alt="姝h劯鍥剧墖" style="display: none;">
+                <img id="left-image" src="" alt="宸︿晶鑴稿浘鐗�" style="display: none;">
+                <img id="right-image" src="" alt="鍙充晶鑴稿浘鐗�" style="display: none;">
+            </div>
+        </div>
+
+        <!-- 鎻愪氦鎸夐挳 -->
+        <button onclick="submitData()" style="display: none;" id="submit-btn">鎻愪氦</button>
+
+        <!-- 鐘舵�佹秷鎭� -->
+        <div class="status-message" id="status-message"></div>
+    </div>
+
+    <script>
+        let cameraStream = null;
+
+        // 妯℃嫙鏌ヨ鐢ㄦ埛淇℃伅
+        function searchUserInfo() {
+            const employeeId = document.getElementById('employee-id').value;
+            if (!employeeId) {
+                alert('璇疯緭鍏ュ伐鍙�');
+                return;
+            }
+
+            // 妯℃嫙鏌ヨ缁撴灉
+            const userInfo = {
+                id: employeeId,
+                name: '寮犱笁',
+                department: '鎶�鏈儴'
+            };
+
+            // 鏄剧ず鐢ㄦ埛淇℃伅
+            document.getElementById('user-details').innerText = `濮撳悕: ${userInfo.name}, 閮ㄩ棬: ${userInfo.department}`;
+            document.getElementById('user-info').style.display = 'block';
+
+            // 鏄剧ず鎽勫儚澶�
+            startCamera();
+        }
+
+        // 鎵撳紑鎽勫儚澶�
+        async function startCamera() {
+            try {
+                cameraStream = await navigator.mediaDevices.getUserMedia({ video: true });
+                const videoElement = document.getElementById('camera-video');
+                videoElement.srcObject = cameraStream;
+                document.getElementById('camera-preview').style.display = 'block';
+            } catch (error) {
+                alert('鏃犳硶璁块棶鎽勫儚澶达紝璇锋鏌ユ潈闄愭垨璁惧鏄惁鍙敤銆�');
+                console.error('鎽勫儚澶磋闂け璐�:', error);
+            }
+        }
+
+        // 鎶撳彇鍥剧墖
+        function captureImage(faceType) {
+            const videoElement = document.getElementById('camera-video');
+            const canvas = document.createElement('canvas');
+            canvas.width = videoElement.videoWidth;
+            canvas.height = videoElement.videoHeight;
+            const context = canvas.getContext('2d');
+            context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
+
+            // 灏嗘姄鍙栫殑鍥剧墖鏄剧ず鍦ㄩ〉闈腑
+            const imageUrl = canvas.toDataURL('image/png');
+            const imageElement = document.getElementById(`${faceType}-image`);
+            imageElement.src = imageUrl;
+            imageElement.style.display = 'block';
+
+            // 濡傛灉涓夊紶鍥剧墖閮藉凡鎶撳彇锛屾樉绀烘彁浜ゆ寜閽�
+            const frontImage = document.getElementById('front-image').src;
+            const leftImage = document.getElementById('left-image').src;
+            const rightImage = document.getElementById('right-image').src;
+            if (frontImage && leftImage && rightImage) {
+                document.getElementById('submit-btn').style.display = 'block';
+            }
+        }
+
+        // 妯℃嫙鎻愪氦鏁版嵁
+        function submitData() {
+            const employeeId = document.getElementById('employee-id').value;
+            if (!employeeId) {
+                alert('璇峰厛杈撳叆宸ュ彿骞舵煡璇俊鎭�');
+                return;
+            }
+
+            // 妯℃嫙涓婁紶鍥剧墖鍜屾彁浜ゆ暟鎹�
+            const statusMessage = document.getElementById('status-message');
+            statusMessage.innerText = '姝e湪涓婁紶鍥剧墖骞舵彁浜ゆ暟鎹�...';
+
+            setTimeout(() => {
+                statusMessage.innerText = '鎻愪氦鎴愬姛锛�';
+            }, 2000); // 妯℃嫙涓婁紶寤惰繜
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git "a/Client/\347\216\213\351\233\250\351\230\263/document/\351\241\271\347\233\256\351\234\200\346\261\202\344\271\2462.0\347\211\210.docx" "b/Client/\347\216\213\351\233\250\351\230\263/document/\351\241\271\347\233\256\351\234\200\346\261\202\344\271\2462.0\347\211\210.docx"
new file mode 100644
index 0000000..20310c4
--- /dev/null
+++ "b/Client/\347\216\213\351\233\250\351\230\263/document/\351\241\271\347\233\256\351\234\200\346\261\202\344\271\2462.0\347\211\210.docx"
Binary files differ
diff --git "a/Client/\347\216\213\351\233\250\351\230\263/log/\346\227\245\345\277\227_\347\216\213\351\233\250\351\230\263_250218.doc" "b/Client/\347\216\213\351\233\250\351\230\263/log/\346\227\245\345\277\227_\347\216\213\351\233\250\351\230\263_250218.doc"
new file mode 100644
index 0000000..133097d
--- /dev/null
+++ "b/Client/\347\216\213\351\233\250\351\230\263/log/\346\227\245\345\277\227_\347\216\213\351\233\250\351\230\263_250218.doc"
Binary files differ
diff --git "a/Client/\347\216\213\351\233\250\351\230\263/log/\347\216\213\351\233\250\351\230\263_250218.doc" "b/Client/\347\216\213\351\233\250\351\230\263/log/\347\216\213\351\233\250\351\230\263_250218.doc"
new file mode 100644
index 0000000..27a819f
--- /dev/null
+++ "b/Client/\347\216\213\351\233\250\351\230\263/log/\347\216\213\351\233\250\351\230\263_250218.doc"
Binary files differ
diff --git "a/Client/\350\221\243\344\275\263\347\220\246/log/\346\227\245\345\277\227_\350\221\243\344\275\263\347\220\246_0218.doc" "b/Client/\350\221\243\344\275\263\347\220\246/log/\346\227\245\345\277\227_\350\221\243\344\275\263\347\220\246_0218.doc"
new file mode 100644
index 0000000..e193b75
--- /dev/null
+++ "b/Client/\350\221\243\344\275\263\347\220\246/log/\346\227\245\345\277\227_\350\221\243\344\275\263\347\220\246_0218.doc"
Binary files differ
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
diff --git "a/Client/\350\247\243\346\235\245\351\221\253/log/\346\227\245\345\277\227_\345\247\223\345\220\215_\346\227\245\346\234\237.doc" "b/Client/\350\247\243\346\235\245\351\221\253/log/\346\227\245\345\277\227_\345\247\223\345\220\215_\346\227\245\346\234\237.doc"
new file mode 100644
index 0000000..0f7e6cd
--- /dev/null
+++ "b/Client/\350\247\243\346\235\245\351\221\253/log/\346\227\245\345\277\227_\345\247\223\345\220\215_\346\227\245\346\234\237.doc"
Binary files differ
diff --git "a/Client/\351\203\255\346\226\207\345\274\272/document/\346\226\260\351\234\200\346\261\202\345\212\237\350\203\275\350\247\204\346\240\274\350\257\264\346\230\216\344\271\246.docx" "b/Client/\351\203\255\346\226\207\345\274\272/document/\346\226\260\351\234\200\346\261\202\345\212\237\350\203\275\350\247\204\346\240\274\350\257\264\346\230\216\344\271\246 - \351\203\255\346\226\207\345\274\272.docx"
similarity index 100%
rename from "Client/\351\203\255\346\226\207\345\274\272/document/\346\226\260\351\234\200\346\261\202\345\212\237\350\203\275\350\247\204\346\240\274\350\257\264\346\230\216\344\271\246.docx"
rename to "Client/\351\203\255\346\226\207\345\274\272/document/\346\226\260\351\234\200\346\261\202\345\212\237\350\203\275\350\247\204\346\240\274\350\257\264\346\230\216\344\271\246 - \351\203\255\346\226\207\345\274\272.docx"
Binary files differ
diff --git "a/Client/\351\203\255\346\226\207\345\274\272/log/\351\203\255\346\226\207\345\274\272_20250218.doc" "b/Client/\351\203\255\346\226\207\345\274\272/log/\351\203\255\346\226\207\345\274\272_20250218.doc"
new file mode 100644
index 0000000..8175193
--- /dev/null
+++ "b/Client/\351\203\255\346\226\207\345\274\272/log/\351\203\255\346\226\207\345\274\272_20250218.doc"
Binary files differ
diff --git "a/Client/\351\203\255\346\226\207\345\274\272/log/\351\203\255\346\226\207\345\274\272_20250219.doc" "b/Client/\351\203\255\346\226\207\345\274\272/log/\351\203\255\346\226\207\345\274\272_20250219.doc"
new file mode 100644
index 0000000..576ec99
--- /dev/null
+++ "b/Client/\351\203\255\346\226\207\345\274\272/log/\351\203\255\346\226\207\345\274\272_20250219.doc"
Binary files differ
diff --git "a/ProjectInformation/1.2\351\241\271\347\233\256\350\277\233\345\272\246\350\241\250.et" "b/ProjectInformation/1.2\351\241\271\347\233\256\350\277\233\345\272\246\350\241\250.et"
index 13267bc..ca4f8aa 100644
--- "a/ProjectInformation/1.2\351\241\271\347\233\256\350\277\233\345\272\246\350\241\250.et"
+++ "b/ProjectInformation/1.2\351\241\271\347\233\256\350\277\233\345\272\246\350\241\250.et"
Binary files differ
diff --git "a/Server/\345\206\211\345\207\257/document/\346\227\245\345\277\227_\345\206\211\345\207\257_20250218.doc" "b/Server/\345\206\211\345\207\257/document/\346\227\245\345\277\227_\345\206\211\345\207\257_20250218.doc"
new file mode 100644
index 0000000..2506676
--- /dev/null
+++ "b/Server/\345\206\211\345\207\257/document/\346\227\245\345\277\227_\345\206\211\345\207\257_20250218.doc"
Binary files differ
diff --git "a/Server/\345\206\211\345\207\257/log/\346\227\245\345\277\227_\345\206\211\345\207\257_20250219.doc" "b/Server/\345\206\211\345\207\257/log/\346\227\245\345\277\227_\345\206\211\345\207\257_20250219.doc"
new file mode 100644
index 0000000..2abf5e1
--- /dev/null
+++ "b/Server/\345\206\211\345\207\257/log/\346\227\245\345\277\227_\345\206\211\345\207\257_20250219.doc"
Binary files differ
diff --git "a/Server/\345\215\242\346\225\217/log/\346\227\245\345\277\227_\345\215\242\346\225\217_2.18.doc" "b/Server/\345\215\242\346\225\217/log/\346\227\245\345\277\227_\345\215\242\346\225\217_2.18.doc"
new file mode 100644
index 0000000..0c4571d
--- /dev/null
+++ "b/Server/\345\215\242\346\225\217/log/\346\227\245\345\277\227_\345\215\242\346\225\217_2.18.doc"
Binary files differ
diff --git "a/Server/\345\215\242\346\225\217/log/\346\227\245\345\277\227_\345\215\242\346\225\217_2.19.doc" "b/Server/\345\215\242\346\225\217/log/\346\227\245\345\277\227_\345\215\242\346\225\217_2.19.doc"
new file mode 100644
index 0000000..4318431
--- /dev/null
+++ "b/Server/\345\215\242\346\225\217/log/\346\227\245\345\277\227_\345\215\242\346\225\217_2.19.doc"
Binary files differ
diff --git "a/Server/\345\274\240\346\225\217\344\270\275/document/\346\227\245\345\277\227_\345\247\223\345\220\215_\346\227\245\346\234\237.doc" "b/Server/\345\274\240\346\225\217\344\270\275/document/\346\227\245\345\277\227_\345\247\223\345\220\215_\346\227\245\346\234\237.doc"
new file mode 100644
index 0000000..3fcca84
--- /dev/null
+++ "b/Server/\345\274\240\346\225\217\344\270\275/document/\346\227\245\345\277\227_\345\247\223\345\220\215_\346\227\245\346\234\237.doc"
Binary files differ

--
Gitblit v1.8.0