mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 881959 - Mute WebAudio nodes that are part of a cycle that contains no DelayNode, and make cycles work. r=ehsan
--HG-- extra : rebase_source : d4bc378128cf15f8d8395b45b4443ca6b06c5bd2
This commit is contained in:
parent
bfa902f4ae
commit
7c95321d67
@ -15,6 +15,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
struct ThreeDPoint;
|
||||
class AudioParamTimeline;
|
||||
class DelayNodeEngine;
|
||||
}
|
||||
|
||||
class AudioNodeStream;
|
||||
@ -206,6 +207,8 @@ public:
|
||||
MOZ_COUNT_DTOR(AudioNodeEngine);
|
||||
}
|
||||
|
||||
virtual dom::DelayNodeEngine* AsDelayNodeEngine() { return nullptr; }
|
||||
|
||||
virtual void SetStreamTimeParameter(uint32_t aIndex, TrackTicks aParam)
|
||||
{
|
||||
NS_ERROR("Invalid SetStreamTimeParameter index");
|
||||
|
@ -286,6 +286,20 @@ AudioNodeStream::ObtainInputBlock(AudioChunk& aTmpChunk, uint32_t aPortIndex)
|
||||
a->IsAudioParamStream()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// It is possible for mLastChunks to be empty here, because `a` might be a
|
||||
// AudioNodeStream that has not been scheduled yet, because it is further
|
||||
// down the graph _but_ as a connection to this node. Because we enforce the
|
||||
// presence of at least one DelayNode, with at least one block of delay, and
|
||||
// because the output of a DelayNode when it has been fed less that
|
||||
// `delayTime` amount of audio is silence, we can simply continue here,
|
||||
// because this input would not influence the output of this node. Next
|
||||
// iteration, a->mLastChunks.IsEmpty() will be false, and everthing will
|
||||
// work as usual.
|
||||
if (a->mLastChunks.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AudioChunk* chunk = &a->mLastChunks[mInputs[i]->OutputNumber()];
|
||||
MOZ_ASSERT(chunk);
|
||||
if (chunk->IsNull() || chunk->mChannelData.IsEmpty()) {
|
||||
@ -412,8 +426,7 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo)
|
||||
uint16_t outputCount = std::max(uint16_t(1), mEngine->OutputCount());
|
||||
mLastChunks.SetLength(outputCount);
|
||||
|
||||
if (mInCycle) {
|
||||
// XXX DelayNode not supported yet so just produce silence
|
||||
if (mMuted) {
|
||||
for (uint16_t i = 0; i < outputCount; ++i) {
|
||||
mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
struct ThreeDPoint;
|
||||
class AudioParamTimeline;
|
||||
class DelayNodeEngine;
|
||||
}
|
||||
|
||||
class ThreadSharedFloatArrayBufferList;
|
||||
@ -54,7 +55,8 @@ public:
|
||||
mKind(aKind),
|
||||
mNumberOfInputChannels(2),
|
||||
mMarkAsFinishedAfterThisBlock(false),
|
||||
mAudioParamStream(false)
|
||||
mAudioParamStream(false),
|
||||
mMuted(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mChannelCountMode = dom::ChannelCountMode::Max;
|
||||
@ -103,6 +105,14 @@ public:
|
||||
{
|
||||
return mAudioParamStream;
|
||||
}
|
||||
void Mute() {
|
||||
mMuted = true;
|
||||
}
|
||||
|
||||
void Unmute() {
|
||||
mMuted = false;
|
||||
}
|
||||
|
||||
const OutputChunks& LastChunks() const
|
||||
{
|
||||
return mLastChunks;
|
||||
@ -153,6 +163,8 @@ protected:
|
||||
bool mMarkAsFinishedAfterThisBlock;
|
||||
// Whether the stream is an AudioParamHelper stream.
|
||||
bool mAudioParamStream;
|
||||
// Whether the stream is muted. Access only on the MediaStreamGraph thread.
|
||||
bool mMuted;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -472,12 +472,32 @@ MediaStreamGraphImpl::UpdateStreamOrderForStream(mozilla::LinkedList<MediaStream
|
||||
NS_ASSERTION(!stream->mHasBeenOrdered, "stream should not have already been ordered");
|
||||
if (stream->mIsOnOrderingStack) {
|
||||
MediaStream* iter = aStack->getLast();
|
||||
AudioNodeStream* ns = stream->AsAudioNodeStream();
|
||||
bool delayNodePresent = ns ? ns->Engine()->AsDelayNodeEngine() != nullptr : false;
|
||||
bool cycleFound = false;
|
||||
if (iter) {
|
||||
do {
|
||||
cycleFound = true;
|
||||
iter->AsProcessedStream()->mInCycle = true;
|
||||
AudioNodeStream* ns = iter->AsAudioNodeStream();
|
||||
if (ns && ns->Engine()->AsDelayNodeEngine()) {
|
||||
delayNodePresent = true;
|
||||
}
|
||||
iter = iter->getPrevious();
|
||||
} while (iter && iter != stream);
|
||||
}
|
||||
if (cycleFound && !delayNodePresent) {
|
||||
// If we have detected a cycle, the previous loop should exit with stream
|
||||
// == iter. Go back in the cycle and mute all nodes we find.
|
||||
MOZ_ASSERT(iter);
|
||||
do {
|
||||
// There can't be non-AudioNodeStream here, MediaStreamAudio{Source,
|
||||
// Destination}Node are connected to regular MediaStreams, but they can't be
|
||||
// in a cycle (there is no content API to do so).
|
||||
MOZ_ASSERT(iter->AsAudioNodeStream());
|
||||
iter->AsAudioNodeStream()->Mute();
|
||||
} while((iter = iter->getNext()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
ProcessedMediaStream* ps = stream->AsProcessedStream();
|
||||
@ -513,6 +533,10 @@ MediaStreamGraphImpl::UpdateStreamOrder()
|
||||
ProcessedMediaStream* ps = stream->AsProcessedStream();
|
||||
if (ps) {
|
||||
ps->mInCycle = false;
|
||||
AudioNodeStream* ns = ps->AsAudioNodeStream();
|
||||
if (ns) {
|
||||
ns->Unmute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,10 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual const DelayNode* AsDelayNode() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioContext* GetParentObject() const
|
||||
{
|
||||
return mContext;
|
||||
|
@ -44,6 +44,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual DelayNodeEngine* AsDelayNodeEngine()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
|
@ -32,6 +32,11 @@ public:
|
||||
return mDelay;
|
||||
}
|
||||
|
||||
virtual const DelayNode* AsDelayNode() const MOZ_OVERRIDE
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual void NotifyInputConnected() MOZ_OVERRIDE
|
||||
{
|
||||
mMediaStreamGraphUpdateIndexAtLastInputConnection =
|
||||
|
Loading…
Reference in New Issue
Block a user