void
AudioNodeStream::DecrementActiveInputCount()
{
  MOZ_ASSERT(mActiveInputCount > 0);
  --mActiveInputCount;
  CheckForInactive();
}
 virtual void Run() override
 {
   auto ns = static_cast<AudioNodeStream*>(mStream);
   ns->CheckForInactive();
 }
// The MediaStreamGraph guarantees that this is actually one block, for
// AudioNodeStreams.
void
AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
{
    uint16_t outputCount = mLastChunks.Length();
    MOZ_ASSERT(outputCount == std::max(uint16_t(1), mEngine->OutputCount()));

    if (!mIsActive) {
        // mLastChunks are already null.
#ifdef DEBUG
        for (const auto& chunk : mLastChunks) {
            MOZ_ASSERT(chunk.IsNull());
        }
#endif
    } else if (InMutedCycle()) {
        mInputChunks.Clear();
        for (uint16_t i = 0; i < outputCount; ++i) {
            mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE);
        }
    } else {
        // We need to generate at least one input
        uint16_t maxInputs = std::max(uint16_t(1), mEngine->InputCount());
        mInputChunks.SetLength(maxInputs);
        for (uint16_t i = 0; i < maxInputs; ++i) {
            ObtainInputBlock(mInputChunks[i], i);
        }
        bool finished = false;
        if (mPassThrough) {
            MOZ_ASSERT(outputCount == 1, "For now, we only support nodes that have one output port");
            mLastChunks[0] = mInputChunks[0];
        } else {
            if (maxInputs <= 1 && outputCount <= 1) {
                mEngine->ProcessBlock(this, aFrom,
                                      mInputChunks[0], &mLastChunks[0], &finished);
            } else {
                mEngine->ProcessBlocksOnPorts(this, mInputChunks, mLastChunks, &finished);
            }
        }
        for (uint16_t i = 0; i < outputCount; ++i) {
            NS_ASSERTION(mLastChunks[i].GetDuration() == WEBAUDIO_BLOCK_SIZE,
                         "Invalid WebAudio chunk size");
        }
        if (finished) {
            mMarkAsFinishedAfterThisBlock = true;
            CheckForInactive();
        }

        if (mDisabledTrackIDs.Contains(static_cast<TrackID>(AUDIO_TRACK))) {
            for (uint32_t i = 0; i < outputCount; ++i) {
                mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE);
            }
        }
    }

    if (!mFinished) {
        // Don't output anything while finished
        if (mFlags & EXTERNAL_OUTPUT) {
            AdvanceOutputSegment();
        }
        if (mMarkAsFinishedAfterThisBlock && (aFlags & ALLOW_FINISH)) {
            // This stream was finished the last time that we looked at it, and all
            // of the depending streams have finished their output as well, so now
            // it's time to mark this stream as finished.
            if (mFlags & EXTERNAL_OUTPUT) {
                FinishOutput();
            }
            FinishOnGraphThread();
        }
    }
}