tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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