uint32_t BufferedAudioStream::Available() { MonitorAutoLock mon(mMonitor); NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Buffer invariant violated."); return BytesToFrames(mBuffer.Available()); }
void BufferedAudioStream::Drain() { MonitorAutoLock mon(mMonitor); if (mState != STARTED) { NS_ASSERTION(mBuffer.Available() == 0, "Draining with unplayed audio"); return; } mState = DRAINING; while (mState == DRAINING) { mon.Wait(); } }
nsresult nsBufferedAudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames) { MonitorAutoLock mon(mMonitor); if (!mCubebStream || mState == ERRORED) { return NS_ERROR_FAILURE; } NS_ASSERTION(mState == INITIALIZED || mState == STARTED, "Stream write in unexpected state."); const uint8_t* src = reinterpret_cast<const uint8_t*>(aBuf); uint32_t bytesToCopy = aFrames * mBytesPerFrame; while (bytesToCopy > 0) { uint32_t available = NS_MIN(bytesToCopy, mBuffer.Available()); NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0, "Must copy complete frames."); mBuffer.AppendElements(src, available); src += available; bytesToCopy -= available; if (mState != STARTED) { int r; { MonitorAutoUnlock mon(mMonitor); r = cubeb_stream_start(mCubebStream); } mState = r == CUBEB_OK ? STARTED : ERRORED; } if (mState != STARTED) { return NS_ERROR_FAILURE; } if (bytesToCopy > 0) { mon.Wait(); } } return NS_OK; }
nsresult BufferedAudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames) { MonitorAutoLock mon(mMonitor); if (!mCubebStream || mState == ERRORED) { return NS_ERROR_FAILURE; } NS_ASSERTION(mState == INITIALIZED || mState == STARTED, "Stream write in unexpected state."); const uint8_t* src = reinterpret_cast<const uint8_t*>(aBuf); uint32_t bytesToCopy = FramesToBytes(aFrames); while (bytesToCopy > 0) { uint32_t available = std::min(bytesToCopy, mBuffer.Available()); NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0, "Must copy complete frames."); mBuffer.AppendElements(src, available); src += available; bytesToCopy -= available; if (bytesToCopy > 0) { // If we are not playing, but our buffer is full, start playing to make // room for soon-to-be-decoded data. if (mState != STARTED) { StartUnlocked(); if (mState != STARTED) { return NS_ERROR_FAILURE; } } mon.Wait(); } } mWritten += aFrames; return NS_OK; }