зеркало из https://github.com/mozilla/gecko-dev.git
Bug 592833 - Split StartDecodeThreads() into StartDecodeThread() and StartAudioThread() for finer control. r=roc
This commit is contained in:
Родитель
553ac96cf1
Коммит
3b48c23ee6
|
@ -191,7 +191,8 @@ nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDe
|
||||||
mPositionChangeQueued(PR_FALSE),
|
mPositionChangeQueued(PR_FALSE),
|
||||||
mAudioCompleted(PR_FALSE),
|
mAudioCompleted(PR_FALSE),
|
||||||
mGotDurationFromMetaData(PR_FALSE),
|
mGotDurationFromMetaData(PR_FALSE),
|
||||||
mStopDecodeThreads(PR_TRUE),
|
mStopDecodeThread(PR_TRUE),
|
||||||
|
mStopAudioThread(PR_TRUE),
|
||||||
mQuickBuffering(PR_FALSE),
|
mQuickBuffering(PR_FALSE),
|
||||||
mEventManager(aDecoder)
|
mEventManager(aDecoder)
|
||||||
{
|
{
|
||||||
|
@ -274,7 +275,7 @@ void nsBuiltinDecoderStateMachine::DecodeLoop()
|
||||||
|
|
||||||
// Main decode loop.
|
// Main decode loop.
|
||||||
while (mState != DECODER_STATE_SHUTDOWN &&
|
while (mState != DECODER_STATE_SHUTDOWN &&
|
||||||
!mStopDecodeThreads &&
|
!mStopDecodeThread &&
|
||||||
(videoPlaying || audioPlaying))
|
(videoPlaying || audioPlaying))
|
||||||
{
|
{
|
||||||
// We don't want to consider skipping to the next keyframe if we've
|
// We don't want to consider skipping to the next keyframe if we've
|
||||||
|
@ -358,7 +359,7 @@ void nsBuiltinDecoderStateMachine::DecodeLoop()
|
||||||
UpdateReadyState();
|
UpdateReadyState();
|
||||||
|
|
||||||
if (mState != DECODER_STATE_SHUTDOWN &&
|
if (mState != DECODER_STATE_SHUTDOWN &&
|
||||||
!mStopDecodeThreads &&
|
!mStopDecodeThread &&
|
||||||
(videoPlaying || audioPlaying) &&
|
(videoPlaying || audioPlaying) &&
|
||||||
(!audioPlaying || (GetDecodedAudioDuration() >= ampleAudioThreshold &&
|
(!audioPlaying || (GetDecodedAudioDuration() >= ampleAudioThreshold &&
|
||||||
audioQueue.GetSize() > 0))
|
audioQueue.GetSize() > 0))
|
||||||
|
@ -380,7 +381,7 @@ void nsBuiltinDecoderStateMachine::DecodeLoop()
|
||||||
|
|
||||||
} // End decode loop.
|
} // End decode loop.
|
||||||
|
|
||||||
if (!mStopDecodeThreads &&
|
if (!mStopDecodeThread &&
|
||||||
mState != DECODER_STATE_SHUTDOWN &&
|
mState != DECODER_STATE_SHUTDOWN &&
|
||||||
mState != DECODER_STATE_SEEKING)
|
mState != DECODER_STATE_SEEKING)
|
||||||
{
|
{
|
||||||
|
@ -426,7 +427,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||||
NS_ASSERTION(mState != DECODER_STATE_DECODING_METADATA,
|
NS_ASSERTION(mState != DECODER_STATE_DECODING_METADATA,
|
||||||
"Should have meta data before audio started playing.");
|
"Should have meta data before audio started playing.");
|
||||||
while (mState != DECODER_STATE_SHUTDOWN &&
|
while (mState != DECODER_STATE_SHUTDOWN &&
|
||||||
!mStopDecodeThreads &&
|
!mStopAudioThread &&
|
||||||
(!IsPlaying() ||
|
(!IsPlaying() ||
|
||||||
mState == DECODER_STATE_BUFFERING ||
|
mState == DECODER_STATE_BUFFERING ||
|
||||||
(mReader->mAudioQueue.GetSize() == 0 &&
|
(mReader->mAudioQueue.GetSize() == 0 &&
|
||||||
|
@ -438,7 +439,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||||
|
|
||||||
// If we're shutting down, break out and exit the audio thread.
|
// If we're shutting down, break out and exit the audio thread.
|
||||||
if (mState == DECODER_STATE_SHUTDOWN ||
|
if (mState == DECODER_STATE_SHUTDOWN ||
|
||||||
mStopDecodeThreads ||
|
mStopAudioThread ||
|
||||||
mReader->mAudioQueue.AtEndOfStream())
|
mReader->mAudioQueue.AtEndOfStream())
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
@ -539,7 +540,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||||
}
|
}
|
||||||
if (mReader->mAudioQueue.AtEndOfStream() &&
|
if (mReader->mAudioQueue.AtEndOfStream() &&
|
||||||
mState != DECODER_STATE_SHUTDOWN &&
|
mState != DECODER_STATE_SHUTDOWN &&
|
||||||
!mStopDecodeThreads)
|
!mStopAudioThread)
|
||||||
{
|
{
|
||||||
// Last sample pushed to audio hardware, wait for the audio to finish,
|
// Last sample pushed to audio hardware, wait for the audio to finish,
|
||||||
// before the audio thread terminates.
|
// before the audio thread terminates.
|
||||||
|
@ -922,21 +923,32 @@ void nsBuiltinDecoderStateMachine::Seek(double aTime)
|
||||||
mState = DECODER_STATE_SEEKING;
|
mState = DECODER_STATE_SEEKING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsBuiltinDecoderStateMachine::StopDecodeThreads()
|
void nsBuiltinDecoderStateMachine::StopDecodeThread()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread),
|
NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread),
|
||||||
"Should be on state machine thread.");
|
"Should be on state machine thread.");
|
||||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||||
mStopDecodeThreads = PR_TRUE;
|
mStopDecodeThread = PR_TRUE;
|
||||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||||
if (mDecodeThread) {
|
if (mDecodeThread) {
|
||||||
|
LOG(PR_LOG_DEBUG, ("%p Shutdown decode thread", mDecoder));
|
||||||
{
|
{
|
||||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||||
mDecodeThread->Shutdown();
|
mDecodeThread->Shutdown();
|
||||||
}
|
}
|
||||||
mDecodeThread = nsnull;
|
mDecodeThread = nsnull;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsBuiltinDecoderStateMachine::StopAudioThread()
|
||||||
|
{
|
||||||
|
NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread),
|
||||||
|
"Should be on state machine thread.");
|
||||||
|
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||||
|
mStopAudioThread = PR_TRUE;
|
||||||
|
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||||
if (mAudioThread) {
|
if (mAudioThread) {
|
||||||
|
LOG(PR_LOG_DEBUG, ("%p Shutdown audio thread", mDecoder));
|
||||||
{
|
{
|
||||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||||
mAudioThread->Shutdown();
|
mAudioThread->Shutdown();
|
||||||
|
@ -946,12 +958,12 @@ void nsBuiltinDecoderStateMachine::StopDecodeThreads()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBuiltinDecoderStateMachine::StartDecodeThreads()
|
nsBuiltinDecoderStateMachine::StartDecodeThread()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread),
|
NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread),
|
||||||
"Should be on state machine thread.");
|
"Should be on state machine thread.");
|
||||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||||
mStopDecodeThreads = PR_FALSE;
|
mStopDecodeThread = PR_FALSE;
|
||||||
if (!mDecodeThread && mState < DECODER_STATE_COMPLETED) {
|
if (!mDecodeThread && mState < DECODER_STATE_COMPLETED) {
|
||||||
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread));
|
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread));
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
|
@ -962,6 +974,16 @@ nsBuiltinDecoderStateMachine::StartDecodeThreads()
|
||||||
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeLoop);
|
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeLoop);
|
||||||
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsBuiltinDecoderStateMachine::StartAudioThread()
|
||||||
|
{
|
||||||
|
NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread),
|
||||||
|
"Should be on state machine thread.");
|
||||||
|
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||||
|
mStopAudioThread = PR_FALSE;
|
||||||
if (HasAudio() && !mAudioThread) {
|
if (HasAudio() && !mAudioThread) {
|
||||||
nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread));
|
nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread));
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
|
@ -1061,7 +1083,8 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
if (IsPlaying()) {
|
if (IsPlaying()) {
|
||||||
StopPlayback(AUDIO_SHUTDOWN);
|
StopPlayback(AUDIO_SHUTDOWN);
|
||||||
}
|
}
|
||||||
StopDecodeThreads();
|
StopAudioThread();
|
||||||
|
StopDecodeThread();
|
||||||
NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN,
|
NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN,
|
||||||
"How did we escape from the shutdown state???");
|
"How did we escape from the shutdown state???");
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -1081,7 +1104,7 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
|
|
||||||
// Start the decode threads, so that we can pre buffer the streams.
|
// Start the decode threads, so that we can pre buffer the streams.
|
||||||
// and calculate the start time in order to determine the duration.
|
// and calculate the start time in order to determine the duration.
|
||||||
if (NS_FAILED(StartDecodeThreads())) {
|
if (NS_FAILED(StartDecodeThread())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1121,6 +1144,7 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING) {
|
if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING) {
|
||||||
if (!IsPlaying()) {
|
if (!IsPlaying()) {
|
||||||
StartPlayback();
|
StartPlayback();
|
||||||
|
StartAudioThread();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1128,7 +1152,7 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
|
|
||||||
case DECODER_STATE_DECODING:
|
case DECODER_STATE_DECODING:
|
||||||
{
|
{
|
||||||
if (NS_FAILED(StartDecodeThreads())) {
|
if (NS_FAILED(StartDecodeThread())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1174,7 +1198,8 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
// we'll need to seek the playback position, so shutdown our decode
|
// we'll need to seek the playback position, so shutdown our decode
|
||||||
// and audio threads.
|
// and audio threads.
|
||||||
StopPlayback(AUDIO_SHUTDOWN);
|
StopPlayback(AUDIO_SHUTDOWN);
|
||||||
StopDecodeThreads();
|
StopDecodeThread();
|
||||||
|
StopAudioThread();
|
||||||
ResetPlayback();
|
ResetPlayback();
|
||||||
nsresult res;
|
nsresult res;
|
||||||
{
|
{
|
||||||
|
@ -1291,10 +1316,11 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
// Notify to allow blocked decoder thread to continue
|
// Notify to allow blocked decoder thread to continue
|
||||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||||
UpdateReadyState();
|
UpdateReadyState();
|
||||||
if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING) {
|
if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING &&
|
||||||
if (!IsPlaying()) {
|
!IsPlaying())
|
||||||
|
{
|
||||||
StartPlayback();
|
StartPlayback();
|
||||||
}
|
StartAudioThread();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1302,7 +1328,9 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
|
|
||||||
case DECODER_STATE_COMPLETED:
|
case DECODER_STATE_COMPLETED:
|
||||||
{
|
{
|
||||||
if (NS_FAILED(StartDecodeThreads())) {
|
StopDecodeThread();
|
||||||
|
|
||||||
|
if (NS_FAILED(StartAudioThread())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1325,8 +1353,7 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
if (mState != DECODER_STATE_COMPLETED)
|
if (mState != DECODER_STATE_COMPLETED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LOG(PR_LOG_DEBUG, ("%p Shutting down the state machine thread", mDecoder));
|
StopAudioThread();
|
||||||
StopDecodeThreads();
|
|
||||||
|
|
||||||
if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING) {
|
if (mDecoder->GetState() == nsBuiltinDecoder::PLAY_STATE_PLAYING) {
|
||||||
PRInt64 videoTime = HasVideo() ? mVideoFrameEndTime : 0;
|
PRInt64 videoTime = HasVideo() ? mVideoFrameEndTime : 0;
|
||||||
|
@ -1343,6 +1370,7 @@ nsresult nsBuiltinDecoderStateMachine::Run()
|
||||||
if (mState == DECODER_STATE_COMPLETED) {
|
if (mState == DECODER_STATE_COMPLETED) {
|
||||||
// We've finished playback. Shutdown the state machine thread,
|
// We've finished playback. Shutdown the state machine thread,
|
||||||
// in order to save memory on thread stacks, particuarly on Linux.
|
// in order to save memory on thread stacks, particuarly on Linux.
|
||||||
|
LOG(PR_LOG_DEBUG, ("%p Shutting down the state machine thread", mDecoder));
|
||||||
nsCOMPtr<nsIRunnable> event =
|
nsCOMPtr<nsIRunnable> event =
|
||||||
new ShutdownThreadEvent(mDecoder->mStateMachineThread);
|
new ShutdownThreadEvent(mDecoder->mStateMachineThread);
|
||||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||||
|
@ -1473,6 +1501,7 @@ void nsBuiltinDecoderStateMachine::AdvanceFrame()
|
||||||
// Start playing now if need be.
|
// Start playing now if need be.
|
||||||
if (!IsPlaying()) {
|
if (!IsPlaying()) {
|
||||||
StartPlayback();
|
StartPlayback();
|
||||||
|
StartAudioThread();
|
||||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -344,13 +344,21 @@ protected:
|
||||||
// queued here. Called on the audio thread.
|
// queued here. Called on the audio thread.
|
||||||
PRUint32 PlayFromAudioQueue(PRUint64 aSampleOffset, PRUint32 aChannels);
|
PRUint32 PlayFromAudioQueue(PRUint64 aSampleOffset, PRUint32 aChannels);
|
||||||
|
|
||||||
// Stops the decode threads. The decoder monitor must be held with exactly
|
// Stops the decode thread. The decoder monitor must be held with exactly
|
||||||
// one lock count. Called on the state machine thread.
|
// one lock count. Called on the state machine thread.
|
||||||
void StopDecodeThreads();
|
void StopDecodeThread();
|
||||||
|
|
||||||
// Starts the decode threads. The decoder monitor must be held with exactly
|
// Stops the audio thread. The decoder monitor must be held with exactly
|
||||||
// one lock count. Called on the state machine thread.
|
// one lock count. Called on the state machine thread.
|
||||||
nsresult StartDecodeThreads();
|
void StopAudioThread();
|
||||||
|
|
||||||
|
// Starts the decode thread. The decoder monitor must be held with exactly
|
||||||
|
// one lock count. Called on the state machine thread.
|
||||||
|
nsresult StartDecodeThread();
|
||||||
|
|
||||||
|
// Starts the audio thread. The decoder monitor must be held with exactly
|
||||||
|
// one lock count. Called on the state machine thread.
|
||||||
|
nsresult StartAudioThread();
|
||||||
|
|
||||||
// The main loop for the audio thread. Sent to the thread as
|
// The main loop for the audio thread. Sent to the thread as
|
||||||
// an nsRunnableMethod. This continually does blocking writes to
|
// an nsRunnableMethod. This continually does blocking writes to
|
||||||
|
@ -516,9 +524,13 @@ protected:
|
||||||
// the media index/metadata. Accessed on the state machine thread.
|
// the media index/metadata. Accessed on the state machine thread.
|
||||||
PRPackedBool mGotDurationFromMetaData;
|
PRPackedBool mGotDurationFromMetaData;
|
||||||
|
|
||||||
// PR_FALSE while decode threads should be running. Accessed on audio,
|
// PR_FALSE while decode thread should be running. Accessed state machine
|
||||||
// state machine and decode threads. Syncrhonised by decoder monitor.
|
// and decode threads. Syncrhonised by decoder monitor.
|
||||||
PRPackedBool mStopDecodeThreads;
|
PRPackedBool mStopDecodeThread;
|
||||||
|
|
||||||
|
// PR_FALSE while audio thread should be running. Accessed state machine
|
||||||
|
// and audio threads. Syncrhonised by decoder monitor.
|
||||||
|
PRPackedBool mStopAudioThread;
|
||||||
|
|
||||||
// If this is PR_TRUE while we're in buffering mode, we can exit early,
|
// If this is PR_TRUE while we're in buffering mode, we can exit early,
|
||||||
// as it's likely we may be able to playback. This happens when we enter
|
// as it's likely we may be able to playback. This happens when we enter
|
||||||
|
|
Загрузка…
Ссылка в новой задаче