Bug 803976: Implementation of LocalMediaStreams for .stop() r=roc,anant

This commit is contained in:
Randell Jesup 2012-10-24 19:21:32 -04:00
parent 781f490022
commit 5d4b72af55
12 changed files with 154 additions and 25 deletions

View File

@ -2007,11 +2007,14 @@ void
SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment)
{
MutexAutoLock lock(mMutex);
TrackData *track = FindDataForTrack(aID);
if (track) {
track->mData->AppendFrom(aSegment);
} else {
NS_ERROR("Append to non-existent track!");
// ::EndAllTrackAndFinished() can end these before the sources notice
if (!mFinished) {
TrackData *track = FindDataForTrack(aID);
if (track) {
track->mData->AppendFrom(aSegment);
} else {
NS_ERROR("Append to non-existent track!");
}
}
if (!mDestroyed) {
GraphImpl()->EnsureNextIteration();
@ -2052,11 +2055,14 @@ void
SourceMediaStream::EndTrack(TrackID aID)
{
MutexAutoLock lock(mMutex);
TrackData *track = FindDataForTrack(aID);
if (track) {
track->mCommands |= TRACK_END;
} else {
NS_ERROR("End of non-existant track");
// ::EndAllTrackAndFinished() can end these before the sources call this
if (!mFinished) {
TrackData *track = FindDataForTrack(aID);
if (track) {
track->mCommands |= TRACK_END;
} else {
NS_ERROR("End of non-existant track");
}
}
if (!mDestroyed) {
GraphImpl()->EnsureNextIteration();
@ -2074,15 +2080,28 @@ SourceMediaStream::AdvanceKnownTracksTime(StreamTime aKnownTime)
}
void
SourceMediaStream::Finish()
SourceMediaStream::FinishWithLockHeld()
{
MutexAutoLock lock(mMutex);
mUpdateFinished = true;
if (!mDestroyed) {
GraphImpl()->EnsureNextIteration();
}
}
void
SourceMediaStream::EndAllTrackAndFinish()
{
{
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mUpdateTracks.Length(); ++i) {
SourceMediaStream::TrackData* data = &mUpdateTracks[i];
data->mCommands |= TRACK_END;
}
}
FinishWithLockHeld();
// we will call NotifyFinished() to let GetUserMedia know
}
void
MediaInputPort::Init()
{

View File

@ -553,7 +553,19 @@ public:
* when all tracks have ended and when latest time sent to
* AdvanceKnownTracksTime() has been reached.
*/
void Finish();
void FinishWithLockHeld();
void Finish()
{
MutexAutoLock lock(mMutex);
FinishWithLockHeld();
}
/**
* End all tracks and Finish() this stream. Used to voluntarily revoke access
* to a LocalMediaStream.
*/
void EndAllTrackAndFinish();
// XXX need a Reset API

View File

@ -28,6 +28,29 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMMediaStream)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
// LocalMediaStream currently is the same C++ class as MediaStream;
// they may eventually split
DOMCI_DATA(LocalMediaStream, nsDOMLocalMediaStream)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMLocalMediaStream)
NS_INTERFACE_MAP_ENTRY(nsIDOMLocalMediaStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMMediaStream, nsDOMMediaStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMLocalMediaStream)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(LocalMediaStream)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMLocalMediaStream)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMLocalMediaStream)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMLocalMediaStream)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMLocalMediaStream)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMLocalMediaStream)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
nsDOMMediaStream::~nsDOMMediaStream()
{
if (mStream) {
@ -42,6 +65,15 @@ nsDOMMediaStream::GetCurrentTime(double *aCurrentTime)
return NS_OK;
}
NS_IMETHODIMP
nsDOMLocalMediaStream::Stop()
{
if (mStream && mStream->AsSourceStream()) {
mStream->AsSourceStream()->EndAllTrackAndFinish();
}
return NS_OK;
}
already_AddRefed<nsDOMMediaStream>
nsDOMMediaStream::CreateInputStream(uint32_t aHintContents)
{
@ -52,6 +84,16 @@ nsDOMMediaStream::CreateInputStream(uint32_t aHintContents)
return stream.forget();
}
already_AddRefed<nsDOMLocalMediaStream>
nsDOMLocalMediaStream::CreateInputStream(uint32_t aHintContents)
{
nsRefPtr<nsDOMLocalMediaStream> stream = new nsDOMLocalMediaStream();
stream->SetHintContents(aHintContents);
MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
stream->mStream = gm->CreateInputStream(stream);
return stream.forget();
}
already_AddRefed<nsDOMMediaStream>
nsDOMMediaStream::CreateTrackUnionStream()
{
@ -61,6 +103,15 @@ nsDOMMediaStream::CreateTrackUnionStream()
return stream.forget();
}
already_AddRefed<nsDOMLocalMediaStream>
nsDOMLocalMediaStream::CreateTrackUnionStream()
{
nsRefPtr<nsDOMLocalMediaStream> stream = new nsDOMLocalMediaStream();
MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
stream->mStream = gm->CreateTrackUnionStream(stream);
return stream.forget();
}
bool
nsDOMMediaStream::CombineWithPrincipal(nsIPrincipal* aPrincipal)
{

View File

@ -11,6 +11,8 @@
#include "nsCycleCollectionParticipant.h"
#include "nsIPrincipal.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.
@ -23,6 +25,7 @@
*/
class nsDOMMediaStream : public nsIDOMMediaStream
{
friend class nsDOMLocalMediaStream;
typedef mozilla::MediaStream MediaStream;
public:
@ -82,4 +85,28 @@ protected:
uint32_t mHintContents;
};
class nsDOMLocalMediaStream : public nsDOMMediaStream,
public nsIDOMLocalMediaStream
{
public:
nsDOMLocalMediaStream() {}
virtual ~nsDOMLocalMediaStream() {}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMLocalMediaStream, nsDOMMediaStream)
NS_DECL_NSIDOMLOCALMEDIASTREAM
NS_FORWARD_NSIDOMMEDIASTREAM(nsDOMMediaStream::)
/**
* Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
*/
static already_AddRefed<nsDOMLocalMediaStream> CreateInputStream(uint32_t aHintContents);
/**
* Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream.
*/
static already_AddRefed<nsDOMLocalMediaStream> CreateTrackUnionStream();
};
#endif /* NSDOMMEDIASTREAM_H_ */

View File

@ -1518,6 +1518,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MediaStream, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(LocalMediaStream, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
#endif
NS_DEFINE_CLASSINFO_DATA(XMLHttpRequestUpload, nsEventTargetSH,
@ -4128,6 +4130,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(MediaStream, nsIDOMMediaStream)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMediaStream)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(LocalMediaStream, nsIDOMLocalMediaStream)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMLocalMediaStream)
DOM_CLASSINFO_MAP_END
#endif
DOM_CLASSINFO_MAP_BEGIN(XMLHttpRequestUpload, nsIXMLHttpRequestUpload)

View File

@ -426,6 +426,7 @@ DOMCI_CLASS(TimeRanges)
// Media streams
DOMCI_CLASS(MediaStream)
DOMCI_CLASS(LocalMediaStream)
#endif
DOMCI_CLASS(XMLHttpRequestUpload)

View File

@ -44,7 +44,7 @@ public:
break;
case STOP:
mDOMPreview->Stop();
mDOMPreview->StopPreview();
break;
case STARTED:
@ -238,9 +238,9 @@ DOMCameraPreview::Started()
}
void
DOMCameraPreview::Stop()
DOMCameraPreview::StopPreview()
{
NS_ASSERTION(NS_IsMainThread(), "Stop() not called from main thread");
NS_ASSERTION(NS_IsMainThread(), "StopPreview() not called from main thread");
if (mState != STARTED) {
return;
}

View File

@ -40,7 +40,7 @@ public:
void Start(); // called by the MediaStreamListener to start preview
void Started(); // called by the CameraControl when preview is started
void Stop(); // called by the MediaStreamListener to stop preview
void StopPreview(); // called by the MediaStreamListener to stop preview
void Stopped(bool aForced = false);
// called by the CameraControl when preview is stopped
void Error(); // something went wrong, NS_RELEASE needed

View File

@ -244,11 +244,11 @@ public:
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
// Create a media stream.
nsCOMPtr<nsDOMMediaStream> stream;
nsRefPtr<nsDOMLocalMediaStream> stream;
uint32_t hints = (mAudioSource ? nsDOMMediaStream::HINT_CONTENTS_AUDIO : 0);
hints |= (mVideoSource ? nsDOMMediaStream::HINT_CONTENTS_VIDEO : 0);
stream = nsDOMMediaStream::CreateInputStream(hints);
stream = nsDOMLocalMediaStream::CreateInputStream(hints);
nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
(nsGlobalWindow::GetInnerWindowWithId(mWindowID));
@ -299,7 +299,7 @@ public:
MutexAutoLock lock(MediaManager::Get()->GetMutex());
if (activeWindows->Get(mWindowID)) {
LOG(("Returning success for getUserMedia()"));
success->OnSuccess(stream);
success->OnSuccess(static_cast<nsIDOMLocalMediaStream*>(stream));
}
}

View File

@ -132,7 +132,7 @@ public:
}
MM_LOG(("started all sources"));
nsCOMPtr<GetUserMediaNotificationEvent> event =
nsRefPtr<GetUserMediaNotificationEvent> event =
new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
@ -153,7 +153,7 @@ public:
// Do this after stopping all tracks with EndTrack()
mSourceStream->Finish();
nsCOMPtr<GetUserMediaNotificationEvent> event =
nsRefPtr<GetUserMediaNotificationEvent> event =
new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STOPPING);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
@ -175,7 +175,7 @@ private:
MediaOperation mType;
nsRefPtr<MediaEngineSource> mAudioSource;
nsRefPtr<MediaEngineSource> mVideoSource;
nsCOMPtr<nsDOMMediaStream> mStream;
nsRefPtr<nsDOMMediaStream> mStream;
SourceMediaStream *mSourceStream;
};
@ -228,11 +228,17 @@ public:
}
}
void
NotifyFinished(MediaStreamGraph* aGraph)
{
Invalidate();
}
private:
nsCOMPtr<nsIThread> mMediaThread;
nsRefPtr<MediaEngineSource> mAudioSource;
nsRefPtr<MediaEngineSource> mVideoSource;
nsCOMPtr<nsDOMMediaStream> mStream;
nsRefPtr<nsDOMMediaStream> mStream;
bool mValid;
};

View File

@ -10,3 +10,10 @@ interface nsIDOMMediaStream : nsISupports
{
readonly attribute double currentTime;
};
[scriptable, builtinclass, uuid(210a16e3-2a38-4ae9-b0f6-0fb5a8252814)]
interface nsIDOMLocalMediaStream : nsIDOMMediaStream
{
void stop();
};

View File

@ -24,7 +24,7 @@ interface nsIDOMGetUserMediaSuccessCallback : nsISupports
{
/*
* value must be a nsIDOMBlob if picture is true and a
* nsIDOMMediaStream if either audio or video are true.
* nsIDOMLocalMediaStream if either audio or video are true.
*/
void onSuccess(in nsISupports value);
};