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 INDEX_H_
6 #define INDEX_H_
7 
8 #include "ByteStream.h"
9 #include "MediaData.h"
10 #include "MediaResource.h"
11 #include "MoofParser.h"
12 #include "mozilla/ResultVariant.h"
13 #include "MP4Interval.h"
14 #include "nsISupportsImpl.h"
15 #include "TimeUnits.h"
16 
17 namespace mozilla {
18 class IndiceWrapper;
19 struct Sample;
20 struct CencSampleEncryptionInfoEntry;
21 
22 class Index;
23 
24 typedef int64_t Microseconds;
25 
26 class SampleIterator {
27  public:
28   explicit SampleIterator(Index* aIndex);
29   ~SampleIterator();
30   already_AddRefed<mozilla::MediaRawData> GetNext();
31   void Seek(Microseconds aTime);
32   Microseconds GetNextKeyframeTime();
33 
34  private:
35   Sample* Get();
36 
37   // Gets the sample description entry for the current moof, or nullptr if
38   // called without a valid current moof.
39   SampleDescriptionEntry* GetSampleDescriptionEntry();
40   CencSampleEncryptionInfoEntry* GetSampleEncryptionEntry();
41 
42   // Determines the encryption scheme in use for the current sample. If the
43   // the scheme cannot be unambiguously determined, will return an error with
44   // the reason.
45   //
46   // Returns: Ok(CryptoScheme) if a crypto scheme, including None, can be
47   // determined, or Err(nsCString) if there is an issue determining the scheme.
48   Result<CryptoScheme, nsCString> GetEncryptionScheme();
49 
50   void Next();
51   RefPtr<Index> mIndex;
52   friend class Index;
53   size_t mCurrentMoof;
54   size_t mCurrentSample;
55 };
56 
57 class Index {
58  public:
59   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Index)
60 
61   struct Indice {
62     uint64_t start_offset;
63     uint64_t end_offset;
64     uint64_t start_composition;
65     uint64_t end_composition;
66     uint64_t start_decode;
67     bool sync;
68   };
69 
70   struct MP4DataOffset {
MP4DataOffsetMP4DataOffset71     MP4DataOffset(uint32_t aIndex, int64_t aStartOffset)
72         : mIndex(aIndex), mStartOffset(aStartOffset), mEndOffset(0) {}
73 
74     bool operator==(int64_t aStartOffset) const {
75       return mStartOffset == aStartOffset;
76     }
77 
78     bool operator!=(int64_t aStartOffset) const {
79       return mStartOffset != aStartOffset;
80     }
81 
82     bool operator<(int64_t aStartOffset) const {
83       return mStartOffset < aStartOffset;
84     }
85 
86     struct EndOffsetComparator {
EqualsMP4DataOffset::EndOffsetComparator87       bool Equals(const MP4DataOffset& a, const int64_t& b) const {
88         return a.mEndOffset == b;
89       }
90 
LessThanMP4DataOffset::EndOffsetComparator91       bool LessThan(const MP4DataOffset& a, const int64_t& b) const {
92         return a.mEndOffset < b;
93       }
94     };
95 
96     uint32_t mIndex;
97     int64_t mStartOffset;
98     int64_t mEndOffset;
99     MP4Interval<Microseconds> mTime;
100   };
101 
102   Index(const mozilla::IndiceWrapper& aIndices, ByteStream* aSource,
103         uint32_t aTrackId, bool aIsAudio);
104 
105   void UpdateMoofIndex(const mozilla::MediaByteRangeSet& aByteRanges,
106                        bool aCanEvict);
107   void UpdateMoofIndex(const mozilla::MediaByteRangeSet& aByteRanges);
108   Microseconds GetEndCompositionIfBuffered(
109       const mozilla::MediaByteRangeSet& aByteRanges);
110   mozilla::media::TimeIntervals ConvertByteRangesToTimeRanges(
111       const mozilla::MediaByteRangeSet& aByteRanges);
112   uint64_t GetEvictionOffset(Microseconds aTime);
IsFragmented()113   bool IsFragmented() { return !!mMoofParser; }
114 
115   friend class SampleIterator;
116 
117  private:
118   ~Index();
119   void RegisterIterator(SampleIterator* aIterator);
120   void UnregisterIterator(SampleIterator* aIterator);
121 
122   ByteStream* mSource;
123   FallibleTArray<Sample> mIndex;
124   FallibleTArray<MP4DataOffset> mDataOffset;
125   UniquePtr<MoofParser> mMoofParser;
126   nsTArray<SampleIterator*> mIterators;
127 
128   // ConvertByteRangesToTimeRanges cache
129   mozilla::MediaByteRangeSet mLastCachedRanges;
130   mozilla::media::TimeIntervals mLastBufferedRanges;
131   bool mIsAudio;
132 };
133 }  // namespace mozilla
134 
135 #endif
136