зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1538023 - Add support for -Inf to media::TimeUnits. r=jya
TimeUnits with a negative infinity value are used in the next patch. Differential Revision: https://phabricator.services.mozilla.com/D30309 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
91b62e5a8d
Коммит
b64a2d776d
|
@ -45,7 +45,7 @@ class TimeUnit final {
|
|||
MOZ_ASSERT(!IsNaN(aValue));
|
||||
|
||||
if (mozilla::IsInfinite<double>(aValue)) {
|
||||
return FromInfinity();
|
||||
return aValue > 0 ? FromInfinity() : FromNegativeInfinity();
|
||||
}
|
||||
// Due to internal double representation, this
|
||||
// operation is not commutative, do not attempt to simplify.
|
||||
|
@ -71,6 +71,10 @@ class TimeUnit final {
|
|||
|
||||
static constexpr TimeUnit FromInfinity() { return TimeUnit(INT64_MAX); }
|
||||
|
||||
static constexpr TimeUnit FromNegativeInfinity() {
|
||||
return TimeUnit(INT64_MIN);
|
||||
}
|
||||
|
||||
static TimeUnit FromTimeDuration(const TimeDuration& aDuration) {
|
||||
return FromSeconds(aDuration.ToSeconds());
|
||||
}
|
||||
|
@ -90,9 +94,12 @@ class TimeUnit final {
|
|||
int64_t ToNanoseconds() const { return mValue.value() * 1000; }
|
||||
|
||||
double ToSeconds() const {
|
||||
if (IsInfinite()) {
|
||||
if (IsPosInf()) {
|
||||
return PositiveInfinity<double>();
|
||||
}
|
||||
if (IsNegInf()) {
|
||||
return NegativeInfinity<double>();
|
||||
}
|
||||
return double(mValue.value()) / USECS_PER_S;
|
||||
}
|
||||
|
||||
|
@ -100,7 +107,7 @@ class TimeUnit final {
|
|||
return TimeDuration::FromMicroseconds(mValue.value());
|
||||
}
|
||||
|
||||
bool IsInfinite() const { return mValue.value() == INT64_MAX; }
|
||||
bool IsInfinite() const { return IsPosInf() || IsNegInf(); }
|
||||
|
||||
bool IsPositive() const { return mValue.value() > 0; }
|
||||
|
||||
|
@ -128,15 +135,25 @@ class TimeUnit final {
|
|||
MOZ_ASSERT(IsValid() && aOther.IsValid());
|
||||
return TimeUnit(mValue % aOther.mValue);
|
||||
}
|
||||
|
||||
TimeUnit operator+(const TimeUnit& aOther) const {
|
||||
if (IsInfinite() || aOther.IsInfinite()) {
|
||||
return FromInfinity();
|
||||
// When adding at least one infinite value, the result is either
|
||||
// +/-Inf, or NaN. So do the calculation in floating point for
|
||||
// simplicity.
|
||||
double result = ToSeconds() + aOther.ToSeconds();
|
||||
return IsNaN(result) ? TimeUnit::Invalid() : FromSeconds(result);
|
||||
}
|
||||
return TimeUnit(mValue + aOther.mValue);
|
||||
}
|
||||
|
||||
TimeUnit operator-(const TimeUnit& aOther) const {
|
||||
if (IsInfinite() && !aOther.IsInfinite()) {
|
||||
return FromInfinity();
|
||||
if (IsInfinite() || aOther.IsInfinite()) {
|
||||
// When subtracting at least one infinite value, the result is either
|
||||
// +/-Inf, or NaN. So do the calculation in floating point for
|
||||
// simplicity.
|
||||
double result = ToSeconds() - aOther.ToSeconds();
|
||||
return IsNaN(result) ? TimeUnit::Invalid() : FromSeconds(result);
|
||||
}
|
||||
MOZ_ASSERT(!IsInfinite() && !aOther.IsInfinite());
|
||||
return TimeUnit(mValue - aOther.mValue);
|
||||
|
@ -177,6 +194,13 @@ class TimeUnit final {
|
|||
|
||||
TimeUnit& operator=(const TimeUnit&) = default;
|
||||
|
||||
bool IsPosInf() const {
|
||||
return mValue.isValid() && mValue.value() == INT64_MAX;
|
||||
}
|
||||
bool IsNegInf() const {
|
||||
return mValue.isValid() && mValue.value() == INT64_MIN;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit constexpr TimeUnit(CheckedInt64 aMicroseconds)
|
||||
: mValue(aMicroseconds) {}
|
||||
|
@ -207,12 +231,11 @@ class TimeIntervals : public IntervalSet<TimeUnit> {
|
|||
: BaseType(std::move(aOther)) {}
|
||||
|
||||
static TimeIntervals Invalid() {
|
||||
return TimeIntervals(TimeInterval(TimeUnit::FromMicroseconds(INT64_MIN),
|
||||
TimeUnit::FromMicroseconds(INT64_MIN)));
|
||||
return TimeIntervals(TimeInterval(TimeUnit::FromNegativeInfinity(),
|
||||
TimeUnit::FromNegativeInfinity()));
|
||||
}
|
||||
bool IsInvalid() const {
|
||||
return Length() == 1 && Start(0).ToMicroseconds() == INT64_MIN &&
|
||||
End(0).ToMicroseconds() == INT64_MIN;
|
||||
return Length() == 1 && Start(0).IsNegInf() && End(0).IsNegInf();
|
||||
}
|
||||
|
||||
TimeIntervals() = default;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <vector>
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::media;
|
||||
|
||||
TEST(TimeUnit, Rounding)
|
||||
{
|
||||
|
@ -20,3 +21,51 @@ TEST(TimeUnit, Rounding)
|
|||
usecs = 4169470;
|
||||
EXPECT_EQ(media::TimeUnit::FromSeconds(seconds).ToMicroseconds(), usecs);
|
||||
}
|
||||
|
||||
TEST(TimeUnit, InfinityMath)
|
||||
{
|
||||
// Operator plus/minus uses floating point behaviour for positive and
|
||||
// negative infinity values, i.e.:
|
||||
// posInf + posInf = inf
|
||||
// posInf + negInf = -nan
|
||||
// posInf + finite = inf
|
||||
// posInf - posInf = -nan
|
||||
// posInf - negInf = inf
|
||||
// posInf - finite = inf
|
||||
// negInf + negInf = -inf
|
||||
// negInf + posInf = -nan
|
||||
// negInf + finite = -inf
|
||||
// negInf - negInf = -nan
|
||||
// negInf - posInf = -inf
|
||||
// negInf - finite = -inf
|
||||
// finite + posInf = inf
|
||||
// finite - posInf = -inf
|
||||
// finite + negInf = -inf
|
||||
// finite - negInf = inf
|
||||
|
||||
const TimeUnit posInf = TimeUnit::FromInfinity();
|
||||
EXPECT_EQ(TimeUnit::FromSeconds(mozilla::PositiveInfinity<double>()), posInf);
|
||||
|
||||
const TimeUnit negInf = TimeUnit::FromNegativeInfinity();
|
||||
EXPECT_EQ(TimeUnit::FromSeconds(mozilla::NegativeInfinity<double>()), negInf);
|
||||
|
||||
EXPECT_EQ(posInf + posInf, posInf);
|
||||
EXPECT_FALSE((posInf + negInf).IsValid());
|
||||
EXPECT_FALSE((posInf - posInf).IsValid());
|
||||
EXPECT_EQ(posInf - negInf, posInf);
|
||||
EXPECT_EQ(negInf + negInf, negInf);
|
||||
EXPECT_FALSE((negInf + posInf).IsValid());
|
||||
EXPECT_FALSE((negInf - negInf).IsValid());
|
||||
EXPECT_EQ(negInf - posInf, negInf);
|
||||
|
||||
const TimeUnit finite = TimeUnit::FromSeconds(42.0);
|
||||
EXPECT_EQ(posInf - finite, posInf);
|
||||
EXPECT_EQ(posInf + finite, posInf);
|
||||
EXPECT_EQ(negInf - finite, negInf);
|
||||
EXPECT_EQ(negInf + finite, negInf);
|
||||
|
||||
EXPECT_EQ(finite + posInf, posInf);
|
||||
EXPECT_EQ(finite - posInf, negInf);
|
||||
EXPECT_EQ(finite + negInf, negInf);
|
||||
EXPECT_EQ(finite - negInf, posInf);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ UNIFIED_SOURCES += [
|
|||
'TestMP4Demuxer.cpp',
|
||||
'TestOpusParser.cpp',
|
||||
'TestRust.cpp',
|
||||
'TestTimeUnit.cpp',
|
||||
'TestVideoSegment.cpp',
|
||||
'TestVideoUtils.cpp',
|
||||
'TestVPXDecoding.cpp',
|
||||
|
|
|
@ -28,7 +28,7 @@ FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FFmpegLibWrapper* aLib,
|
|||
mExtraData(nullptr),
|
||||
mCodecID(aCodecID),
|
||||
mTaskQueue(aTaskQueue),
|
||||
mLastInputDts(media::TimeUnit::FromMicroseconds(INT64_MIN)) {
|
||||
mLastInputDts(media::TimeUnit::FromNegativeInfinity()) {
|
||||
MOZ_ASSERT(aLib);
|
||||
MOZ_COUNT_CTOR(FFmpegDataDecoder);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче