Skip to content

Commit

Permalink
Backed out changeset a8bae4554679 (bug 1259831)
Browse files Browse the repository at this point in the history
  • Loading branch information
BavarianTomcat committed Apr 29, 2016
1 parent 0324fd4 commit b82e37d
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 1 deletion.
18 changes: 17 additions & 1 deletion dom/media/webaudio/AudioContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,15 @@ AudioContext::AudioContext(nsPIDOMWindowInner* aWindow,
nsresult
AudioContext::Init()
{
// We skip calling SetIsOnlyNodeForContext and the creation of the
// audioChannelAgent during mDestination's constructor, because we can only
// call them after mDestination has been set up.
if (!mIsOffline) {
nsresult rv = mDestination->CreateAudioChannelAgent();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mDestination->SetIsOnlyNodeForContext(true);
}

return NS_OK;
Expand Down Expand Up @@ -678,7 +682,8 @@ double
AudioContext::CurrentTime() const
{
MediaStream* stream = Destination()->Stream();
return stream->StreamTimeToSeconds(stream->GetCurrentTime());
return stream->StreamTimeToSeconds(stream->GetCurrentTime() +
Destination()->ExtraCurrentTime());
}

void
Expand Down Expand Up @@ -988,13 +993,24 @@ AudioContext::RegisterNode(AudioNode* aNode)
{
MOZ_ASSERT(!mAllNodes.Contains(aNode));
mAllNodes.PutEntry(aNode);
// mDestinationNode may be null when we're destroying nodes unlinked by CC.
// Skipping unnecessary calls after shutdown avoids RunInStableState events
// getting stuck in CycleCollectedJSRuntime during final cycle collection
// (bug 1200514).
if (mDestination && !mIsShutDown) {
mDestination->SetIsOnlyNodeForContext(mAllNodes.Count() == 1);
}
}

void
AudioContext::UnregisterNode(AudioNode* aNode)
{
MOZ_ASSERT(mAllNodes.Contains(aNode));
mAllNodes.RemoveEntry(aNode);
// mDestinationNode may be null when we're destroying nodes unlinked by CC
if (mDestination) {
mDestination->SetIsOnlyNodeForContext(mAllNodes.Count() == 1);
}
}

JSObject*
Expand Down
69 changes: 69 additions & 0 deletions dom/media/webaudio/AudioDestinationNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
, mAudioChannel(AudioChannel::Normal)
, mIsOffline(aIsOffline)
, mAudioChannelAgentPlaying(false)
, mExtraCurrentTimeSinceLastStartedBlocking(0)
, mExtraCurrentTimeUpdatedSinceLastStableState(false)
, mCaptured(false)
{
MediaStreamGraph* graph = aIsOffline ?
Expand Down Expand Up @@ -646,6 +648,73 @@ AudioDestinationNode::CreateAudioChannelAgent()
return NS_OK;
}

void
AudioDestinationNode::NotifyStableState()
{
mExtraCurrentTimeUpdatedSinceLastStableState = false;
}

void
AudioDestinationNode::ScheduleStableStateNotification()
{
// Dispatch will fail if this is called on AudioNode destruction during
// shutdown, in which case failure can be ignored.
nsContentUtils::RunInStableState(NewRunnableMethod(this,
&AudioDestinationNode::NotifyStableState));
}

StreamTime
AudioDestinationNode::ExtraCurrentTime()
{
if (!mStartedBlockingDueToBeingOnlyNode.IsNull() &&
!mExtraCurrentTimeUpdatedSinceLastStableState) {
mExtraCurrentTimeUpdatedSinceLastStableState = true;
// Round to nearest processing block.
double seconds =
(TimeStamp::Now() - mStartedBlockingDueToBeingOnlyNode).ToSeconds();
mExtraCurrentTimeSinceLastStartedBlocking = WEBAUDIO_BLOCK_SIZE *
StreamTime(seconds * Context()->SampleRate() / WEBAUDIO_BLOCK_SIZE + 0.5);
ScheduleStableStateNotification();
}
return mExtraCurrentTimeSinceLastStartedBlocking;
}

void
AudioDestinationNode::SetIsOnlyNodeForContext(bool aIsOnlyNode)
{
if (!mStartedBlockingDueToBeingOnlyNode.IsNull() == aIsOnlyNode) {
// Nothing changed.
return;
}

if (!mStream) {
// DestroyMediaStream has been called, presumably during CC Unlink().
return;
}

if (mIsOffline) {
// Don't block the destination stream for offline AudioContexts, since
// we expect the zero data produced when there are no other nodes to
// show up in its result buffer. Also, we would get confused by adding
// ExtraCurrentTime before StartRendering has even been called.
return;
}

if (aIsOnlyNode) {
mStream->Suspend();
mStartedBlockingDueToBeingOnlyNode = TimeStamp::Now();
// Don't do an update of mExtraCurrentTimeSinceLastStartedBlocking until the next stable state.
mExtraCurrentTimeUpdatedSinceLastStableState = true;
ScheduleStableStateNotification();
} else {
// Force update of mExtraCurrentTimeSinceLastStartedBlocking if necessary
ExtraCurrentTime();
mStream->AdvanceAndResume(mExtraCurrentTimeSinceLastStartedBlocking);
mExtraCurrentTimeSinceLastStartedBlocking = 0;
mStartedBlockingDueToBeingOnlyNode = TimeStamp();
}
}

void
AudioDestinationNode::InputMuted(bool aMuted)
{
Expand Down
13 changes: 13 additions & 0 deletions dom/media/webaudio/AudioDestinationNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ class AudioDestinationNode final : public AudioNode
void NotifyMainThreadStreamFinished() override;
void FireOfflineCompletionEvent();

// An amount that should be added to the MediaStream's current time to
// get the AudioContext.currentTime.
StreamTime ExtraCurrentTime();

// When aIsOnlyNode is true, this is the only node for the AudioContext.
void SetIsOnlyNodeForContext(bool aIsOnlyNode);

nsresult CreateAudioChannelAgent();
void DestroyAudioChannelAgent();

Expand Down Expand Up @@ -94,6 +101,9 @@ class AudioDestinationNode final : public AudioNode

void SetCanPlay(float aVolume, bool aMuted);

void NotifyStableState();
void ScheduleStableStateNotification();

SelfReference<AudioDestinationNode> mOfflineRenderingRef;
uint32_t mFramesToProduce;

Expand All @@ -107,6 +117,9 @@ class AudioDestinationNode final : public AudioNode
bool mIsOffline;
bool mAudioChannelAgentPlaying;

TimeStamp mStartedBlockingDueToBeingOnlyNode;
StreamTime mExtraCurrentTimeSinceLastStartedBlocking;
bool mExtraCurrentTimeUpdatedSinceLastStableState;
bool mCaptured;
};

Expand Down

0 comments on commit b82e37d

Please sign in to comment.