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 #ifndef mozilla_dom_MediaSource_h_
8 #define mozilla_dom_MediaSource_h_
9 
10 #include "MediaSourceDecoder.h"
11 #include "js/RootingAPI.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/Attributes.h"
14 #include "mozilla/DOMEventTargetHelper.h"
15 #include "mozilla/MozPromise.h"
16 #include "mozilla/dom/MediaSourceBinding.h"
17 #include "nsCOMPtr.h"
18 #include "nsCycleCollectionNoteChild.h"
19 #include "nsCycleCollectionParticipant.h"
20 #include "nsID.h"
21 #include "nsISupports.h"
22 #include "nscore.h"
23 #include "TimeUnits.h"
24 
25 struct JSContext;
26 class JSObject;
27 class nsPIDOMWindowInner;
28 
29 namespace mozilla {
30 
31 class AbstractThread;
32 class ErrorResult;
33 template <typename T>
34 class AsyncEventRunner;
35 class MediaResult;
36 
37 namespace dom {
38 class MediaSource;
39 }  // namespace dom
40 DDLoggedTypeName(dom::MediaSource);
41 
42 namespace dom {
43 
44 class GlobalObject;
45 class SourceBuffer;
46 class SourceBufferList;
47 template <typename T>
48 class Optional;
49 
50 #define MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID   \
51   {                                                  \
52     0x3839d699, 0x22c5, 0x439f, {                    \
53       0x94, 0xca, 0x0e, 0x0b, 0x26, 0xf9, 0xca, 0xbf \
54     }                                                \
55   }
56 
57 class MediaSource final : public DOMEventTargetHelper,
58                           public DecoderDoctorLifeLogger<MediaSource> {
59  public:
60   /** WebIDL Methods. */
61   static already_AddRefed<MediaSource> Constructor(const GlobalObject& aGlobal,
62                                                    ErrorResult& aRv);
63 
64   SourceBufferList* SourceBuffers();
65   SourceBufferList* ActiveSourceBuffers();
66   MediaSourceReadyState ReadyState();
67 
68   double Duration();
69   void SetDuration(double aDuration, ErrorResult& aRv);
70 
71   already_AddRefed<SourceBuffer> AddSourceBuffer(const nsAString& aType,
72                                                  ErrorResult& aRv);
73   void RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv);
74 
75   void EndOfStream(const Optional<MediaSourceEndOfStreamError>& aError,
76                    ErrorResult& aRv);
77   void EndOfStream(const MediaResult& aError);
78 
79   void SetLiveSeekableRange(double aStart, double aEnd, ErrorResult& aRv);
80   void ClearLiveSeekableRange(ErrorResult& aRv);
81 
82   static bool IsTypeSupported(const GlobalObject&, const nsAString& aType);
83   // Throws on aRv if not supported.
84   static void IsTypeSupported(const nsAString& aType,
85                               DecoderDoctorDiagnostics* aDiagnostics,
86                               ErrorResult& aRv);
87 
88   IMPL_EVENT_HANDLER(sourceopen);
89   IMPL_EVENT_HANDLER(sourceended);
90   IMPL_EVENT_HANDLER(sourceclosed);
91 
92   /** End WebIDL Methods. */
93 
94   NS_DECL_ISUPPORTS_INHERITED
95   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaSource, DOMEventTargetHelper)
96   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
97 
98   nsPIDOMWindowInner* GetParentObject() const;
99 
100   JSObject* WrapObject(JSContext* aCx,
101                        JS::Handle<JSObject*> aGivenProto) override;
102 
103   // Attach this MediaSource to Decoder aDecoder.  Returns false if already
104   // attached.
105   bool Attach(MediaSourceDecoder* aDecoder);
106   void Detach();
107 
108   // Set mReadyState to aState and fire the required events at the MediaSource.
109   void SetReadyState(MediaSourceReadyState aState);
110 
111   // Used by SourceBuffer to call CreateSubDecoder.
GetDecoder()112   MediaSourceDecoder* GetDecoder() { return mDecoder; }
113 
GetPrincipal()114   nsIPrincipal* GetPrincipal() { return mPrincipal; }
115 
116   // Returns a structure describing the state of the MediaSource internal
117   // buffered data. Used for debugging purposes.
118   already_AddRefed<Promise> MozDebugReaderData(ErrorResult& aRv);
119 
HasLiveSeekableRange()120   bool HasLiveSeekableRange() const { return mLiveSeekableRange.isSome(); }
LiveSeekableRange()121   media::TimeInterval LiveSeekableRange() const {
122     return mLiveSeekableRange.value();
123   }
124 
AbstractMainThread()125   AbstractThread* AbstractMainThread() const { return mAbstractMainThread; }
126 
127   // Resolve all CompletionPromise pending.
128   void CompletePendingTransactions();
129 
130  private:
131   // SourceBuffer uses SetDuration and SourceBufferIsActive
132   friend class mozilla::dom::SourceBuffer;
133 
134   ~MediaSource();
135 
136   explicit MediaSource(nsPIDOMWindowInner* aWindow);
137 
138   friend class AsyncEventRunner<MediaSource>;
139   void DispatchSimpleEvent(const char* aName);
140   void QueueAsyncSimpleEvent(const char* aName);
141 
142   void DurationChange(double aNewDuration, ErrorResult& aRv);
143 
144   // SetDuration with no checks.
145   void SetDuration(double aDuration);
146 
147   typedef MozPromise<bool, MediaResult, /* IsExclusive = */ true>
148       ActiveCompletionPromise;
149   // Mark SourceBuffer as active and rebuild ActiveSourceBuffers.
150   // Return a MozPromise that will be resolved once all related operations are
151   // completed, or can't progress any further.
152   // Such as, transition of readyState from HAVE_NOTHING to HAVE_METADATA.
153   RefPtr<ActiveCompletionPromise> SourceBufferIsActive(
154       SourceBuffer* aSourceBuffer);
155 
156   RefPtr<SourceBufferList> mSourceBuffers;
157   RefPtr<SourceBufferList> mActiveSourceBuffers;
158 
159   RefPtr<MediaSourceDecoder> mDecoder;
160   // Ensures the media element remains alive to dispatch progress and
161   // durationchanged events.
162   RefPtr<HTMLMediaElement> mMediaElement;
163 
164   RefPtr<nsIPrincipal> mPrincipal;
165 
166   const RefPtr<AbstractThread> mAbstractMainThread;
167 
168   MediaSourceReadyState mReadyState;
169 
170   Maybe<media::TimeInterval> mLiveSeekableRange;
171   nsTArray<MozPromiseHolder<ActiveCompletionPromise>> mCompletionPromises;
172 };
173 
174 NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource,
175                               MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
176 
177 }  // namespace dom
178 
179 }  // namespace mozilla
180 
181 #endif /* mozilla_dom_MediaSource_h_ */
182