/
klischa
/
AstraScanner2
Обзор
Документация
Войти
/
klischa
/
AstraScanner2
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/controllers/CaptureSessionController.cpp
159 строк
6 KB
k k
fix: убрать terminate() из остановки захвата, добавить проверки границ в параллакс
15 июл 2026, 14:07
15 июл 2026, 14:07
dc2e5a0
Код
Авторство
О чём код?
#include "CaptureSessionController.h" #include "../capture/CaptureWorker.h" #include "../tracking/NeuralTracker.h" #include "../project/ProjectManager.h" #include <QThread> #include <QDebug> #include <QCoreApplication> #include <QEventLoop> CaptureSessionController::CaptureSessionController(QObject *parent) : QObject(parent) { } CaptureSessionController::~CaptureSessionController() { // Disconnect all signals before stopping to prevent use-after-free // from queued lambdas referencing 'this' after destruction. if (m_captureThread) { disconnect(m_captureThread, nullptr, this, nullptr); } if (m_worker) { disconnect(m_worker, nullptr, this, nullptr); } stop(); } void CaptureSessionController::setProjectManager(ProjectManager *projectManager) { m_projectManager = projectManager; if (m_worker) { m_worker->setProjectManager(projectManager); } } void CaptureSessionController::createWorker(bool enableCloudProcessing, float depthMin, float depthMax, bool colorCameraEnabled) { // Bug 12: Do NOT parent QThread to 'this' — deleting parent would kill // a running thread. Let the cleanup chain handle thread lifetime. m_captureThread = new QThread(); m_captureThread->setObjectName("CaptureWorkerThread"); m_worker = new CaptureWorker(); m_worker->moveToThread(m_captureThread); m_worker->setCloudProcessingEnabled(enableCloudProcessing); m_worker->resetTransform(); m_worker->setDepthRange(depthMin, depthMax); m_worker->setColorCameraEnabled(colorCameraEnabled); if (m_projectManager) { m_worker->setProjectManager(m_projectManager); } } void CaptureSessionController::initializeWorkerTracking(bool neuralTrackingEnabled, bool useCudaForNeural, const std::string &modelPath) { if (!neuralTrackingEnabled || !m_worker) { return; } qDebug() << "[CaptureSessionController] Creating NeuralTracker..."; auto neuralTracker = std::make_unique<NeuralTracker>(); if (neuralTracker->loadModel(modelPath, useCudaForNeural)) { qInfo() << "[CaptureSessionController] NeuralTracker model loaded" << (useCudaForNeural ? "(GPU)" : "(CPU)"); m_worker->setNeuralTracker(std::move(neuralTracker)); } else { qWarning() << "[CaptureSessionController] Failed to load NeuralTracker model"; } } void CaptureSessionController::connectWorkerSignals() { connect(m_captureThread, &QThread::started, m_worker, &CaptureWorker::process); connect(m_worker, &CaptureWorker::frameCaptured, this, &CaptureSessionController::frameCaptured); connect(m_worker, &CaptureWorker::pointCloudReady, this, &CaptureSessionController::pointCloudReady); connect(m_worker, &CaptureWorker::error, this, &CaptureSessionController::error); connect(m_worker, &CaptureWorker::frameProcessed, this, &CaptureSessionController::frameProcessed); connect(m_worker, &CaptureWorker::warning, this, &CaptureSessionController::warning); connect(m_worker, &CaptureWorker::markersDetected, this, &CaptureSessionController::markersDetected); connect(m_worker, &CaptureWorker::poseUpdated, this, &CaptureSessionController::poseUpdated); connect(m_worker, &CaptureWorker::scanQualityUpdated, this, &CaptureSessionController::scanQualityUpdated); connect(m_worker, &CaptureWorker::scannerPoseForProject, this, &CaptureSessionController::scannerPoseForProject); connect(m_worker, &CaptureWorker::trackingModeChangedForProject, this, &CaptureSessionController::trackingModeChangedForProject); connect(m_worker, &CaptureWorker::finished, this, &CaptureSessionController::finished); connect(m_worker, &CaptureWorker::finished, m_captureThread, [this]() { if (m_captureThread) m_captureThread->quit(); }); // Bug fix: guard the cleanup lambda so stale thread's finished signal // doesn't null out a NEW thread's pointer. QThread *thisThread = m_captureThread; connect(m_captureThread, &QThread::finished, m_captureThread, &QObject::deleteLater); connect(m_captureThread, &QThread::finished, this, [this, thisThread]() { if (m_captureThread == thisThread) { m_captureThread = nullptr; m_worker = nullptr; } }, Qt::QueuedConnection); } void CaptureSessionController::cleanupThread() { if (!m_captureThread) { m_worker = nullptr; return; } if (m_worker) { m_worker->requestStop(); } if (!m_captureThread->wait(5000)) { qWarning() << "Capture thread did not stop within 5s — disconnecting signals"; // Do NOT call terminate() — it corrupts COM objects and causes delayed crashes. // Disconnect all signals so the orphaned thread cannot deliver events to destroyed objects. m_captureThread->disconnect(); if (m_worker) { m_worker->disconnect(); m_worker = nullptr; } m_captureThread = nullptr; return; } m_worker = nullptr; m_captureThread = nullptr; } void CaptureSessionController::start(bool enableCloudProcessing, float depthMin, float depthMax, bool colorCameraEnabled, bool neuralTrackingEnabled, bool useCudaForNeural, const std::string &modelPath) { if (!stop()) { qCritical() << "CaptureSessionController: cannot start — previous thread still alive"; return; } createWorker(enableCloudProcessing, depthMin, depthMax, colorCameraEnabled); initializeWorkerTracking(neuralTrackingEnabled, useCudaForNeural, modelPath); connectWorkerSignals(); m_captureThread->start(); } bool CaptureSessionController::stop() { cleanupThread(); return true; } void CaptureSessionController::setCloudProcessingEnabled(bool enabled) { if (m_worker) { m_worker->setCloudProcessingEnabled(enabled); } }