mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 1922912
apply PlaybackParams at AudioSink::Start() r=padenot
for single thread access to AudioSinkWrapper::mParams. Differential Revision: https://phabricator.services.mozilla.com/D225020
This commit is contained in:
parent
5a7954ec49
commit
de8c8c0ed6
@ -98,7 +98,7 @@ AudioSink::~AudioSink() {
|
||||
}
|
||||
|
||||
nsresult AudioSink::InitializeAudioStream(
|
||||
const PlaybackParams& aParams, const RefPtr<AudioDeviceInfo>& aAudioDevice,
|
||||
const RefPtr<AudioDeviceInfo>& aAudioDevice,
|
||||
AudioSink::InitializationType aInitializationType) {
|
||||
if (aInitializationType == AudioSink::InitializationType::UNMUTING) {
|
||||
// Consider the stream to be audible immediately, before initialization
|
||||
@ -133,19 +133,19 @@ nsresult AudioSink::InitializeAudioStream(
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<MediaSink::EndedPromise> AudioSink::Start(
|
||||
const PlaybackParams& aParams, const media::TimeUnit& aStartTime) {
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
|
||||
// Set playback params before calling Start() so they can take effect
|
||||
// as soon as the 1st DataCallback of the AudioStream fires.
|
||||
mAudioStream->SetVolume(aParams.mVolume);
|
||||
mAudioStream->SetPlaybackRate(aParams.mPlaybackRate);
|
||||
mAudioStream->SetPreservesPitch(aParams.mPreservesPitch);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<MediaSink::EndedPromise> AudioSink::Start(
|
||||
const media::TimeUnit& aStartTime) {
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
|
||||
mAudioQueueListener = mAudioQueue.PushEvent().Connect(
|
||||
mOwnerThread, this, &AudioSink::OnAudioPushed);
|
||||
mAudioQueueFinishListener = mAudioQueue.FinishEvent().Connect(
|
||||
|
@ -47,13 +47,13 @@ class AudioSink : private AudioStream::DataSource {
|
||||
~AudioSink();
|
||||
|
||||
// Allocate and initialize mAudioStream. Returns NS_OK on success.
|
||||
nsresult InitializeAudioStream(const PlaybackParams& aParams,
|
||||
const RefPtr<AudioDeviceInfo>& aAudioDevice,
|
||||
nsresult InitializeAudioStream(const RefPtr<AudioDeviceInfo>& aAudioDevice,
|
||||
InitializationType aInitializationType);
|
||||
|
||||
// Start audio playback. aStartTime is compared with MediaData::mTime to
|
||||
// identify the first audio frame to be played.
|
||||
RefPtr<MediaSink::EndedPromise> Start(const media::TimeUnit& aStartTime);
|
||||
RefPtr<MediaSink::EndedPromise> Start(const PlaybackParams& aParams,
|
||||
const media::TimeUnit& aStartTime);
|
||||
|
||||
/*
|
||||
* All public functions are not thread-safe.
|
||||
|
@ -332,8 +332,8 @@ void AudioSinkWrapper::StartAudioSink(UniquePtr<AudioSink> aAudioSink,
|
||||
AssertOwnerThread();
|
||||
MOZ_ASSERT(!mAudioSink);
|
||||
mAudioSink = std::move(aAudioSink);
|
||||
mAudioSink->Start(aStartTime)
|
||||
->Then(mOwnerThread.get(), __func__, this,
|
||||
mAudioSink->Start(mParams, aStartTime)
|
||||
->Then(mOwnerThread.GetEventTarget(), __func__, this,
|
||||
&AudioSinkWrapper::OnAudioEnded)
|
||||
->Track(mAudioSinkEndedRequest);
|
||||
}
|
||||
@ -370,37 +370,36 @@ RefPtr<GenericPromise> AudioSinkWrapper::MaybeAsyncCreateAudioSink(
|
||||
++mAsyncCreateCount;
|
||||
using Promise =
|
||||
MozPromise<UniquePtr<AudioSink>, nsresult, /* IsExclusive = */ true>;
|
||||
return InvokeAsync(mAsyncInitTaskQueue,
|
||||
"MaybeAsyncCreateAudioSink (Async part: initialization)",
|
||||
[self = RefPtr<AudioSinkWrapper>(this),
|
||||
audioSink{std::move(audioSink)},
|
||||
audioDevice = mAudioDevice, this]() mutable {
|
||||
if (!audioSink || !mAsyncInitTaskQueue->IsEmpty()) {
|
||||
// Either an AudioSink is not required or there's a
|
||||
// pending task to init an AudioSink with a possibly
|
||||
// different device.
|
||||
return Promise::CreateAndResolve(nullptr, __func__);
|
||||
}
|
||||
return InvokeAsync(
|
||||
mAsyncInitTaskQueue,
|
||||
"MaybeAsyncCreateAudioSink (Async part: initialization)",
|
||||
[self = RefPtr<AudioSinkWrapper>(this),
|
||||
audioSink{std::move(audioSink)}, audioDevice = mAudioDevice,
|
||||
this]() mutable {
|
||||
if (!audioSink || !mAsyncInitTaskQueue->IsEmpty()) {
|
||||
// Either an AudioSink is not required or there's a
|
||||
// pending task to init an AudioSink with a possibly
|
||||
// different device.
|
||||
return Promise::CreateAndResolve(nullptr, __func__);
|
||||
}
|
||||
|
||||
LOG("AudioSink initialization on background thread");
|
||||
// This can take about 200ms, e.g. on Windows, we don't
|
||||
// want to do it on the MDSM thread, because it would
|
||||
// make the clock not update for that amount of time, and
|
||||
// the video would therefore not update. The Start() call
|
||||
// is very cheap on the other hand, we can do it from the
|
||||
// MDSM thread.
|
||||
nsresult rv = audioSink->InitializeAudioStream(
|
||||
mParams, audioDevice,
|
||||
AudioSink::InitializationType::UNMUTING);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG("Async AudioSink initialization failed");
|
||||
return Promise::CreateAndReject(rv, __func__);
|
||||
}
|
||||
return Promise::CreateAndResolve(std::move(audioSink),
|
||||
__func__);
|
||||
})
|
||||
LOG("AudioSink initialization on background thread");
|
||||
// This can take about 200ms, e.g. on Windows, we don't
|
||||
// want to do it on the MDSM thread, because it would
|
||||
// make the clock not update for that amount of time, and
|
||||
// the video would therefore not update. The Start() call
|
||||
// is very cheap on the other hand, we can do it from the
|
||||
// MDSM thread.
|
||||
nsresult rv = audioSink->InitializeAudioStream(
|
||||
audioDevice, AudioSink::InitializationType::UNMUTING);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG("Async AudioSink initialization failed");
|
||||
return Promise::CreateAndReject(rv, __func__);
|
||||
}
|
||||
return Promise::CreateAndResolve(std::move(audioSink), __func__);
|
||||
})
|
||||
->Then(
|
||||
mOwnerThread,
|
||||
mOwnerThread.GetEventTarget(),
|
||||
"MaybeAsyncCreateAudioSink (Async part: start from MDSM thread)",
|
||||
[self = RefPtr<AudioSinkWrapper>(this), audioDevice = mAudioDevice,
|
||||
this](Promise::ResolveOrRejectValue&& aValue) mutable {
|
||||
@ -478,7 +477,7 @@ nsresult AudioSinkWrapper::SyncCreateAudioSink(const TimeUnit& aStartTime) {
|
||||
|
||||
UniquePtr<AudioSink> audioSink = mSinkCreator();
|
||||
nsresult rv = audioSink->InitializeAudioStream(
|
||||
mParams, mAudioDevice, AudioSink::InitializationType::INITIAL);
|
||||
mAudioDevice, AudioSink::InitializationType::INITIAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG("Sync AudioSinkWrapper initialization failed");
|
||||
// If a specific device has been specified through setSinkId()
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define AudioSinkWrapper_h_
|
||||
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/EventTargetCapability.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
@ -85,8 +86,8 @@ class AudioSinkWrapper : public MediaSink {
|
||||
void OnMuted(bool aMuted);
|
||||
virtual ~AudioSinkWrapper();
|
||||
|
||||
void AssertOwnerThread() const {
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
void AssertOwnerThread() const MOZ_ASSERT_CAPABILITY(mOwnerThread) {
|
||||
mOwnerThread.AssertOnCurrentThread();
|
||||
}
|
||||
|
||||
bool NeedAudioSink();
|
||||
@ -121,7 +122,7 @@ class AudioSinkWrapper : public MediaSink {
|
||||
|
||||
bool IsAudioSourceEnded(const MediaInfo& aInfo) const;
|
||||
|
||||
const RefPtr<AbstractThread> mOwnerThread;
|
||||
const EventTargetCapability<AbstractThread> mOwnerThread;
|
||||
const RefPtr<TaskQueue> mAsyncInitTaskQueue;
|
||||
SinkCreator mSinkCreator;
|
||||
UniquePtr<AudioSink> mAudioSink;
|
||||
@ -133,7 +134,7 @@ class AudioSinkWrapper : public MediaSink {
|
||||
MozPromiseHolder<EndedPromise> mEndedPromiseHolder;
|
||||
// true between Start() and Stop()
|
||||
bool mIsStarted = false;
|
||||
PlaybackParams mParams;
|
||||
PlaybackParams MOZ_GUARDED_BY(mOwnerThread) mParams;
|
||||
// mClockStartTime is null before Start(), after Stop(), and between
|
||||
// SetPlaying(false) and SetPlaying(true). When the system time is used for
|
||||
// the clock, this is the time corresponding to mPositionAtClockStart. When
|
||||
|
Loading…
Reference in New Issue
Block a user