Try to do a non-failed double->crl::time cast.

A crash on some old CPUs show, that in video frame processing
sometimes a cast from double to crl::time fails, writing to
the resulting crl::time value INT64_MIN (0x8000000000000000).

This is shown in crash logs, with lines like:

...,rounded:104,casted:-9223372036854775808,...

where logs are written like:

...
).arg(std::round(adjust * _options.speed)
).arg(crl::time(std::round(adjust * _options.speed))
...

I don't know what to do and how to workaround this. Trying other casts.
This commit is contained in:
John Preston 2021-08-23 17:58:59 +03:00
parent 3a92a181a1
commit 27d58ba07b
1 changed files with 94 additions and 7 deletions

View File

@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "zlib.h"
extern "C" {
extern int __isa_available;
}
#define TO_LOG(x) debugLog(QString x)
namespace Media {
@ -199,7 +203,7 @@ VideoTrackObject::VideoTrackObject(
Expects(_error != nullptr);
TO_LOG(("created,speed:%1,mode:%2,position:%3,sync:%4,"
"loop:%5,wait:%6,duration:%7,initialized:%8"
"loop:%5,wait:%6,duration:%7,initialized:%8,isa:%9"
).arg(options.speed
).arg(int(options.mode)
).arg(options.position
@ -207,7 +211,8 @@ VideoTrackObject::VideoTrackObject(
).arg(options.loop ? "true" : "false"
).arg(options.waitForMarkAsShown ? "true" : "false"
).arg(_stream.duration
).arg(_shared->initialized() ? "true" : "false"));
).arg(_shared->initialized() ? "true" : "false"
).arg(__isa_available));
}
rpl::producer<> VideoTrackObject::checkNextFrame() const {
@ -846,16 +851,98 @@ TimePoint VideoTrackObject::trackTime() const {
}
}
const auto adjust = (result.worldTime - _syncTimePoint.worldTime);
result.trackTime = _syncTimePoint.trackTime
+ crl::time(std::round(adjust * _options.speed));
const auto adjustSpeed = adjust * _options.speed;
const auto roundAdjustSpeed = std::round(adjustSpeed);
auto timeRoundAdjustSpeed = crl::time(roundAdjustSpeed);
const auto fpuErrorHappened = [](crl::time value) {
return uint64(value) == 0x8000'0000'0000'0000ULL
|| uint64(value) == 0x8000'0000ULL
|| uint64(value) == 0xFFFF'FFFF'FFFF'FFFFULL
|| uint64(value) == 0xFFFF'FFFFULL;
};
if (roundAdjustSpeed > -1000'000'000.
&& roundAdjustSpeed < 1000'000'000.
&& fpuErrorHappened(timeRoundAdjustSpeed)) {
TO_LOG(("BAD1,round:%1").arg(roundAdjustSpeed));
timeRoundAdjustSpeed = crl::time(roundAdjustSpeed);
if (!fpuErrorHappened(timeRoundAdjustSpeed)) {
TO_LOG(("GOOD2,round:%1,result:%2").arg(roundAdjustSpeed).arg(timeRoundAdjustSpeed));
debugAssertKnownTime(-1, kTimeUnknown);
} else {
TO_LOG(("BAD2,round:%1").arg(roundAdjustSpeed));
}
const auto floatRoundAdjustSpeed = float(roundAdjustSpeed);
timeRoundAdjustSpeed = crl::time(floatRoundAdjustSpeed);
if (!fpuErrorHappened(timeRoundAdjustSpeed)) {
TO_LOG(("GOOD3,round:%1,result:%2").arg(floatRoundAdjustSpeed).arg(timeRoundAdjustSpeed));
debugAssertKnownTime(-2, kTimeUnknown);
} else {
TO_LOG(("BAD3,round:%1").arg(floatRoundAdjustSpeed));
}
const auto intRoundAdjustSpeet = int(roundAdjustSpeed);
timeRoundAdjustSpeed = crl::time(intRoundAdjustSpeet);
if (!fpuErrorHappened(timeRoundAdjustSpeed)) {
TO_LOG(("GOOD4,int:%1,result:%2").arg(intRoundAdjustSpeet).arg(timeRoundAdjustSpeed));
debugAssertKnownTime(-3, kTimeUnknown);
} else {
TO_LOG(("BAD4,int:%1").arg(intRoundAdjustSpeet));
}
const auto intFloatRoundAdjustSpeed = int(floatRoundAdjustSpeed);
timeRoundAdjustSpeed = crl::time(intFloatRoundAdjustSpeed);
if (!fpuErrorHappened(timeRoundAdjustSpeed)) {
TO_LOG(("GOOD5,int:%1,result:%2").arg(intFloatRoundAdjustSpeed).arg(timeRoundAdjustSpeed));
debugAssertKnownTime(-4, kTimeUnknown);
} else {
TO_LOG(("BAD5,int:%1").arg(intFloatRoundAdjustSpeed));
}
const auto uint64RoundAdjustSpeed = uint64((roundAdjustSpeed >= 0.)
? roundAdjustSpeed
: -roundAdjustSpeed);
if (!fpuErrorHappened(uint64RoundAdjustSpeed)) {
TO_LOG(("GOOD6,round:%1,uint:%2").arg(roundAdjustSpeed).arg(uint64RoundAdjustSpeed));
debugAssertKnownTime(-5, kTimeUnknown);
} else {
TO_LOG(("BAD6,uint:%1").arg(uint64RoundAdjustSpeed));
}
const auto uint64FloatRoundAdjustSpeed = uint64((floatRoundAdjustSpeed >= 0.)
? floatRoundAdjustSpeed
: -floatRoundAdjustSpeed);
if (!fpuErrorHappened(uint64FloatRoundAdjustSpeed)) {
TO_LOG(("GOOD7,round:%1,uint:%2").arg(floatRoundAdjustSpeed).arg(uint64FloatRoundAdjustSpeed));
debugAssertKnownTime(-6, kTimeUnknown);
} else {
TO_LOG(("BAD7,uint:%1").arg(uint64FloatRoundAdjustSpeed));
}
const auto uint32RoundAdjustSpeed = uint32((roundAdjustSpeed >= 0.)
? roundAdjustSpeed
: -roundAdjustSpeed);
if (!fpuErrorHappened(uint32RoundAdjustSpeed)) {
TO_LOG(("GOOD8,round:%1,uint:%2").arg(roundAdjustSpeed).arg(uint32RoundAdjustSpeed));
debugAssertKnownTime(-7, kTimeUnknown);
} else {
TO_LOG(("BAD8,uint:%1").arg(uint32RoundAdjustSpeed));
}
const auto uint32FloatRoundAdjustSpeed = uint32((floatRoundAdjustSpeed >= 0.)
? floatRoundAdjustSpeed
: -floatRoundAdjustSpeed);
if (!fpuErrorHappened(uint32FloatRoundAdjustSpeed)) {
TO_LOG(("GOOD9,round:%1,uint:%2").arg(floatRoundAdjustSpeed).arg(uint32FloatRoundAdjustSpeed));
debugAssertKnownTime(-8, kTimeUnknown);
} else {
TO_LOG(("BAD9,uint:%1").arg(uint32FloatRoundAdjustSpeed));
}
debugAssertKnownTime(-9, kTimeUnknown);
}
const auto trackTime = _syncTimePoint.trackTime + timeRoundAdjustSpeed;
TO_LOG(("track_time_adjusted,world:%1,adjust:%2,speed:%3,delta:%4,rounded:%5,casted:%6,final:%7"
).arg(result.worldTime
).arg(adjust
).arg(_options.speed
).arg(adjust * _options.speed
).arg(std::round(adjust * _options.speed)
).arg(crl::time(std::round(adjust * _options.speed))
).arg(adjustSpeed
).arg(roundAdjustSpeed
).arg(timeRoundAdjustSpeed
).arg(result.trackTime));
result.trackTime = trackTime;
debugAssertKnownTime(11, result.trackTime);
return result;
}