зеркало из https://github.com/mozilla/pjs.git
Bug 486991. Convert nsMediaStream and media decoders to use TimeStamp/TimeDuration. r=doublec
This commit is contained in:
Родитель
4aa26d8ece
Коммит
004a9ff890
|
@ -45,7 +45,7 @@
|
|||
#include "gfxContext.h"
|
||||
#include "gfxRect.h"
|
||||
#include "nsITimer.h"
|
||||
#include "prinrval.h"
|
||||
#include "nsTimeStamp.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gVideoDecoderLog;
|
||||
|
@ -61,7 +61,10 @@ class nsHTMLMediaElement;
|
|||
// called from any thread.
|
||||
class nsMediaDecoder : public nsIObserver
|
||||
{
|
||||
public:
|
||||
public:
|
||||
typedef mozilla::TimeStamp TimeStamp;
|
||||
typedef mozilla::TimeDuration TimeDuration;
|
||||
|
||||
nsMediaDecoder();
|
||||
virtual ~nsMediaDecoder();
|
||||
|
||||
|
@ -265,14 +268,14 @@ protected:
|
|||
|
||||
// Time that the last progress event was fired. Read/Write from the
|
||||
// main thread only.
|
||||
PRIntervalTime mProgressTime;
|
||||
TimeStamp mProgressTime;
|
||||
|
||||
// Time that data was last read from the media resource. Used for
|
||||
// computing if the download has stalled and to rate limit progress events
|
||||
// when data is arriving slower than PROGRESS_MS. A value of 0 indicates
|
||||
// when data is arriving slower than PROGRESS_MS. A value of null indicates
|
||||
// that a stall event has already fired and not to fire another one until
|
||||
// more data is received. Read/Write from the main thread only.
|
||||
PRIntervalTime mDataTime;
|
||||
TimeStamp mDataTime;
|
||||
|
||||
// Lock around the video RGB, width and size data. This
|
||||
// is used in the decoder backend threads and the main thread
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "nsIStreamListener.h"
|
||||
#include "prlock.h"
|
||||
#include "nsMediaCache.h"
|
||||
#include "nsTimeStamp.h"
|
||||
|
||||
// For HTTP seeking, if number of bytes needing to be
|
||||
// seeked forward is less than this value then a read is
|
||||
|
@ -64,25 +65,28 @@ class nsMediaDecoder;
|
|||
* kind of average of the data passing through over the time the
|
||||
* channel is active.
|
||||
*
|
||||
* Timestamps and time durations are measured in PRIntervalTimes, but
|
||||
* all methods take "now" as a parameter so the user of this class can
|
||||
* define what the timeline means.
|
||||
* All methods take "now" as a parameter so the user of this class can
|
||||
* control the timeline used.
|
||||
*/
|
||||
class nsChannelStatistics {
|
||||
public:
|
||||
typedef mozilla::TimeStamp TimeStamp;
|
||||
typedef mozilla::TimeDuration TimeDuration;
|
||||
|
||||
nsChannelStatistics() { Reset(); }
|
||||
void Reset() {
|
||||
mLastStartTime = mAccumulatedTime = 0;
|
||||
mLastStartTime = TimeStamp();
|
||||
mAccumulatedTime = TimeDuration(0);
|
||||
mAccumulatedBytes = 0;
|
||||
mIsStarted = PR_FALSE;
|
||||
}
|
||||
void Start(PRIntervalTime aNow) {
|
||||
void Start(TimeStamp aNow) {
|
||||
if (mIsStarted)
|
||||
return;
|
||||
mLastStartTime = aNow;
|
||||
mIsStarted = PR_TRUE;
|
||||
}
|
||||
void Stop(PRIntervalTime aNow) {
|
||||
void Stop(TimeStamp aNow) {
|
||||
if (!mIsStarted)
|
||||
return;
|
||||
mAccumulatedTime += aNow - mLastStartTime;
|
||||
|
@ -97,25 +101,28 @@ public:
|
|||
mAccumulatedBytes += aBytes;
|
||||
}
|
||||
double GetRateAtLastStop(PRPackedBool* aReliable) {
|
||||
*aReliable = mAccumulatedTime >= PR_TicksPerSecond();
|
||||
return double(mAccumulatedBytes)*PR_TicksPerSecond()/mAccumulatedTime;
|
||||
double seconds = mAccumulatedTime.ToSeconds();
|
||||
*aReliable = seconds >= 1.0;
|
||||
if (seconds <= 0.0)
|
||||
return 0.0;
|
||||
return double(mAccumulatedBytes)/seconds;
|
||||
}
|
||||
double GetRate(PRIntervalTime aNow, PRPackedBool* aReliable) {
|
||||
PRIntervalTime time = mAccumulatedTime;
|
||||
double GetRate(TimeStamp aNow, PRPackedBool* aReliable) {
|
||||
TimeDuration time = mAccumulatedTime;
|
||||
if (mIsStarted) {
|
||||
time += aNow - mLastStartTime;
|
||||
}
|
||||
*aReliable = time >= PR_TicksPerSecond();
|
||||
NS_ASSERTION(time >= 0, "Time wraparound?");
|
||||
if (time <= 0)
|
||||
double seconds = time.ToSeconds();
|
||||
*aReliable = seconds >= 1.0;
|
||||
if (seconds <= 0.0)
|
||||
return 0.0;
|
||||
return double(mAccumulatedBytes)*PR_TicksPerSecond()/time;
|
||||
return double(mAccumulatedBytes)/seconds;
|
||||
}
|
||||
private:
|
||||
PRInt64 mAccumulatedBytes;
|
||||
PRIntervalTime mAccumulatedTime;
|
||||
PRIntervalTime mLastStartTime;
|
||||
PRPackedBool mIsStarted;
|
||||
PRInt64 mAccumulatedBytes;
|
||||
TimeDuration mAccumulatedTime;
|
||||
TimeStamp mLastStartTime;
|
||||
PRPackedBool mIsStarted;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -68,8 +68,8 @@ nsMediaDecoder::nsMediaDecoder() :
|
|||
mElement(0),
|
||||
mRGBWidth(-1),
|
||||
mRGBHeight(-1),
|
||||
mProgressTime(0),
|
||||
mDataTime(0),
|
||||
mProgressTime(),
|
||||
mDataTime(),
|
||||
mVideoUpdateLock(nsnull),
|
||||
mFramerate(0.0),
|
||||
mSizeChanged(PR_FALSE),
|
||||
|
@ -153,25 +153,27 @@ void nsMediaDecoder::Progress(PRBool aTimer)
|
|||
if (!mElement)
|
||||
return;
|
||||
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
if (!aTimer) {
|
||||
mDataTime = now;
|
||||
}
|
||||
|
||||
PRUint32 progressDelta = PR_IntervalToMilliseconds(now - mProgressTime);
|
||||
PRUint32 networkDelta = PR_IntervalToMilliseconds(now - mDataTime);
|
||||
|
||||
// If PROGRESS_MS has passed since the last progress event fired and more
|
||||
// data has arrived since then, fire another progress event.
|
||||
if (progressDelta >= PROGRESS_MS && networkDelta <= PROGRESS_MS) {
|
||||
if ((mProgressTime.IsNull() ||
|
||||
now - mProgressTime >= TimeDuration::FromMilliseconds(PROGRESS_MS)) &&
|
||||
!mDataTime.IsNull() &&
|
||||
now - mDataTime <= TimeDuration::FromMilliseconds(PROGRESS_MS)) {
|
||||
mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress"));
|
||||
mProgressTime = now;
|
||||
}
|
||||
|
||||
if (mDataTime != 0 && networkDelta >= STALL_MS) {
|
||||
if (!mDataTime.IsNull() &&
|
||||
now - mDataTime >= TimeDuration::FromMilliseconds(STALL_MS)) {
|
||||
mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("stalled"));
|
||||
mDataTime = 0;
|
||||
// Null it out
|
||||
mDataTime = TimeStamp();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@
|
|||
#define HTTP_OK_CODE 200
|
||||
#define HTTP_PARTIAL_RESPONSE_CODE 206
|
||||
|
||||
using mozilla::TimeStamp;
|
||||
|
||||
nsMediaChannelStream::nsMediaChannelStream(nsMediaDecoder* aDecoder,
|
||||
nsIChannel* aChannel, nsIURI* aURI)
|
||||
: nsMediaStream(aDecoder, aChannel, aURI),
|
||||
|
@ -207,7 +209,7 @@ nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest)
|
|||
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
mChannelStatistics.Start(PR_IntervalNow());
|
||||
mChannelStatistics.Start(TimeStamp::Now());
|
||||
}
|
||||
|
||||
if (mSuspendCount > 0) {
|
||||
|
@ -229,7 +231,7 @@ nsMediaChannelStream::OnStopRequest(nsIRequest* aRequest, nsresult aStatus)
|
|||
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
mChannelStatistics.Stop(PR_IntervalNow());
|
||||
mChannelStatistics.Stop(TimeStamp::Now());
|
||||
}
|
||||
|
||||
mCacheStream.NotifyDataEnded(aStatus);
|
||||
|
@ -376,7 +378,7 @@ void nsMediaChannelStream::CloseChannel()
|
|||
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
mChannelStatistics.Stop(PR_IntervalNow());
|
||||
mChannelStatistics.Stop(TimeStamp::Now());
|
||||
}
|
||||
|
||||
if (mListener) {
|
||||
|
@ -429,7 +431,7 @@ void nsMediaChannelStream::Suspend()
|
|||
if (mSuspendCount == 0 && mChannel) {
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
mChannelStatistics.Stop(PR_IntervalNow());
|
||||
mChannelStatistics.Stop(TimeStamp::Now());
|
||||
}
|
||||
mChannel->Suspend();
|
||||
}
|
||||
|
@ -444,7 +446,7 @@ void nsMediaChannelStream::Resume()
|
|||
if (mSuspendCount == 0 && mChannel) {
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
mChannelStatistics.Start(PR_IntervalNow());
|
||||
mChannelStatistics.Start(TimeStamp::Now());
|
||||
}
|
||||
mChannel->Resume();
|
||||
// XXX need to do something fancier here because we often won't
|
||||
|
@ -586,7 +588,7 @@ double
|
|||
nsMediaChannelStream::GetDownloadRate(PRPackedBool* aIsReliable)
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
return mChannelStatistics.GetRate(PR_IntervalNow(), aIsReliable);
|
||||
return mChannelStatistics.GetRate(TimeStamp::Now(), aIsReliable);
|
||||
}
|
||||
|
||||
PRInt64
|
||||
|
|
|
@ -53,6 +53,9 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsOggDecoder.h"
|
||||
|
||||
using mozilla::TimeDuration;
|
||||
using mozilla::TimeStamp;
|
||||
|
||||
/*
|
||||
The maximum height and width of the video. Used for
|
||||
sanitizing the memory allocation of the RGB buffer
|
||||
|
@ -395,18 +398,18 @@ private:
|
|||
// for synchronising frames. It is reset after a seek as the mTime member
|
||||
// of FrameData is reset to start at 0 from the first frame after a seek.
|
||||
// Accessed only via the decoder thread.
|
||||
PRIntervalTime mPlayStartTime;
|
||||
TimeStamp mPlayStartTime;
|
||||
|
||||
// The time that playback was most recently paused, either via
|
||||
// buffering or pause. This is used to compute mPauseDuration for
|
||||
// a/v sync adjustments. Accessed only via the decoder thread.
|
||||
PRIntervalTime mPauseStartTime;
|
||||
TimeStamp mPauseStartTime;
|
||||
|
||||
// The total time that has been spent in completed pauses (via
|
||||
// 'pause' or buffering). This is used to adjust for these
|
||||
// pauses when computing a/v synchronisation. Accessed only via the
|
||||
// decoder thread.
|
||||
PRIntervalTime mPauseDuration;
|
||||
TimeDuration mPauseDuration;
|
||||
|
||||
// PR_TRUE if the media is playing and the decoder has started
|
||||
// the sound and adjusted the sync time for pauses. PR_FALSE
|
||||
|
@ -432,7 +435,7 @@ private:
|
|||
|
||||
// Time that buffering started. Used for buffering timeout and only
|
||||
// accessed in the decoder thread.
|
||||
PRIntervalTime mBufferingStart;
|
||||
TimeStamp mBufferingStart;
|
||||
|
||||
// Download position where we should stop buffering. Only
|
||||
// accessed in the decoder thread.
|
||||
|
@ -497,8 +500,8 @@ private:
|
|||
nsOggDecodeStateMachine::nsOggDecodeStateMachine(nsOggDecoder* aDecoder) :
|
||||
mDecoder(aDecoder),
|
||||
mPlayer(0),
|
||||
mPlayStartTime(0),
|
||||
mPauseStartTime(0),
|
||||
mPlayStartTime(),
|
||||
mPauseStartTime(),
|
||||
mPauseDuration(0),
|
||||
mPlaying(PR_FALSE),
|
||||
mCallbackPeriod(1.0),
|
||||
|
@ -507,7 +510,7 @@ nsOggDecodeStateMachine::nsOggDecodeStateMachine(nsOggDecoder* aDecoder) :
|
|||
mAudioRate(0),
|
||||
mAudioChannels(0),
|
||||
mAudioTrack(-1),
|
||||
mBufferingStart(0),
|
||||
mBufferingStart(),
|
||||
mBufferingEndOffset(0),
|
||||
mLastFrameTime(0),
|
||||
mLastFramePosition(-1),
|
||||
|
@ -554,9 +557,17 @@ nsOggDecodeStateMachine::FrameData* nsOggDecodeStateMachine::NextFrame()
|
|||
if (mLastFramePosition >= 0) {
|
||||
NS_ASSERTION(frame->mEndStreamPosition >= mLastFramePosition,
|
||||
"Playback positions must not decrease without an intervening reset");
|
||||
mDecoder->mPlaybackStatistics.Start(frame->mTime*PR_TicksPerSecond());
|
||||
TimeStamp base = mPlayStartTime;
|
||||
if (base.IsNull()) {
|
||||
// It doesn't really matter what 'base' is, so just use 'now' if
|
||||
// we haven't started playback.
|
||||
base = TimeStamp::Now();
|
||||
}
|
||||
mDecoder->mPlaybackStatistics.Start(
|
||||
base + TimeDuration::FromMilliseconds(NS_round(frame->mTime*1000)));
|
||||
mDecoder->mPlaybackStatistics.AddBytes(frame->mEndStreamPosition - mLastFramePosition);
|
||||
mDecoder->mPlaybackStatistics.Stop(mLastFrameTime*PR_TicksPerSecond());
|
||||
mDecoder->mPlaybackStatistics.Stop(
|
||||
base + TimeDuration::FromMilliseconds(NS_round(mLastFrameTime*1000)));
|
||||
mDecoder->UpdatePlaybackRate();
|
||||
}
|
||||
mLastFramePosition = frame->mEndStreamPosition;
|
||||
|
@ -653,16 +664,17 @@ void nsOggDecodeStateMachine::PlayFrame() {
|
|||
|
||||
if (!mDecodedFrames.IsEmpty()) {
|
||||
FrameData* frame = mDecodedFrames.Peek();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
if (frame->mState == OGGPLAY_STREAM_JUST_SEEKED) {
|
||||
// After returning from a seek all mTime members of
|
||||
// FrameData start again from a time position of 0.
|
||||
// Reset the play start time.
|
||||
mPlayStartTime = PR_IntervalNow();
|
||||
mPauseDuration = 0;
|
||||
mPlayStartTime = now;
|
||||
mPauseDuration = TimeDuration(0);
|
||||
frame->mState = OGGPLAY_STREAM_INITIALISED;
|
||||
}
|
||||
|
||||
double time = (PR_IntervalToMilliseconds(PR_IntervalNow()-mPlayStartTime-mPauseDuration)/1000.0);
|
||||
double time = (now - mPlayStartTime - mPauseDuration).ToSeconds();
|
||||
if (time >= frame->mTime) {
|
||||
// Audio for the current frame is played, but video for the next frame
|
||||
// is displayed, to account for lag from the time the audio is written
|
||||
|
@ -786,13 +798,15 @@ void nsOggDecodeStateMachine::StartPlayback()
|
|||
mPlaying = PR_TRUE;
|
||||
|
||||
// If this is the very first play, then set the initial start time
|
||||
if (mPlayStartTime == 0) {
|
||||
mPlayStartTime = PR_IntervalNow();
|
||||
if (mPlayStartTime.IsNull()) {
|
||||
mPlayStartTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
// If we have been paused previously, then compute duration spent paused
|
||||
if (mPauseStartTime != 0) {
|
||||
mPauseDuration += PR_IntervalNow() - mPauseStartTime;
|
||||
if (!mPauseStartTime.IsNull()) {
|
||||
mPauseDuration += TimeStamp::Now() - mPauseStartTime;
|
||||
// Null out mPauseStartTime
|
||||
mPauseStartTime = TimeStamp();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -801,7 +815,7 @@ void nsOggDecodeStateMachine::StopPlayback()
|
|||
// NS_ASSERTION(PR_InMonitor(mDecoder->GetMonitor()), "StopPlayback() called without acquiring decoder monitor");
|
||||
StopAudio();
|
||||
mPlaying = PR_FALSE;
|
||||
mPauseStartTime = PR_IntervalNow();
|
||||
mPauseStartTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
void nsOggDecodeStateMachine::UpdatePlaybackPosition(float aTime)
|
||||
|
@ -1010,7 +1024,7 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
NS_NEW_RUNNABLE_METHOD(nsOggDecoder, mDecoder, UpdateReadyStateForData);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
|
||||
mBufferingStart = PR_IntervalNow();
|
||||
mBufferingStart = TimeStamp::Now();
|
||||
PRPackedBool reliable;
|
||||
double playbackRate = mDecoder->ComputePlaybackRate(&reliable);
|
||||
mBufferingEndOffset = mDecoder->mDecoderPosition +
|
||||
|
@ -1100,15 +1114,15 @@ nsresult nsOggDecodeStateMachine::Run()
|
|||
|
||||
case DECODER_STATE_BUFFERING:
|
||||
{
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
if ((PR_IntervalToMilliseconds(now - mBufferingStart) < BUFFERING_WAIT*1000) &&
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
if (now - mBufferingStart < TimeDuration::FromSeconds(BUFFERING_WAIT) &&
|
||||
mDecoder->mReader->Stream()->GetCachedDataEnd(mDecoder->mDecoderPosition) < mBufferingEndOffset &&
|
||||
!mDecoder->mReader->Stream()->IsDataCachedToEndOfStream(mDecoder->mDecoderPosition) &&
|
||||
!mDecoder->mReader->Stream()->IsSuspendedByCache()) {
|
||||
LOG(PR_LOG_DEBUG,
|
||||
("In buffering: buffering data until %d bytes available or %d milliseconds",
|
||||
("In buffering: buffering data until %d bytes available or %f seconds",
|
||||
PRUint32(mBufferingEndOffset - mDecoder->mReader->Stream()->GetCachedDataEnd(mDecoder->mDecoderPosition)),
|
||||
BUFFERING_WAIT*1000 - (PR_IntervalToMilliseconds(now - mBufferingStart))));
|
||||
BUFFERING_WAIT - (now - mBufferingStart).ToSeconds()));
|
||||
mon.Wait(PR_MillisecondsToInterval(1000));
|
||||
if (mState == DECODER_STATE_SHUTDOWN)
|
||||
continue;
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsWaveDecoder.h"
|
||||
|
||||
using mozilla::TimeDuration;
|
||||
using mozilla::TimeStamp;
|
||||
|
||||
// Maximum number of seconds to wait when buffering.
|
||||
#define BUFFERING_TIMEOUT 3
|
||||
|
||||
|
@ -114,7 +117,7 @@ class nsWaveStateMachine : public nsRunnable
|
|||
{
|
||||
public:
|
||||
nsWaveStateMachine(nsWaveDecoder* aDecoder,
|
||||
PRUint32 aBufferWaitTime, float aInitialVolume);
|
||||
TimeDuration aBufferWaitTime, float aInitialVolume);
|
||||
~nsWaveStateMachine();
|
||||
|
||||
void SetStream(nsMediaStream* aStream) { mStream = aStream; }
|
||||
|
@ -257,12 +260,12 @@ private:
|
|||
// playback resumes, so it is possible for this to be null.
|
||||
nsAutoPtr<nsAudioStream> mAudioStream;
|
||||
|
||||
// Maximum time in milliseconds to spend waiting for data during buffering.
|
||||
PRUint32 mBufferingWait;
|
||||
// Maximum time to spend waiting for data during buffering.
|
||||
TimeDuration mBufferingWait;
|
||||
|
||||
// Machine time that buffering began, used with mBufferingWait to time out
|
||||
// buffering.
|
||||
PRIntervalTime mBufferingStart;
|
||||
TimeStamp mBufferingStart;
|
||||
|
||||
// Download position where we should stop buffering. Only accessed
|
||||
// in the decoder thread.
|
||||
|
@ -334,11 +337,12 @@ private:
|
|||
};
|
||||
|
||||
nsWaveStateMachine::nsWaveStateMachine(nsWaveDecoder* aDecoder,
|
||||
PRUint32 aBufferWaitTime, float aInitialVolume)
|
||||
TimeDuration aBufferWaitTime,
|
||||
float aInitialVolume)
|
||||
: mDecoder(aDecoder),
|
||||
mStream(nsnull),
|
||||
mBufferingWait(aBufferWaitTime),
|
||||
mBufferingStart(0),
|
||||
mBufferingStart(),
|
||||
mBufferingEndOffset(0),
|
||||
mSampleRate(0),
|
||||
mChannels(0),
|
||||
|
@ -512,15 +516,15 @@ nsWaveStateMachine::Run()
|
|||
break;
|
||||
|
||||
case STATE_BUFFERING: {
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
if ((PR_IntervalToMilliseconds(now - mBufferingStart) < mBufferingWait) &&
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
if (now - mBufferingStart < mBufferingWait &&
|
||||
mStream->GetCachedDataEnd(mPlaybackPosition) < mBufferingEndOffset &&
|
||||
!mStream->IsDataCachedToEndOfStream(mPlaybackPosition) &&
|
||||
!mStream->IsSuspendedByCache()) {
|
||||
LOG(PR_LOG_DEBUG,
|
||||
("In buffering: buffering data until %d bytes available or %d milliseconds\n",
|
||||
("In buffering: buffering data until %d bytes available or %f seconds\n",
|
||||
PRUint32(mBufferingEndOffset - mStream->GetCachedDataEnd(mPlaybackPosition)),
|
||||
mBufferingWait - (PR_IntervalToMilliseconds(now - mBufferingStart))));
|
||||
(mBufferingWait - (now - mBufferingStart)).ToSeconds()));
|
||||
monitor.Wait(PR_MillisecondsToInterval(1000));
|
||||
} else {
|
||||
ChangeState(mNextState);
|
||||
|
@ -541,13 +545,12 @@ nsWaveStateMachine::Run()
|
|||
}
|
||||
}
|
||||
|
||||
PRUint32 startTime = PR_IntervalToMilliseconds(PR_IntervalNow());
|
||||
startTime -= AUDIO_BUFFER_LENGTH;
|
||||
PRIntervalTime lastWakeup = PR_MillisecondsToInterval(startTime);
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
TimeStamp lastWakeup = now -
|
||||
TimeDuration::FromMilliseconds(AUDIO_BUFFER_LENGTH);
|
||||
|
||||
do {
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
PRInt32 sleepTime = PR_IntervalToMilliseconds(now - lastWakeup);
|
||||
TimeDuration sleepTime = now - lastWakeup;
|
||||
lastWakeup = now;
|
||||
|
||||
// We aim to have AUDIO_BUFFER_LENGTH milliseconds of audio
|
||||
|
@ -556,12 +559,13 @@ nsWaveStateMachine::Run()
|
|||
// wake early, we only buffer sleepTime milliseconds of audio since
|
||||
// there is still AUDIO_BUFFER_LENGTH - sleepTime milliseconds of
|
||||
// audio buffered.
|
||||
PRInt32 targetTime = AUDIO_BUFFER_LENGTH;
|
||||
TimeDuration targetTime =
|
||||
TimeDuration::FromMilliseconds(AUDIO_BUFFER_LENGTH);
|
||||
if (sleepTime < targetTime) {
|
||||
targetTime = sleepTime;
|
||||
}
|
||||
|
||||
PRInt64 len = TimeToBytes(float(targetTime) / 1000.0f);
|
||||
PRInt64 len = TimeToBytes(targetTime.ToSeconds());
|
||||
|
||||
PRInt64 leftToPlay =
|
||||
GetDataLength() - (mPlaybackPosition - mWavePCMOffset);
|
||||
|
@ -578,9 +582,9 @@ nsWaveStateMachine::Run()
|
|||
// we need to advance playback to free up cache space)
|
||||
if (mState != STATE_ENDED && available < len &&
|
||||
!mStream->IsSuspendedByCache()) {
|
||||
mBufferingStart = PR_IntervalNow();
|
||||
mBufferingStart = now;
|
||||
mBufferingEndOffset = mPlaybackPosition +
|
||||
TimeToBytes(float(mBufferingWait) / 1000.0f);
|
||||
TimeToBytes(mBufferingWait.ToSeconds());
|
||||
mNextState = mState;
|
||||
ChangeState(STATE_BUFFERING);
|
||||
|
||||
|
@ -633,6 +637,7 @@ nsWaveStateMachine::Run()
|
|||
|
||||
if (mState == STATE_PLAYING) {
|
||||
monitor.Wait(PR_MillisecondsToInterval(AUDIO_BUFFER_WAKEUP));
|
||||
now = TimeStamp::Now();
|
||||
}
|
||||
} while (mState == STATE_PLAYING);
|
||||
break;
|
||||
|
@ -1295,8 +1300,8 @@ nsWaveDecoder::Load(nsIURI* aURI, nsIChannel* aChannel, nsIStreamListener** aStr
|
|||
RegisterShutdownObserver();
|
||||
|
||||
mPlaybackStateMachine = new nsWaveStateMachine(this,
|
||||
BUFFERING_TIMEOUT * 1000,
|
||||
mInitialVolume);
|
||||
TimeDuration::FromMilliseconds(BUFFERING_TIMEOUT),
|
||||
mInitialVolume);
|
||||
NS_ENSURE_TRUE(mPlaybackStateMachine, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Open the stream *after* setting mPlaybackStateMachine, to ensure
|
||||
|
|
Загрузка…
Ссылка в новой задаче