mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-30 05:35:31 +00:00
071a2ca6e9
fix GetTrackTypesAvailable to not report placeholder tracks
380 lines
13 KiB
C++
380 lines
13 KiB
C++
/* -*- 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 "nsCycleCollectionParticipant.h"
|
|
#include "nsWrapperCache.h"
|
|
#include "StreamBuffer.h"
|
|
#include "nsIDOMWindow.h"
|
|
#include "nsIPrincipal.h"
|
|
#include "mozilla/PeerIdentity.h"
|
|
#include "mozilla/DOMEventTargetHelper.h"
|
|
|
|
class nsXPCClassInfo;
|
|
|
|
// 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 dom/media/webaudio/AudioContext.h for more fun!
|
|
#ifdef CurrentTime
|
|
#undef CurrentTime
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
|
|
class DOMLocalMediaStream;
|
|
class MediaStream;
|
|
class MediaEngineSource;
|
|
|
|
namespace dom {
|
|
class AudioNode;
|
|
class MediaStreamTrack;
|
|
class AudioStreamTrack;
|
|
class VideoStreamTrack;
|
|
class AudioTrack;
|
|
class VideoTrack;
|
|
class AudioTrackList;
|
|
class VideoTrackList;
|
|
class MediaTrackListListener;
|
|
}
|
|
|
|
class MediaStreamDirectListener;
|
|
|
|
#define NS_DOMMEDIASTREAM_IID \
|
|
{ 0x8cb65468, 0x66c0, 0x444e, \
|
|
{ 0x89, 0x9f, 0x89, 0x1d, 0x9e, 0xd2, 0xbe, 0x7c } }
|
|
|
|
/**
|
|
* DOM wrapper for MediaStreams.
|
|
*/
|
|
class DOMMediaStream : public DOMEventTargetHelper
|
|
{
|
|
friend class DOMLocalMediaStream;
|
|
typedef dom::MediaStreamTrack MediaStreamTrack;
|
|
typedef dom::AudioStreamTrack AudioStreamTrack;
|
|
typedef dom::VideoStreamTrack VideoStreamTrack;
|
|
typedef dom::AudioTrack AudioTrack;
|
|
typedef dom::VideoTrack VideoTrack;
|
|
typedef dom::AudioTrackList AudioTrackList;
|
|
typedef dom::VideoTrackList VideoTrackList;
|
|
typedef dom::MediaTrackListListener MediaTrackListListener;
|
|
|
|
public:
|
|
typedef uint8_t TrackTypeHints;
|
|
|
|
DOMMediaStream();
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
|
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMMediaStream,
|
|
DOMEventTargetHelper)
|
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMMEDIASTREAM_IID)
|
|
|
|
nsIDOMWindow* GetParentObject() const
|
|
{
|
|
return mWindow;
|
|
}
|
|
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
|
|
|
// WebIDL
|
|
double CurrentTime();
|
|
|
|
void GetAudioTracks(nsTArray<nsRefPtr<AudioStreamTrack> >& aTracks);
|
|
void GetVideoTracks(nsTArray<nsRefPtr<VideoStreamTrack> >& aTracks);
|
|
void GetTracks(nsTArray<nsRefPtr<MediaStreamTrack> >& aTracks);
|
|
bool HasTrack(const MediaStreamTrack& aTrack) const;
|
|
|
|
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);
|
|
|
|
virtual void StopTrack(TrackID aTrackID);
|
|
|
|
virtual DOMLocalMediaStream* AsDOMLocalMediaStream() { return nullptr; }
|
|
|
|
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; }
|
|
|
|
/**
|
|
* These are used in WebRTC. A peerIdentity constrained MediaStream cannot be sent
|
|
* across the network to anything other than a peer with the provided identity.
|
|
* If this is set, then mPrincipal should be an instance of nsNullPrincipal.
|
|
*/
|
|
PeerIdentity* GetPeerIdentity() const { return mPeerIdentity; }
|
|
void SetPeerIdentity(PeerIdentity* aPeerIdentity)
|
|
{
|
|
mPeerIdentity = aPeerIdentity;
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
|
|
/**
|
|
* This is used in WebRTC to move from a protected state (nsNullPrincipal) to
|
|
* one where the stream is accessible to script. Don't call this.
|
|
* CombineWithPrincipal is almost certainly more appropriate.
|
|
*/
|
|
void SetPrincipal(nsIPrincipal* aPrincipal);
|
|
|
|
/**
|
|
* Used to learn about dynamic changes in principal occur.
|
|
* Operations relating to these observers must be confined to the main thread.
|
|
*/
|
|
class PrincipalChangeObserver
|
|
{
|
|
public:
|
|
virtual void PrincipalChanged(DOMMediaStream* aMediaStream) = 0;
|
|
};
|
|
bool AddPrincipalChangeObserver(PrincipalChangeObserver* aObserver);
|
|
bool RemovePrincipalChangeObserver(PrincipalChangeObserver* aObserver);
|
|
|
|
/**
|
|
* 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,
|
|
HINT_CONTENTS_UNKNOWN = 1 << 2
|
|
};
|
|
TrackTypeHints GetHintContents() const { return mHintContents; }
|
|
void SetHintContents(TrackTypeHints aHintContents);
|
|
|
|
TrackTypeHints GetTrackTypesAvailable() const { return mTrackTypesAvailable; }
|
|
|
|
/**
|
|
* Create an nsDOMMediaStream whose underlying stream is a SourceMediaStream.
|
|
*/
|
|
static already_AddRefed<DOMMediaStream>
|
|
CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
|
|
|
|
/**
|
|
* Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream.
|
|
*/
|
|
static already_AddRefed<DOMMediaStream>
|
|
CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0);
|
|
|
|
void SetLogicalStreamStartTime(StreamTime aTime)
|
|
{
|
|
mLogicalStreamStartTime = aTime;
|
|
}
|
|
|
|
// Notifications from StreamListener.
|
|
// BindDOMTrack should only be called when it's safe to run script.
|
|
MediaStreamTrack* BindDOMTrack(TrackID aTrackID, MediaSegment::Type aType);
|
|
MediaStreamTrack* CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType);
|
|
MediaStreamTrack* GetDOMTrackFor(TrackID aTrackID);
|
|
|
|
class OnTracksAvailableCallback {
|
|
public:
|
|
explicit 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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* If loading and playing a MediaStream in a media element, for each
|
|
* MediaStreamTrack in the MediaStream, create a corresponding AudioTrack or
|
|
* VideoTrack during the phase of resource fetching.
|
|
*/
|
|
void ConstructMediaTracks(AudioTrackList* aAudioTrackList,
|
|
VideoTrackList* aVideoTrackList);
|
|
|
|
/**
|
|
* MUST call this before the AudioTrackList or VideoTrackList go away
|
|
*/
|
|
void DisconnectTrackListListeners(const AudioTrackList* aAudioTrackList,
|
|
const VideoTrackList* aVideoTrackList);
|
|
|
|
virtual void NotifyMediaStreamTrackCreated(MediaStreamTrack* aTrack);
|
|
|
|
virtual void NotifyMediaStreamTrackEnded(MediaStreamTrack* aTrack);
|
|
|
|
protected:
|
|
virtual ~DOMMediaStream();
|
|
|
|
void Destroy();
|
|
void InitSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
|
|
void InitTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
|
|
void InitStreamCommon(MediaStream* aStream);
|
|
already_AddRefed<AudioTrack> CreateAudioTrack(AudioStreamTrack* aStreamTrack);
|
|
already_AddRefed<VideoTrack> CreateVideoTrack(VideoStreamTrack* aStreamTrack);
|
|
|
|
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<nsIDOMWindow> 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;
|
|
|
|
nsAutoTArray<nsRefPtr<MediaStreamTrack>,2> mTracks;
|
|
nsRefPtr<StreamListener> mListener;
|
|
|
|
nsTArray<nsAutoPtr<OnTracksAvailableCallback> > mRunOnTracksAvailable;
|
|
|
|
// Keep these alive until the stream finishes
|
|
nsTArray<nsCOMPtr<nsISupports> > mConsumersToKeepAlive;
|
|
|
|
// Indicate what track types we eventually expect to add to this stream
|
|
uint8_t mHintContents;
|
|
// Indicate what track types have arrived in this stream
|
|
uint8_t mTrackTypesAvailable;
|
|
bool mNotifiedOfMediaStreamGraphShutdown;
|
|
|
|
// Send notifications to AudioTrackList or VideoTrackList, if this MediaStream
|
|
// is consumed by a HTMLMediaElement.
|
|
nsTArray<MediaTrackListListener> mMediaTrackListListeners;
|
|
|
|
private:
|
|
void NotifyPrincipalChanged();
|
|
|
|
// 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<nsIPrincipal> mPrincipal;
|
|
nsTArray<PrincipalChangeObserver*> mPrincipalChangeObservers;
|
|
// this is used in gUM and WebRTC to identify peers that this stream
|
|
// is allowed to be sent to
|
|
nsAutoPtr<PeerIdentity> mPeerIdentity;
|
|
};
|
|
|
|
NS_DEFINE_STATIC_IID_ACCESSOR(DOMMediaStream,
|
|
NS_DOMMEDIASTREAM_IID)
|
|
|
|
#define NS_DOMLOCALMEDIASTREAM_IID \
|
|
{ 0xb1437260, 0xec61, 0x4dfa, \
|
|
{ 0x92, 0x54, 0x04, 0x44, 0xe2, 0xb5, 0x94, 0x9c } }
|
|
|
|
class DOMLocalMediaStream : public DOMMediaStream
|
|
{
|
|
public:
|
|
DOMLocalMediaStream() {}
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMLOCALMEDIASTREAM_IID)
|
|
|
|
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
|
|
|
virtual void Stop();
|
|
|
|
virtual MediaEngineSource* GetMediaEngine(TrackID aTrackID) { return nullptr; }
|
|
|
|
/**
|
|
* Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
|
|
*/
|
|
static already_AddRefed<DOMLocalMediaStream>
|
|
CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
|
|
|
|
/**
|
|
* Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream.
|
|
*/
|
|
static already_AddRefed<DOMLocalMediaStream>
|
|
CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0);
|
|
|
|
protected:
|
|
virtual ~DOMLocalMediaStream();
|
|
};
|
|
|
|
NS_DEFINE_STATIC_IID_ACCESSOR(DOMLocalMediaStream,
|
|
NS_DOMLOCALMEDIASTREAM_IID)
|
|
|
|
class DOMAudioNodeMediaStream : public DOMMediaStream
|
|
{
|
|
typedef dom::AudioNode AudioNode;
|
|
public:
|
|
explicit 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<DOMAudioNodeMediaStream>
|
|
CreateTrackUnionStream(nsIDOMWindow* aWindow,
|
|
AudioNode* aNode,
|
|
TrackTypeHints aHintContents = 0);
|
|
|
|
protected:
|
|
~DOMAudioNodeMediaStream();
|
|
|
|
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<AudioNode> mStreamNode;
|
|
};
|
|
|
|
}
|
|
|
|
#endif /* NSDOMMEDIASTREAM_H_ */
|