author | Paul Adenot <paul@paul.cx> |
Tue, 24 May 2022 13:09:06 +0000 | |
changeset 618728 | 30cd5bcfee929d4d1244c7135af0892614a553e4 |
parent 618727 | acb4ae1c1e57de7130cbfb499d6c30dcf134dfbb |
child 618729 | 37f01a81dac4f4767e2e05cd9e8dfcbac0ab7282 |
push id | 163385 |
push user | padenot@mozilla.com |
push date | Tue, 24 May 2022 13:12:53 +0000 |
treeherder | autoland@3774e6ab3869 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | alwu, media-playback-reviewers |
bugs | 1743834 |
milestone | 102.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/media/AudioStream.cpp +++ b/dom/media/AudioStream.cpp @@ -143,17 +143,19 @@ AudioStream::AudioStream(DataSource& aSo mMonitor("AudioStream"), mOutChannels(aOutputChannels), mState(INITIALIZED), mDataSource(aSource), mAudioThreadId(ProfilerThreadId{}), mSandboxed(CubebUtils::SandboxEnabled()), mPlaybackComplete(false), mPlaybackRate(1.0f), - mPreservesPitch(true) {} + mPreservesPitch(true), + mCallbacksStarted(false) + {} AudioStream::~AudioStream() { LOG("deleted, state %d", mState.load()); MOZ_ASSERT(mState == SHUTDOWN && !mCubebStream, "Should've called Shutdown() before deleting an AudioStream"); } size_t AudioStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { @@ -226,18 +228,18 @@ int AudioStream::InvokeCubeb(Function aF return aFunction(mCubebStream.get(), std::forward<Args>(aArgs)...); } nsresult AudioStream::Init(AudioDeviceInfo* aSinkInfo) NO_THREAD_SAFETY_ANALYSIS { auto startTime = TimeStamp::Now(); TRACE("AudioStream::Init"); - LOG("%s channels: %d, rate: %d", __FUNCTION__, mOutChannels, - mAudioClock.GetInputRate()); + LOG("%s channels: %d, rate: %d", __FUNCTION__, mOutChannels, mAudioClock.GetInputRate()); + mSinkInfo = aSinkInfo; cubeb_stream_params params; params.rate = mAudioClock.GetInputRate(); params.channels = mOutChannels; params.layout = static_cast<uint32_t>(mChannelMap); params.format = CubebUtils::ToCubebFormat<AUDIO_OUTPUT_FORMAT>::value; params.prefs = CubebUtils::GetDefaultStreamPrefs(CUBEB_DEVICE_TYPE_OUTPUT); @@ -590,16 +592,19 @@ void AudioStream::UpdatePlaybackRateIfNe } } long AudioStream::DataCallback(void* aBuffer, long aFrames) { if (CheckThreadIdChanged() && !mSandboxed) { CubebUtils::GetAudioThreadRegistry()->Register(mAudioThreadId); } WebCore::DenormalDisabler disabler; + if (!mCallbacksStarted) { + mCallbacksStarted = true; + } TRACE_AUDIO_CALLBACK_BUDGET(aFrames, mAudioClock.GetInputRate()); TRACE("AudioStream::DataCallback"); MOZ_ASSERT(mState != SHUTDOWN, "No data callback after shutdown"); if (SoftRealTimeLimitReached()) { DemoteThreadFromRealTime(); }
--- a/dom/media/AudioStream.h +++ b/dom/media/AudioStream.h @@ -292,16 +292,19 @@ class AudioStream final { // Switch between resampling (if false) and time stretching (if true, // default). nsresult SetPreservesPitch(bool aPreservesPitch); size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; bool IsPlaybackCompleted() const; + // Returns true if at least one DataCallback has been called. + bool CallbackStarted() const { return mCallbacksStarted; } + protected: friend class AudioClock; // Return the position, measured in audio frames played since the stream was // opened, of the audio hardware, not adjusted for the changes of playback // rate or underrun frames. // Caller must own the monitor. int64_t GetPositionInFramesUnlocked(); @@ -381,13 +384,14 @@ class AudioStream final { MozPromiseHolder<MediaSink::EndedPromise> mEndedPromise GUARDED_BY(mMonitor); std::atomic<bool> mPlaybackComplete; // Both written on the MDSM thread, read on the audio thread. std::atomic<float> mPlaybackRate; std::atomic<bool> mPreservesPitch; // Audio thread only bool mAudioThreadChanged = false; + Atomic<bool> mCallbacksStarted; }; } // namespace mozilla #endif
--- a/dom/media/mediasink/AudioSink.h +++ b/dom/media/mediasink/AudioSink.h @@ -72,16 +72,22 @@ class AudioSink : private AudioStream::D void SetPlaying(bool aPlaying); MediaEventSource<bool>& AudibleEvent() { return mAudibleEvent; } void GetDebugInfo(dom::MediaSinkDebugInfo& aInfo); const RefPtr<AudioDeviceInfo>& AudioDevice() { return mAudioDevice; } + // This returns true if the audio callbacks are being called, and so the + // audio stream-based clock is moving forward. + bool AudioStreamCallbackStarted() { + return mAudioStream && mAudioStream->CallbackStarted(); + } + private: // Allocate and initialize mAudioStream. Returns NS_OK on success. nsresult InitializeAudioStream(const PlaybackParams& aParams); // Interface of AudioStream::DataSource. // Called on the callback thread of cubeb. Returns the number of frames that // were available. uint32_t PopFrames(AudioDataValue* aBuffer, uint32_t aFrames,
--- a/dom/media/mediasink/AudioSinkWrapper.cpp +++ b/dom/media/mediasink/AudioSinkWrapper.cpp @@ -72,18 +72,17 @@ bool AudioSinkWrapper::IsMuted() const { TimeUnit AudioSinkWrapper::GetPosition(TimeStamp* aTimeStamp) { AssertOwnerThread(); MOZ_ASSERT(mIsStarted, "Must be called after playback starts."); TimeUnit pos; TimeStamp t = TimeStamp::Now(); - if (!mAudioEnded && !IsMuted()) { - MOZ_ASSERT(mAudioSink); + if (!mAudioEnded && !IsMuted() && mAudioSink && mAudioSink->AudioStreamCallbackStarted()) { // Rely on the audio sink to report playback position when it is not ended. pos = mAudioSink->GetPosition(); LOGV("%p: Getting position from the Audio Sink %lf", this, pos.ToSeconds()); } else if (!mPlayStartTime.IsNull()) { // Calculate playback position using system clock if we are still playing, // but not rendering the audio, because this audio sink is muted. pos = GetSystemClockPosition(t); LOGV("%p: Getting position from the system clock %lf", this,