BlackBorderProcessor.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include <iostream>
  2. #include <cmath>
  3. #include <hyperion/Hyperion.h>
  4. // Blackborder includes
  5. #include <blackborder/BlackBorderProcessor.h>
  6. using namespace hyperion;
  7. BlackBorderProcessor::BlackBorderProcessor(Hyperion* hyperion, QObject* parent)
  8. : QObject(parent)
  9. , _hyperion(hyperion)
  10. , _enabled(false)
  11. , _unknownSwitchCnt(600)
  12. , _borderSwitchCnt(50)
  13. , _maxInconsistentCnt(10)
  14. , _blurRemoveCnt(1)
  15. , _detectionMode("default")
  16. , _detector(nullptr)
  17. , _currentBorder({true, -1, -1})
  18. , _previousDetectedBorder({true, -1, -1})
  19. , _consistentCnt(0)
  20. , _inconsistentCnt(10)
  21. , _oldThreshold(-0.1)
  22. , _hardDisabled(false)
  23. , _userEnabled(false)
  24. {
  25. // init
  26. handleSettingsUpdate(settings::BLACKBORDER, _hyperion->getSetting(settings::BLACKBORDER));
  27. // listen for settings updates
  28. connect(_hyperion, &Hyperion::settingsChanged, this, &BlackBorderProcessor::handleSettingsUpdate);
  29. // listen for component state changes
  30. connect(_hyperion, &Hyperion::compStateChangeRequest, this, &BlackBorderProcessor::handleCompStateChangeRequest);
  31. _detector = new BlackBorderDetector(_oldThreshold);
  32. }
  33. BlackBorderProcessor::~BlackBorderProcessor()
  34. {
  35. delete _detector;
  36. }
  37. void BlackBorderProcessor::handleSettingsUpdate(settings::type type, const QJsonDocument& config)
  38. {
  39. if(type == settings::BLACKBORDER)
  40. {
  41. if (_hyperion->isComponentEnabled(COMP_BLACKBORDER) == -1)
  42. {
  43. //Disable, if service is not available
  44. _enabled = false;
  45. _userEnabled = false;
  46. }
  47. else
  48. {
  49. const QJsonObject& obj = config.object();
  50. _unknownSwitchCnt = obj["unknownFrameCnt"].toInt(600);
  51. _borderSwitchCnt = obj["borderFrameCnt"].toInt(50);
  52. _maxInconsistentCnt = obj["maxInconsistentCnt"].toInt(10);
  53. _blurRemoveCnt = obj["blurRemoveCnt"].toInt(1);
  54. _detectionMode = obj["mode"].toString("default");
  55. const double newThreshold = obj["threshold"].toDouble(5.0) / 100.0;
  56. if (fabs(_oldThreshold - newThreshold) > std::numeric_limits<double>::epsilon())
  57. {
  58. _oldThreshold = newThreshold;
  59. delete _detector;
  60. _detector = new BlackBorderDetector(newThreshold);
  61. }
  62. Debug(Logger::getInstance("BLACKBORDER", "I"+QString::number(_hyperion->getInstanceIndex())), "Set mode to: %s", QSTRING_CSTR(_detectionMode));
  63. // eval the comp state
  64. handleCompStateChangeRequest(hyperion::COMP_BLACKBORDER, obj["enable"].toBool(true));
  65. }
  66. }
  67. }
  68. void BlackBorderProcessor::handleCompStateChangeRequest(hyperion::Components component, bool enable)
  69. {
  70. if(component == hyperion::COMP_BLACKBORDER)
  71. {
  72. _userEnabled = enable;
  73. if(enable)
  74. {
  75. // eg effects and probably other components don't want a BB, mimik a wrong comp state to the comp register
  76. if(!_hardDisabled)
  77. _enabled = enable;
  78. }
  79. else
  80. {
  81. _enabled = enable;
  82. }
  83. _hyperion->setNewComponentState(hyperion::COMP_BLACKBORDER, enable);
  84. }
  85. }
  86. void BlackBorderProcessor::setHardDisable(bool disable)
  87. {
  88. if (disable)
  89. {
  90. _enabled = false;
  91. }
  92. else
  93. {
  94. // the user has the last word to enable
  95. if(_userEnabled)
  96. _enabled = true;
  97. }
  98. _hardDisabled = disable;
  99. };
  100. BlackBorder BlackBorderProcessor::getCurrentBorder() const
  101. {
  102. return _currentBorder;
  103. }
  104. bool BlackBorderProcessor::enabled() const
  105. {
  106. return _enabled;
  107. }
  108. void BlackBorderProcessor::setEnabled(bool enable)
  109. {
  110. _enabled = enable;
  111. }
  112. bool BlackBorderProcessor::updateBorder(const BlackBorder & newDetectedBorder)
  113. {
  114. // the new changes ignore false small borders (no reset of consistance)
  115. // as long as the previous stable state returns within 10 frames
  116. // and will only switch to a new border if it is realy detected stable >50 frames
  117. // sometimes the grabber delivers "bad" frames with a smaller black border (looks like random number every few frames and even when freezing the image)
  118. // maybe some interferences of the power supply or bad signal causing this effect - not exactly sure what causes it but changing the power supply of the converter significantly increased that "random" effect on my system
  119. // (you can check with the debug output below or if you want i can provide some output logs)
  120. // this "random effect" caused the old algorithm to switch to that smaller border immediatly, resulting in a too small border being detected
  121. // makes it look like the border detectionn is not working - since the new 3 line detection algorithm is more precise this became a problem specialy in dark scenes
  122. // wisc
  123. // set the consistency counter
  124. if (newDetectedBorder == _previousDetectedBorder)
  125. {
  126. ++_consistentCnt;
  127. _inconsistentCnt = 0;
  128. }
  129. else
  130. {
  131. ++_inconsistentCnt;
  132. if (_inconsistentCnt <= _maxInconsistentCnt)// only few inconsistent frames
  133. {
  134. //discard the newDetectedBorder -> keep the consistent count for previousDetectedBorder
  135. return false;
  136. }
  137. // the inconsistency threshold is reached
  138. // -> give the newDetectedBorder a chance to proof that its consistent
  139. _previousDetectedBorder = newDetectedBorder;
  140. _consistentCnt = 0;
  141. }
  142. // check if there is a change
  143. if (_currentBorder == newDetectedBorder)
  144. {
  145. // No change required
  146. _inconsistentCnt = 0; // we have found a consistent border -> reset _inconsistentCnt
  147. return false;
  148. }
  149. bool borderChanged = false;
  150. if (newDetectedBorder.unknown)
  151. {
  152. // apply the unknown border if we consistently can't determine a border
  153. if (_consistentCnt == _unknownSwitchCnt)
  154. {
  155. _currentBorder = newDetectedBorder;
  156. borderChanged = true;
  157. }
  158. }
  159. else
  160. {
  161. // apply the detected border if it has been detected consistently
  162. if (_currentBorder.unknown || _consistentCnt == _borderSwitchCnt)
  163. {
  164. _currentBorder = newDetectedBorder;
  165. borderChanged = true;
  166. }
  167. }
  168. return borderChanged;
  169. }