MP4Interval.h (4053B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef INTERVAL_H_ 6 #define INTERVAL_H_ 7 8 #include <nsString.h> 9 10 #include <algorithm> 11 12 #include "nsTArray.h" 13 14 namespace mozilla { 15 16 template <typename T> 17 struct MP4Interval { 18 MP4Interval() : start{}, end{} {} 19 MP4Interval(T aStart, T aEnd) : start(aStart), end(aEnd) { 20 MOZ_ASSERT(aStart <= aEnd); 21 } 22 T Length() { return end - start; } 23 MP4Interval Intersection(const MP4Interval& aOther) const { 24 T s = start > aOther.start ? start : aOther.start; 25 T e = end < aOther.end ? end : aOther.end; 26 if (s > e) { 27 return MP4Interval(); 28 } 29 return MP4Interval(s, e); 30 } 31 bool Contains(const MP4Interval& aOther) const { 32 return aOther.start >= start && aOther.end <= end; 33 } 34 bool operator==(const MP4Interval& aOther) const { 35 return start == aOther.start && end == aOther.end; 36 } 37 bool operator!=(const MP4Interval& aOther) const { 38 return !(*this == aOther); 39 } 40 bool IsNull() const { return end == start; } 41 MP4Interval Extents(const MP4Interval& aOther) const { 42 if (IsNull()) { 43 return aOther; 44 } 45 return MP4Interval(std::min(start, aOther.start), 46 std::max(end, aOther.end)); 47 } 48 49 T start; 50 T end; 51 52 nsCString ToString() { 53 return nsPrintfCString("[%s, %s]", start.ToString().get(), 54 end.ToString().get()); 55 } 56 57 static void SemiNormalAppend(nsTArray<MP4Interval<T>>& aIntervals, 58 MP4Interval<T> aMP4Interval) { 59 if (!aIntervals.IsEmpty() && 60 aIntervals.LastElement().end == aMP4Interval.start) { 61 aIntervals.LastElement().end = aMP4Interval.end; 62 } else { 63 aIntervals.AppendElement(aMP4Interval); 64 } 65 } 66 67 static void Normalize(const nsTArray<MP4Interval<T>>& aIntervals, 68 nsTArray<MP4Interval<T>>* aNormalized) { 69 if (!aNormalized || !aIntervals.Length()) { 70 MOZ_ASSERT(aNormalized); 71 return; 72 } 73 MOZ_ASSERT(aNormalized->IsEmpty()); 74 75 nsTArray<MP4Interval<T>> sorted = aIntervals.Clone(); 76 sorted.Sort(Compare()); 77 78 MP4Interval<T> current = sorted[0]; 79 for (size_t i = 1; i < sorted.Length(); i++) { 80 MOZ_ASSERT(sorted[i].start <= sorted[i].end); 81 if (current.Contains(sorted[i])) { 82 continue; 83 } 84 if (current.end >= sorted[i].start) { 85 current.end = sorted[i].end; 86 } else { 87 aNormalized->AppendElement(current); 88 current = sorted[i]; 89 } 90 } 91 aNormalized->AppendElement(current); 92 } 93 94 static void Intersection(const nsTArray<MP4Interval<T>>& a0, 95 const nsTArray<MP4Interval<T>>& a1, 96 nsTArray<MP4Interval<T>>* aIntersection) { 97 MOZ_ASSERT(IsNormalized(a0)); 98 MOZ_ASSERT(IsNormalized(a1)); 99 size_t i0 = 0; 100 size_t i1 = 0; 101 while (i0 < a0.Length() && i1 < a1.Length()) { 102 MP4Interval i = a0[i0].Intersection(a1[i1]); 103 if (i.Length()) { 104 aIntersection->AppendElement(i); 105 } 106 if (a0[i0].end < a1[i1].end) { 107 i0++; 108 // Assert that the array is sorted 109 MOZ_ASSERT(i0 == a0.Length() || a0[i0 - 1].start < a0[i0].start); 110 } else { 111 i1++; 112 // Assert that the array is sorted 113 MOZ_ASSERT(i1 == a1.Length() || a1[i1 - 1].start < a1[i1].start); 114 } 115 } 116 } 117 118 static bool IsNormalized(const nsTArray<MP4Interval<T>>& aIntervals) { 119 for (size_t i = 1; i < aIntervals.Length(); i++) { 120 if (aIntervals[i - 1].end >= aIntervals[i].start) { 121 return false; 122 } 123 } 124 return true; 125 } 126 127 struct Compare { 128 bool Equals(const MP4Interval<T>& a0, const MP4Interval<T>& a1) const { 129 return a0.start == a1.start && a0.end == a1.end; 130 } 131 132 bool LessThan(const MP4Interval<T>& a0, const MP4Interval<T>& a1) const { 133 return a0.start < a1.start; 134 } 135 }; 136 }; 137 } // namespace mozilla 138 139 #endif