diff -r 000000000000 -r 6474c204b198 content/media/DOMMediaStream.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/content/media/DOMMediaStream.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,270 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef NSDOMMEDIASTREAM_H_ +#define NSDOMMEDIASTREAM_H_ + +#include "nsIDOMMediaStream.h" +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" +#include "StreamBuffer.h" +#include "nsIDOMWindow.h" + +class nsXPCClassInfo; +class nsIPrincipal; + +// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to +// GetTickCount() and conflicts with NS_DECL_NSIDOMMEDIASTREAM, containing +// currentTime getter. +#ifdef GetCurrentTime +#undef GetCurrentTime +#endif +// X11 has a #define for CurrentTime. Unbelievable :-(. +// See content/media/webaudio/AudioContext.h for more fun! +#ifdef CurrentTime +#undef CurrentTime +#endif + +namespace mozilla { + +class MediaStream; + +namespace dom { +class AudioNode; +class MediaStreamTrack; +class AudioStreamTrack; +class VideoStreamTrack; +} + +class MediaStreamDirectListener; + +/** + * DOM wrapper for MediaStreams. + */ +class DOMMediaStream : public nsIDOMMediaStream, + public nsWrapperCache +{ + friend class DOMLocalMediaStream; + typedef dom::MediaStreamTrack MediaStreamTrack; + typedef dom::AudioStreamTrack AudioStreamTrack; + typedef dom::VideoStreamTrack VideoStreamTrack; + +public: + typedef uint8_t TrackTypeHints; + + DOMMediaStream(); + virtual ~DOMMediaStream(); + + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMMediaStream) + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + + nsIDOMWindow* GetParentObject() const + { + return mWindow; + } + virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; + + // WebIDL + double CurrentTime(); + + void GetAudioTracks(nsTArray >& aTracks); + void GetVideoTracks(nsTArray >& aTracks); + + MediaStream* GetStream() const { return mStream; } + + /** + * Overridden in DOMLocalMediaStreams to allow getUserMedia to pass + * data directly to RTCPeerConnection without going through graph queuing. + * Returns a bool to let us know if direct data will be delivered. + */ + virtual bool AddDirectListener(MediaStreamDirectListener *aListener) { return false; } + virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) {} + + /** + * Overridden in DOMLocalMediaStreams to allow getUserMedia to disable + * media at the SourceMediaStream. + */ + virtual void SetTrackEnabled(TrackID aTrackID, bool aEnabled); + + bool IsFinished(); + /** + * Returns a principal indicating who may access this stream. The stream contents + * can only be accessed by principals subsuming this principal. + */ + nsIPrincipal* GetPrincipal() { return mPrincipal; } + + /** + * Indicate that data will be contributed to this stream from origin aPrincipal. + * If aPrincipal is null, this is ignored. Otherwise, from now on the contents + * of this stream can only be accessed by principals that subsume aPrincipal. + * Returns true if the stream's principal changed. + */ + bool CombineWithPrincipal(nsIPrincipal* aPrincipal); + + /** + * Called when this stream's MediaStreamGraph has been shut down. Normally + * MSGs are only shut down when all streams have been removed, so this + * will only be called during a forced shutdown due to application exit. + */ + void NotifyMediaStreamGraphShutdown(); + /** + * Called when the main-thread state of the MediaStream changed. + */ + void NotifyStreamStateChanged(); + + // Indicate what track types we eventually expect to add to this stream + enum { + HINT_CONTENTS_AUDIO = 1 << 0, + HINT_CONTENTS_VIDEO = 1 << 1 + }; + TrackTypeHints GetHintContents() const { return mHintContents; } + void SetHintContents(TrackTypeHints aHintContents) { mHintContents = aHintContents; } + + /** + * Create an nsDOMMediaStream whose underlying stream is a SourceMediaStream. + */ + static already_AddRefed + CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); + + /** + * Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream. + */ + static already_AddRefed + CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0); + + void SetLogicalStreamStartTime(StreamTime aTime) + { + mLogicalStreamStartTime = aTime; + } + + // Notifications from StreamListener. + // CreateDOMTrack should only be called when it's safe to run script. + MediaStreamTrack* CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType); + MediaStreamTrack* GetDOMTrackFor(TrackID aTrackID); + + class OnTracksAvailableCallback { + public: + OnTracksAvailableCallback(uint8_t aExpectedTracks = 0) + : mExpectedTracks(aExpectedTracks) {} + virtual ~OnTracksAvailableCallback() {} + virtual void NotifyTracksAvailable(DOMMediaStream* aStream) = 0; + TrackTypeHints GetExpectedTracks() { return mExpectedTracks; } + void SetExpectedTracks(TrackTypeHints aExpectedTracks) { mExpectedTracks = aExpectedTracks; } + private: + TrackTypeHints mExpectedTracks; + }; + // When one track of the appropriate type has been added for each bit set + // in aCallback->GetExpectedTracks(), run aCallback->NotifyTracksAvailable. + // It is allowed to do anything, including run script. + // aCallback may run immediately during this call if tracks are already + // available! + // We only care about track additions, we'll fire the notification even if + // some of the tracks have been removed. + // Takes ownership of aCallback. + // If GetExpectedTracks() returns 0, the callback will be fired as soon as there are any tracks. + void OnTracksAvailable(OnTracksAvailableCallback* aCallback); + + /** + * Add an nsISupports object that this stream will keep alive as long as + * the stream is not finished. + */ + void AddConsumerToKeepAlive(nsISupports* aConsumer) + { + if (!IsFinished() && !mNotifiedOfMediaStreamGraphShutdown) { + mConsumersToKeepAlive.AppendElement(aConsumer); + } + } + +protected: + void Destroy(); + void InitSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); + void InitTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); + void InitStreamCommon(MediaStream* aStream); + + void CheckTracksAvailable(); + + class StreamListener; + friend class StreamListener; + + // StreamTime at which the currentTime attribute would return 0. + StreamTime mLogicalStreamStartTime; + + // We need this to track our parent object. + nsCOMPtr mWindow; + + // MediaStream is owned by the graph, but we tell it when to die, and it won't + // die until we let it. + MediaStream* mStream; + // Principal identifying who may access the contents of this stream. + // If null, this stream can be used by anyone because it has no content yet. + nsCOMPtr mPrincipal; + + nsAutoTArray,2> mTracks; + nsRefPtr mListener; + + nsTArray > mRunOnTracksAvailable; + + // Keep these alive until the stream finishes + nsTArray > mConsumersToKeepAlive; + + // Indicate what track types we eventually expect to add to this stream + uint8_t mHintContents; + // Indicate what track types have been added to this stream + uint8_t mTrackTypesAvailable; + bool mNotifiedOfMediaStreamGraphShutdown; +}; + +class DOMLocalMediaStream : public DOMMediaStream, + public nsIDOMLocalMediaStream +{ +public: + DOMLocalMediaStream() {} + virtual ~DOMLocalMediaStream(); + + NS_DECL_ISUPPORTS_INHERITED + + virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; + + virtual void Stop(); + + /** + * Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream. + */ + static already_AddRefed + CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); + + /** + * Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream. + */ + static already_AddRefed + CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0); +}; + +class DOMAudioNodeMediaStream : public DOMMediaStream +{ + typedef dom::AudioNode AudioNode; +public: + DOMAudioNodeMediaStream(AudioNode* aNode); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream) + + /** + * Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream. + */ + static already_AddRefed + CreateTrackUnionStream(nsIDOMWindow* aWindow, + AudioNode* aNode, + TrackTypeHints aHintContents = 0); + +private: + // If this object wraps a stream owned by an AudioNode, we need to ensure that + // the node isn't cycle-collected too early. + nsRefPtr mStreamNode; +}; + +} + +#endif /* NSDOMMEDIASTREAM_H_ */