diff --git a/cmake/installers.cmake b/cmake/installers.cmake index d1767608b..d8f734e1f 100644 --- a/cmake/installers.cmake +++ b/cmake/installers.cmake @@ -2,18 +2,6 @@ macro(DeployApple TARGET) if(EXISTS ${TARGET_FILE}) install ( TARGETS hyperhdr DESTINATION "share/.." COMPONENT "HyperHDR" ) - execute_process( - COMMAND bash -c "cd ${CMAKE_CURRENT_BINARY_DIR} && tar -xzf ${PROJECT_SOURCE_DIR}/resources/lut/lut_lin_tables.tar.xz" - RESULT_VARIABLE STATUS - OUTPUT_VARIABLE OUTPUT1 - ) - if(STATUS AND NOT STATUS EQUAL 0) - message( FATAL_ERROR "LUT tar.xz Bad exit status (xz-tools installed?)") - else() - message( STATUS "LUT tar.xz tar extracted") - endif() - - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lut_lin_tables.3d" DESTINATION "hyperhdr.app/Contents/lut" COMPONENT "HyperHDR") install(FILES "${PROJECT_SOURCE_DIR}/cmake/osx/Hyperhdr.icns" DESTINATION "hyperhdr.app/Contents/Resources" COMPONENT "HyperHDR") install(FILES "${PROJECT_SOURCE_DIR}/LICENSE" DESTINATION "hyperhdr.app/Contents/Resources" COMPONENT "HyperHDR") install(FILES "${PROJECT_SOURCE_DIR}/3RD_PARTY_LICENSES" DESTINATION "hyperhdr.app/Contents/Resources" COMPONENT "HyperHDR") @@ -214,8 +202,6 @@ macro(DeployUnix TARGET) if (EXISTS ${TARGET_FILE}) include(GetPrerequisites) - # Install LUT - install(FILES "${PROJECT_SOURCE_DIR}/resources/lut/lut_lin_tables.tar.xz" DESTINATION "share/hyperhdr/lut" COMPONENT "HyperHDR") install(FILES "${PROJECT_SOURCE_DIR}/LICENSE" DESTINATION "share/hyperhdr" COMPONENT "HyperHDR") install(FILES "${PROJECT_SOURCE_DIR}/3RD_PARTY_LICENSES" DESTINATION "share/hyperhdr" COMPONENT "HyperHDR") @@ -622,12 +608,6 @@ macro(DeployWindows TARGET) COMPONENT "HyperHDR" ) - install( - FILES ${PROJECT_SOURCE_DIR}/resources/lut/lut_lin_tables.tar.xz - DESTINATION "bin" - COMPONENT "HyperHDR" - ) - INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION bin COMPONENT "HyperHDR") install(FILES "${PROJECT_SOURCE_DIR}/LICENSE" DESTINATION bin COMPONENT "HyperHDR") diff --git a/cmake/linux/arch/INSTALL b/cmake/linux/arch/INSTALL index 46c79a9fd..f0042b374 100644 --- a/cmake/linux/arch/INSTALL +++ b/cmake/linux/arch/INSTALL @@ -84,10 +84,6 @@ post_install() { start_msg="" restart_msg="" - echo "Extracting LUT table..." - tar -xf /usr/share/hyperhdr/lut/lut_lin_tables.tar.xz -C /usr/share/hyperhdr/lut/ - rm -f -v /usr/share/hyperhdr/lut/lut_lin_tables.tar.xz - if grep -m1 systemd /proc/1/comm > /dev/null then # systemd @@ -255,8 +251,6 @@ pre_remove() { rm -v /usr/share/applications/hyperhdr* 2>/dev/null rm -rv /usr/share/pixmaps/hyperhdr 2>/dev/null - echo "Removing LUT table" - rm -f -v /usr/share/hyperhdr/lut/lut_lin_tables.3d exit 0 } diff --git a/cmake/linux/debian/postinst b/cmake/linux/debian/postinst index bfc69a585..ecaec4269 100644 --- a/cmake/linux/debian/postinst +++ b/cmake/linux/debian/postinst @@ -44,10 +44,6 @@ fi start_msg="" restart_msg="" -echo "Extracting LUT table..." -tar -xf /usr/share/hyperhdr/lut/lut_lin_tables.tar.xz -C /usr/share/hyperhdr/lut/ -rm -f -v /usr/share/hyperhdr/lut/lut_lin_tables.tar.xz - if grep -m1 systemd /proc/1/comm > /dev/null then # systemd diff --git a/cmake/linux/debian/prerm b/cmake/linux/debian/prerm index 80d891567..38ae4f282 100644 --- a/cmake/linux/debian/prerm +++ b/cmake/linux/debian/prerm @@ -48,6 +48,4 @@ desktop-file-edit --set-key=NoDisplay --set-value=true /usr/share/applications/h rm -v /usr/share/applications/hyperhdr* 2>/dev/null rm -rv /usr/share/pixmaps/hyperhdr 2>/dev/null -echo "Removing LUT table" -rm -f -v /usr/share/hyperhdr/lut/lut_lin_tables.3d exit 0 diff --git a/cmake/linux/rpm/postinst b/cmake/linux/rpm/postinst index 305885f42..f091ba954 100644 --- a/cmake/linux/rpm/postinst +++ b/cmake/linux/rpm/postinst @@ -44,10 +44,6 @@ fi start_msg="" restart_msg="" -echo "Extracting LUT table..." -tar -xf /usr/share/hyperhdr/lut/lut_lin_tables.tar.xz -C /usr/share/hyperhdr/lut/ -rm -f -v /usr/share/hyperhdr/lut/lut_lin_tables.tar.xz - if grep -m1 systemd /proc/1/comm > /dev/null then # systemd diff --git a/cmake/linux/rpm/prerm b/cmake/linux/rpm/prerm index 51404971d..4c55df23f 100644 --- a/cmake/linux/rpm/prerm +++ b/cmake/linux/rpm/prerm @@ -54,6 +54,4 @@ then firewall-cmd --remove-port=8090/tcp fi -echo "Removing LUT table" -rm -f -v /usr/share/hyperhdr/lut/lut_lin_tables.3d exit 0 diff --git a/cmake/windows/plugins/ExtractLut.dll b/cmake/windows/plugins/ExtractLut.dll deleted file mode 100644 index d58a14a1a..000000000 Binary files a/cmake/windows/plugins/ExtractLut.dll and /dev/null differ diff --git a/cmake/windows/template/NSIS.template.in b/cmake/windows/template/NSIS.template.in index ab2e97f5b..0333ec8df 100644 --- a/cmake/windows/template/NSIS.template.in +++ b/cmake/windows/template/NSIS.template.in @@ -793,16 +793,6 @@ Section "-Core installation" ; Install Visual c++ Redistributable ExecWait '"$INSTDIR\bin\vc_redist.x64.exe" /install /quiet /norestart' -Push "$INSTDIR\bin\lut_lin_tables.tar.xz" -Push "$INSTDIR\bin\lut_lin_tables.3d" - -ExtractLut::extract -Pop $0 -StrCmp $0 success SUCCESS -MessageBox MB_OK|MB_ICONSTOP "$0" -MessageBox MB_OK|MB_ICONSTOP "Please extract $INSTDIR\bin\lut_lin_tables.tar.xz manually using 7-zip" -SUCCESS: - SectionEnd Section "-Add to path" @@ -925,7 +915,7 @@ Section "Uninstall" ;Remove files we installed. ;Keep the list of directories here in sync with the File commands above. @CPACK_NSIS_DELETE_FILES@ -Delete "$INSTDIR\bin\lut_lin_tables.3d" + @CPACK_NSIS_DELETE_DIRECTORIES@ !ifdef CPACK_NSIS_ADD_REMOVE diff --git a/include/base/Grabber.h b/include/base/Grabber.h index 954597fe1..d7e854871 100644 --- a/include/base/Grabber.h +++ b/include/base/Grabber.h @@ -93,6 +93,8 @@ class Grabber : public DetectionAutomatic, public DetectionManual, protected Lut int getActualFps() override; + void pleaseWaitForLut(bool videoGrabber = true); + void setEncoding(QString enc); void setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue); diff --git a/include/base/HyperHdrManager.h b/include/base/HyperHdrManager.h index 1683dd071..e10a1415e 100644 --- a/include/base/HyperHdrManager.h +++ b/include/base/HyperHdrManager.h @@ -89,6 +89,8 @@ public slots: void clearInstancePriority(int instance, int priority); std::list getEffects(); + void handleLutRequestSignal(); + signals: void SignalInstanceStateChanged(InstanceState state, quint8 instance, const QString& name = QString()); diff --git a/include/grabber/linux/v4l2/V4L2Grabber.h b/include/grabber/linux/v4l2/V4L2Grabber.h index 3c21f34b8..a1fac27f8 100644 --- a/include/grabber/linux/v4l2/V4L2Grabber.h +++ b/include/grabber/linux/v4l2/V4L2Grabber.h @@ -50,7 +50,7 @@ private slots: void enumerateV4L2devices(bool silent); - void loadLutFile(PixelFormat color = PixelFormat::NO_CHANGE); + void loadLutFile(PixelFormat color = PixelFormat::NO_CHANGE, bool silent = false); void getV4L2devices(); diff --git a/include/grabber/osx/AVF/AVFGrabber.h b/include/grabber/osx/AVF/AVFGrabber.h index b6ba7c2b0..44fa0d567 100644 --- a/include/grabber/osx/AVF/AVFGrabber.h +++ b/include/grabber/osx/AVF/AVFGrabber.h @@ -60,7 +60,7 @@ public slots: void enumerateAVFdevices(bool silent); - void loadLutFile(PixelFormat color = PixelFormat::NO_CHANGE); + void loadLutFile(PixelFormat color = PixelFormat::NO_CHANGE, bool silent = false); void enumerateAVFdevices(); diff --git a/include/grabber/windows/DX/DxGrabber.h b/include/grabber/windows/DX/DxGrabber.h index ff3e6a5bc..23eefa480 100644 --- a/include/grabber/windows/DX/DxGrabber.h +++ b/include/grabber/windows/DX/DxGrabber.h @@ -115,7 +115,7 @@ public slots: void enumerateDevices(bool silent); - void loadLutFile(PixelFormat color = PixelFormat::NO_CHANGE); + void loadLutFile(PixelFormat color = PixelFormat::NO_CHANGE, bool silent = false); void getDevices(); diff --git a/include/grabber/windows/MF/MFGrabber.h b/include/grabber/windows/MF/MFGrabber.h index e8fe95f26..6aa5dbd24 100644 --- a/include/grabber/windows/MF/MFGrabber.h +++ b/include/grabber/windows/MF/MFGrabber.h @@ -39,7 +39,7 @@ public slots: void enumerateMFdevices(bool silent); - void loadLutFile(PixelFormat color = PixelFormat::NO_CHANGE); + void loadLutFile(PixelFormat color = PixelFormat::NO_CHANGE, bool silent = false); void getMFdevices(); diff --git a/include/lut-calibrator/LutCalibrator.h b/include/lut-calibrator/LutCalibrator.h index 8245bfa02..764f288c3 100644 --- a/include/lut-calibrator/LutCalibrator.h +++ b/include/lut-calibrator/LutCalibrator.h @@ -72,6 +72,7 @@ class LutCalibrator : public QObject ~LutCalibrator(); static void sendReport(Logger* _log, QString report); static QString CreateLutFile(Logger* _log, QString _rootPath, BestResult* bestResult, std::vector>>* all); + static void CreateDefaultLut(QString filepath); signals: void SignalLutCalibrationUpdated(const QJsonObject& data); diff --git a/include/utils/GlobalSignals.h b/include/utils/GlobalSignals.h index 4be144493..c15d5f816 100644 --- a/include/utils/GlobalSignals.h +++ b/include/utils/GlobalSignals.h @@ -97,4 +97,6 @@ class GlobalSignals : public QObject void SignalDiscoveryEvent(DiscoveryRecord message); void SignalSetLut(MemoryBuffer* lut); + + void SignalLutRequest(); }; diff --git a/sources/base/Grabber.cpp b/sources/base/Grabber.cpp index 858243496..7e54ff3fd 100644 --- a/sources/base/Grabber.cpp +++ b/sources/base/Grabber.cpp @@ -37,6 +37,11 @@ const QString Grabber::AUTO_SETTING = QString("auto"); const int Grabber::AUTO_INPUT = -1; const int Grabber::AUTO_FPS = 0; +namespace +{ + const unsigned char pleasewait[] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x1f,0xff,0xff,0xff,0x31,0x88,0x25,0xb5,0xfe,0x21,0x9f,0xfe,0xdb,0x7b,0x6d,0xb6,0x7f,0x6d,0xbf,0xfe,0xfb,0xc,0x6d,0xb5,0xbf,0x6d,0xbf,0xfe,0xdb,0x6f,0x6d,0xb5,0xbf,0x6d,0xbf,0xff,0x30,0x98,0xc5,0x6,0x3f,0x6d,0x1f,0xff,0xff,0xff,0xef,0xff,0xff,0x7f,0xbf,0xff,0xff,0xff,0xef,0xff,0xff,0x7f,0xbf,0xff,0xff,0xff,0xfd,0xff,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x3c,0x44,0x13,0x9f,0xdb,0x84,0x4f,0xff,0x7e,0xbd,0xbd,0x7f,0xdb,0xb6,0xdf,0xff,0x7e,0x86,0x3b,0xf,0xa5,0xc6,0xdf,0xff,0xe,0xb7,0xb7,0x6f,0xb6,0xf6,0xdf,0xff,0x76,0xcc,0x79,0x9f,0x24,0x8c,0x8f,0xff,0x76,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0x76,0xff,0xff,0xff,0xff,0xff,0xdf,0xfe,0xc,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; +}; + Grabber::Grabber(const QString& configurationPath, const QString& grabberName) : _configurationPath(configurationPath) @@ -83,6 +88,64 @@ Grabber::~Grabber() disconnect(GlobalSignals::getInstance(), &GlobalSignals::SignalSetLut, this, &Grabber::signalSetLutHandler); } +void Grabber::pleaseWaitForLut(bool videoGrabber) +{ + Image image(_actualWidth, _actualHeight); + double sizeX = _actualWidth / 64.0; + double sizeY = _actualHeight / 32.0; + + auto timer = InternalClock::now() / 1200; + + ColorRgb fgColor, bgColor; + + if (timer % 8 < 2) + { + bgColor = ColorRgb::WHITE; + fgColor = ColorRgb::BLACK; + } + else if (timer % 8 < 4) + { + bgColor = ColorRgb::RED; + fgColor = ColorRgb::BLACK; + } + else if (timer % 8 < 6) + { + bgColor = ColorRgb::GREEN; + fgColor = ColorRgb::BLACK; + } + else + { + bgColor = ColorRgb::BLUE; + fgColor = ColorRgb::WHITE; + } + + image.fastBox(0, 0, image.width(), image.height(), bgColor.red, bgColor.green, bgColor.blue); + + for (int y = 0; y < 32; y++) + for (int x = 0; x < 64; x++) + { + int index = (31 - y) * 8 + (x / 8); + uint8_t bit = 1 << (7 - (x % 8)); + if (index < static_cast(sizeof(pleasewait)) && !(pleasewait[index] & bit)) + { + int fromX = sizeX * x; + int fromY = sizeY * y; + image.fastBox(fromX, fromY, fromX + sizeX, fromY + sizeY, fgColor.red, fgColor.green, fgColor.blue); + } + } + + if (videoGrabber) + { + emit GlobalSignals::getInstance()->SignalNewVideoImage(_deviceName, image); + } + else + { + emit GlobalSignals::getInstance()->SignalNewSystemImage(_deviceName, image); + } + + emit GlobalSignals::getInstance()->SignalLutRequest(); +} + bool sortDevicePropertiesItem(const Grabber::DevicePropertiesItem& v1, const Grabber::DevicePropertiesItem& v2) { if (v1.x != v2.x) diff --git a/sources/base/HyperHdrManager.cpp b/sources/base/HyperHdrManager.cpp index ac39e0dd9..a098c6d0a 100644 --- a/sources/base/HyperHdrManager.cpp +++ b/sources/base/HyperHdrManager.cpp @@ -38,6 +38,7 @@ #include #include #include +#include QString HyperHdrManager::getRootPath() { @@ -58,6 +59,7 @@ HyperHdrManager::HyperHdrManager(const QString& rootPath) connect(this, &HyperHdrManager::SignalBenchmarkCapture, &_videoBenchmark, &VideoBenchmark::benchmarkCapture); connect(GlobalSignals::getInstance(), &GlobalSignals::SignalRequestComponent, this, &HyperHdrManager::handleRequestComponent); + connect(GlobalSignals::getInstance(), &GlobalSignals::SignalLutRequest, this, &HyperHdrManager::handleLutRequestSignal); } void HyperHdrManager::handleRequestComponent(hyperhdr::Components component, int hyperHdrInd, bool listen) @@ -74,6 +76,18 @@ HyperHdrManager::~HyperHdrManager() Debug(_log, "HyperHdrManager has been removed"); } +void HyperHdrManager::handleLutRequestSignal() +{ + static bool requested = false; + + if (!requested) + { + requested = true; + + LutCalibrator::CreateDefaultLut(_rootPath); + } +} + void HyperHdrManager::startAll(bool disableOnStartup) { auto instanceList = _instanceTable->getAllInstances(true); diff --git a/sources/grabber/linux/v4l2/V4L2Grabber.cpp b/sources/grabber/linux/v4l2/V4L2Grabber.cpp index 56275355b..83a34c0b3 100644 --- a/sources/grabber/linux/v4l2/V4L2Grabber.cpp +++ b/sources/grabber/linux/v4l2/V4L2Grabber.cpp @@ -123,14 +123,14 @@ QString V4L2Grabber::GetSharedLut() return ret; } -void V4L2Grabber::loadLutFile(PixelFormat color) +void V4L2Grabber::loadLutFile(PixelFormat color, bool silent) { // load lut table QString fileName1 = QString("%1%2").arg(_configurationPath).arg("/lut_lin_tables.3d"); QString fileName2 = QString("%1%2").arg(GetSharedLut()).arg("/lut_lin_tables.3d"); QString fileName3 = QString("/usr/share/hyperhdr/lut/lut_lin_tables.3d"); - Grabber::loadLutFile(_log, color, QList{fileName1, fileName2, fileName3}); + Grabber::loadLutFile((!silent) ? _log : nullptr, color, QList{fileName1, fileName2, fileName3}); } void V4L2Grabber::setHdrToneMappingEnabled(int mode) @@ -1210,9 +1210,23 @@ bool V4L2Grabber::process_image(v4l2_buffer* buf, const void* frameImageBuffer, V4L2Worker* _workerThread = _V4L2WorkerManager.workers[i]; if ((_actualVideoFormat == PixelFormat::YUYV || _actualVideoFormat == PixelFormat::I420 || - _actualVideoFormat == PixelFormat::NV12) && !_lutBufferInit) + _actualVideoFormat == PixelFormat::NV12 || _hdrToneMappingEnabled) && !_lutBufferInit) { - loadLutFile(); + if ((_actualVideoFormat == PixelFormat::YUYV) || (_actualVideoFormat == PixelFormat::I420) || (_actualVideoFormat == PixelFormat::NV12) || (_actualVideoFormat == PixelFormat::MJPEG)) + { + loadLutFile(PixelFormat::YUYV, true); + } + else + { + loadLutFile(PixelFormat::RGB24, true); + } + + if (!_lutBufferInit) + { + pleaseWaitForLut(); + _V4L2WorkerManager.workers[i]->noBusy(); + return true; + } } bool directAccess = !(_signalAutoDetectionEnabled || _signalDetectionEnabled || isCalibrating() ); diff --git a/sources/grabber/osx/AVF/AVFGrabber.mm b/sources/grabber/osx/AVF/AVFGrabber.mm index fd2c33cad..d9d2248d2 100644 --- a/sources/grabber/osx/AVF/AVFGrabber.mm +++ b/sources/grabber/osx/AVF/AVFGrabber.mm @@ -176,13 +176,13 @@ - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleB return ret; } -void AVFGrabber::loadLutFile(PixelFormat color) +void AVFGrabber::loadLutFile(PixelFormat color, bool silent) { // load lut table QString fileName1 = QString("%1%2").arg(_configurationPath).arg("/lut_lin_tables.3d"); QString fileName2 = QString("%1%2").arg(GetSharedLut()).arg("/lut_lin_tables.3d"); - Grabber::loadLutFile(_log, color, QList{fileName1, fileName2}); + Grabber::loadLutFile((!silent) ? _log : nullptr, color, QList{fileName1, fileName2}); } void AVFGrabber::setHdrToneMappingEnabled(int mode) @@ -813,9 +813,23 @@ - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleB AVFWorker* _workerThread = _AVFWorkerManager.workers[i]; if ((_actualVideoFormat == PixelFormat::YUYV || _actualVideoFormat == PixelFormat::I420 || - _actualVideoFormat == PixelFormat::NV12) && !_lutBufferInit) + _actualVideoFormat == PixelFormat::NV12 || _hdrToneMappingEnabled) && !_lutBufferInit) { - loadLutFile(); + if ((_actualVideoFormat == PixelFormat::YUYV) || (_actualVideoFormat == PixelFormat::I420) || (_actualVideoFormat == PixelFormat::NV12) || (_actualVideoFormat == PixelFormat::MJPEG)) + { + loadLutFile(PixelFormat::YUYV, true); + } + else + { + loadLutFile(PixelFormat::RGB24, true); + } + + if (!_lutBufferInit) + { + pleaseWaitForLut(); + _AVFWorkerManager.workers[i]->noBusy(); + return true; + } } bool directAccess = !(_signalAutoDetectionEnabled || _signalDetectionEnabled || isCalibrating()); diff --git a/sources/grabber/windows/DX/DxGrabber.cpp b/sources/grabber/windows/DX/DxGrabber.cpp index b3fc5048a..66d42faee 100644 --- a/sources/grabber/windows/DX/DxGrabber.cpp +++ b/sources/grabber/windows/DX/DxGrabber.cpp @@ -83,13 +83,13 @@ QString DxGrabber::GetSharedLut() return QCoreApplication::applicationDirPath(); } -void DxGrabber::loadLutFile(PixelFormat color) +void DxGrabber::loadLutFile(PixelFormat color, bool silent) { // load lut table QString fileName1 = QString("%1%2").arg(_configurationPath).arg("/lut_lin_tables.3d"); QString fileName2 = QString("%1%2").arg(GetSharedLut()).arg("/lut_lin_tables.3d"); - Grabber::loadLutFile(_log, color, QList{fileName1, fileName2}); + Grabber::loadLutFile((!silent) ? _log : nullptr, color, QList{fileName1, fileName2}); } void DxGrabber::setHdrToneMappingEnabled(int mode) @@ -848,7 +848,16 @@ void DxGrabber::captureFrame(DisplayHandle& display) if (CHECK(status) && CHECK(_d3dContext->Map(display.d3dSourceTexture, 0, D3D11_MAP_READ, 0, &internalMap))) { - processSystemFrameBGRA((uint8_t*)internalMap.pData, (int)internalMap.RowPitch, !(_hardware && display.wideGamut)); + bool useLut = !(_hardware && display.wideGamut); + if (_hdrToneMappingEnabled && !_lutBufferInit && useLut) + { + loadLutFile(PixelFormat::RGB24, true); + pleaseWaitForLut(false); + } + else + { + processSystemFrameBGRA((uint8_t*)internalMap.pData, (int)internalMap.RowPitch, _hdrToneMappingEnabled && useLut); + } _d3dContext->Unmap(display.d3dSourceTexture, 0); } @@ -930,7 +939,16 @@ int DxGrabber::captureFrame(DisplayHandle& display, Image& image) int divide = getTargetSystemFrameDimension(display.actualWidth, display.actualHeight, targetSizeX, targetSizeY); image = Image(targetSizeX, targetSizeY); - FrameDecoder::processSystemImageBGRA(image, targetSizeX, targetSizeY, 0, 0, (uint8_t*)internalMap.pData, display.actualWidth, display.actualHeight, divide, (_hdrToneMappingEnabled == 0 || !_lutBufferInit || !useLut) ? nullptr : _lut.data(), lineSize); + + if (_hdrToneMappingEnabled && !_lutBufferInit && useLut) + { + loadLutFile(PixelFormat::RGB24, true); + pleaseWaitForLut(false); + } + else + { + FrameDecoder::processSystemImageBGRA(image, targetSizeX, targetSizeY, 0, 0, (uint8_t*)internalMap.pData, display.actualWidth, display.actualHeight, divide, (_hdrToneMappingEnabled == 0 || !_lutBufferInit || !useLut) ? nullptr : _lut.data(), lineSize); + } result = 1; _d3dContext->Unmap(display.d3dSourceTexture, 0); diff --git a/sources/grabber/windows/MF/MFGrabber.cpp b/sources/grabber/windows/MF/MFGrabber.cpp index f46867ded..b6f6f8ea2 100644 --- a/sources/grabber/windows/MF/MFGrabber.cpp +++ b/sources/grabber/windows/MF/MFGrabber.cpp @@ -166,13 +166,13 @@ QString MFGrabber::GetSharedLut() return QCoreApplication::applicationDirPath(); } -void MFGrabber::loadLutFile(PixelFormat color) +void MFGrabber::loadLutFile(PixelFormat color, bool silent) { // load lut table QString fileName1 = QString("%1%2").arg(_configurationPath).arg("/lut_lin_tables.3d"); QString fileName2 = QString("%1%2").arg(GetSharedLut()).arg("/lut_lin_tables.3d"); - Grabber::loadLutFile(_log, color, QList{fileName1, fileName2}); + Grabber::loadLutFile((!silent) ? _log : nullptr, color, QList{fileName1, fileName2}); } void MFGrabber::setHdrToneMappingEnabled(int mode) @@ -1008,9 +1008,23 @@ bool MFGrabber::process_image(const void* frameImageBuffer, int size) MFWorker* _workerThread = _MFWorkerManager.workers[i]; if ((_actualVideoFormat == PixelFormat::YUYV || _actualVideoFormat == PixelFormat::I420 || - _actualVideoFormat == PixelFormat::NV12) && !_lutBufferInit) + _actualVideoFormat == PixelFormat::NV12 || _hdrToneMappingEnabled) && !_lutBufferInit) { - loadLutFile(); + if ((_actualVideoFormat == PixelFormat::YUYV) || (_actualVideoFormat == PixelFormat::I420) || (_actualVideoFormat == PixelFormat::NV12) || (_actualVideoFormat == PixelFormat::MJPEG)) + { + loadLutFile(PixelFormat::YUYV, true); + } + else + { + loadLutFile(PixelFormat::RGB24, true); + } + + if (!_lutBufferInit) + { + pleaseWaitForLut(); + _MFWorkerManager.workers[i]->noBusy(); + return true; + } } bool directAccess = !(_signalAutoDetectionEnabled || _signalDetectionEnabled || isCalibrating()); diff --git a/sources/lut-calibrator/LutCalibrator.cpp b/sources/lut-calibrator/LutCalibrator.cpp index 7ec8e9b64..e56057fb1 100644 --- a/sources/lut-calibrator/LutCalibrator.cpp +++ b/sources/lut-calibrator/LutCalibrator.cpp @@ -95,6 +95,22 @@ class CreateLutWorker : public QRunnable void run() override; }; +class DefaultLutCreatorWorker : public QRunnable +{ + Logger* log; + BestResult bestResult; + QString path; +public: + DefaultLutCreatorWorker(BestResult& _bestResult,QString _path) : + log(Logger::getInstance("LUT_CREATOR")), + bestResult(_bestResult), + path(_path) + { + setAutoDelete(true); + }; + void run() override; +}; + ///////////////////////////////////////////////////////////////// // LUT CALIBRATOR // ///////////////////////////////////////////////////////////////// @@ -1511,7 +1527,8 @@ void CreateLutWorker::run() QString LutCalibrator::CreateLutFile(Logger* _log, QString _rootPath, BestResult* bestResult, std::vector>>* all) { // write LUT table - QString fileName = QString("%1%2").arg(_rootPath).arg("/lut_lin_tables.3d"); + QString fileName = QString("%1%2").arg(_rootPath).arg("/lut_lin_tables.3d.tmp"); + QString finalFileName = QString("%1%2").arg(_rootPath).arg("/lut_lin_tables.3d"); std::fstream file; file.open(fileName.toStdString(), std::ios::trunc | std::ios::out | std::ios::binary); @@ -1523,21 +1540,25 @@ QString LutCalibrator::CreateLutFile(Logger* _log, QString _rootPath, BestResult { MemoryBuffer _lut; YuvConverter yuvConverter; + QThreadPool threadPool; + + std::remove(finalFileName.toStdString().c_str()); - Info(_log, "Writing LUT file to: %s", QSTRING_CSTR(fileName)); + Info(_log, "Writing LUT to temp file: %s", QSTRING_CSTR(fileName)); + Info(_log, "Number of threads for LUT creator: %i", threadPool.maxThreadCount()); _lut.resize(LUT_FILE_SIZE); for (int phase = 0; phase < 3; phase++) { - const int vDelta = std::ceil(256.0 / QThreadPool::globalInstance()->maxThreadCount()); + const int vDelta = std::ceil(256.0 / threadPool.maxThreadCount()); for (int v = 0; v <= 255; v += vDelta) { auto worker = new CreateLutWorker(v, std::min(v + vDelta, 256), phase, &yuvConverter, bestResult, _lut.data()); - QThreadPool::globalInstance()->start(worker); + threadPool.start(worker); } - QThreadPool::globalInstance()->waitForDone(); + threadPool.waitForDone(); if (phase == 1 && all != nullptr) { @@ -1566,8 +1587,15 @@ QString LutCalibrator::CreateLutFile(Logger* _log, QString _rootPath, BestResult file.write(reinterpret_cast(_lut.data()), _lut.size()); } + file.flush(); file.close(); + } + + if (std::rename(fileName.toStdString().c_str(), finalFileName.toStdString().c_str())) + { + return QString("Could not rename %1 to %2").arg(fileName).arg(finalFileName); } + return QString(); } @@ -1779,3 +1807,56 @@ bool LutCalibrator::setTestData() return true; } +void LutCalibrator::CreateDefaultLut(QString filepath) +{ + BestResult bestResult; + bestResult.coef = YuvConverter::YUV_COEFS(1); + bestResult.coefMatrix = double4x4{ {1.16438356164, 1.16438356164, 1.16438356164, 0}, {-4.43119136738e-17, -0.387076923077, 2.02178571429, 0}, {1.58691964286, -0.821942994505, -1.77247654695e-16, 0}, {-0.869630789302, 0.53382122535, -1.08791650359, 1} }; + bestResult.coefDelta = double2{ 0.004, -0.002 }; + bestResult.coloredAspectMode = 3; + bestResult.colorAspect = std::pair(double3{ 1.08301468119, 1.00959155269, 1.10863646026 }, double3{ 1.06441799482, 1.00700595321, 1.06831049137 }); + bestResult.aspect = double3{ 0.9925, 1, 1.035 }; + bestResult.bt2020Range = 0; + bestResult.altConvert = 1; + bestResult.altPrimariesToSrgb = double3x3{ {1.62995144161, -0.159968936426, -0.0191389994477}, {-0.556261837808, 1.17281602107, -0.104271698501}, {-0.0736896038051, -0.0128470846442, 1.12341069795} }; + bestResult.gamma = ColorSpaceMath::HDR_GAMMA(0); + bestResult.gammaHLG = 0.000000; + bestResult.lchEnabled = 0; + bestResult.lchPrimaries = LchLists{ + std::list{ + + }, + + std::list{ + + }, + + std::list{ + + }, + }; + bestResult.nits = 229.625687; + bestResult.signal.range = YuvConverter::COLOR_RANGE(2); + bestResult.signal.yRange = 0.858824; + bestResult.signal.upYLimit = 0.572549; + bestResult.signal.downYLimit = 0.062745; + bestResult.signal.yShift = 0.062745; + bestResult.signal.isSourceP010 = 0; + bestResult.minError = 212.883333; + + auto worker = new DefaultLutCreatorWorker(bestResult, filepath); + QThreadPool::globalInstance()->start(worker); +} + +void DefaultLutCreatorWorker::run() +{ + QString errorMessage = LutCalibrator::CreateLutFile(log, path, &bestResult, nullptr); + if (!errorMessage.isEmpty()) + { + Error(log, "Error while creating LUT: %s", QSTRING_CSTR(errorMessage)); + } + else + { + Info(log, "The default LUT has been created: %s/lut_lin_tables.3d", QSTRING_CSTR(path)); + } +} diff --git a/sources/utils/LutLoader.cpp b/sources/utils/LutLoader.cpp index baa9efac5..53018a8a9 100644 --- a/sources/utils/LutLoader.cpp +++ b/sources/utils/LutLoader.cpp @@ -41,32 +41,9 @@ void LutLoader::loadLutFile(Logger* _log, PixelFormat color, const QList %s", length, (LUT_FILE_SIZE * 3), QSTRING_CSTR(fileName3d)); + { + if (_log) Error(_log, "LUT file has invalid length: %i vs %i => %s", length, (LUT_FILE_SIZE * 3), QSTRING_CSTR(fileName3d)); + } file.close(); return; } else - Warning(_log, "LUT file is not found here: %s", QSTRING_CSTR(fileName3d)); + { + if (_log) Warning(_log, "LUT file is not found here: %s", QSTRING_CSTR(fileName3d)); + } } - Error(_log, "Could not find any required LUT file"); + if (_log) Error(_log, "Could not find any required LUT file"); } }