Bug 1091008 - Teach MediaDecoderReader about its start time. r=cpearce

Duplicating state is never great, but this lets the reader make calculations
using this immutable state variable without involving the state machine. We
could alternatively punch a hole from MediaDecoderReader to
MediaDecoderStateMachine and access it there, but that would create tighter
coupling, and weird relationships for MSE.
This commit is contained in:
Bobby Holley 2014-11-11 20:50:20 -08:00
parent 35735b1f12
commit 64ca5577a7
4 changed files with 38 additions and 1 deletions

View File

@ -61,6 +61,7 @@ MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder)
: mAudioCompactor(mAudioQueue)
, mDecoder(aDecoder)
, mIgnoreAudioOutputFormat(false)
, mStartTime(-1)
, mAudioDiscontinuity(false)
, mVideoDiscontinuity(false)
{
@ -120,6 +121,13 @@ VideoData* MediaDecoderReader::DecodeToFirstVideoData()
return (d = VideoQueue().PeekFront()) ? d : nullptr;
}
void
MediaDecoderReader::SetStartTime(int64_t aStartTime)
{
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
mStartTime = aStartTime;
}
nsresult
MediaDecoderReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered,
int64_t aStartTime)

View File

@ -185,6 +185,7 @@ public:
// Indicates if the media is seekable.
// ReadMetada should be called before calling this method.
virtual bool IsMediaSeekable() = 0;
void SetStartTime(int64_t aStartTime);
MediaTaskQueue* GetTaskQueue() {
return mTaskQueue;
@ -245,6 +246,11 @@ protected:
// what we support.
bool mIgnoreAudioOutputFormat;
// The start time of the media, in microseconds. This is the presentation
// time of the first frame decoded from the media. This is initialized to -1,
// and then set to a value >= by MediaDecoderStateMachine::SetStartTime(),
// after which point it never changes.
int64_t mStartTime;
private:
nsRefPtr<RequestSampleCallback> mSampleDecodedCallback;

View File

@ -3034,6 +3034,11 @@ void MediaDecoderStateMachine::SetStartTime(int64_t aStartTimeUsecs)
mEndTime = mStartTime + mEndTime;
}
}
// Pass along this immutable value to the reader so that it can make
// calculations independently of the state machine.
mReader->SetStartTime(mStartTime);
// Set the audio start time to be start of media. If this lies before the
// first actual audio frame we have, we'll inject silence during playback
// to ensure the audio starts at the correct time.
@ -3121,7 +3126,16 @@ void MediaDecoderStateMachine::StartBuffering()
#endif
}
nsresult MediaDecoderStateMachine::GetBuffered(dom::TimeRanges* aBuffered) {
nsresult MediaDecoderStateMachine::GetBuffered(dom::TimeRanges* aBuffered)
{
// It's possible for JS to query .buffered before we've determined the start
// time from metadata, in which case the reader isn't ready to be asked this
// question.
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mStartTime < 0) {
return NS_OK;
}
MediaResource* resource = mDecoder->GetResource();
NS_ENSURE_TRUE(resource, NS_ERROR_FAILURE);
resource->Pin();

View File

@ -353,6 +353,15 @@ MediaSourceReader::CreateSubDecoder(const nsACString& aType)
if (!reader) {
return nullptr;
}
// MSE uses a start time of 0 everywhere. Set that immediately on the
// subreader to make sure that it's always in a state where we can invoke
// GetBuffered on it.
{
ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor());
reader->SetStartTime(0);
}
// Set a callback on the subreader that forwards calls to this reader.
// This reader will then forward them onto the state machine via this
// reader's callback.