mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 556893 - Make playback time remaining accurate in media readyState transition calculation. r=doublec
This commit is contained in:
parent
6f5d537cbc
commit
de44118d0b
@ -815,3 +815,9 @@ void nsBuiltinDecoder::MoveLoadsToBackground()
|
||||
mStream->MoveLoadsToBackground();
|
||||
}
|
||||
}
|
||||
|
||||
void nsBuiltinDecoder::UpdatePlaybackOffset(PRInt64 aOffset)
|
||||
{
|
||||
MonitorAutoEnter mon(mMonitor);
|
||||
mPlaybackPosition = NS_MAX(aOffset, mPlaybackPosition);
|
||||
}
|
||||
|
@ -405,6 +405,10 @@ class nsBuiltinDecoder : public nsMediaDecoder
|
||||
// position.
|
||||
PRInt64 GetDownloadPosition();
|
||||
|
||||
// Updates the approximate byte offset which playback has reached. This is
|
||||
// used to calculate the readyState transitions.
|
||||
void UpdatePlaybackOffset(PRInt64 aOffset);
|
||||
|
||||
public:
|
||||
// Notifies the element that decoding has failed.
|
||||
void DecodeError();
|
||||
|
@ -379,6 +379,7 @@ void nsOggPlayStateMachine::AudioLoop()
|
||||
sound->AudioDataLength(),
|
||||
PR_TRUE);
|
||||
mAudioEndTime = sound->mTime + sound->mDuration;
|
||||
mDecoder->UpdatePlaybackOffset(sound->mOffset);
|
||||
} else {
|
||||
mReader->mAudioQueue.PushFront(sound);
|
||||
sound.forget();
|
||||
@ -1122,6 +1123,7 @@ void nsOggPlayStateMachine::AdvanceFrame()
|
||||
mVideoFrameTime = data->mTime;
|
||||
videoData = data;
|
||||
mReader->mVideoQueue.PopFront();
|
||||
mDecoder->UpdatePlaybackOffset(data->mOffset);
|
||||
if (mReader->mVideoQueue.GetSize() == 0)
|
||||
break;
|
||||
data = mReader->mVideoQueue.PeekFront();
|
||||
|
@ -82,12 +82,13 @@ PRBool MulOverflow32(PRUint32 a, PRUint32 b, PRUint32& aResult) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
VideoData* VideoData::Create(PRInt64 aTime,
|
||||
VideoData* VideoData::Create(PRInt64 aOffset,
|
||||
PRInt64 aTime,
|
||||
th_ycbcr_buffer aBuffer,
|
||||
PRBool aKeyframe,
|
||||
PRInt64 aGranulepos)
|
||||
{
|
||||
nsAutoPtr<VideoData> v(new VideoData(aTime, aKeyframe, aGranulepos));
|
||||
nsAutoPtr<VideoData> v(new VideoData(aOffset, aTime, aKeyframe, aGranulepos));
|
||||
for (PRUint32 i=0; i < 3; ++i) {
|
||||
PRUint32 size = 0;
|
||||
if (!MulOverflow32(PR_ABS(aBuffer[i].height),
|
||||
@ -199,7 +200,8 @@ nsresult nsOggReader::DecodeVorbis(nsTArray<SoundData*>& aChunks,
|
||||
PRInt64 duration = mVorbisState->Time((PRInt64)samples);
|
||||
PRInt64 startTime = (mVorbisGranulepos != -1) ?
|
||||
mVorbisState->Time(mVorbisGranulepos) : -1;
|
||||
SoundData* s = new SoundData(startTime,
|
||||
SoundData* s = new SoundData(mPageOffset,
|
||||
startTime,
|
||||
duration,
|
||||
samples,
|
||||
buffer,
|
||||
@ -357,14 +359,16 @@ nsresult nsOggReader::DecodeTheora(nsTArray<VideoData*>& aFrames,
|
||||
PRInt64 time = (aPacket->granulepos != -1)
|
||||
? mTheoraState->StartTime(aPacket->granulepos) : -1;
|
||||
if (ret == TH_DUPFRAME) {
|
||||
aFrames.AppendElement(VideoData::CreateDuplicate(time,
|
||||
aFrames.AppendElement(VideoData::CreateDuplicate(mPageOffset,
|
||||
time,
|
||||
aPacket->granulepos));
|
||||
} else if (ret == 0) {
|
||||
th_ycbcr_buffer buffer;
|
||||
ret = th_decode_ycbcr_out(mTheoraState->mCtx, buffer);
|
||||
NS_ASSERTION(ret == 0, "th_decode_ycbcr_out failed");
|
||||
PRBool isKeyframe = th_packet_iskeyframe(aPacket) == 1;
|
||||
VideoData *v = VideoData::Create(time,
|
||||
VideoData *v = VideoData::Create(mPageOffset,
|
||||
time,
|
||||
buffer,
|
||||
isKeyframe,
|
||||
aPacket->granulepos);
|
||||
|
@ -61,12 +61,14 @@ using mozilla::TimeStamp;
|
||||
// Holds chunk a decoded sound samples.
|
||||
class SoundData {
|
||||
public:
|
||||
SoundData(PRInt64 aTime,
|
||||
SoundData(PRInt64 aOffset,
|
||||
PRInt64 aTime,
|
||||
PRInt64 aDuration,
|
||||
PRUint32 aSamples,
|
||||
float* aData,
|
||||
PRUint32 aChannels)
|
||||
: mTime(aTime),
|
||||
: mOffset(aOffset),
|
||||
mTime(aTime),
|
||||
mDuration(aDuration),
|
||||
mSamples(aSamples),
|
||||
mChannels(aChannels),
|
||||
@ -75,11 +77,13 @@ public:
|
||||
MOZ_COUNT_CTOR(SoundData);
|
||||
}
|
||||
|
||||
SoundData(PRInt64 aDuration,
|
||||
SoundData(PRInt64 aOffset,
|
||||
PRInt64 aDuration,
|
||||
PRUint32 aSamples,
|
||||
float* aData,
|
||||
PRUint32 aChannels)
|
||||
: mTime(-1),
|
||||
: mOffset(aOffset),
|
||||
mTime(-1),
|
||||
mDuration(aDuration),
|
||||
mSamples(aSamples),
|
||||
mChannels(aChannels),
|
||||
@ -97,6 +101,10 @@ public:
|
||||
return mChannels * mSamples;
|
||||
}
|
||||
|
||||
// Approximate byte offset of the end of the page on which this sample
|
||||
// chunk ends.
|
||||
const PRInt64 mOffset;
|
||||
|
||||
PRInt64 mTime; // Start time of samples in ms.
|
||||
const PRInt64 mDuration; // In ms.
|
||||
const PRUint32 mSamples;
|
||||
@ -111,7 +119,8 @@ public:
|
||||
// Constructs a VideoData object. Makes a copy of YCbCr data in aBuffer.
|
||||
// This may return nsnull if we run out of memory when allocating buffers
|
||||
// to store the frame.
|
||||
static VideoData* Create(PRInt64 aTime,
|
||||
static VideoData* Create(PRInt64 aOffset,
|
||||
PRInt64 aTime,
|
||||
th_ycbcr_buffer aBuffer,
|
||||
PRBool aKeyframe,
|
||||
PRInt64 aGranulepos);
|
||||
@ -119,10 +128,11 @@ public:
|
||||
// Constructs a duplicate VideoData object. This intrinsically tells the
|
||||
// player that it does not need to update the displayed frame when this
|
||||
// frame is played; this frame is identical to the previous.
|
||||
static VideoData* CreateDuplicate(PRInt64 aTime,
|
||||
static VideoData* CreateDuplicate(PRInt64 aOffset,
|
||||
PRInt64 aTime,
|
||||
PRInt64 aGranulepos)
|
||||
{
|
||||
return new VideoData(aTime, aGranulepos);
|
||||
return new VideoData(aOffset, aTime, aGranulepos);
|
||||
}
|
||||
|
||||
~VideoData()
|
||||
@ -133,6 +143,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Approximate byte offset of the end of the frame in the media.
|
||||
PRInt64 mOffset;
|
||||
|
||||
// Start time of frame in milliseconds.
|
||||
PRInt64 mTime;
|
||||
PRInt64 mGranulepos;
|
||||
@ -145,23 +158,26 @@ public:
|
||||
PRPackedBool mKeyframe;
|
||||
|
||||
private:
|
||||
VideoData(PRInt64 aTime, PRInt64 aGranulepos) :
|
||||
mTime(aTime),
|
||||
mGranulepos(aGranulepos),
|
||||
mDuplicate(PR_TRUE),
|
||||
mKeyframe(PR_FALSE)
|
||||
VideoData(PRInt64 aOffset, PRInt64 aTime, PRInt64 aGranulepos)
|
||||
: mOffset(aOffset),
|
||||
mTime(aTime),
|
||||
mGranulepos(aGranulepos),
|
||||
mDuplicate(PR_TRUE),
|
||||
mKeyframe(PR_FALSE)
|
||||
{
|
||||
MOZ_COUNT_CTOR(VideoData);
|
||||
memset(&mBuffer, 0, sizeof(th_ycbcr_buffer));
|
||||
}
|
||||
|
||||
VideoData(PRInt64 aTime,
|
||||
VideoData(PRInt64 aOffset,
|
||||
PRInt64 aTime,
|
||||
PRBool aKeyframe,
|
||||
PRInt64 aGranulepos)
|
||||
: mTime(aTime),
|
||||
mGranulepos(aGranulepos),
|
||||
mDuplicate(PR_FALSE),
|
||||
mKeyframe(aKeyframe)
|
||||
: mOffset(aOffset),
|
||||
mTime(aTime),
|
||||
mGranulepos(aGranulepos),
|
||||
mDuplicate(PR_FALSE),
|
||||
mKeyframe(aKeyframe)
|
||||
{
|
||||
MOZ_COUNT_CTOR(VideoData);
|
||||
}
|
||||
@ -278,8 +294,8 @@ private:
|
||||
// extremities of a range to seek in.
|
||||
class ByteRange {
|
||||
public:
|
||||
ByteRange() :
|
||||
mOffsetStart(0),
|
||||
ByteRange()
|
||||
: mOffsetStart(0),
|
||||
mOffsetEnd(0),
|
||||
mTimeStart(0),
|
||||
mTimeEnd(0)
|
||||
|
Loading…
Reference in New Issue
Block a user