Backed out changeset a8bae4554679 (bug 1259831)

--HG--
extra : rebase_source : 18ccc0c8c21d4d42afa5e8db22921b5468117b30
This commit is contained in:
Carsten "Tomcat" Book 2016-04-29 14:21:12 +02:00
Родитель 998c45f522
Коммит 2dc450ceba
3 изменённых файлов: 99 добавлений и 1 удалений

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

@ -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;
@ -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
@ -988,6 +993,13 @@ 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
@ -995,6 +1007,10 @@ 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*

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

@ -332,6 +332,8 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
, mAudioChannel(AudioChannel::Normal)
, mIsOffline(aIsOffline)
, mAudioChannelAgentPlaying(false)
, mExtraCurrentTimeSinceLastStartedBlocking(0)
, mExtraCurrentTimeUpdatedSinceLastStableState(false)
, mCaptured(false)
{
MediaStreamGraph* graph = aIsOffline ?
@ -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)
{

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

@ -65,6 +65,13 @@ public:
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();
@ -94,6 +101,9 @@ private:
void SetCanPlay(float aVolume, bool aMuted);
void NotifyStableState();
void ScheduleStableStateNotification();
SelfReference<AudioDestinationNode> mOfflineRenderingRef;
uint32_t mFramesToProduce;
@ -107,6 +117,9 @@ private:
bool mIsOffline;
bool mAudioChannelAgentPlaying;
TimeStamp mStartedBlockingDueToBeingOnlyNode;
StreamTime mExtraCurrentTimeSinceLastStartedBlocking;
bool mExtraCurrentTimeUpdatedSinceLastStableState;
bool mCaptured;
};