Compare commits

...

2 Commits

277 changed files with 228639 additions and 165 deletions

View File

@ -138,6 +138,9 @@
<ClInclude Include="SourceCode\Media\VideoDecoder\RingBuffer.h" />
<QtMoc Include="SourceCode\Network\DelUserWindows.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="icon.rc" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2C8A5A59-2E79-4283-A0ED-D70DB305557E}</ProjectGuid>
<Keyword>QtVS_v304</Keyword>

View File

@ -309,4 +309,7 @@
<Filter>Network\mdns\qmdnsengine\include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="icon.rc" />
</ItemGroup>
</Project>

BIN
FactoryTestTool/Icon96.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 KiB

View File

@ -13,6 +13,85 @@ void yuvToRgb(int y, int u, int v, int& r, int& g, int& b)
b = qBound(0, b, 255);
}
// 将 QImage 数据转换为 YUV422
QByteArray convertQImageToYUV422(const QImage& image)
{
int width = image.width();
int height = image.height();
QByteArray yuvData;
yuvData.resize(width * height * 2); // YUV422: 每个像素2字节
int index = 0;
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; x += 2) {
QRgb pixel0 = image.pixel(x, y);
QRgb pixel1 = image.pixel(x + 1, y);
int r0 = qRed(pixel0);
int g0 = qGreen(pixel0);
int b0 = qBlue(pixel0);
int r1 = qRed(pixel1);
int g1 = qGreen(pixel1);
int b1 = qBlue(pixel1);
// 计算YUV值
int y0 = (0.299 * r0 + 0.587 * g0 + 0.114 * b0);
int u = (-0.169 * r0 - 0.331 * g0 + 0.5 * b0 + 128);
int y1 = (0.299 * r1 + 0.587 * g1 + 0.114 * b1);
int v = (0.5 * r0 - 0.419 * g0 - 0.081 * b0 + 128);
yuvData[index++] = static_cast<char>(qBound(0, y0, 255));
yuvData[index++] = static_cast<char>(qBound(0, u, 255));
yuvData[index++] = static_cast<char>(qBound(0, y1, 255));
yuvData[index++] = static_cast<char>(qBound(0, v, 255));
}
}
return yuvData;
}
// 将 QImage 数据转换为 YUV420
QByteArray convertQImageToYUV420(const QImage& image)
{
int width = image.width();
int height = image.height();
QByteArray yuvData;
int ySize = width * height;
int uvSize = (width / 2) * (height / 2);
yuvData.resize(ySize + 2 * uvSize); // Y 分量 + U 分量 + V 分量
int yIndex = 0;
int uIndex = ySize;
int vIndex = ySize + uvSize;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
QRgb pixel = image.pixel(x, y);
int r = qRed(pixel);
int g = qGreen(pixel);
int b = qBlue(pixel);
// 计算 YUV 值
int Y = qBound(0, static_cast<int>(0.299 * r + 0.587 * g + 0.114 * b), 255);
int U = qBound(0, static_cast<int>(-0.169 * r - 0.331 * g + 0.5 * b + 128), 255);
int V = qBound(0, static_cast<int>(0.5 * r - 0.419 * g - 0.081 * b + 128), 255);
// 填充 Y 分量
yuvData[yIndex++] = static_cast<char>(Y);
// 对 U 和 V 分量进行抽样
if (y % 2 == 0 && x % 2 == 0) {
yuvData[uIndex++] = static_cast<char>(U);
yuvData[vIndex++] = static_cast<char>(V);
}
}
}
return yuvData;
}
// 将 YUV422 数据转换为 QImage
QImage convertYUV422ToQImage(const QByteArray& yuv422Data, int width, int height)
{
@ -72,47 +151,72 @@ QImage convertYUV420ToQImage(const QByteArray& yuv420Data, int width, int height
return image;
}
void showPic(QLabel* leftLens_m_imageLabel, QLabel* rightLens_m_imageLabel, const QString& client, const QByteArray& valData)
void DataHandler::showPic(QSize labelSize, int lens_n,
int width, int height, int format, const QByteArray* valData)
{
int lens_n = static_cast<unsigned char>(valData[0]);
int width = (static_cast<unsigned char>(valData[2]) << 8) | static_cast<unsigned char>(valData[1]);
int height = (static_cast<unsigned char>(valData[4]) << 8) | static_cast<unsigned char>(valData[3]);
int format = static_cast<unsigned char>(valData[5]);
qDebug() << "lens_n = " << lens_n;
qDebug() << "format = " << format;
qDebug() << "width = " << width;
qDebug() << "height = " << height;
QByteArray yuvData = valData.mid(6);
qDebug() << "yuvData size = " << yuvData.size();
qDebug() << "yuvData size = " << valData->size();
QImage image;
if (format == YUV422) {
image = convertYUV422ToQImage(yuvData, width, height);
image = convertYUV422ToQImage(*valData, width, height);
}
else if (format == YUV420) {
image = convertYUV420ToQImage(yuvData, width, height);
image = convertYUV420ToQImage(*valData, width, height);
}
else {
qWarning() << "Unsupported image format!";
qWarning() << "Unsupported image format! Please use YUV422 or YUV420 format";
return;
}
// 旋转图像90度
QTransform transform;
transform.rotate(90); // 可以调整旋转角度
QImage rotatedImage = image.transformed(transform);
QImage scaledImage = rotatedImage.scaled(leftLens_m_imageLabel->size(), Qt::KeepAspectRatio);
QImage scaledImage = rotatedImage.scaled(labelSize, Qt::KeepAspectRatio);
QPixmap pixmap = QPixmap::fromImage(scaledImage);
if (lens_n == 0) {
leftLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
//rightLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
//leftLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
emit updateLeftLensImage(pixmap);
}
else if (lens_n == 1) {
rightLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
//rightLens_m_imageLabel->setPixmap(QPixmap::fromImage(scaledImage));
emit updateRightLensImage(pixmap);
}
else {
qWarning() << "Unsupported image lens!";
}
// 生成保存图片的目录
QString saveDirPath = QDir::currentPath() + "/frontBoardImage";
QDir saveDir(saveDirPath);
if (!saveDir.exists()) {
saveDir.mkpath(saveDirPath);
}
QString currentTime = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
QByteArray rotatedYuvData;
if (format == YUV422) {
rotatedYuvData = convertQImageToYUV422(rotatedImage);
}
else if (format == YUV420) {
rotatedYuvData = convertQImageToYUV420(rotatedImage);
}
QString yuvFileName = saveDirPath + "/" + currentTime + ".yuv";
QFile yuvFile(yuvFileName);
if (yuvFile.open(QIODevice::WriteOnly)) {
yuvFile.write(rotatedYuvData);
yuvFile.close();
qDebug() << "YUV image saved to" << yuvFileName;
}
else {
qWarning() << "Failed to save rotated YUV image to" << yuvFileName;
}
// 额外可以保存旋转后的图像为JPG或PNG格式
QString rotatedImageFileName = saveDirPath + "/" + currentTime + ".jpg";
rotatedImage.save(rotatedImageFileName, "JPG");
qDebug() << "JPG image saved to" << rotatedImageFileName;
}

View File

@ -7,18 +7,18 @@
#include <QLabel>
#include <QDebug>
#include "../RecvDataHandler/RecvDataHandler.h"
#define YUV420 1
#define YUV422 2
// YUV 转换为 RGB 的辅助函数
void yuvToRgb(int y, int u, int v, int& r, int& g, int& b);
QByteArray convertQImageToYUV422(const QImage& image);
QByteArray convertQImageToYUV420(const QImage& image);
// 转换YUV422
QImage convertYUV422ToQImage(const QByteArray& yuv422Data, int width, int height);
QImage convertYUV420ToQImage(const QByteArray& yuv420Data, int width, int height);
// 显示图片和视频的函数
void showPic(QLabel* leftLens_m_imageLabel, QLabel* rightLens_m_imageLabel, const QString& client, const QByteArray& valData);
//void showVideo(QLabel* videoLabel, const QString& client, const QByteArray& valData);
#endif // MEDIA_H

View File

@ -11,16 +11,16 @@ FFmpegDecoder::FFmpegDecoder(QObject* parent) :
frame(nullptr),
packet(nullptr),
swsContext(nullptr),
videoStreamIndex(-1) // 初始化成员变量
videoStreamIndex(-1)
{
av_log_set_level(AV_LOG_QUIET); // 设置日志级别为安静模式
avformat_network_init(); // 初始化网络
qDebug() << "FFmpegDecoder created";
qDebug() << "FFmpegDecoder thread created";
}
FFmpegDecoder::~FFmpegDecoder()
{
qDebug() << "Destroying FFmpegDecoder";
qDebug() << "Destroying FFmpegDecoder thread";
mutex.lock();
abort = true;
condition.wakeOne();
@ -28,7 +28,7 @@ FFmpegDecoder::~FFmpegDecoder()
wait();
cleanup();
avformat_network_deinit(); // 反初始化网络
qDebug() << "FFmpegDecoder destroyed";
qDebug() << "FFmpegDecoder thread destroyed";
}
void FFmpegDecoder::processVideo(int itemIndex)
@ -72,7 +72,7 @@ void FFmpegDecoder::stopFFmpegDecoder()
{
mutex.lock();
abort = true;
condition.wakeOne(); // 唤醒等待的线程
condition.wakeOne();
mutex.unlock();
}
@ -134,10 +134,8 @@ void FFmpegDecoder::run()
if (currentFileSize > fileSize) {
fileSize = currentFileSize;
file.seek(fileSize); // 设置文件读取位置到末尾
//qDebug() << "---------------1---------------";
// 读取并处理数据包
while (av_read_frame(formatContext, packet) >= 0) {
//qDebug() << "---------------2---------------";
if (packet->stream_index == videoStreamIndex) {
int ret = avcodec_send_packet(codecContext, packet);
if (ret < 0) {
@ -145,7 +143,6 @@ void FFmpegDecoder::run()
av_packet_unref(packet);
continue;
}
//qDebug() << "---------------3---------------";
while (ret >= 0) {
ret = avcodec_receive_frame(codecContext, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
@ -156,31 +153,23 @@ void FFmpegDecoder::run()
qWarning() << "Error during decoding";
break;
}
//qDebug() << "---------------4---------------";
QImage img = avFrameToQImage(frame);
//qDebug() << "---------------5---------------";
QImage scaledImage = img.scaled(labelSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
//qDebug() << "---------------6---------------";
currentVideoLabel->setPixmap(QPixmap::fromImage(scaledImage));
QThread::msleep(10); // Simulate 25 FPS frame rate
//qDebug() << "---------------7---------------";
}
}
av_packet_unref(packet);
//qDebug() << "---------------8---------------";
}
}
//qDebug() << "---------------9---------------";
mutex.lock();
if (restart) {
restart = false;
mutex.unlock();
break;
}
//qDebug() << "---------------10---------------";
mutex.unlock();
}
//qDebug() << "---------------11---------------";
cleanup();
file.close();

View File

@ -4,6 +4,7 @@
#include "ImageEnrollWindow.h"
#include "PasswordEnrollWindow.h"
#if TEST_TCP_MOVE_TO_MAIN
ClientHandler::ClientHandler(QTcpSocket* socket,
QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
@ -11,6 +12,14 @@ ClientHandler::ClientHandler(QTcpSocket* socket,
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson,
QJsonArray getPicJson, QJsonArray getVideoJson, int clientId, int isBackBoardOrAllBoard, QObject* parent)
: QObject(parent), socket(socket),
#else
ClientHandler::ClientHandler(QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig,
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson,
QJsonArray getPicJson, QJsonArray getVideoJson, int clientId, int isBackBoardOrAllBoard, QObject* parent)
: QObject(parent),
#endif
frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest),
frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson),
frontBoardLicenseJson(frontBoardLicenseJson),
@ -24,14 +33,30 @@ ClientHandler::ClientHandler(QTcpSocket* socket,
currentFrontBoardIndex(0), currentLicenseIndex(0), currentUuidIndex(0),
currentBackBoardIndex(0)
{
#if TEST_TCP_MOVE_TO_MAIN
connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onDataReceived);
connect(socket, &QTcpSocket::disconnected, this, &ClientHandler::onDisconnected);
qint64 bufferSize = socket->socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption).toLongLong();
#endif
}
ClientHandler::~ClientHandler() {
#if !TEST_TCP_MOVE_TO_MAIN
void ClientHandler::initialize(QTcpSocket* socket)
{
this->socket = socket;
// 连接信号槽,将其放在同一线程中处理
connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onDataReceived);
connect(socket, &QTcpSocket::disconnected, this, &ClientHandler::onDisconnected);
// 其他的 socket 操作都将在这个线程中进行
}
#endif
ClientHandler::~ClientHandler()
{
qDebug() << "ClientHandler destroyed for clientId:" << clientId;
}
@ -125,6 +150,30 @@ QString ClientHandler::getClientAddress() const
return socket->peerAddress().toString() + ":" + QString::number(socket->peerPort());
}
#if !TEST_TCP_MOVE_TO_MAIN
void ClientHandler::onSendData(const QByteArray& data, int isBoardType)
{
qDebug() << "Sending data isBoardType:" << isBoardType;
QByteArray prefix;
QDataStream stream(&prefix, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << quint32(0x55AA55AA);
if (isBoardType != 0) {
stream << quint16(0x0421);
}
else {
stream << quint16(0x0420);
}
stream << quint32(data.size());
prefix.append(data);
qDebug() << "Sending data:" << prefix.toHex();
socket->write(prefix);
socket->flush();
}
#endif
void ClientHandler::sendDataToClient(const QByteArray& data)
{
emit sendData(data, isBackBoardOrAllBoard);
@ -142,13 +191,11 @@ void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, con
isClickedSend = true;
isRecvImgData = false;
if (itemType == "handleVideo") {
if (itemIndex == 0) {
qDebug() << "0 itemIndex: " << itemIndex;
if (itemIndex == 0) {
isSingleSend = false;
isClickedSend = false;
}
else {
qDebug() << "!0 itemIndex: " << itemIndex;
stopReadVideoDataTimer(preVideoClientId);
}
}
@ -157,8 +204,8 @@ void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, con
isClickedSend = false;
isRecvImgData = true;
}
qDebug() << "itemIndex" << itemIndex;
qDebug() << "jsonArray.size()" << jsonArray.size();
//qDebug() << "itemIndex" << itemIndex;
//qDebug() << "jsonArray.size()" << jsonArray.size();
if (itemIndex >= 0 && itemIndex < jsonArray.size()) {
currentItemIndex = (itemType == "test") ? itemIndex : 0;
currentFuncItemIndex = (itemType == "func") ? itemIndex : 0;
@ -182,7 +229,7 @@ void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, con
}
QString itemData = QJsonDocument(currentItem).toJson();
//emit sendData(itemData.toUtf8());
sendDataToSomeClient(controlClientId, itemData.toUtf8());
emit sendDataToSomeClient(controlClientId, itemData.toUtf8());
// 设置超时处理
if (currentItem.contains("timeout")) {
@ -210,12 +257,11 @@ void ClientHandler::sendGetPicItem(int itemIndex, int GetPicCamIndex)
void ClientHandler::sendGetVideoItem(int itemIndex, int GetVideoCamIndex)
{
qDebug() << "sendGetVideoItem itemIndex:" << itemIndex;
qDebug() << "sendGetVideoItem GetVideoCamIndex:" << GetVideoCamIndex;
if(isBackBoardOrAllBoard) {
sendJsonItem(getVideoJson, itemIndex, QString::number(GetVideoCamIndex), "handleVideo");
}
else {
sendJsonItem(getVideoJson, itemIndex, "", "handleVideo");
sendJsonItem(getVideoJson, itemIndex, QString::number(GetVideoCamIndex), "handleVideo");
}
}
@ -339,7 +385,7 @@ void ClientHandler::sendDevInfoJsonItem(const QJsonObject& jsonItem, int itemInd
QString itemData = QJsonDocument(jsonItem).toJson();
//emit sendData(itemData.toUtf8());
sendDataToSomeClient(controlClientId, itemData.toUtf8());
emit sendDataToSomeClient(controlClientId, itemData.toUtf8());
if (jsonItem.contains("timeout")) {
int timeout = jsonItem.value("timeout").toInt();
@ -400,7 +446,7 @@ void ClientHandler::sendNextItem()
}
}
//emit sendData(itemData.toUtf8());
sendDataToSomeClient(controlClientId, itemData.toUtf8());
emit sendDataToSomeClient(controlClientId, itemData.toUtf8());
if (currentItem.contains("timeout")) {
int timeout = currentItem.value("timeout").toInt();
@ -521,7 +567,7 @@ void ClientHandler::setThreadPriority(QThread::Priority priority) {
QThread* thread = QThread::currentThread();
if (thread) {
thread->setPriority(priority);
qDebug() << "Thread priority set to" << priority << "for clientId:" << clientId;
//qDebug() << "Thread priority set to" << priority << "for clientId:" << clientId;
}
else {
qWarning() << "Failed to set thread priority. Current thread is null.";
@ -531,7 +577,6 @@ void ClientHandler::setThreadPriority(QThread::Priority priority) {
// 处理数据接收
void ClientHandler::onDataReceived()
{
// 接收其他数据 添加区分 视频与其他数据 的标志位
//qDebug() << "isRecvVideoData:" << isRecvVideoData;
//qDebug() << "isPowerOnSend:" << isPowerOnSend;
//qDebug() << "isClickedSend:" << isClickedSend;
@ -556,20 +601,16 @@ void ClientHandler::onDataReceived()
emit startTimeout(0);
}
if (!allData.isEmpty()) {
//emit dataReceived(getClientAddress(), allData, 0xFF, currentItemIndex, currentFuncItemIndex, "", "");
emit dataReceived(getClientAddress(), allData, 0xFF, currentItemIndex, currentFuncItemIndex, getCurrentItemLable(), "", currentJson, currentJsonItem);
if (!isSingleSend && !isPowerOnSend) {
currentItemIndex ++;
itemsProcessedCount ++;
}
}
// 由于启动了 onTimeoutRead 所以 isSingleSend = false 导致连续发送
//if (isSingleSend && clientId >= 4) {
if (isSingleSend) {
isSingleSend = false; // 重置标志
isSingleSend = false;
isClickedSend = false;
}
else if (isPowerOnSend && currentFrontBoardIndex < frontBoardDevInfoJson.size()) {
sendDevInfoItem();
}

View File

@ -24,26 +24,37 @@
#include "DelUserWindows.h"
#define TEST_TCP_MOVE_TO_MAIN 0
class ClientHandler : public QObject, public QRunnable
{
Q_OBJECT
public:
#if TEST_TCP_MOVE_TO_MAIN
explicit ClientHandler(QTcpSocket* socket, QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest,
QJsonArray frontBoardFuncConfig, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson,
QJsonArray backBoardUuidJson, QJsonArray getPicJson, QJsonArray getVideoJson,
int clientId, int isBackBoardOrAllBoard, QObject* parent = nullptr);
#else
explicit ClientHandler(QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest,
QJsonArray frontBoardFuncConfig, QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig, QJsonArray backBoardDevInfoJson,
QJsonArray backBoardUuidJson, QJsonArray getPicJson, QJsonArray getVideoJson,
int clientId, int isBackBoardOrAllBoard, QObject* parent = nullptr);
#endif
~ClientHandler();
int preVideoClientId = 0;
int controlClientId = 0;
void sendDevInfoItem();
//int preVideoClientId = 0;
bool isData_Stuck() const;
//static int pre_H264_clientId; // 预览H264的客户端ID
QTcpSocket* getSocket() const { return socket; }
#if !TEST_TCP_MOVE_TO_MAIN
void ClientHandler::initialize(QTcpSocket* socket);
#endif
// QRunnable 的虚函数,在线程池中执行
void run() override;
// 开始处理客户端
@ -103,12 +114,15 @@ signals:
void allItemsProcessed(const QString& client, int itemsProcessedCount);
// 通知主线程启动定时器
void startTimeout(int timeout);
void selectClientDisconnected(int clientId);
void startReadTimer(int clientId);
void stopReadTimer(int clientId);
void sendDataToSomeClient(int clientId, const QByteArray& data);
void selectClientDisconnected(int client_Id);
void startReadTimer(int client_Id);
void stopReadTimer(int client_Id);
void sendDataToSomeClient(int client_Id, const QByteArray& data);
public slots:
#if !TEST_TCP_MOVE_TO_MAIN
void onSendData(const QByteArray& data, int isBoardType);
#endif
// 处理数据接收
void onDataReceived();
// 处理超时

View File

@ -2,20 +2,16 @@
#include "RecvDataHandler.h"
#include "../Network/ClientHandler.h"
DataHandler::DataHandler(QLabel* leftLens_imageLabel, QLabel* rightLens_imageLabel, QLabel* videoLabel,
QLineEdit* VideoResolutionEdit,
QTextEdit* licenseHwInfoEdit, QMap<QString, QLineEdit*>* devInfoLineEdits,
QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig,
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson,
QJsonArray getPicJson, QJsonArray getVideoJson, QObject* parent)
DataHandler::DataHandler(QLabel* videoLabel, QLineEdit* VideoResolutionEdit, QSize labelSize, QMap<QString, QLineEdit*>* devInfoLineEdits,
QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig,
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson,
QJsonArray getPicJson, QJsonArray getVideoJson, QObject* parent)
: QObject(parent),
leftLens_m_imageLabel(leftLens_imageLabel),
rightLens_m_imageLabel(rightLens_imageLabel),
videoLabel(videoLabel),
VideoResolutionEdit(VideoResolutionEdit),
licenseHwInfoEdit(licenseHwInfoEdit),
labelSize(labelSize),
devInfoLineEdits(devInfoLineEdits),
frontBoardOneClickTest(frontBoardOneClickTest), frontBoardTest(frontBoardTest),
frontBoardFuncConfig(frontBoardFuncConfig), frontBoardDevInfoJson(frontBoardDevInfoJson),
@ -23,18 +19,18 @@ DataHandler::DataHandler(QLabel* leftLens_imageLabel, QLabel* rightLens_imageLab
backBoardOneClickTest(backBoardOneClickTest), backBoardTest(backBoardTest),
backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson),
backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson),
ffmpegDecoder(new FFmpegDecoder()), // 初始化FFmpeg解码器
buffer(new QByteArray())
buffer(new QByteArray()), picBuffer(new QByteArray()),
ffmpegDecoder(new FFmpegDecoder()) // 初始化FFmpeg解码器
{
ffmpegDecoder->initialize(); // 初始化解码器
clearAllRecvData();
initializeMsgIdToCmdMap();
qDebug() << "DataHandler created";
qDebug() << "DataHandler thread created";
}
DataHandler::~DataHandler()
{
qDebug() << "---1--- DataHandler destroyed";
if (ffmpegDecoder) {
ffmpegDecoder->stopFFmpegDecoder();
ffmpegDecoder->requestInterruption();
@ -44,7 +40,7 @@ DataHandler::~DataHandler()
}
delete buffer;
buffer = nullptr;
qDebug() << "---2--- DataHandler destroyed";
qDebug() << "DataHandler thread destroyed";
}
void DataHandler::handleOpenFocusWindow(int itemIndex)
@ -96,7 +92,8 @@ void DataHandler::showVideo(const QString& client, const QByteArray& valData)
void DataHandler::updateLineEdit(int msg_id, const QByteArray& actual_data) {
QString dataStr = QString(actual_data.toHex(' '));
licenseHwInfoEdit->setPlainText(dataStr);
//licenseHwInfoEdit->setPlainText(dataStr);
emit updateLicenseHwInfoEdit(dataStr);
if (msgIdToCmdMap.contains(msg_id)) {
QString cmd = msgIdToCmdMap[msg_id];
@ -133,7 +130,6 @@ void DataHandler::handleData(const QString& client, const QByteArray& recvData,
qDebug() << "read file data size:" << recvdata.size();
#endif
//qDebug() << "---Received data size:" << recvData.size();
// 将接收到的数据追加到buffer
buffer->append(recvData);
@ -147,18 +143,16 @@ void DataHandler::handleData(const QString& client, const QByteArray& recvData,
(static_cast<unsigned char>(buffer->at(7)) << 8) |
(static_cast<unsigned char>(buffer->at(6)));
//qDebug() << "---Received dataSize:" << dataSize;
//qDebug() << "---msg_id:" << QString::number(msg_id, 16).toUpper();
//qDebug() << "---(static_cast<unsigned char>(buffer->at(10)):" << static_cast<unsigned char>(buffer->at(10));
//qDebug() << "---(static_cast<unsigned char>(buffer->at(11)):" << static_cast<unsigned char>(buffer->at(11));
//qDebug() << "---(static_cast<unsigned char>(buffer->at(12)):" << static_cast<unsigned char>(buffer->at(12));
//qDebug() << "---(static_cast<unsigned char>(buffer->at(13)):" << static_cast<unsigned char>(buffer->at(13));
//qDebug() << "---(static_cast<unsigned char>(buffer->at(14)):" << static_cast<unsigned char>(buffer->at(14));
//qDebug() << "---(static_cast<unsigned char>(buffer->at(15)):" << static_cast<unsigned char>(buffer->at(15));
//qDebug() << "---msg_id:" << QString::number(msg_id, 16).toUpper();
// 第11字节为返回 OK/NG
bool success = (static_cast<unsigned char>(buffer->at(10)) == 0x00);
int totalSize = 10 + dataSize; // 数据头大小(10字节) + 实际数据大小
if (buffer->size() >= totalSize) {
// 调试查看收到的前19个字节
/*for (int i = 0; i < 19; i++) {
qDebug() << "buffer->at(" << i << "):" << QString::number(static_cast<unsigned char>(buffer->at(i)), 16).toUpper();
}*/
// 去掉前面 11 字节
QByteArray data = buffer->mid(11, dataSize);
//QByteArray data = buffer->mid(10, dataSize);
@ -166,7 +160,7 @@ void DataHandler::handleData(const QString& client, const QByteArray& recvData,
QByteArray actual_data = hexStringToByteArray(hexString);
//qDebug() << "---Received hexString:" << hexString;
buffer->remove(0, totalSize); // 移除已处理的数据
if(msg_id != 0x0040 && msg_id != START_VIDEO) {
if(msg_id != 0x0040 && msg_id != START_VIDEO && msg_id != GET_IMG) {
//if (msg_id != 0x0040) {
qDebug() << "--- msg_id:" << msg_id;
qDebug() << "--- clientLastMsgId.value(client, 0):" << clientLastMsgId.value(client, 0);
@ -179,8 +173,6 @@ void DataHandler::handleData(const QString& client, const QByteArray& recvData,
true, itemData, funcItemData, jsonArray, itemJsonIndex);
}
clientLastMsgId[client] = msg_id;
qDebug() << "--- client:" << client;
qDebug() << "--- clientLastMsgId[client]:" << clientLastMsgId[client];
}
handleCmd(msg_id, client, actual_data);
}
@ -225,21 +217,6 @@ void DataHandler::handleCmd(int msg_id, const QString& client, QByteArray actual
void DataHandler::handleFrontCmd(int msg_id, const QString& client, QByteArray actual_data)
{
switch (msg_id) {
case 0x0019:
{
showPic(leftLens_m_imageLabel, rightLens_m_imageLabel, client, actual_data);
}
break;
case 0x0011:
{
showVideo(client, actual_data);
}
break;
case 0x0021:
{
//showVideo(client, actual_data);
}
break;
case FACE_ENROLL_SINGLE:
{
@ -297,7 +274,29 @@ void DataHandler::handleFrontCmd(int msg_id, const QString& client, QByteArray a
break;
case GET_IMG:
{
showPic(leftLens_m_imageLabel, rightLens_m_imageLabel, client, actual_data);
int lens_n = static_cast<unsigned char>(actual_data[1]);
int width = (static_cast<unsigned char>(actual_data[3]) << 8) | static_cast<unsigned char>(actual_data[2]);
int height = (static_cast<unsigned char>(actual_data[5]) << 8) | static_cast<unsigned char>(actual_data[4]);
int format = static_cast<unsigned char>(actual_data[6]);
qint32 picSize = width * height * 1.5;
QByteArray yuvData = actual_data.mid(7);
qDebug() << "showPic width * height * 1.5:" << picSize;
qDebug() << "showPic picBuffer.size():" << picBuffer->size();
if (yuvData.size() + picBuffer->size() == picSize) {
picBuffer->append(yuvData);
showPic(labelSize, lens_n, width, height, format, picBuffer);
picBuffer->remove(0, picSize);
}
else if (yuvData.size() + picBuffer->size() > picSize) {
picBuffer->append(yuvData);
qDebug() << "width is " << width << " height is " << height << "PIC size is" << picSize;
qDebug() << "But recv PIC size is " << picBuffer->size();
picBuffer->remove(0, picBuffer->size());
}
else {
picBuffer->append(yuvData);
}
}
break;
case START_VIDEO:
@ -507,7 +506,6 @@ void DataHandler::handleDevInfo(int msg_id, const QString& client, QByteArray ac
case GET_FRONT_HW_INFO:
{
qDebug() << "GET_FRONT_HW_INFO";
//QString dataStr = QString(actual_data.toHex(' '));
QStringList hexList;
QString dataStr;
qDebug() << "actual_data.size(): " << actual_data.size();
@ -521,7 +519,8 @@ void DataHandler::handleDevInfo(int msg_id, const QString& client, QByteArray ac
else
dataStr = "前板发送的HW INFO 数据大小不正确";
QString displayText = dataStr;
licenseHwInfoEdit->setPlainText(displayText);
//licenseHwInfoEdit->setPlainText(displayText);
emit updateLicenseHwInfoEdit(displayText);
}
break;
case WRITE_FRONT_LICENSE:

View File

@ -33,9 +33,7 @@ class DataHandler : public QObject
Q_OBJECT
public:
explicit DataHandler(QLabel* leftLens_imageLabel, QLabel* rightLens_imageLabel, QLabel* videoLabel,
QLineEdit* VideoResolutionEdit,
QTextEdit* licenseHwInfoEdit, QMap<QString, QLineEdit*>* devInfoLineEdits,
explicit DataHandler(QLabel* videoLabel, QLineEdit* VideoResolutionEdit, QSize labelSize, QMap<QString, QLineEdit*>* devInfoLineEdits,
QJsonArray frontBoardOneClickTest, QJsonArray frontBoardTest, QJsonArray frontBoardFuncConfig,
QJsonArray frontBoardDevInfoJson, QJsonArray frontBoardLicenseJson,
QJsonArray backBoardOneClickTest, QJsonArray backBoardTest, QJsonArray backBoardFuncConfig,
@ -52,7 +50,11 @@ signals:
void statusUpdated(const QString& clientAddress, int currentItemIndex, int currentFuncItemIndex,
bool success, const QString& currentItemLabel, const QString& currentFuncItemLabel,
const QJsonArray& jsonArray, int itemJsonIndex);
void updateLicenseHwInfoEdit(const QString& text);
void updateLeftLensImage(const QPixmap& pixmap);
void updateRightLensImage(const QPixmap& pixmap);
void updateVideoLabel(const QPixmap& pixmap);
void updateVideoResolution(const QString& resolutionText);
private:
QJsonArray frontBoardOneClickTest; // 前板一键功能测试 JSON
QJsonArray frontBoardTest; // 前板单项测试 JSON
@ -67,20 +69,22 @@ private:
QJsonArray getDevInfoJson; // 获取设备信息 JSON 配置
QJsonArray getPicJson; // 发送取图指令 JSON 配置
QJsonArray getVideoJson; // 发送拉视频指令 JSON 配置
QLabel* leftLens_m_imageLabel;
QLabel* rightLens_m_imageLabel;
//QLabel* leftLens_m_imageLabel;
//QLabel* rightLens_m_imageLabel;
QLabel* videoLabel;
QLineEdit* VideoResolutionEdit;
QTextEdit* licenseHwInfoEdit;
//QTextEdit* licenseHwInfoEdit;
QByteArray allRecvData; // 完整的一帧数据
int remain = 0;
int start_run = 0;
long dataLen = 0;
FFmpegDecoder* ffmpegDecoder;
QByteArray *buffer;
QByteArray* buffer;
QByteArray* picBuffer;
QHash<QString, unsigned char> clientLastMsgId;
QMap<QString, QLineEdit*>* devInfoLineEdits;
QMap<int, QString> msgIdToCmdMap;
QSize labelSize;
// 如果接收十六进制数据,转为二进制
QByteArray hexStringToByteArray(const QString& hexString);
@ -92,6 +96,8 @@ private:
void handleBackCmd(int msg_id, const QString& client, QByteArray actual_data);
void initializeMsgIdToCmdMap();
void updateLineEdit(int msg_id, const QByteArray& actual_data);
void showPic(QSize labelSize, int lens_n,
int width, int height, int format, const QByteArray* valData);
};
#endif // DATAHANDLER_H

View File

@ -43,17 +43,17 @@ MainWidget::MainWidget(QWidget* parent) :
connect(server, &QTcpServer::newConnection, this, [this]() {
// 检查是否有挂起的连接
while (server->hasPendingConnections()) {
QTcpSocket* socket = server->nextPendingConnection();
int clientId = nextClientId ++;
QHostAddress clientIp = socket->peerAddress();
quint16 clientPort = socket->peerPort();
QString ipString = clientIp.toString();
QTcpSocket* socket = server->nextPendingConnection();
int clientId = nextClientId ++;
QHostAddress clientIp = socket->peerAddress();
quint16 clientPort = socket->peerPort();
QString ipString = clientIp.toString();
if (ipString.startsWith("::ffff:")) {
ipString = ipString.mid(7);
}
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
qDebug() << "> A client is connected. ID:" << clientId;
qDebug() << "> Client IP:" << ipString << " Port:" << clientPort;
qDebug() << "> Client IP:" << ipString << " Port:" << clientPort;
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
if (ipString.startsWith("10.10.10")) {
@ -64,7 +64,6 @@ MainWidget::MainWidget(QWidget* parent) :
qDebug() << "The client IP address is back board or all board";
isBackBoardOrAllBoard = clientId;
}
stopMdnsService();
connectedClientsCount ++;
updateServerButtonText();
@ -87,27 +86,38 @@ MainWidget::MainWidget(QWidget* parent) :
});
QThread* thread = new QThread(this);
#if TEST_TCP_MOVE_TO_MAIN
ClientHandler* handler = new ClientHandler(socket, frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson,
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
backBoardUuidJson, getPicJson, getVideoJson, clientId, isBackBoardOrAllBoard, nullptr);
#else
ClientHandler* handler = new ClientHandler(frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson,
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
backBoardUuidJson, getPicJson, getVideoJson, clientId, isBackBoardOrAllBoard, nullptr);
/*
* QObject::moveToThread: Cannot move objects with a parent
* 线线
*/
socket->setParent(nullptr);
// 将 socket 移动到新的线程中
socket->moveToThread(thread);
// 将 socket 传递到 handler
handler->initialize(socket);
#endif
// 将 ClientHandler 移到线程池中的线程
handler->moveToThread(thread);
// 创建 DataHandler 对象并连接信号
DataHandler* dataHandler = new DataHandler(leftLens_imageLabel, rightLens_imageLabel, videoLabel,
VideoResolutionEdit,
licenseHwInfoEdit, &devInfoLineEdits,
DataHandler* dataHandler = new DataHandler(videoLabel, VideoResolutionEdit, leftLens_imageLabel->size(), &devInfoLineEdits,
frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson,
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
backBoardUuidJson, getPicJson, getVideoJson, nullptr);
qDebug() << "dataHandler->moveToThread(thread)";
// 将 DataHandler 移到线程池中的线程
dataHandler->moveToThread(thread);
#if TEST_TCP_MOVE_TO_MAIN
// 将sendData信号连接到主线程中的槽上
connect(handler, &ClientHandler::sendData, this, [socket](const QByteArray& data, int isBoardType) {
/*socket->write(data);
@ -131,7 +141,9 @@ MainWidget::MainWidget(QWidget* parent) :
socket->write(prefix);
socket->flush();
});
#else
connect(handler, &ClientHandler::sendData, handler, &ClientHandler::onSendData, Qt::QueuedConnection);
#endif
connect(handler, &ClientHandler::startTimeout, this, [this, clientId](int timeout) {
this->onStartTimeout(clientId, timeout);
});
@ -143,8 +155,7 @@ MainWidget::MainWidget(QWidget* parent) :
connect(handler, &ClientHandler::clientDisconnected, this, &MainWidget::onClientDisconnected);
connect(handler, &ClientHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed);
connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient);
dataHandlers[clientId] = dataHandler;
connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData);
connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
@ -152,15 +163,21 @@ MainWidget::MainWidget(QWidget* parent) :
connect(thread, &QThread::finished, this, [=]() {
onThreadFinished(thread, handler, dataHandler);
});
connect(dataHandler, &DataHandler::updateLicenseHwInfoEdit, this, [this](const QString& text) {
licenseHwInfoEdit->setPlainText(text);
});
connect(dataHandler, &DataHandler::updateLeftLensImage, leftLens_imageLabel, &QLabel::setPixmap);
connect(dataHandler, &DataHandler::updateRightLensImage, rightLens_imageLabel, &QLabel::setPixmap);
connect(dataHandler, &DataHandler::updateVideoLabel, videoLabel, &QLabel::setPixmap);
connect(dataHandler, &DataHandler::updateVideoResolution, VideoResolutionEdit, &QLineEdit::setText);
// 启动新的线程
thread->start();
connect(handler, &ClientHandler::startReadTimer, this, &MainWidget::startClientReadTimer);
connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer);
//handler->getClientId() == handler->preVideoClientId
qDebug() << "---- handler->getClientId():" << handler->getClientId();
qDebug() << "---- handler->preVideoClientId:" << handler->preVideoClientId;
connect(this, &MainWidget::openFocusWindowRequested, dataHandler, &DataHandler::handleOpenFocusWindow);
connect(handler, &ClientHandler::startReadTimer, this, &MainWidget::startClientReadTimer);
connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer);
connect(this, &MainWidget::openFocusWindowRequested, dataHandler, &DataHandler::handleOpenFocusWindow);
// 创建和管理定时器
QTimer* readTimer = new QTimer(this);
@ -295,7 +312,6 @@ void MainWidget::onClientDisconnected(ClientHandler* handler)
*/
handler->deleteLater(); // 延迟删除 ClientHandler 对象
qDebug() << "-----------dataHandlers-----------";
if (dataHandlers.contains(clientId)) {
DataHandler* dataHandler = dataHandlers[clientId];
dataHandlers.remove(clientId); // 从容器中移除
@ -448,7 +464,7 @@ void MainWidget::setupUI()
mainLayout->addLayout(rightVerticalLayout, 3);
setLayout(mainLayout);
setWindowTitle("SL100 工厂产测工具 - V0.0.1");
setWindowTitle("SL100 工厂产测工具 - V0.0.4");
resize(1340, 900);
connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked);
@ -680,7 +696,7 @@ void MainWidget::FactoryToolSendPostLicenseToHttpServer(const QString& hardware_
}
void MainWidget::startClientReadTimer(int clientId) {
qDebug() << "------ startClientReadTimer clientId:" << clientId;
//qDebug() << "------ startClientReadTimer clientId:" << clientId;
if (clientReadTimers.contains(clientId)) {
clientReadTimers[clientId]->start(10);
}
@ -1095,24 +1111,6 @@ void MainWidget::stopMdnsService()
mServiceProvider->stopServiceBroadcast();
}
#if TEST_UDP_BROADCAST
void MainWidget::sendMulticastMessage()
{
QByteArray datagram = "--------------------------------- Test multicast message from MainWidget";
QHostAddress groupAddress("224.0.0.251");
quint16 port = 5353;
qint64 sentBytes = multicastSocket->writeDatagram(datagram, groupAddress, port);
if (sentBytes == -1) {
qWarning() << "Failed to send multicast message:" << multicastSocket->errorString();
}
else {
qDebug() << "Multicast message sentBytes:" << sentBytes;
qDebug() << "Multicast message sent:" << datagram;
}
}
#endif
// 处理开始服务器按键点击事件
void MainWidget::onStartServerClicked()
{
@ -1187,7 +1185,6 @@ void MainWidget::onSendGetPicClicked()
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("getPicIndex").toInt();
if (itemIndex < 2) {
button->setStyleSheet("background-color: green;");
if (lastClickedGetPicCamIndex != -1 && lastClickedGetPicCamIndex != itemIndex) {
@ -1268,6 +1265,7 @@ void MainWidget::onSendGetVideoClicked()
//QMutexLocker locker(&mutex);
for (ClientHandler* handler : clients) {
if (handler->getClientId() == handler->controlClientId) {
qDebug() << "lens number:" << lastClickedGetVideoCamIndex;
handler->sendGetVideoItem(itemIndex - 7, lastClickedGetVideoCamIndex);
break;
}

View File

@ -52,7 +52,6 @@
#include "../Network/ClientHandler.h"
#include "../Network/httpClient.h"
#include "../Network/mdns/qmdnsengine/include/server.h"
#include "../Network/mdns/qmdnsengine/include/hostname.h"
#include "../Network/mdns/qmdnsengine/include/provider.h"

View File

@ -23,8 +23,8 @@ int main(int argc, char* argv[]) {
//FreeConsole(); // 关闭控制台窗口
QApplication app(argc, argv);
qDebug() << "Current working directory:" << QDir::currentPath();
QIcon appIcon("./app_icon.ico");
app.setWindowIcon(appIcon);
//QIcon appIcon("./app_icon.ico");
//app.setWindowIcon(appIcon);
MainWidget w;
w.show();

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More