long AudioStream::DataCallback(void* aBuffer, long aFrames) { MonitorAutoLock mon(mMonitor); MOZ_ASSERT(mState != SHUTDOWN, "No data callback after shutdown"); auto writer = AudioBufferWriter( reinterpret_cast<AudioDataValue*>(aBuffer), mOutChannels, aFrames); // FIXME: cubeb_pulse sometimes calls us before cubeb_stream_start() is called. // We don't want to consume audio data until Start() is called by the client. if (mState == INITIALIZED) { NS_WARNING("data callback fires before cubeb_stream_start() is called"); mAudioClock.UpdateFrameHistory(0, aFrames); return writer.WriteZeros(aFrames); } // NOTE: wasapi (others?) can call us back *after* stop()/Shutdown() (mState == SHUTDOWN) // Bug 996162 // callback tells us cubeb succeeded initializing if (mState == STARTED) { mState = RUNNING; } if (mInRate == mOutRate) { GetUnprocessed(writer); } else { GetTimeStretched(writer); } // Always send audible frames first, and silent frames later. // Otherwise it will break the assumption of FrameHistory. if (!mDataSource.Ended()) { mAudioClock.UpdateFrameHistory(aFrames - writer.Available(), writer.Available()); if (writer.Available() > 0) { LOGW("lost %d frames", writer.Available()); writer.WriteZeros(writer.Available()); } } else { // No more new data in the data source. Don't send silent frames so the // cubeb stream can start draining. mAudioClock.UpdateFrameHistory(aFrames - writer.Available(), 0); } WriteDumpFile(mDumpFile, this, aFrames, aBuffer); return aFrames - writer.Available(); }
long AudioStream::DataCallback(void* aBuffer, long aFrames) { MonitorAutoLock mon(mMonitor); MOZ_ASSERT(mState != SHUTDOWN, "No data callback after shutdown"); auto writer = AudioBufferWriter( reinterpret_cast<AudioDataValue*>(aBuffer), mOutChannels, aFrames); if (mPrefillQuirk) { // Don't consume audio data until Start() is called. // Expected only with cubeb winmm backend. if (mState == INITIALIZED) { NS_WARNING("data callback fires before cubeb_stream_start() is called"); mAudioClock.UpdateFrameHistory(0, aFrames); return writer.WriteZeros(aFrames); } } else { MOZ_ASSERT(mState != INITIALIZED); } // NOTE: wasapi (others?) can call us back *after* stop()/Shutdown() (mState == SHUTDOWN) // Bug 996162 if (mAudioClock.GetInputRate() == mAudioClock.GetOutputRate()) { GetUnprocessed(writer); } else { GetTimeStretched(writer); } // Always send audible frames first, and silent frames later. // Otherwise it will break the assumption of FrameHistory. if (!mDataSource.Ended()) { mAudioClock.UpdateFrameHistory(aFrames - writer.Available(), writer.Available()); if (writer.Available() > 0) { LOGW("lost %d frames", writer.Available()); writer.WriteZeros(writer.Available()); } } else { // No more new data in the data source. Don't send silent frames so the // cubeb stream can start draining. mAudioClock.UpdateFrameHistory(aFrames - writer.Available(), 0); } WriteDumpFile(mDumpFile, this, aFrames, aBuffer); return aFrames - writer.Available(); }