Bug 1186801 - Remove decoder monitor from AudioSink. r=kinetik.

This commit is contained in:
JW Wang 2015-07-24 14:24:42 +08:00
parent 4a9562f506
commit bc6998fae7
3 changed files with 33 additions and 22 deletions

View File

@ -23,12 +23,11 @@ extern PRLogModuleInfo* gMediaDecoderLog;
static const int64_t AUDIO_FUZZ_FRAMES = 1;
AudioSink::AudioSink(MediaQueue<AudioData>& aAudioQueue,
ReentrantMonitor& aMonitor,
int64_t aStartTime,
const AudioInfo& aInfo,
dom::AudioChannel aChannel)
: mAudioQueue(aAudioQueue)
, mDecoderMonitor(aMonitor)
, mMonitor("AudioSink::mMonitor")
, mStartTime(aStartTime)
, mWritten(0)
, mLastGoodPosition(0)
@ -71,7 +70,7 @@ AudioSink::Init()
int64_t
AudioSink::GetPosition()
{
AssertCurrentThreadInMonitor();
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
int64_t pos;
if (mAudioStream &&
@ -86,7 +85,7 @@ AudioSink::GetPosition()
bool
AudioSink::HasUnplayedFrames()
{
AssertCurrentThreadInMonitor();
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
// Experimentation suggests that GetPositionInFrames() is zero-indexed,
// so we need to add 1 here before comparing it to mWritten.
return mAudioStream && mAudioStream->GetPositionInFrames() + 1 < mWritten;
@ -95,13 +94,14 @@ AudioSink::HasUnplayedFrames()
void
AudioSink::Shutdown()
{
AssertCurrentThreadInMonitor();
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mStopAudioThread = true;
if (mAudioStream) {
mAudioStream->Cancel();
}
GetReentrantMonitor().NotifyAll();
// Exit the monitor so audio loop can enter the monitor and finish its job.
ReentrantMonitorAutoExit exit(GetReentrantMonitor());
mThread->Shutdown();
mThread = nullptr;
@ -114,7 +114,7 @@ AudioSink::Shutdown()
void
AudioSink::SetVolume(double aVolume)
{
AssertCurrentThreadInMonitor();
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mVolume = aVolume;
mSetVolume = true;
}
@ -122,7 +122,7 @@ AudioSink::SetVolume(double aVolume)
void
AudioSink::SetPlaybackRate(double aPlaybackRate)
{
AssertCurrentThreadInMonitor();
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
NS_ASSERTION(mPlaybackRate != 0, "Don't set the playbackRate to 0 on AudioStream");
mPlaybackRate = aPlaybackRate;
mSetPlaybackRate = true;
@ -131,7 +131,7 @@ AudioSink::SetPlaybackRate(double aPlaybackRate)
void
AudioSink::SetPreservesPitch(bool aPreservesPitch)
{
AssertCurrentThreadInMonitor();
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mPreservesPitch = aPreservesPitch;
mSetPreservesPitch = true;
}
@ -139,11 +139,18 @@ AudioSink::SetPreservesPitch(bool aPreservesPitch)
void
AudioSink::SetPlaying(bool aPlaying)
{
AssertCurrentThreadInMonitor();
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mPlaying = aPlaying;
GetReentrantMonitor().NotifyAll();
}
void
AudioSink::NotifyData()
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
GetReentrantMonitor().NotifyAll();
}
void
AudioSink::AudioLoop()
{

View File

@ -26,7 +26,6 @@ public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AudioSink)
AudioSink(MediaQueue<AudioData>& aAudioQueue,
ReentrantMonitor& aMonitor,
int64_t aStartTime,
const AudioInfo& aInfo,
dom::AudioChannel aChannel);
@ -35,9 +34,10 @@ public:
// or rejected if any error.
nsRefPtr<GenericPromise> Init();
/*
* All public functions below are thread-safe.
*/
int64_t GetPosition();
// Thread-safe. Can be called on any thread.
int64_t GetEndTime() const;
// Check whether we've pushed more frames to the audio hardware than it has
@ -45,15 +45,17 @@ public:
bool HasUnplayedFrames();
// Shut down the AudioSink's resources.
// Must be called with the decoder monitor held.
void Shutdown();
void SetVolume(double aVolume);
void SetPlaybackRate(double aPlaybackRate);
void SetPreservesPitch(bool aPreservesPitch);
void SetPlaying(bool aPlaying);
// Wake up the audio loop if it is waiting for data to play or the audio
// queue is finished.
void NotifyData();
private:
~AudioSink() {}
@ -104,7 +106,7 @@ private:
}
ReentrantMonitor& GetReentrantMonitor() const {
return mDecoderMonitor;
return mMonitor;
}
void AssertCurrentThreadInMonitor() const {
@ -114,7 +116,7 @@ private:
void AssertOnAudioThread();
MediaQueue<AudioData>& mAudioQueue;
ReentrantMonitor& mDecoderMonitor;
mutable ReentrantMonitor mMonitor;
// Thread for pushing audio onto the audio hardware.
// The "audio push thread".

View File

@ -642,8 +642,9 @@ MediaDecoderStateMachine::Push(AudioData* aSample)
UpdateNextFrameStatus();
DispatchDecodeTasksIfNeeded();
// XXXbholley - Still necessary?
mDecoder->GetReentrantMonitor().NotifyAll();
if (mAudioSink) {
mAudioSink->NotifyData();
}
}
void
@ -789,6 +790,10 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
case DECODER_STATE_DECODING: {
CheckIfDecodeComplete();
mDecoder->GetReentrantMonitor().NotifyAll();
// Tell AudioSink to wake up for audio queue is finished.
if (mAudioSink) {
mAudioSink->NotifyData();
}
// Schedule the state machine to notify track ended as soon as possible.
if (mAudioCaptured) {
ScheduleStateMachine();
@ -1053,9 +1058,6 @@ void MediaDecoderStateMachine::StopPlayback()
mPlayDuration = GetClock();
SetPlayStartTime(TimeStamp());
}
// Notify the audio sink, so that it notices that we've stopped playing,
// so it can pause audio playback.
mDecoder->GetReentrantMonitor().NotifyAll();
NS_ASSERTION(!IsPlaying(), "Should report not playing at end of StopPlayback()");
DispatchDecodeTasksIfNeeded();
@ -1794,7 +1796,7 @@ MediaDecoderStateMachine::StartAudioThread()
if (HasAudio() && !mAudioSink) {
mAudioCompleted = false;
mAudioSink = new AudioSink(mAudioQueue, mDecoder->GetReentrantMonitor(),
mAudioSink = new AudioSink(mAudioQueue,
GetMediaTime(), mInfo.mAudio,
mDecoder->GetAudioChannel());