| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIB_MEDIA_CPP_TIMELINE_FUNCTION_H_ |
| #define LIB_MEDIA_CPP_TIMELINE_FUNCTION_H_ |
| |
| #include <lib/media/cpp/timeline_rate.h> |
| #include <zircon/assert.h> |
| |
| namespace media { |
| |
| // TODO(dalesat): Consider always allowing inexact results. |
| |
| // A linear function from int64_t to int64_t with non-negative slope that |
| // translates reference timeline values into subject timeline values (the |
| // 'subject' being the timeline that's represented by the function). The |
| // representation is in point-slope form. The point is represented as two |
| // int64_t time values (subject_time, reference_time), and the slope (rate) is |
| // represented as a TimelineRate, the ratio of two uint32_t values |
| // (subject_delta / reference_delta). |
| class TimelineFunction final { |
| public: |
| // Applies a timeline function. |
| static int64_t Apply(int64_t subject_time, int64_t reference_time, |
| TimelineRate rate, // subject_delta / reference_delta |
| int64_t reference_input); |
| |
| // Applies the inverse of a timeline function. |
| static int64_t ApplyInverse(int64_t subject_time, int64_t reference_time, |
| TimelineRate rate, // subject_delta / reference_delta |
| int64_t subject_input) { |
| ZX_DEBUG_ASSERT(rate.reference_delta() != 0u); |
| return Apply(reference_time, subject_time, rate.Inverse(), subject_input); |
| } |
| |
| // Composes two timeline functions B->C and A->B producing A->C. If exact is |
| // true, DCHECKs on loss of precision. |
| static TimelineFunction Compose(const TimelineFunction& bc, const TimelineFunction& ab, |
| bool exact = true); |
| |
| TimelineFunction() : subject_time_(0), reference_time_(0) {} |
| |
| TimelineFunction(int64_t subject_time, int64_t reference_time, uint32_t subject_delta, |
| uint32_t reference_delta) |
| : subject_time_(subject_time), |
| reference_time_(reference_time), |
| rate_(subject_delta, reference_delta) {} |
| |
| TimelineFunction(int64_t subject_time, int64_t reference_time, TimelineRate rate) |
| : subject_time_(subject_time), reference_time_(reference_time), rate_(rate) {} |
| |
| explicit TimelineFunction(TimelineRate rate) |
| : subject_time_(0), reference_time_(0), rate_(rate) {} |
| |
| // Determines whether this |TimelineFunction| is invertible. |
| bool invertible() const { return rate_.invertible(); } |
| |
| // Applies the function. Returns TimelineRate::kOverflow on overflow. |
| int64_t Apply(int64_t reference_input) const { |
| return Apply(subject_time_, reference_time_, rate_, reference_input); |
| } |
| |
| // Applies the inverse of the function. Returns TimelineRate::kOverflow on |
| // overflow. |
| int64_t ApplyInverse(int64_t subject_input) const { |
| ZX_DEBUG_ASSERT(rate_.reference_delta() != 0u); |
| return ApplyInverse(subject_time_, reference_time_, rate_, subject_input); |
| } |
| |
| // Applies the function. Returns TimelineRate::kOverflow on overflow. |
| int64_t operator()(int64_t reference_input) const { return Apply(reference_input); } |
| |
| // Returns a timeline function that is the inverse of this timeline function. |
| TimelineFunction Inverse() const { |
| ZX_DEBUG_ASSERT(rate_.reference_delta() != 0u); |
| return TimelineFunction(reference_time_, subject_time_, rate_.Inverse()); |
| } |
| |
| int64_t subject_time() const { return subject_time_; } |
| |
| int64_t reference_time() const { return reference_time_; } |
| |
| const TimelineRate& rate() const { return rate_; } |
| |
| uint32_t subject_delta() const { return rate_.subject_delta(); } |
| |
| uint32_t reference_delta() const { return rate_.reference_delta(); } |
| |
| private: |
| int64_t subject_time_; |
| int64_t reference_time_; |
| TimelineRate rate_; // subject_delta / reference_delta |
| }; |
| |
| // Tests two timeline functions for equality. Equality requires equal basis |
| // values. |
| inline bool operator==(const TimelineFunction& a, const TimelineFunction& b) { |
| return a.subject_time() == b.subject_time() && a.reference_time() == b.reference_time() && |
| a.rate() == b.rate(); |
| } |
| |
| // Tests two timeline functions for inequality. Equality requires equal basis |
| // values. |
| inline bool operator!=(const TimelineFunction& a, const TimelineFunction& b) { return !(a == b); } |
| |
| // Composes two timeline functions B->C and A->B producing A->C. DCHECKs on |
| // loss of precision. |
| inline TimelineFunction operator*(const TimelineFunction& bc, const TimelineFunction& ab) { |
| return TimelineFunction::Compose(bc, ab); |
| } |
| |
| } // namespace media |
| |
| #endif // LIB_MEDIA_CPP_TIMELINE_FUNCTION_H_ |