зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1404977 - Part 9 - Propagate the changes to the GraphDrivers, simplifying them, and brokering all access through the MSG. r=pehrsons
For an AudioCallbackDriver, the number of input channels is immutable, and passed at construction, so that it's less necessary to rely on global state. MozReview-Commit-ID: F9TL1H92z3W --HG-- extra : rebase_source : 5193488592ca97273eb2b6f43d4c7a0e4beb0a33
This commit is contained in:
Родитель
064d4d9b47
Коммит
6622a3551d
|
@ -74,7 +74,14 @@ void GraphDriver::SwitchAtNextIteration(GraphDriver* aNextDriver)
|
|||
aNextDriver,
|
||||
aNextDriver->AsAudioCallbackDriver() ? "AudioCallbackDriver"
|
||||
: "SystemClockDriver"));
|
||||
|
||||
if (mNextDriver &&
|
||||
mNextDriver != GraphImpl()->CurrentDriver()) {
|
||||
LOG(LogLevel::Debug,
|
||||
("Discarding previous next driver: %p (%s)",
|
||||
mNextDriver.get(),
|
||||
mNextDriver->AsAudioCallbackDriver() ? "AudioCallbackDriver"
|
||||
: "SystemClockDriver"));
|
||||
}
|
||||
SetNextDriver(aNextDriver);
|
||||
}
|
||||
|
||||
|
@ -538,19 +545,17 @@ StreamAndPromiseForOperation::StreamAndPromiseForOperation(MediaStream* aStream,
|
|||
// MOZ_ASSERT(aPromise);
|
||||
}
|
||||
|
||||
AudioCallbackDriver::AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl)
|
||||
AudioCallbackDriver::AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl, uint32_t aInputChannelCount)
|
||||
: GraphDriver(aGraphImpl)
|
||||
, mOutputChannels(0)
|
||||
, mSampleRate(0)
|
||||
, mInputChannels(1)
|
||||
, mInputChannelCount(aInputChannelCount)
|
||||
, mIterationDurationMS(MEDIA_GRAPH_TARGET_PERIOD_MS)
|
||||
, mStarted(false)
|
||||
, mAudioInput(nullptr)
|
||||
, mInitShutdownThread(SharedThreadPool::Get(NS_LITERAL_CSTRING("CubebOperation"), 1))
|
||||
, mAddedMixer(false)
|
||||
, mAudioThreadId(std::thread::id())
|
||||
, mAudioThreadRunning(false)
|
||||
, mMicrophoneActive(false)
|
||||
, mShouldFallbackIfError(false)
|
||||
, mFromFallback(false)
|
||||
{
|
||||
|
@ -637,7 +642,7 @@ AudioCallbackDriver::Init()
|
|||
}
|
||||
|
||||
// Query and set the number of channels this AudioCallbackDriver will use.
|
||||
mOutputChannels = mGraphImpl->AudioChannelCount();
|
||||
mOutputChannels = GraphImpl()->AudioOutputChannelCount();
|
||||
if (!mOutputChannels) {
|
||||
LOG(LogLevel::Warning, ("Output number of channels is 0."));
|
||||
MonitorAutoLock lock(GraphImpl()->GetMonitor());
|
||||
|
@ -661,81 +666,62 @@ AudioCallbackDriver::Init()
|
|||
}
|
||||
|
||||
input = output;
|
||||
input.channels = mInputChannels;
|
||||
input.channels = mInputChannelCount;
|
||||
input.layout = CUBEB_LAYOUT_UNDEFINED;
|
||||
|
||||
#ifdef MOZ_WEBRTC
|
||||
if (mGraphImpl->mInputWanted) {
|
||||
StaticMutexAutoLock lock(AudioInputCubeb::Mutex());
|
||||
uint32_t userChannels = 0;
|
||||
AudioInputCubeb::GetUserChannelCount(mGraphImpl->mInputDeviceID, userChannels);
|
||||
input.channels = mInputChannels = std::min<uint32_t>(8, userChannels);
|
||||
}
|
||||
#endif
|
||||
|
||||
cubeb_stream* stream = nullptr;
|
||||
CubebUtils::AudioDeviceID input_id = nullptr, output_id = nullptr;
|
||||
// We have to translate the deviceID values to cubeb devid's since those can be
|
||||
// freed whenever enumerate is called.
|
||||
{
|
||||
#ifdef MOZ_WEBRTC
|
||||
StaticMutexAutoLock lock(AudioInputCubeb::Mutex());
|
||||
#endif
|
||||
if ((!mGraphImpl->mInputWanted
|
||||
#ifdef MOZ_WEBRTC
|
||||
|| AudioInputCubeb::GetDeviceID(mGraphImpl->mInputDeviceID, input_id)
|
||||
#endif
|
||||
) &&
|
||||
(mGraphImpl->mOutputDeviceID == -1 // pass nullptr for ID for default output
|
||||
#ifdef MOZ_WEBRTC
|
||||
// XXX we should figure out how we would use a deviceID for output without webrtc.
|
||||
// Currently we don't set this though, so it's ok
|
||||
|| AudioInputCubeb::GetDeviceID(mGraphImpl->mOutputDeviceID, output_id)
|
||||
#endif
|
||||
) &&
|
||||
// XXX Only pass input input if we have an input listener. Always
|
||||
// set up output because it's easier, and it will just get silence.
|
||||
// XXX Add support for adding/removing an input listener later.
|
||||
cubeb_stream_init(cubebContext, &stream,
|
||||
"AudioCallbackDriver",
|
||||
input_id,
|
||||
mGraphImpl->mInputWanted ? &input : nullptr,
|
||||
output_id,
|
||||
mGraphImpl->mOutputWanted ? &output : nullptr, latency_frames,
|
||||
DataCallback_s, StateCallback_s, this) == CUBEB_OK) {
|
||||
mAudioStream.own(stream);
|
||||
DebugOnly<int> rv = cubeb_stream_set_volume(mAudioStream, CubebUtils::GetVolumeScale());
|
||||
NS_WARNING_ASSERTION(
|
||||
rv == CUBEB_OK,
|
||||
"Could not set the audio stream volume in GraphDriver.cpp");
|
||||
CubebUtils::ReportCubebBackendUsed();
|
||||
} else {
|
||||
#ifdef MOZ_WEBRTC
|
||||
StaticMutexAutoUnlock unlock(AudioInputCubeb::Mutex());
|
||||
#endif
|
||||
NS_WARNING("Could not create a cubeb stream for MediaStreamGraph, falling back to a SystemClockDriver");
|
||||
// Only report failures when we're not coming from a driver that was
|
||||
// created itself as a fallback driver because of a previous audio driver
|
||||
// failure.
|
||||
if (!mFromFallback) {
|
||||
CubebUtils::ReportCubebStreamInitFailure(firstStream);
|
||||
}
|
||||
MonitorAutoLock lock(GraphImpl()->GetMonitor());
|
||||
FallbackToSystemClockDriver();
|
||||
return true;
|
||||
bool inputWanted = mInputChannelCount > 0;
|
||||
CubebUtils::AudioDeviceID output_id = GraphImpl()->mOutputDeviceID;
|
||||
CubebUtils::AudioDeviceID input_id = GraphImpl()->mInputDeviceID;
|
||||
|
||||
// XXX Only pass input input if we have an input listener. Always
|
||||
// set up output because it's easier, and it will just get silence.
|
||||
if (cubeb_stream_init(cubebContext,
|
||||
&stream,
|
||||
"AudioCallbackDriver",
|
||||
input_id,
|
||||
inputWanted ? &input : nullptr,
|
||||
output_id,
|
||||
&output,
|
||||
latency_frames,
|
||||
DataCallback_s,
|
||||
StateCallback_s,
|
||||
this) == CUBEB_OK) {
|
||||
mAudioStream.own(stream);
|
||||
DebugOnly<int> rv =
|
||||
cubeb_stream_set_volume(mAudioStream, CubebUtils::GetVolumeScale());
|
||||
NS_WARNING_ASSERTION(
|
||||
rv == CUBEB_OK,
|
||||
"Could not set the audio stream volume in GraphDriver.cpp");
|
||||
CubebUtils::ReportCubebBackendUsed();
|
||||
} else {
|
||||
NS_WARNING("Could not create a cubeb stream for MediaStreamGraph, falling "
|
||||
"back to a SystemClockDriver");
|
||||
// Only report failures when we're not coming from a driver that was
|
||||
// created itself as a fallback driver because of a previous audio driver
|
||||
// failure.
|
||||
if (!mFromFallback) {
|
||||
CubebUtils::ReportCubebStreamInitFailure(firstStream);
|
||||
}
|
||||
MonitorAutoLock lock(GraphImpl()->GetMonitor());
|
||||
FallbackToSystemClockDriver();
|
||||
return true;
|
||||
}
|
||||
SetMicrophoneActive(mGraphImpl->mInputWanted);
|
||||
|
||||
cubeb_stream_register_device_changed_callback(mAudioStream,
|
||||
AudioCallbackDriver::DeviceChangedCallback_s);
|
||||
#ifdef XP_MACOSX
|
||||
PanOutputIfNeeded(inputWanted);
|
||||
#endif
|
||||
|
||||
cubeb_stream_register_device_changed_callback(
|
||||
mAudioStream, AudioCallbackDriver::DeviceChangedCallback_s);
|
||||
|
||||
if (!StartStream()) {
|
||||
LOG(LogLevel::Warning, ("AudioCallbackDriver couldn't start stream."));
|
||||
LOG(LogLevel::Warning, ("%p: AudioCallbackDriver couldn't start a cubeb stream.", GraphImpl()));
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(LogLevel::Debug, ("AudioCallbackDriver started."));
|
||||
LOG(LogLevel::Debug, ("%p: AudioCallbackDriver started.", GraphImpl()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1150,21 +1136,9 @@ AudioCallbackDriver::DeviceChangedCallback()
|
|||
// Tell the audio engine the device has changed, it might want to reset some
|
||||
// state.
|
||||
MonitorAutoLock mon(mGraphImpl->GetMonitor());
|
||||
if (mAudioInput) {
|
||||
mAudioInput->DeviceChanged();
|
||||
}
|
||||
GraphImpl()->DeviceChanged();
|
||||
#ifdef XP_MACOSX
|
||||
PanOutputIfNeeded(mMicrophoneActive);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
AudioCallbackDriver::SetMicrophoneActive(bool aActive)
|
||||
{
|
||||
mMicrophoneActive = aActive;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
PanOutputIfNeeded(mMicrophoneActive);
|
||||
PanOutputIfNeeded(mInputChannelCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -263,8 +263,7 @@ public:
|
|||
*/
|
||||
void RunThread();
|
||||
friend class MediaStreamGraphInitThreadRunnable;
|
||||
uint32_t IterationDuration() override
|
||||
{
|
||||
uint32_t IterationDuration() override {
|
||||
return MEDIA_GRAPH_TARGET_PERIOD_MS;
|
||||
}
|
||||
|
||||
|
@ -400,7 +399,8 @@ class AudioCallbackDriver : public GraphDriver,
|
|||
#endif
|
||||
{
|
||||
public:
|
||||
explicit AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl);
|
||||
/** If aInputChannelCount is zero, then this driver is output-only. */
|
||||
AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl, uint32_t aInputChannelCount);
|
||||
virtual ~AudioCallbackDriver();
|
||||
|
||||
void Start() override;
|
||||
|
@ -418,15 +418,16 @@ public:
|
|||
const void * aInputBuffer,
|
||||
void * aOutputBuffer,
|
||||
long aFrames);
|
||||
static void StateCallback_s(cubeb_stream* aStream, void * aUser,
|
||||
cubeb_state aState);
|
||||
static void StateCallback_s(cubeb_stream* aStream, void * aUser, cubeb_state aState);
|
||||
static void DeviceChangedCallback_s(void * aUser);
|
||||
/* This function is called by the underlying audio backend when a refill is
|
||||
* needed. This is what drives the whole graph when it is used to output
|
||||
* audio. If the return value is exactly aFrames, this function will get
|
||||
* called again. If it is less than aFrames, the stream will go in draining
|
||||
* mode, and this function will not be called again. */
|
||||
long DataCallback(const AudioDataValue* aInputBuffer, AudioDataValue* aOutputBuffer, long aFrames);
|
||||
long DataCallback(const AudioDataValue* aInputBuffer,
|
||||
AudioDataValue* aOutputBuffer,
|
||||
long aFrames);
|
||||
/* This function is called by the underlying audio backend, but is only used
|
||||
* for informational purposes at the moment. */
|
||||
void StateCallback(cubeb_state aState);
|
||||
|
@ -463,6 +464,11 @@ public:
|
|||
return mOutputChannels;
|
||||
}
|
||||
|
||||
uint32_t InputChannelCount()
|
||||
{
|
||||
return mInputChannelCount;
|
||||
}
|
||||
|
||||
/* Enqueue a promise that is going to be resolved when a specific operation
|
||||
* occurs on the cubeb stream. */
|
||||
void EnqueueStreamAndPromiseForOperation(MediaStream* aStream,
|
||||
|
@ -483,10 +489,6 @@ public:
|
|||
* mStarted for details. */
|
||||
bool IsStarted();
|
||||
|
||||
/* Tell the driver whether this process is using a microphone or not. This is
|
||||
* thread safe. */
|
||||
void SetMicrophoneActive(bool aActive);
|
||||
|
||||
void CompleteAudioContextOperations(AsyncCubebOperation aOperation);
|
||||
|
||||
private:
|
||||
|
@ -536,9 +538,9 @@ private:
|
|||
/* The sample rate for the aforementionned cubeb stream. This is set on
|
||||
* initialization and can be read safely afterwards. */
|
||||
uint32_t mSampleRate;
|
||||
/* The number of input channels from cubeb. Should be set before opening cubeb
|
||||
* and then be static. */
|
||||
uint32_t mInputChannels;
|
||||
/* The number of input channels from cubeb. Set before opening cubeb. If it is
|
||||
* zero then the driver is output-only. */
|
||||
const uint32_t mInputChannelCount;
|
||||
/* Approximation of the time between two callbacks. This is used to schedule
|
||||
* video frames. This is in milliseconds. Only even used (after
|
||||
* inizatialization) on the audio callback thread. */
|
||||
|
@ -558,8 +560,6 @@ private:
|
|||
* This is synchronized by the Graph's monitor.
|
||||
* */
|
||||
Atomic<bool> mStarted;
|
||||
/* Listener for mic input, if any. */
|
||||
RefPtr<AudioDataListener> mAudioInput;
|
||||
|
||||
struct AutoInCallback
|
||||
{
|
||||
|
@ -585,10 +585,6 @@ private:
|
|||
/* True when audio thread is running. False before
|
||||
* starting and after stopping it the audio thread. */
|
||||
Atomic<bool> mAudioThreadRunning;
|
||||
/**
|
||||
* True if microphone is being used by this process. This is synchronized by
|
||||
* the graph's monitor. */
|
||||
Atomic<bool> mMicrophoneActive;
|
||||
/* Indication of whether a fallback SystemClockDriver should be started if
|
||||
* StateCallback() receives an error. No mutex need be held during access.
|
||||
* The transition to true happens before cubeb_stream_start() is called.
|
||||
|
|
|
@ -411,7 +411,7 @@ MediaStreamGraphImpl::UpdateStreamOrder()
|
|||
!switching) {
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
if (LifecycleStateRef() == LIFECYCLE_RUNNING) {
|
||||
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
|
||||
AudioCallbackDriver* driver = new AudioCallbackDriver(this, AudioInputChannelCount());
|
||||
CurrentDriver()->SwitchAtNextIteration(driver);
|
||||
}
|
||||
}
|
||||
|
@ -666,7 +666,7 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(MediaStream* aStream)
|
|||
!switching) {
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
if (LifecycleStateRef() == LIFECYCLE_RUNNING) {
|
||||
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
|
||||
AudioCallbackDriver* driver = new AudioCallbackDriver(this, AudioInputChannelCount());
|
||||
CurrentDriver()->SwitchAtNextIteration(driver);
|
||||
}
|
||||
}
|
||||
|
@ -822,8 +822,7 @@ MediaStreamGraphImpl::OpenAudioInputImpl(CubebUtils::AudioDeviceID aID,
|
|||
AudioCallbackDriver* driver = new AudioCallbackDriver(this, AudioInputChannelCount());
|
||||
LOG(
|
||||
LogLevel::Debug,
|
||||
("OpenAudioInput: starting new AudioCallbackDriver(input) %p", driver));
|
||||
driver->SetInputListener(aListener);
|
||||
("%p OpenAudioInput: starting new AudioCallbackDriver(input) %p", this, driver));
|
||||
CurrentDriver()->SwitchAtNextIteration(driver);
|
||||
} else {
|
||||
LOG(LogLevel::Error, ("OpenAudioInput in shutdown!"));
|
||||
|
@ -3668,8 +3667,8 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
|
|||
{
|
||||
if (mRealtime) {
|
||||
if (aDriverRequested == AUDIO_THREAD_DRIVER) {
|
||||
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
|
||||
mDriver = driver;
|
||||
// Always start with zero input channels.
|
||||
mDriver = new AudioCallbackDriver(this, 0);
|
||||
} else {
|
||||
mDriver = new SystemClockDriver(this);
|
||||
}
|
||||
|
@ -4198,7 +4197,7 @@ MediaStreamGraphImpl::ApplyAudioContextOperationImpl(
|
|||
MOZ_ASSERT(nextDriver->AsAudioCallbackDriver());
|
||||
driver = nextDriver->AsAudioCallbackDriver();
|
||||
} else {
|
||||
driver = new AudioCallbackDriver(this);
|
||||
driver = new AudioCallbackDriver(this, AudioInputChannelCount());
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
CurrentDriver()->SwitchAtNextIteration(driver);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче