Bug 866514. Part 1: Add DOMMediaStream::OnTracksAvailableCallback. r=jesup

--HG--
extra : rebase_source : 8d8da0bc2a55fa14f837cb85f35236ca33d2437d
This commit is contained in:
Robert O'Callahan 2013-05-03 17:02:55 +12:00
Родитель b1b2cbcf67
Коммит 829a481dde
4 изменённых файлов: 124 добавлений и 27 удалений

Просмотреть файл

@ -113,7 +113,8 @@ private:
};
DOMMediaStream::DOMMediaStream()
: mStream(nullptr), mHintContents(0)
: mStream(nullptr), mHintContents(0), mTrackTypesAvailable(0),
mNotifiedOfMediaStreamGraphShutdown(false)
{
SetIsDOMBinding();
}
@ -177,7 +178,7 @@ DOMMediaStream::IsFinished()
}
void
DOMMediaStream::InitSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents)
DOMMediaStream::InitSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents)
{
mWindow = aWindow;
SetHintContents(aHintContents);
@ -186,7 +187,7 @@ DOMMediaStream::InitSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents)
}
void
DOMMediaStream::InitTrackUnionStream(nsIDOMWindow* aWindow, uint32_t aHintContents)
DOMMediaStream::InitTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents)
{
mWindow = aWindow;
SetHintContents(aHintContents);
@ -205,7 +206,7 @@ DOMMediaStream::InitStreamCommon(MediaStream* aStream)
}
already_AddRefed<DOMMediaStream>
DOMMediaStream::CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents)
DOMMediaStream::CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents)
{
nsRefPtr<DOMMediaStream> stream = new DOMMediaStream();
stream->InitSourceStream(aWindow, aHintContents);
@ -213,7 +214,7 @@ DOMMediaStream::CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents
}
already_AddRefed<DOMMediaStream>
DOMMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow, uint32_t aHintContents)
DOMMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents)
{
nsRefPtr<DOMMediaStream> stream = new DOMMediaStream();
stream->InitTrackUnionStream(aWindow, aHintContents);
@ -233,16 +234,20 @@ DOMMediaStream::CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType)
switch (aType) {
case MediaSegment::AUDIO:
track = new AudioStreamTrack(this, aTrackID);
mTrackTypesAvailable |= HINT_CONTENTS_AUDIO;
break;
case MediaSegment::VIDEO:
track = new VideoStreamTrack(this, aTrackID);
mTrackTypesAvailable |= HINT_CONTENTS_VIDEO;
break;
default:
MOZ_NOT_REACHED("Unhandled track type");
return nullptr;
}
mTracks.AppendElement(track);
CheckTracksAvailable();
return track;
}
@ -260,6 +265,44 @@ DOMMediaStream::GetDOMTrackFor(TrackID aTrackID)
return nullptr;
}
void
DOMMediaStream::NotifyMediaStreamGraphShutdown()
{
// No more tracks will ever be added, so just clear these callbacks now
// to prevent leaks.
mNotifiedOfMediaStreamGraphShutdown = true;
mRunOnTracksAvailable.Clear();
}
void
DOMMediaStream::OnTracksAvailable(OnTracksAvailableCallback* aRunnable)
{
if (mNotifiedOfMediaStreamGraphShutdown) {
// No more tracks will ever be added, so just delete the callback now.
delete aRunnable;
return;
}
mRunOnTracksAvailable.AppendElement(aRunnable);
CheckTracksAvailable();
}
void
DOMMediaStream::CheckTracksAvailable()
{
nsTArray<nsAutoPtr<OnTracksAvailableCallback> > callbacks;
callbacks.SwapElements(mRunOnTracksAvailable);
for (uint32_t i = 0; i < callbacks.Length(); ++i) {
OnTracksAvailableCallback* cb = callbacks[i];
if (~mTrackTypesAvailable & cb->GetExpectedTracks()) {
// Some expected tracks not available yet. Try this callback again later.
*mRunOnTracksAvailable.AppendElement() = callbacks[i].forget();
continue;
}
cb->NotifyTracksAvailable(this);
}
}
DOMLocalMediaStream::~DOMLocalMediaStream()
{
if (mStream) {
@ -283,7 +326,8 @@ DOMLocalMediaStream::Stop()
}
already_AddRefed<DOMLocalMediaStream>
DOMLocalMediaStream::CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents)
DOMLocalMediaStream::CreateSourceStream(nsIDOMWindow* aWindow,
TrackTypeHints aHintContents)
{
nsRefPtr<DOMLocalMediaStream> stream = new DOMLocalMediaStream();
stream->InitSourceStream(aWindow, aHintContents);
@ -291,7 +335,8 @@ DOMLocalMediaStream::CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintCon
}
already_AddRefed<DOMLocalMediaStream>
DOMLocalMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow, uint32_t aHintContents)
DOMLocalMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow,
TrackTypeHints aHintContents)
{
nsRefPtr<DOMLocalMediaStream> stream = new DOMLocalMediaStream();
stream->InitTrackUnionStream(aWindow, aHintContents);

Просмотреть файл

@ -12,6 +12,7 @@
#include "nsWrapperCache.h"
#include "nsIDOMWindow.h"
#include "StreamBuffer.h"
#include "nsIRunnable.h"
class nsXPCClassInfo;
@ -49,6 +50,8 @@ class DOMMediaStream : public nsIDOMMediaStream,
typedef dom::VideoStreamTrack VideoStreamTrack;
public:
typedef uint8_t TrackTypeHints;
DOMMediaStream();
virtual ~DOMMediaStream();
@ -83,36 +86,66 @@ public:
*/
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();
// 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<DOMMediaStream>
CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents);
// Hints to tell the SDP generator about whether this
// MediaStream probably has audio and/or video
enum {
HINT_CONTENTS_AUDIO = 0x00000001U,
HINT_CONTENTS_VIDEO = 0x00000002U
};
uint32_t GetHintContents() const { return mHintContents; }
void SetHintContents(uint32_t aHintContents) { mHintContents = aHintContents; }
CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
/**
* Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream.
*/
static already_AddRefed<DOMMediaStream>
CreateTrackUnionStream(nsIDOMWindow* aWindow, uint32_t aHintContents = 0);
CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0);
// Notifications from StreamListener
// 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.
void OnTracksAvailable(OnTracksAvailableCallback* aCallback);
protected:
void Destroy();
void InitSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents);
void InitTrackUnionStream(nsIDOMWindow* aWindow, uint32_t aHintContents);
void InitSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
void InitTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
void InitStreamCommon(MediaStream* aStream);
void CheckTracksAvailable();
class StreamListener;
friend class StreamListener;
@ -130,9 +163,13 @@ protected:
nsAutoTArray<nsRefPtr<MediaStreamTrack>,2> mTracks;
nsRefPtr<StreamListener> mListener;
// tells the SDP generator about whether this
// MediaStream probably has audio and/or video
uint32_t mHintContents;
nsTArray<nsAutoPtr<OnTracksAvailableCallback> > mRunOnTracksAvailable;
// 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,
@ -153,13 +190,13 @@ public:
* Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
*/
static already_AddRefed<DOMLocalMediaStream>
CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents);
CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
/**
* Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream.
*/
static already_AddRefed<DOMLocalMediaStream>
CreateTrackUnionStream(nsIDOMWindow* aWindow, uint32_t aHintContents = 0);
CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0);
};
}

Просмотреть файл

@ -22,6 +22,7 @@
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
#include <algorithm>
#include "DOMMediaStream.h"
using namespace mozilla::layers;
using namespace mozilla::dom;
@ -1137,6 +1138,7 @@ public:
{
NS_ASSERTION(mGraph->mDetectedNotRunning,
"We should know the graph thread control loop isn't running!");
// mGraph's thread is not running so it's OK to do whatever here
if (mGraph->IsEmpty()) {
// mGraph is no longer needed, so delete it. If the graph is not empty
@ -1144,6 +1146,13 @@ public:
// detect that the manager has been emptied, and delete it.
delete mGraph;
} else {
for (uint32_t i = 0; i < mGraph->mStreams.Length(); ++i) {
DOMMediaStream* s = mGraph->mStreams[i]->GetWrapper();
if (s) {
s->NotifyMediaStreamGraphShutdown();
}
}
NS_ASSERTION(mGraph->mForceShutDown, "Not in forced shutdown?");
mGraph->mLifecycleState =
MediaStreamGraphImpl::LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION;

Просмотреть файл

@ -427,6 +427,12 @@ public:
bool HasCurrentData() { return mHasCurrentData; }
DOMMediaStream* GetWrapper()
{
NS_ASSERTION(NS_IsMainThread(), "Only use DOMMediaStream on main thread");
return mWrapper;
}
protected:
virtual void AdvanceTimeVaryingValuesToCurrentTime(GraphTime aCurrentTime, GraphTime aBlockedTime)
{