From 5d07a5937b7e83a6c20a45a6fa66017c6f807d79 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Thu, 17 Oct 2013 15:44:52 +0200 Subject: [PATCH] Bug 907817 - Allow AudioStream users to pass-in latency requirements. r=kinetik --HG-- extra : rebase_source : 3cf1971913b3cfd8000c58614b0d0be8b7805af0 --- content/html/content/src/HTMLAudioElement.cpp | 2 +- content/media/AudioStream.cpp | 33 ++++++++++++++++--- content/media/AudioStream.h | 7 +++- content/media/MediaDecoderStateMachine.cpp | 2 +- content/media/MediaStreamGraph.cpp | 2 +- 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/content/html/content/src/HTMLAudioElement.cpp b/content/html/content/src/HTMLAudioElement.cpp index e0e077189fae..ad43500a8ce4 100644 --- a/content/html/content/src/HTMLAudioElement.cpp +++ b/content/html/content/src/HTMLAudioElement.cpp @@ -114,7 +114,7 @@ HTMLAudioElement::MozSetup(uint32_t aChannels, uint32_t aRate, ErrorResult& aRv) #endif mAudioStream = AudioStream::AllocateStream(); - aRv = mAudioStream->Init(aChannels, aRate, mAudioChannelType); + aRv = mAudioStream->Init(aChannels, aRate, mAudioChannelType, AudioStream::HighLatency); if (aRv.Failed()) { mAudioStream->Shutdown(); mAudioStream = nullptr; diff --git a/content/media/AudioStream.cpp b/content/media/AudioStream.cpp index cf1641f9f684..e255b23ae184 100644 --- a/content/media/AudioStream.cpp +++ b/content/media/AudioStream.cpp @@ -41,6 +41,8 @@ PRLogModuleInfo* gAudioStreamLog = nullptr; static Mutex* gAudioPrefsLock = nullptr; static double gVolumeScale; static uint32_t gCubebLatency; +static bool gCubebLatencyPrefSet; +static const uint32_t CUBEB_NORMAL_LATENCY_MS = 100; /** * When MOZ_DUMP_AUDIO is set in the environment (to anything), @@ -65,9 +67,10 @@ static int PrefChanged(const char* aPref, void* aClosure) // Arbitrary default stream latency of 100ms. The higher this // value, the longer stream volume changes will take to become // audible. - uint32_t value = Preferences::GetUint(aPref, 100); + gCubebLatencyPrefSet = Preferences::HasUserValue(aPref); + uint32_t value = Preferences::GetUint(aPref, CUBEB_NORMAL_LATENCY_MS); MutexAutoLock lock(*gAudioPrefsLock); - gCubebLatency = std::min(std::max(value, 20), 1000); + gCubebLatency = std::min(std::max(value, 1), 1000); } return 0; } @@ -97,6 +100,12 @@ static uint32_t GetCubebLatency() MutexAutoLock lock(*gAudioPrefsLock); return gCubebLatency; } + +static bool CubebLatencyPrefSet() +{ + MutexAutoLock lock(*gAudioPrefsLock); + return gCubebLatencyPrefSet; +} #endif #if defined(MOZ_CUBEB) && defined(__ANDROID__) && defined(MOZ_B2G) @@ -311,7 +320,8 @@ class BufferedAudioStream : public AudioStream ~BufferedAudioStream(); nsresult Init(int32_t aNumChannels, int32_t aRate, - const dom::AudioChannelType aAudioChannelType); + const dom::AudioChannelType aAudioChannelType, + AudioStream::LatencyRequest aLatencyRequest); void Shutdown(); nsresult Write(const AudioDataValue* aBuf, uint32_t aFrames); uint32_t Available(); @@ -526,7 +536,8 @@ BufferedAudioStream::EnsureTimeStretcherInitialized() nsresult BufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate, - const dom::AudioChannelType aAudioChannelType) + const dom::AudioChannelType aAudioChannelType, + AudioStream::LatencyRequest aLatencyRequest) { cubeb* cubebContext = GetCubebContext(); @@ -562,10 +573,22 @@ BufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate, mAudioClock.Init(); + // If the latency pref is set, use it. Otherwise, if this stream is intended + // for low latency playback, try to get the lowest latency possible. + // Otherwise, for normal streams, use 100ms. + uint32_t latency; + if (aLatencyRequest == AudioStream::LowLatency && !CubebLatencyPrefSet()) { + if (cubeb_get_min_latency(cubebContext, params, &latency) != CUBEB_OK) { + latency = GetCubebLatency(); + } + } else { + latency = GetCubebLatency(); + } + { cubeb_stream* stream; if (cubeb_stream_init(cubebContext, &stream, "BufferedAudioStream", params, - GetCubebLatency(), DataCallback_S, StateCallback_S, this) == CUBEB_OK) { + latency, DataCallback_S, StateCallback_S, this) == CUBEB_OK) { mCubebStream.own(stream); } } diff --git a/content/media/AudioStream.h b/content/media/AudioStream.h index a657a3abaa74..482a2f43019e 100644 --- a/content/media/AudioStream.h +++ b/content/media/AudioStream.h @@ -92,6 +92,10 @@ class AudioClock class AudioStream { public: + enum LatencyRequest { + HighLatency, + LowLatency + }; AudioStream(); virtual ~AudioStream(); @@ -116,7 +120,8 @@ public: // channels (1 for mono, 2 for stereo, etc) and aRate is the sample rate // (22050Hz, 44100Hz, etc). virtual nsresult Init(int32_t aNumChannels, int32_t aRate, - const dom::AudioChannelType aAudioStreamType) = 0; + const dom::AudioChannelType aAudioStreamType, + LatencyRequest aLatencyRequest) = 0; // Closes the stream. All future use of the stream is an error. virtual void Shutdown() = 0; diff --git a/content/media/MediaDecoderStateMachine.cpp b/content/media/MediaDecoderStateMachine.cpp index 45b55185c3ac..031db39c5e9e 100644 --- a/content/media/MediaDecoderStateMachine.cpp +++ b/content/media/MediaDecoderStateMachine.cpp @@ -1059,7 +1059,7 @@ void MediaDecoderStateMachine::AudioLoop() // circumstances, so we take care to drop the decoder monitor while // initializing. nsAutoPtr audioStream(AudioStream::AllocateStream()); - audioStream->Init(channels, rate, audioChannelType); + audioStream->Init(channels, rate, audioChannelType, AudioStream::HighLatency); audioStream->SetVolume(volume); if (audioStream->SetPreservesPitch(preservesPitch) != NS_OK) { NS_WARNING("Setting the pitch preservation failed at AudioLoop start."); diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index 425e82364143..aff55ab0cd0a 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -768,7 +768,7 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(GraphTime aAudioOutputStartTim audioOutputStream->mStream = AudioStream::AllocateStream(); // XXX for now, allocate stereo output. But we need to fix this to // match the system's ideal channel configuration. - audioOutputStream->mStream->Init(2, tracks->GetRate(), AUDIO_CHANNEL_NORMAL); + audioOutputStream->mStream->Init(2, tracks->GetRate(), AUDIO_CHANNEL_NORMAL, AudioStream::LowLatency); audioOutputStream->mTrackID = tracks->GetID(); } }