зеркало из https://github.com/mozilla/gecko-dev.git
Bug 499874 - If decoding finishes when seeking to end of media, don't attempt to decode additional frames. Fixes a hang caused by violating oggplay's assumptions. r=roc
--HG-- extra : rebase_source : b8510182821e4babf667b0ff7d63060a82535c7c
This commit is contained in:
Родитель
e346510322
Коммит
8bd8cb870d
|
@ -397,8 +397,8 @@ protected:
|
|||
|
||||
// Decodes from the current position until encountering a frame with time
|
||||
// greater or equal to aSeekTime.
|
||||
void DecodeToFrame(nsAutoMonitor& aMonitor,
|
||||
float aSeekTime);
|
||||
PRBool DecodeToFrame(nsAutoMonitor& aMonitor,
|
||||
float aSeekTime);
|
||||
|
||||
// Convert the OggPlay frame information into a format used by Gecko
|
||||
// (RGB for video, float for sound, etc).The decoder monitor must be
|
||||
|
@ -1315,8 +1315,8 @@ nsresult nsOggDecodeStateMachine::Seek(float aTime, nsChannelReader* aReader)
|
|||
return (rv < 0) ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
void nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
||||
float aTime)
|
||||
PRBool nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
||||
float aTime)
|
||||
{
|
||||
// Drop frames before the target time.
|
||||
float target = aTime - mCallbackPeriod / 2.0;
|
||||
|
@ -1356,7 +1356,7 @@ void nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
|||
|
||||
if (mState == DECODER_STATE_SHUTDOWN) {
|
||||
delete frame;
|
||||
return;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(frame != nsnull, "No frame after decode!");
|
||||
|
@ -1380,6 +1380,8 @@ void nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
|
|||
UpdatePlaybackPosition(frame->mDecodedFrameTime);
|
||||
PlayVideo(frame);
|
||||
}
|
||||
|
||||
return r == E_OGGPLAY_OK;
|
||||
}
|
||||
|
||||
void nsOggDecodeStateMachine::StopStepDecodeThread(nsAutoMonitor* aMonitor)
|
||||
|
@ -1411,8 +1413,8 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
nsChannelReader* reader = mDecoder->GetReader();
|
||||
NS_ENSURE_TRUE(reader, NS_ERROR_NULL_POINTER);
|
||||
while (PR_TRUE) {
|
||||
nsAutoMonitor mon(mDecoder->GetMonitor());
|
||||
switch(mState) {
|
||||
nsAutoMonitor mon(mDecoder->GetMonitor());
|
||||
switch(mState) {
|
||||
case DECODER_STATE_SHUTDOWN:
|
||||
if (mPlaying) {
|
||||
StopPlayback();
|
||||
|
@ -1557,7 +1559,7 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
PRPackedBool reliable;
|
||||
double playbackRate = mDecoder->ComputePlaybackRate(&reliable);
|
||||
mBufferingEndOffset = mDecoder->mDecoderPosition +
|
||||
BUFFERING_RATE(playbackRate) * BUFFERING_WAIT;
|
||||
BUFFERING_RATE(playbackRate) * BUFFERING_WAIT;
|
||||
mState = DECODER_STATE_BUFFERING;
|
||||
if (mPlaying) {
|
||||
PausePlayback();
|
||||
|
@ -1621,8 +1623,9 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
if (mState == DECODER_STATE_SHUTDOWN)
|
||||
continue;
|
||||
|
||||
PRBool atEnd = PR_FALSE;
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
DecodeToFrame(mon, seekTime);
|
||||
atEnd = DecodeToFrame(mon, seekTime);
|
||||
// mSeekTime should not have changed. While we seek, mPlayState
|
||||
// should always be PLAY_STATE_SEEKING and no-one will call
|
||||
// nsOggDecoderStateMachine::Seek.
|
||||
|
@ -1631,29 +1634,34 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
continue;
|
||||
}
|
||||
|
||||
OggPlayErrorCode r;
|
||||
// Now try to decode another frame to see if we're at the end.
|
||||
do {
|
||||
mon.Exit();
|
||||
r = DecodeFrame();
|
||||
mon.Enter();
|
||||
} while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT);
|
||||
HandleDecodeErrors(r);
|
||||
if (mState == DECODER_STATE_SHUTDOWN)
|
||||
continue;
|
||||
if (!atEnd) {
|
||||
OggPlayErrorCode r;
|
||||
// Now try to decode another frame to see if we're at the end.
|
||||
do {
|
||||
mon.Exit();
|
||||
r = DecodeFrame();
|
||||
mon.Enter();
|
||||
} while (mState != DECODER_STATE_SHUTDOWN && r == E_OGGPLAY_TIMEOUT);
|
||||
HandleDecodeErrors(r);
|
||||
if (mState == DECODER_STATE_SHUTDOWN)
|
||||
continue;
|
||||
atEnd = r == E_OGGPLAY_OK;
|
||||
}
|
||||
QueueDecodedFrames();
|
||||
}
|
||||
|
||||
// Change state to DECODING now. SeekingStopped will call
|
||||
// nsOggDecodeStateMachine::Seek to reset our state to SEEKING
|
||||
// Change state to DECODING or COMPLETED now. SeekingStopped will
|
||||
// call nsOggDecodeStateMachine::Seek to reset our state to SEEKING
|
||||
// if we need to seek again.
|
||||
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to DECODING", mDecoder, seekTime));
|
||||
mState = DECODER_STATE_DECODING;
|
||||
nsCOMPtr<nsIRunnable> stopEvent;
|
||||
if (mDecodedFrames.GetCount() > 1) {
|
||||
if (!atEnd && mDecodedFrames.GetCount() > 1) {
|
||||
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to DECODING",
|
||||
mDecoder, seekTime));
|
||||
stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStopped);
|
||||
mState = DECODER_STATE_DECODING;
|
||||
} else {
|
||||
LOG(PR_LOG_DEBUG, ("%p Changed state from SEEKING (to %f) to COMPLETED",
|
||||
mDecoder, seekTime));
|
||||
stopEvent = NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, SeekingStoppedAtEnd);
|
||||
mState = DECODER_STATE_COMPLETED;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче