1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #if !defined(MediaDataDemuxer_h)
8 #  define MediaDataDemuxer_h
9 
10 #  include "DecoderDoctorLogger.h"
11 #  include "mozilla/MozPromise.h"
12 #  include "mozilla/UniquePtr.h"
13 
14 #  include "MediaData.h"
15 #  include "MediaInfo.h"
16 #  include "MediaResult.h"
17 #  include "TimeUnits.h"
18 #  include "nsISupportsImpl.h"
19 #  include "mozilla/RefPtr.h"
20 #  include "nsTArray.h"
21 
22 namespace mozilla {
23 
24 class MediaTrackDemuxer;
25 class TrackMetadataHolder;
26 
27 DDLoggedTypeDeclName(MediaDataDemuxer);
28 DDLoggedTypeName(MediaTrackDemuxer);
29 
30 // Allows reading the media data: to retrieve the metadata and demux samples.
31 // MediaDataDemuxer isn't designed to be thread safe.
32 // When used by the MediaFormatDecoder, care is taken to ensure that the demuxer
33 // will never be called from more than one thread at once.
34 class MediaDataDemuxer : public DecoderDoctorLifeLogger<MediaDataDemuxer> {
35  public:
36   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDemuxer)
37 
38   typedef MozPromise<MediaResult, MediaResult, /* IsExclusive = */ true>
39       InitPromise;
40 
41   // Initializes the demuxer. Other methods cannot be called unless
42   // initialization has completed and succeeded.
43   // Typically a demuxer will wait to parse the metadata before resolving the
44   // promise. The promise must not be resolved until sufficient data is
45   // supplied. For example, an incomplete metadata would cause the promise to be
46   // rejected should no more data be coming, while the demuxer would wait
47   // otherwise.
48   virtual RefPtr<InitPromise> Init() = 0;
49 
50   // Returns the number of tracks of aType type available. A value of
51   // 0 indicates that no such type is available.
52   virtual uint32_t GetNumberTracks(TrackInfo::TrackType aType) const = 0;
53 
54   // Returns the MediaTrackDemuxer associated with aTrackNumber aType track.
55   // aTrackNumber is not to be confused with the Track ID.
56   // aTrackNumber must be constrained between  0 and  GetNumberTracks(aType) - 1
57   // The actual Track ID is to be retrieved by calling
58   // MediaTrackDemuxer::TrackInfo.
59   virtual already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
60       TrackInfo::TrackType aType, uint32_t aTrackNumber) = 0;
61 
62   // Returns true if the underlying resource allows seeking.
63   virtual bool IsSeekable() const = 0;
64 
65   // Returns true if the underlying resource can only seek within buffered
66   // ranges.
IsSeekableOnlyInBufferedRanges()67   virtual bool IsSeekableOnlyInBufferedRanges() const { return false; }
68 
69   // Returns the media's crypto information, or nullptr if media isn't
70   // encrypted.
GetCrypto()71   virtual UniquePtr<EncryptionInfo> GetCrypto() { return nullptr; }
72 
73   // Notifies the demuxer that the underlying resource has received more data
74   // since the demuxer was initialized.
75   // The demuxer can use this mechanism to inform all track demuxers that new
76   // data is available and to refresh its buffered range.
NotifyDataArrived()77   virtual void NotifyDataArrived() {}
78 
79   // Notifies the demuxer that the underlying resource has had data removed
80   // since the demuxer was initialized.
81   // The demuxer can use this mechanism to inform all track demuxers to update
82   // its buffered range.
83   // This will be called should the demuxer be used with MediaSource.
NotifyDataRemoved()84   virtual void NotifyDataRemoved() {}
85 
86   // Indicate to MediaFormatReader if it should compute the start time
87   // of the demuxed data. If true (default) the first sample returned will be
88   // used as reference time base.
ShouldComputeStartTime()89   virtual bool ShouldComputeStartTime() const { return true; }
90 
91  protected:
92   virtual ~MediaDataDemuxer() = default;
93 };
94 
95 class MediaTrackDemuxer : public DecoderDoctorLifeLogger<MediaTrackDemuxer> {
96  public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTrackDemuxer)97   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTrackDemuxer)
98 
99   class SamplesHolder {
100    public:
101     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SamplesHolder)
102 
103     void AppendSample(RefPtr<MediaRawData>& aSample) {
104       MOZ_DIAGNOSTIC_ASSERT(aSample->HasValidTime());
105       mSamples.AppendElement(aSample);
106     }
107 
108     const nsTArray<RefPtr<MediaRawData>>& GetSamples() const {
109       return mSamples;
110     }
111 
112     // This method is only used to do the move semantic for mSamples, do not
113     // append any element to the samples we returns. We should always append new
114     // sample to mSamples via `AppendSample()`.
115     nsTArray<RefPtr<MediaRawData>>& GetMovableSamples() { return mSamples; }
116 
117    private:
118     ~SamplesHolder() = default;
119     nsTArray<RefPtr<MediaRawData>> mSamples;
120   };
121 
122   class SkipFailureHolder {
123    public:
SkipFailureHolder(const MediaResult & aFailure,uint32_t aSkipped)124     SkipFailureHolder(const MediaResult& aFailure, uint32_t aSkipped)
125         : mFailure(aFailure), mSkipped(aSkipped) {}
126     MediaResult mFailure;
127     uint32_t mSkipped;
128   };
129 
130   typedef MozPromise<media::TimeUnit, MediaResult, /* IsExclusive = */ true>
131       SeekPromise;
132   typedef MozPromise<RefPtr<SamplesHolder>, MediaResult,
133                      /* IsExclusive = */ true>
134       SamplesPromise;
135   typedef MozPromise<uint32_t, SkipFailureHolder, /* IsExclusive = */ true>
136       SkipAccessPointPromise;
137 
138   // Returns the TrackInfo (a.k.a Track Description) for this track.
139   // The TrackInfo returned will be:
140   // TrackInfo::kVideoTrack -> VideoInfo.
141   // TrackInfo::kAudioTrack -> AudioInfo.
142   // respectively.
143   virtual UniquePtr<TrackInfo> GetInfo() const = 0;
144 
145   // Seeks to aTime. Upon success, SeekPromise will be resolved with the
146   // actual time seeked to. Typically the random access point time
147   virtual RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) = 0;
148 
149   // Returns the next aNumSamples sample(s) available.
150   // If only a lesser amount of samples is available, only those will be
151   // returned.
152   // A aNumSamples value of -1 indicates to return all remaining samples.
153   // A video sample is typically made of a single video frame while an audio
154   // sample will contains multiple audio frames.
155   virtual RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) = 0;
156 
157   // Returns true if a call to GetSamples() may block while waiting on the
158   // underlying resource to return the data.
159   // This is used by the MediaFormatReader to determine if buffering heuristics
160   // should be used.
GetSamplesMayBlock()161   virtual bool GetSamplesMayBlock() const { return true; }
162 
163   // Cancel all pending actions (Seek, GetSamples) and reset current state
164   // All pending promises are to be rejected with CANCEL.
165   // The next call to GetSamples would return the first sample available in the
166   // track.
167   virtual void Reset() = 0;
168 
169   // Returns timestamp of next random access point or an error if the demuxer
170   // can't report this.
GetNextRandomAccessPoint(media::TimeUnit * aTime)171   virtual nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) {
172     return NS_ERROR_NOT_IMPLEMENTED;
173   }
174 
175   // Returns timestamp of previous random access point or an error if the
176   // demuxer can't report this.
GetPreviousRandomAccessPoint(media::TimeUnit * aTime)177   virtual nsresult GetPreviousRandomAccessPoint(media::TimeUnit* aTime) {
178     return NS_ERROR_NOT_IMPLEMENTED;
179   }
180 
181   // Skip frames until the next Random Access Point located after
182   // aTimeThreshold.
183   // The first frame returned by the next call to GetSamples() will be the
184   // first random access point found after aTimeThreshold.
185   // Upon success, returns the number of frames skipped.
186   virtual RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
187       const media::TimeUnit& aTimeThreshold) = 0;
188 
189   // Gets the resource's offset used for the last Seek() or GetSample().
190   // A negative value indicates that this functionality isn't supported.
GetResourceOffset()191   virtual int64_t GetResourceOffset() const { return -1; }
192 
GetType()193   virtual TrackInfo::TrackType GetType() const { return GetInfo()->GetType(); }
194 
195   virtual media::TimeIntervals GetBuffered() = 0;
196 
197   // By default, it is assumed that the entire resource can be evicted once
198   // all samples have been demuxed.
GetEvictionOffset(const media::TimeUnit & aTime)199   virtual int64_t GetEvictionOffset(const media::TimeUnit& aTime) {
200     return INT64_MAX;
201   }
202 
203   // If the MediaTrackDemuxer and MediaDataDemuxer hold cross references.
204   // BreakCycles must be overridden.
BreakCycles()205   virtual void BreakCycles() {}
206 
207  protected:
208   virtual ~MediaTrackDemuxer() = default;
209 };
210 
211 }  // namespace mozilla
212 
213 #endif  // MediaDataDemuxer_h
214