Bug 822956: convert to TrackUnionStreams for getUserMedia (and add hint support) r=roc

This commit is contained in:
Randell Jesup 2012-12-19 02:07:37 -05:00
parent ed8ded286d
commit 7ddd77aaa3
4 changed files with 23 additions and 7 deletions

View File

@ -95,18 +95,20 @@ nsDOMLocalMediaStream::CreateSourceStream(uint32_t aHintContents)
}
already_AddRefed<nsDOMMediaStream>
nsDOMMediaStream::CreateTrackUnionStream()
nsDOMMediaStream::CreateTrackUnionStream(uint32_t aHintContents)
{
nsRefPtr<nsDOMMediaStream> stream = new nsDOMMediaStream();
stream->SetHintContents(aHintContents);
MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
stream->mStream = gm->CreateTrackUnionStream(stream);
return stream.forget();
}
already_AddRefed<nsDOMLocalMediaStream>
nsDOMLocalMediaStream::CreateTrackUnionStream()
nsDOMLocalMediaStream::CreateTrackUnionStream(uint32_t aHintContents)
{
nsRefPtr<nsDOMLocalMediaStream> stream = new nsDOMLocalMediaStream();
stream->SetHintContents(aHintContents);
MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
stream->mStream = gm->CreateTrackUnionStream(stream);
return stream.forget();

View File

@ -70,7 +70,7 @@ public:
/**
* Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream.
*/
static already_AddRefed<nsDOMMediaStream> CreateTrackUnionStream();
static already_AddRefed<nsDOMMediaStream> CreateTrackUnionStream(uint32_t aHintContents = 0);
protected:
// MediaStream is owned by the graph, but we tell it when to die, and it won't
@ -106,7 +106,7 @@ public:
/**
* Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream.
*/
static already_AddRefed<nsDOMLocalMediaStream> CreateTrackUnionStream();
static already_AddRefed<nsDOMLocalMediaStream> CreateTrackUnionStream(uint32_t aHintContents = 0);
};
#endif /* NSDOMMEDIASTREAM_H_ */

View File

@ -268,21 +268,29 @@ public:
// Create a media stream.
nsRefPtr<nsDOMLocalMediaStream> stream;
nsRefPtr<nsDOMLocalMediaStream> trackunion;
uint32_t hints = (mAudioSource ? nsDOMMediaStream::HINT_CONTENTS_AUDIO : 0);
hints |= (mVideoSource ? nsDOMMediaStream::HINT_CONTENTS_VIDEO : 0);
stream = nsDOMLocalMediaStream::CreateSourceStream(hints);
if (!stream) {
stream = nsDOMLocalMediaStream::CreateSourceStream(hints);
trackunion = nsDOMLocalMediaStream::CreateTrackUnionStream(hints);
if (!stream || !trackunion) {
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
LOG(("Returning error for getUserMedia() - no stream"));
error->OnError(NS_LITERAL_STRING("NO_STREAM"));
return NS_OK;
}
// connect the source stream to the track union stream to avoid us blocking
trackunion->GetStream()->AsProcessedStream()->SetAutofinish(true);
nsRefPtr<MediaInputPort> port = trackunion->GetStream()->AsProcessedStream()->
AllocateInputPort(stream->GetStream()->AsSourceStream(),
MediaInputPort::FLAG_BLOCK_OUTPUT);
nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
(nsGlobalWindow::GetInnerWindowWithId(mWindowID));
if (window && window->GetExtantDoc()) {
stream->CombineWithPrincipal(window->GetExtantDoc()->NodePrincipal());
trackunion->CombineWithPrincipal(window->GetExtantDoc()->NodePrincipal());
}
// Ensure there's a thread for gum to proxy to off main thread
@ -293,6 +301,7 @@ public:
// when the page is invalidated (on navigation or close).
GetUserMediaCallbackMediaStreamListener* listener =
new GetUserMediaCallbackMediaStreamListener(mediaThread, stream,
port.forget(),
mAudioSource,
mVideoSource);
stream->GetStream()->AddListener(listener);
@ -317,7 +326,7 @@ public:
// This is safe since we're on main-thread, and the windowlist can only
// be invalidated from the main-thread (see OnNavigation)
LOG(("Returning success for getUserMedia()"));
success->OnSuccess(static_cast<nsIDOMLocalMediaStream*>(stream));
success->OnSuccess(static_cast<nsIDOMLocalMediaStream*>(trackunion));
return NS_OK;
}

View File

@ -71,12 +71,14 @@ class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener
public:
GetUserMediaCallbackMediaStreamListener(nsIThread *aThread,
nsDOMMediaStream* aStream,
already_AddRefed<MediaInputPort> aPort,
MediaEngineSource* aAudioSource,
MediaEngineSource* aVideoSource)
: mMediaThread(aThread)
, mAudioSource(aAudioSource)
, mVideoSource(aVideoSource)
, mStream(aStream)
, mPort(aPort)
, mSourceStream(aStream->GetStream()->AsSourceStream())
, mLastEndTimeAudio(0)
, mLastEndTimeVideo(0) { MOZ_ASSERT(mSourceStream); }
@ -135,6 +137,7 @@ private:
nsRefPtr<MediaEngineSource> mAudioSource;
nsRefPtr<MediaEngineSource> mVideoSource;
nsRefPtr<nsDOMMediaStream> mStream;
nsRefPtr<MediaInputPort> mPort;
SourceMediaStream *mSourceStream; // mStream controls ownership
TrackTicks mLastEndTimeAudio;
TrackTicks mLastEndTimeVideo;
@ -161,6 +164,7 @@ public:
, mStream(aStream)
{}
// so we can send Stop without AddRef()ing from the MSG thread
MediaOperationRunnable(MediaOperation aType,
GetUserMediaCallbackMediaStreamListener* aListener,
MediaEngineSource* aAudioSource,
@ -242,6 +246,7 @@ public:
}
// Do this after stopping all tracks with EndTrack()
source->Finish();
// the TrackUnion destination of the port will autofinish
nsRefPtr<GetUserMediaNotificationEvent> event =
new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STOPPING);