Workaround both std::round-s in video streaming.

This commit is contained in:
John Preston 2021-08-24 12:42:27 +03:00
parent f21d7821e7
commit 8f5830d520
1 changed files with 30 additions and 25 deletions

View File

@ -78,6 +78,31 @@ static_assert(kDisplaySkipped != kTimeUnknown);
return result; return result;
} }
[[nodiscard]] float64 SafeRound(float64 value) {
Expects(!std::isnan(value));
if (const auto result = std::round(value); !std::isnan(result)) {
return result;
}
const auto errors = std::fetestexcept(FE_ALL_EXCEPT);
LOG(("Streaming Error: Got NAN in std::round(%1), fe: %2."
).arg(value
).arg(errors));
if (const auto result = std::round(value); !std::isnan(result)) {
return result;
}
std::feclearexcept(FE_ALL_EXCEPT);
if (const auto result = std::round(value); !std::isnan(result)) {
return result;
}
CrashReports::SetAnnotation("FE-Error-Value", QString::number(value));
CrashReports::SetAnnotation("FE-Errors-Were", QString::number(errors));
CrashReports::SetAnnotation(
"FE-Errors-Now",
QString::number(std::fetestexcept(FE_ALL_EXCEPT)));
Unexpected("NAN after third std::round.");
}
} // namespace } // namespace
class VideoTrackObject final { class VideoTrackObject final {
@ -379,6 +404,7 @@ void VideoTrackObject::debugLog(const QString &entry) const {
_debugLog.push_back("stp.worldTime:" _debugLog.push_back("stp.worldTime:"
+ QString::number(_syncTimePoint.worldTime) + QString::number(_syncTimePoint.worldTime)
+ ";stp.trackTime:" + QString::number(_syncTimePoint.trackTime) + ";stp.trackTime:" + QString::number(_syncTimePoint.trackTime)
+ ";fe:" + QString::number(std::fetestexcept(FE_ALL_EXCEPT))
+ ";" + entry); + ";" + entry);
} }
@ -826,8 +852,6 @@ void VideoTrackObject::callReady() {
} }
TimePoint VideoTrackObject::trackTime() const { TimePoint VideoTrackObject::trackTime() const {
const auto errors1 = std::fetestexcept(FE_ALL_EXCEPT);
debugAssertKnownTime(7, _syncTimePoint.trackTime); debugAssertKnownTime(7, _syncTimePoint.trackTime);
auto result = TimePoint(); auto result = TimePoint();
@ -855,28 +879,7 @@ TimePoint VideoTrackObject::trackTime() const {
} }
const auto adjust = (result.worldTime - _syncTimePoint.worldTime); const auto adjust = (result.worldTime - _syncTimePoint.worldTime);
const auto adjustSpeed = adjust * _options.speed; const auto adjustSpeed = adjust * _options.speed;
const auto errors2 = std::fetestexcept(FE_ALL_EXCEPT); const auto roundAdjustSpeed = SafeRound(adjustSpeed);
auto roundAdjustSpeed = std::round(adjustSpeed);
if (std::isnan(roundAdjustSpeed)) {
TO_LOG(("NAN1,errors1:%1,errors2:%2,errors:%3").arg(errors1).arg(errors2).arg(std::fetestexcept(FE_ALL_EXCEPT)));
roundAdjustSpeed = std::round(adjustSpeed);
if (!std::isnan(roundAdjustSpeed)) {
TO_LOG(("WELL2,adjust:%1,rounded:%2").arg(adjustSpeed).arg(roundAdjustSpeed));
debugAssertKnownTime(-1, kTimeUnknown);
} else {
TO_LOG(("NAN2,adjust:%1").arg(adjustSpeed));
}
std::feclearexcept(FE_ALL_EXCEPT);
const auto errors3 = std::fetestexcept(FE_ALL_EXCEPT);
roundAdjustSpeed = std::round(adjustSpeed);
if (!std::isnan(roundAdjustSpeed)) {
TO_LOG(("WELL3,adjust:%1,rounded:%2").arg(adjustSpeed).arg(roundAdjustSpeed));
debugAssertKnownTime(-2, kTimeUnknown);
} else {
TO_LOG(("NAN3,adjust:%1,errors3:%2,errors:%3").arg(adjustSpeed).arg(errors3).arg(std::fetestexcept(FE_ALL_EXCEPT)));
}
TO_LOG(("qRound:%1,qRound64:%2").arg(qRound(adjustSpeed)).arg(qRound64(adjustSpeed)));
}
auto timeRoundAdjustSpeed = crl::time(roundAdjustSpeed); auto timeRoundAdjustSpeed = crl::time(roundAdjustSpeed);
const auto fpuErrorHappened = [](crl::time value) { const auto fpuErrorHappened = [](crl::time value) {
return uint64(value) == 0x8000'0000'0000'0000ULL return uint64(value) == 0x8000'0000'0000'0000ULL
@ -1099,9 +1102,11 @@ auto VideoTrack::Shared::presentFrame(
return { kTimeUnknown, kTimeUnknown, addedWorldTimeDelay }; return { kTimeUnknown, kTimeUnknown, addedWorldTimeDelay };
} }
const auto trackLeft = position - time.trackTime; const auto trackLeft = position - time.trackTime;
const auto adjustedBySpeed = trackLeft / playbackSpeed;
const auto roundedAdjustedBySpeed = SafeRound(adjustedBySpeed);
frame->display = time.worldTime frame->display = time.worldTime
+ addedWorldTimeDelay + addedWorldTimeDelay
+ crl::time(std::round(trackLeft / playbackSpeed)); + crl::time(roundedAdjustedBySpeed);
// Release this frame to the main thread for rendering. // Release this frame to the main thread for rendering.
_counter.store( _counter.store(