--- a/content/media/ogg/nsOggDecoder.cpp
+++ b/content/media/ogg/nsOggDecoder.cpp
@@ -223,47 +223,47 @@ public:
return result;
}
PRBool IsEmpty() const
{
return mCount == 0;
}
- PRInt32 GetCount() const
+ PRUint32 GetCount() const
{
return mCount;
}
PRBool IsFull() const
{
return mCount == OGGPLAY_BUFFER_SIZE;
}
- float ResetTimes(float aPeriod)
+ PRUint32 ResetTimes(float aPeriod)
{
- float time = 0.0;
+ PRUint32 frames = 0;
if (mCount > 0) {
- PRInt32 current = mHead;
+ PRUint32 current = mHead;
do {
- mQueue[current]->mTime = time;
- time += aPeriod;
+ mQueue[current]->mTime = frames * aPeriod;
+ frames += 1;
current = (current + 1) % OGGPLAY_BUFFER_SIZE;
} while (current != mTail);
}
- return time;
+ return frames;
}
private:
FrameData* mQueue[OGGPLAY_BUFFER_SIZE];
- PRInt32 mHead;
- PRInt32 mTail;
+ PRUint32 mHead;
+ PRUint32 mTail;
// This isn't redundant with mHead/mTail, since when mHead == mTail
// it's ambiguous whether the queue is full or empty
- PRInt32 mCount;
+ PRUint32 mCount;
};
// Enumeration for the valid states
enum State {
DECODER_STATE_DECODING_METADATA,
DECODER_STATE_DECODING,
DECODER_STATE_SEEKING,
DECODER_STATE_BUFFERING,
@@ -488,17 +488,17 @@ private:
// the sound and adjusted the sync time for pauses. PR_FALSE
// if the media is paused and the decoder has stopped the sound
// and adjusted the sync time for pauses. Accessed only via the
// decoder thread.
PRPackedBool mPlaying;
// Number of seconds of data video/audio data held in a frame.
// Accessed only via the decoder thread.
- float mCallbackPeriod;
+ double mCallbackPeriod;
// Video data. These are initially set when the metadata is loaded.
// They are only accessed from the decoder thread.
PRInt32 mVideoTrack;
float mFramerate;
float mAspectRatio;
// Audio data. These are initially set when the metadata is loaded.
@@ -510,20 +510,19 @@ private:
// Time that buffering started. Used for buffering timeout and only
// accessed in the decoder thread.
TimeStamp mBufferingStart;
// Download position where we should stop buffering. Only
// accessed in the decoder thread.
PRInt64 mBufferingEndOffset;
- // The time value of the last decoded video frame. Used for
- // computing the sleep period between frames for a/v sync.
- // Read/Write from the decode thread only.
- float mLastFrameTime;
+ // The last decoded video frame. Used for computing the sleep period
+ // between frames for a/v sync. Read/Write from the decode thread only.
+ PRUint64 mLastFrame;
// The decoder position of the end of the last decoded video frame.
// Read/Write from the decode thread only.
PRInt64 mLastFramePosition;
// Thread that steps through decoding each frame using liboggplay. Only accessed
// via the decode thread.
nsCOMPtr<nsIThread> mStepDecodeThread;
@@ -697,17 +696,17 @@ nsOggDecodeStateMachine::nsOggDecodeStat
mVideoTrack(-1),
mFramerate(0.0),
mAspectRatio(1.0),
mAudioRate(0),
mAudioChannels(0),
mAudioTrack(-1),
mBufferingStart(),
mBufferingEndOffset(0),
- mLastFrameTime(0),
+ mLastFrame(0),
mLastFramePosition(-1),
mState(DECODER_STATE_DECODING_METADATA),
mSeekTime(0.0),
mCurrentFrameTime(0.0),
mPlaybackStartTime(0.0),
mVolume(1.0),
mDuration(-1),
mSeekable(PR_TRUE),
@@ -755,34 +754,34 @@ nsOggDecodeStateMachine::FrameData* nsOg
if (!info)
return nsnull;
FrameData* frame = new FrameData();
if (!frame) {
return nsnull;
}
- frame->mTime = mLastFrameTime;
+ frame->mTime = mCallbackPeriod * mLastFrame;
frame->mEndStreamPosition = mDecoder->mDecoderPosition;
- mLastFrameTime += mCallbackPeriod;
+ mLastFrame += 1;
if (mLastFramePosition >= 0) {
NS_ASSERTION(frame->mEndStreamPosition >= mLastFramePosition,
"Playback positions must not decrease without an intervening reset");
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(
- base + TimeDuration::FromMilliseconds(NS_round(mLastFrameTime*1000)));
+ base + TimeDuration::FromMilliseconds(NS_round(mCallbackPeriod*mLastFrame*1000)));
mDecoder->UpdatePlaybackRate();
}
mLastFramePosition = frame->mEndStreamPosition;
int num_tracks = oggplay_get_num_tracks(mPlayer);
float audioTime = -1.0;
float videoTime = -1.0;
@@ -1068,33 +1067,33 @@ void nsOggDecodeStateMachine::StartPlayb
mPlayStartTime = TimeStamp::Now();
mPauseDuration = 0;
}
void nsOggDecodeStateMachine::StopPlayback()
{
// NS_ASSERTION(PR_InMonitor(mDecoder->GetMonitor()), "StopPlayback() called without acquiring decoder monitor");
- mLastFrameTime = mDecodedFrames.ResetTimes(mCallbackPeriod);
+ mLastFrame = mDecodedFrames.ResetTimes(mCallbackPeriod);
StopAudio();
mPlaying = PR_FALSE;
mPauseStartTime = TimeStamp::Now();
}
void nsOggDecodeStateMachine::PausePlayback()
{
if (!mAudioStream) {
StopPlayback();
return;
}
mAudioStream->Pause();
mPlaying = PR_FALSE;
mPauseStartTime = TimeStamp::Now();
if (mAudioStream->GetPosition() < 0) {
- mLastFrameTime = mDecodedFrames.ResetTimes(mCallbackPeriod);
+ mLastFrame = mDecodedFrames.ResetTimes(mCallbackPeriod);
}
}
void nsOggDecodeStateMachine::ResumePlayback()
{
if (!mAudioStream) {
StartPlayback();
return;
@@ -1315,17 +1314,18 @@ nsresult nsOggDecodeStateMachine::Seek(f
void nsOggDecodeStateMachine::DecodeToFrame(nsAutoMonitor& aMonitor,
float aTime)
{
// Drop frames before the target time.
float target = aTime - mCallbackPeriod / 2.0;
FrameData* frame = nsnull;
OggPlayErrorCode r;
- mLastFrameTime = 0;
+ mLastFrame = 0;
+
// Some of the audio data from previous frames actually belongs
// to this frame and later frames. So rescue that data and stuff
// it into the first frame.
float audioTime = 0;
nsTArray<float> audioData;
do {
if (frame) {
audioData.AppendElements(frame->mAudioData);
@@ -1365,17 +1365,17 @@ void nsOggDecodeStateMachine::DecodeToFr
// numExtraSamples must be evenly divisble by number of channels.
size_t numExtraSamples = mAudioChannels *
PRInt32(NS_ceil(mAudioRate*audioTime));
float* data = audioData.Elements() + audioData.Length() - numExtraSamples;
float* dst = frame->mAudioData.InsertElementsAt(0, numExtraSamples);
memcpy(dst, data, numExtraSamples * sizeof(float));
}
- mLastFrameTime = 0;
+ mLastFrame = 0;
frame->mTime = 0;
frame->mState = OGGPLAY_STREAM_JUST_SEEKED;
mDecodedFrames.Push(frame);
UpdatePlaybackPosition(frame->mDecodedFrameTime);
PlayVideo(frame);
}
}
@@ -1432,17 +1432,17 @@ nsresult nsOggDecodeStateMachine::Run()
mon.Enter();
}
HandleDecodeErrors(r);
if (mState == DECODER_STATE_SHUTDOWN)
continue;
- mLastFrameTime = 0;
+ mLastFrame = 0;
FrameData* frame = NextFrame();
if (frame) {
mDecodedFrames.Push(frame);
mDecoder->mPlaybackPosition = frame->mEndStreamPosition;
mPlaybackStartTime = frame->mDecodedFrameTime;
UpdatePlaybackPosition(frame->mDecodedFrameTime);
// Now that we know the start offset, we can tell the channel
// reader the last frame time.