gecko-dev/dom/media/TimeUnits.h
Ryan VanderMeulen d9ca5de3ed Backed out 8 changesets (bug 1175768) for frequent media test failures.
Backed out changeset a369cfb95b59 (bug 1175768)
Backed out changeset e02dd312d622 (bug 1175768)
Backed out changeset 6776ce74b9e5 (bug 1175768)
Backed out changeset 6aa5fa1d318e (bug 1175768)
Backed out changeset a8bd7a0d2aea (bug 1175768)
Backed out changeset 41ffc9a9ac48 (bug 1175768)
Backed out changeset 2d2cefa397dc (bug 1175768)
Backed out changeset 4e06368496d2 (bug 1175768)

CLOSED TREE
2015-06-23 16:20:15 -04:00

298 lines
7.5 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef TIME_UNITS_H
#define TIME_UNITS_H
#include "Intervals.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Maybe.h"
#include "mozilla/dom/TimeRanges.h"
namespace mozilla {
namespace media {
class TimeIntervals;
}
}
// CopyChooser specalization for nsTArray
template<>
struct nsTArray_CopyChooser<mozilla::media::TimeIntervals>
{
typedef nsTArray_CopyWithConstructors<mozilla::media::TimeIntervals> Type;
};
namespace mozilla {
// Number of microseconds per second. 1e6.
static const int64_t USECS_PER_S = 1000000;
// Number of microseconds per millisecond.
static const int64_t USECS_PER_MS = 1000;
namespace media {
// Number of nanoseconds per second. 1e9.
static const int64_t NSECS_PER_S = 1000000000;
struct Microseconds {
Microseconds()
: mValue(0)
{}
explicit Microseconds(int64_t aValue)
: mValue(aValue)
{}
double ToSeconds() {
return double(mValue) / USECS_PER_S;
}
static Microseconds FromSeconds(double aValue) {
MOZ_ASSERT(!IsNaN(aValue));
double val = aValue * USECS_PER_S;
if (val >= double(INT64_MAX)) {
return Microseconds(INT64_MAX);
} else if (val <= double(INT64_MIN)) {
return Microseconds(INT64_MIN);
} else {
return Microseconds(int64_t(val));
}
}
bool operator == (const Microseconds& aOther) const {
return mValue == aOther.mValue;
}
bool operator > (const Microseconds& aOther) const {
return mValue > aOther.mValue;
}
bool operator >= (const Microseconds& aOther) const {
return mValue >= aOther.mValue;
}
bool operator < (const Microseconds& aOther) const {
return mValue < aOther.mValue;
}
bool operator <= (const Microseconds& aOther) const {
return mValue <= aOther.mValue;
}
int64_t mValue;
};
// TimeUnit at present uses a CheckedInt64 as storage.
// INT64_MAX has the special meaning of being +oo.
class TimeUnit final {
public:
static TimeUnit FromSeconds(double aValue) {
MOZ_ASSERT(!IsNaN(aValue));
if (mozilla::IsInfinite<double>(aValue)) {
return FromInfinity();
}
double val = aValue * USECS_PER_S;
if (val >= double(INT64_MAX)) {
return FromMicroseconds(INT64_MAX);
} else if (val <= double(INT64_MIN)) {
return FromMicroseconds(INT64_MIN);
} else {
return FromMicroseconds(int64_t(val));
}
}
static TimeUnit FromMicroseconds(int64_t aValue) {
return TimeUnit(aValue);
}
static TimeUnit FromMicroseconds(Microseconds aValue) {
return TimeUnit(aValue.mValue);
}
static TimeUnit FromNanoseconds(int64_t aValue) {
return TimeUnit(aValue / 1000);
}
static TimeUnit FromInfinity() {
return TimeUnit(INT64_MAX);
}
int64_t ToMicroseconds() const {
return mValue.value();
}
int64_t ToNanoseconds() const {
return mValue.value() * 1000;
}
double ToSeconds() const {
if (IsInfinite()) {
return PositiveInfinity<double>();
}
return double(mValue.value()) / USECS_PER_S;
}
bool IsInfinite() const {
return mValue.value() == INT64_MAX;
}
bool operator == (const TimeUnit& aOther) const {
MOZ_ASSERT(IsValid() && aOther.IsValid());
return mValue.value() == aOther.mValue.value();
}
bool operator != (const TimeUnit& aOther) const {
MOZ_ASSERT(IsValid() && aOther.IsValid());
return mValue.value() != aOther.mValue.value();
}
bool operator >= (const TimeUnit& aOther) const {
MOZ_ASSERT(IsValid() && aOther.IsValid());
return mValue.value() >= aOther.mValue.value();
}
bool operator > (const TimeUnit& aOther) const {
return !(*this <= aOther);
}
bool operator <= (const TimeUnit& aOther) const {
MOZ_ASSERT(IsValid() && aOther.IsValid());
return mValue.value() <= aOther.mValue.value();
}
bool operator < (const TimeUnit& aOther) const {
return !(*this >= aOther);
}
TimeUnit operator + (const TimeUnit& aOther) const {
if (IsInfinite() || aOther.IsInfinite()) {
return FromInfinity();
}
return TimeUnit(mValue + aOther.mValue);
}
TimeUnit operator - (const TimeUnit& aOther) const {
if (IsInfinite() && !aOther.IsInfinite()) {
return FromInfinity();
}
MOZ_ASSERT(!IsInfinite() && !aOther.IsInfinite());
return TimeUnit(mValue - aOther.mValue);
}
TimeUnit& operator += (const TimeUnit& aOther) {
*this = *this + aOther;
return *this;
}
TimeUnit& operator -= (const TimeUnit& aOther) {
*this = *this - aOther;
return *this;
}
friend TimeUnit operator* (int aVal, const TimeUnit& aUnit) {
return TimeUnit(aUnit.mValue * aVal);
}
friend TimeUnit operator* (const TimeUnit& aUnit, int aVal) {
return TimeUnit(aUnit.mValue * aVal);
}
bool IsValid() const
{
return mValue.isValid();
}
TimeUnit()
: mValue(CheckedInt64(0))
{}
explicit TimeUnit(const Microseconds& aMicroseconds)
: mValue(aMicroseconds.mValue)
{}
TimeUnit& operator = (const Microseconds& aMicroseconds)
{
mValue = aMicroseconds.mValue;
return *this;
}
TimeUnit(const TimeUnit&) = default;
TimeUnit& operator = (const TimeUnit&) = default;
private:
explicit TimeUnit(CheckedInt64 aMicroseconds)
: mValue(aMicroseconds)
{}
// Our internal representation is in microseconds.
CheckedInt64 mValue;
};
typedef Maybe<TimeUnit> NullableTimeUnit;
typedef Interval<TimeUnit> TimeInterval;
class TimeIntervals : public IntervalSet<TimeUnit>
{
public:
typedef IntervalSet<TimeUnit> BaseType;
// We can't use inherited constructors yet. So we have to duplicate all the
// constructors found in IntervalSet base class.
// all this could be later replaced with:
// using IntervalSet<TimeUnit>::IntervalSet;
// MOZ_IMPLICIT as we want to enable initialization in the form:
// TimeIntervals i = ... like we would do with IntervalSet<T> i = ...
MOZ_IMPLICIT TimeIntervals(const BaseType& aOther)
: BaseType(aOther)
{}
MOZ_IMPLICIT TimeIntervals(BaseType&& aOther)
: BaseType(Move(aOther))
{}
explicit TimeIntervals(const BaseType::ElemType& aOther)
: BaseType(aOther)
{}
explicit TimeIntervals(BaseType::ElemType&& aOther)
: BaseType(Move(aOther))
{}
static TimeIntervals Invalid()
{
return TimeIntervals(TimeInterval(TimeUnit::FromMicroseconds(INT64_MIN),
TimeUnit::FromMicroseconds(INT64_MIN)));
}
bool IsInvalid()
{
return Length() == 1 && Start(0).ToMicroseconds() == INT64_MIN &&
End(0).ToMicroseconds() == INT64_MIN;
}
TimeIntervals() = default;
// Make TimeIntervals interchangeable with dom::TimeRanges.
explicit TimeIntervals(dom::TimeRanges* aRanges)
{
for (uint32_t i = 0; i < aRanges->Length(); i++) {
ErrorResult rv;
*this +=
TimeInterval(TimeUnit::FromSeconds(aRanges->Start(i, rv)),
TimeUnit::FromSeconds(aRanges->End(i, rv)));
}
}
TimeIntervals& operator = (dom::TimeRanges* aRanges)
{
*this = TimeIntervals(aRanges);
return *this;
}
static TimeIntervals FromTimeRanges(dom::TimeRanges* aRanges)
{
return TimeIntervals(aRanges);
}
void ToTimeRanges(dom::TimeRanges* aRanges) const
{
for (IndexType i = 0; i < Length(); i++) {
aRanges->Add(Start(i).ToSeconds(), End(i).ToSeconds());
}
}
};
} // namespace media
} // namespace mozilla
#endif // TIME_UNITS_H