1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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(MediaSourceDemuxer_h_)
8 #define MediaSourceDemuxer_h_
9 
10 #include "mozilla/Atomics.h"
11 #include "mozilla/Maybe.h"
12 #include "mozilla/Monitor.h"
13 #include "AutoTaskQueue.h"
14 
15 #include "MediaDataDemuxer.h"
16 #include "MediaResource.h"
17 #include "MediaSource.h"
18 #include "TrackBuffersManager.h"
19 
20 namespace mozilla {
21 
22 class AbstractThread;
23 class MediaResult;
24 class MediaSourceTrackDemuxer;
25 
26 DDLoggedTypeDeclNameAndBase(MediaSourceDemuxer, MediaDataDemuxer);
27 DDLoggedTypeNameAndBase(MediaSourceTrackDemuxer, MediaTrackDemuxer);
28 
29 class MediaSourceDemuxer : public MediaDataDemuxer,
30                            public DecoderDoctorLifeLogger<MediaSourceDemuxer> {
31  public:
32   explicit MediaSourceDemuxer(AbstractThread* aAbstractMainThread);
33 
34   RefPtr<InitPromise> Init() override;
35 
36   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
37 
38   already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
39       TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
40 
41   bool IsSeekable() const override;
42 
43   UniquePtr<EncryptionInfo> GetCrypto() override;
44 
ShouldComputeStartTime()45   bool ShouldComputeStartTime() const override { return false; }
46 
47   /* interface for TrackBuffersManager */
48   void AttachSourceBuffer(RefPtr<TrackBuffersManager>& aSourceBuffer);
49   void DetachSourceBuffer(RefPtr<TrackBuffersManager>& aSourceBuffer);
GetTaskQueue()50   AutoTaskQueue* GetTaskQueue() { return mTaskQueue; }
51   void NotifyInitDataArrived();
52 
53   // Returns a string describing the state of the MediaSource internal
54   // buffered data. Used for debugging purposes.
55   void GetMozDebugReaderData(nsACString& aString);
56 
57   void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes);
58 
59   // Gap allowed between frames.
60   // Due to inaccuracies in determining buffer end
61   // frames (Bug 1065207). This value is based on videos seen in the wild.
62   static constexpr media::TimeUnit EOS_FUZZ =
63       media::TimeUnit::FromMicroseconds(500000);
64 
65  private:
66   ~MediaSourceDemuxer();
67   friend class MediaSourceTrackDemuxer;
68   // Scan source buffers and update information.
69   bool ScanSourceBuffersForContent();
70   RefPtr<TrackBuffersManager> GetManager(TrackInfo::TrackType aType);
71   TrackInfo* GetTrackInfo(TrackInfo::TrackType);
72   void DoAttachSourceBuffer(RefPtr<TrackBuffersManager>&& aSourceBuffer);
73   void DoDetachSourceBuffer(RefPtr<TrackBuffersManager>&& aSourceBuffer);
OnTaskQueue()74   bool OnTaskQueue() {
75     return !GetTaskQueue() || GetTaskQueue()->IsCurrentThreadIn();
76   }
77 
78   RefPtr<AutoTaskQueue> mTaskQueue;
79   nsTArray<RefPtr<MediaSourceTrackDemuxer>> mDemuxers;
80 
81   nsTArray<RefPtr<TrackBuffersManager>> mSourceBuffers;
82 
83   MozPromiseHolder<InitPromise> mInitPromise;
84 
85   // Monitor to protect members below across multiple threads.
86   mutable Monitor mMonitor;
87   RefPtr<TrackBuffersManager> mAudioTrack;
88   RefPtr<TrackBuffersManager> mVideoTrack;
89   MediaInfo mInfo;
90 };
91 
92 class MediaSourceTrackDemuxer
93     : public MediaTrackDemuxer,
94       public DecoderDoctorLifeLogger<MediaSourceTrackDemuxer> {
95  public:
96   MediaSourceTrackDemuxer(MediaSourceDemuxer* aParent,
97                           TrackInfo::TrackType aType,
98                           TrackBuffersManager* aManager);
99 
100   UniquePtr<TrackInfo> GetInfo() const override;
101 
102   RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override;
103 
104   RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
105 
106   void Reset() override;
107 
108   nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) override;
109 
110   RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
111       const media::TimeUnit& aTimeThreshold) override;
112 
113   media::TimeIntervals GetBuffered() override;
114 
115   void BreakCycles() override;
116 
GetSamplesMayBlock()117   bool GetSamplesMayBlock() const override { return false; }
118 
119   bool HasManager(TrackBuffersManager* aManager) const;
120   void DetachManager();
121 
122  private:
OnTaskQueue()123   bool OnTaskQueue() const {
124     MOZ_ASSERT(mParent);
125     auto taskQueue = mParent->GetTaskQueue();
126     MOZ_ASSERT(taskQueue);
127     return taskQueue->IsCurrentThreadIn();
128   }
129 
130   RefPtr<SeekPromise> DoSeek(const media::TimeUnit& aTime);
131   RefPtr<SamplesPromise> DoGetSamples(int32_t aNumSamples);
132   RefPtr<SkipAccessPointPromise> DoSkipToNextRandomAccessPoint(
133       const media::TimeUnit& aTimeThreadshold);
134   already_AddRefed<MediaRawData> GetSample(MediaResult& aError);
135   // Return the timestamp of the next keyframe after mLastSampleIndex.
136   media::TimeUnit GetNextRandomAccessPoint();
137 
138   RefPtr<MediaSourceDemuxer> mParent;
139   TrackInfo::TrackType mType;
140   // Monitor protecting members below accessed from multiple threads.
141   Monitor mMonitor;
142   media::TimeUnit mNextRandomAccessPoint;
143   // Would be accessed in MFR's demuxer proxy task queue and TaskQueue, and
144   // only be set on the TaskQueue. It can be accessed while on TaskQueue without
145   // the need for the lock.
146   RefPtr<TrackBuffersManager> mManager;
147 
148   Maybe<RefPtr<MediaRawData>> mNextSample;
149   // Set to true following a reset. Ensure that the next sample demuxed
150   // is available at position 0.
151   bool mReset;
152 
153   // Amount of pre-roll time when seeking.
154   // Set to 80ms if track is Opus.
155   const media::TimeUnit mPreRoll;
156 };
157 
158 }  // namespace mozilla
159 
160 #endif
161