Bug 1156472 - Part 6 - Connect HTMLMediaElement and AudioContext to the capture stream when capturing is needed. r=roc

This commit is contained in:
Paul Adenot 2015-07-24 14:28:17 +02:00
parent f692e0d9ce
commit b195db60a7
4 changed files with 64 additions and 18 deletions

View File

@ -2030,6 +2030,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mAllowCasting(false), mAllowCasting(false),
mIsCasting(false), mIsCasting(false),
mAudioCaptured(false), mAudioCaptured(false),
mAudioCapturedByWindow(false),
mPlayingBeforeSeek(false), mPlayingBeforeSeek(false),
mPlayingThroughTheAudioChannelBeforeSeek(false), mPlayingThroughTheAudioChannelBeforeSeek(false),
mPausedForInactiveDocumentOrChannel(false), mPausedForInactiveDocumentOrChannel(false),
@ -2097,6 +2098,11 @@ HTMLMediaElement::~HTMLMediaElement()
EndSrcMediaStreamPlayback(); EndSrcMediaStreamPlayback();
} }
if (mCaptureStreamPort) {
mCaptureStreamPort->Destroy();
mCaptureStreamPort = nullptr;
}
NS_ASSERTION(MediaElementTableCount(this, mLoadingSrc) == 0, NS_ASSERTION(MediaElementTableCount(this, mLoadingSrc) == 0,
"Destroyed media element should no longer be in element table"); "Destroyed media element should no longer be in element table");
@ -4475,8 +4481,7 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
(!mPaused && (!mPaused &&
(HasAttr(kNameSpaceID_None, nsGkAtoms::loop) || (HasAttr(kNameSpaceID_None, nsGkAtoms::loop) ||
(mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA && (mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
!IsPlaybackEnded() && !IsPlaybackEnded()) ||
(!mSrcStream || HasAudio())) ||
mPlayingThroughTheAudioChannelBeforeSeek)); mPlayingThroughTheAudioChannelBeforeSeek));
if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) { if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) {
mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel; mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;
@ -4681,9 +4686,31 @@ HTMLMediaElement::GetTopLevelPrincipal()
NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged() NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
{ {
MOZ_ASSERT(mAudioChannelAgent); MOZ_ASSERT(mAudioChannelAgent);
DebugOnly<bool> captured = OwnerDoc()->GetInnerWindow()->GetAudioCaptured();
// Something is going to happen here!! if (!OwnerDoc()->GetInnerWindow()) {
return NS_OK;
}
bool captured = OwnerDoc()->GetInnerWindow()->GetAudioCaptured();
if (captured != mAudioCapturedByWindow) {
if (captured) {
mAudioCapturedByWindow = true;
nsCOMPtr<nsPIDOMWindow> window =
do_QueryInterface(OwnerDoc()->GetParentObject());
uint64_t id = window->WindowID();
MediaStreamGraph* msg = MediaStreamGraph::GetInstance();
if (!mPlaybackStream) {
nsRefPtr<DOMMediaStream> stream = CaptureStreamInternal(false, msg);
mCaptureStreamPort = msg->ConnectToCaptureStream(id, stream->GetStream());
} else {
mCaptureStreamPort = msg->ConnectToCaptureStream(id, mPlaybackStream->GetStream());
}
} else {
// TODO: uncapture
}
}
return NS_OK; return NS_OK;
} }

View File

@ -1074,6 +1074,9 @@ protected:
// Holds a reference to a MediaInputPort connecting mSrcStream to mPlaybackStream. // Holds a reference to a MediaInputPort connecting mSrcStream to mPlaybackStream.
nsRefPtr<MediaInputPort> mPlaybackStreamInputPort; nsRefPtr<MediaInputPort> mPlaybackStreamInputPort;
// Holds a reference to the stream connecting this stream to the capture sink.
nsRefPtr<MediaInputPort> mCaptureStreamPort;
// Holds a reference to a stream with mSrcStream as input but intended for // Holds a reference to a stream with mSrcStream as input but intended for
// playback. Used so we don't block playback of other video elements // playback. Used so we don't block playback of other video elements
// playing the same mSrcStream. // playing the same mSrcStream.
@ -1283,6 +1286,9 @@ protected:
// True if the sound is being captured. // True if the sound is being captured.
bool mAudioCaptured; bool mAudioCaptured;
// True if the sound is being captured by the window.
bool mAudioCapturedByWindow;
// If TRUE then the media element was actively playing before the currently // If TRUE then the media element was actively playing before the currently
// in progress seeking. If FALSE then the media element is either not seeking // in progress seeking. If FALSE then the media element is either not seeking
// or was not actively playing before the current seek. Used to decide whether // or was not actively playing before the current seek. Used to decide whether

View File

@ -313,12 +313,9 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
bool aIsOffline, bool aIsOffline,
AudioChannel aChannel, AudioChannel aChannel,
uint32_t aNumberOfChannels, uint32_t aNumberOfChannels,
uint32_t aLength, uint32_t aLength, float aSampleRate)
float aSampleRate) : AudioNode(aContext, aIsOffline ? aNumberOfChannels : 2,
: AudioNode(aContext, ChannelCountMode::Explicit, ChannelInterpretation::Speakers)
aIsOffline ? aNumberOfChannels : 2,
ChannelCountMode::Explicit,
ChannelInterpretation::Speakers)
, mFramesToProduce(aLength) , mFramesToProduce(aLength)
, mAudioChannel(AudioChannel::Normal) , mAudioChannel(AudioChannel::Normal)
, mIsOffline(aIsOffline) , mIsOffline(aIsOffline)
@ -326,6 +323,7 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
, mExtraCurrentTime(0) , mExtraCurrentTime(0)
, mExtraCurrentTimeSinceLastStartedBlocking(0) , mExtraCurrentTimeSinceLastStartedBlocking(0)
, mExtraCurrentTimeUpdatedSinceLastStableState(false) , mExtraCurrentTimeUpdatedSinceLastStableState(false)
, mCaptured(false)
{ {
bool startWithAudioDriver = true; bool startWithAudioDriver = true;
MediaStreamGraph* graph = aIsOffline ? MediaStreamGraph* graph = aIsOffline ?
@ -510,13 +508,25 @@ AudioDestinationNode::WindowAudioCaptureChanged()
{ {
MOZ_ASSERT(mAudioChannelAgent); MOZ_ASSERT(mAudioChannelAgent);
if (!mStream) { if (!mStream || Context()->IsOffline()) {
return NS_OK; return NS_OK;
} }
DebugOnly<bool> captured = GetOwner()->GetAudioCaptured(); bool captured = GetOwner()->GetAudioCaptured();
if (captured != mCaptured) {
if (captured) {
nsCOMPtr<nsPIDOMWindow> window = Context()->GetParentObject();
uint64_t id = window->WindowID();
mCaptureStreamPort =
mStream->Graph()->ConnectToCaptureStream(id, mStream);
} else {
mCaptureStreamPort->Disconnect();
mCaptureStreamPort->Destroy();
}
mCaptured = captured;
}
// XXXtodopadenot actually capture
return NS_OK; return NS_OK;
} }
@ -699,6 +709,7 @@ AudioDestinationNode::InputMuted(bool aMuted)
return; return;
} }
WindowAudioCaptureChanged();
WindowVolumeChanged(volume, muted); WindowVolumeChanged(volume, muted);
} }

View File

@ -99,6 +99,7 @@ private:
uint32_t mFramesToProduce; uint32_t mFramesToProduce;
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent; nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
nsRefPtr<MediaInputPort> mCaptureStreamPort;
nsRefPtr<Promise> mOfflineRenderingPromise; nsRefPtr<Promise> mOfflineRenderingPromise;
@ -111,6 +112,7 @@ private:
double mExtraCurrentTime; double mExtraCurrentTime;
double mExtraCurrentTimeSinceLastStartedBlocking; double mExtraCurrentTimeSinceLastStartedBlocking;
bool mExtraCurrentTimeUpdatedSinceLastStableState; bool mExtraCurrentTimeUpdatedSinceLastStableState;
bool mCaptured;
}; };
} // namespace dom } // namespace dom