Backed out changeset 44f27b3c35d4 (bug 1065827)

This commit is contained in:
Carsten "Tomcat" Book 2014-11-06 14:59:04 +01:00
parent 0f4abd109e
commit 121ca1d0c2
16 changed files with 77 additions and 338 deletions

View File

@ -2903,11 +2903,11 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
// If this element had a video track, but consists only of an audio track now, // If this element had a video track, but consists only of an audio track now,
// delete the VideoFrameContainer. This happens when the src is changed to an // delete the VideoFrameContainer. This happens when the src is changed to an
// audio only file. // audio only file.
// Else update its dimensions. if (!aInfo->HasVideo() && mVideoFrameContainer) {
if (!aInfo->HasVideo()) { // call ForgetElement() such that callbacks from |mVideoFrameContainer|
ResetState(); // won't reach us anymore.
} else { mVideoFrameContainer->ForgetElement();
UpdateMediaSize(aInfo->mVideo.mDisplay); mVideoFrameContainer = nullptr;
} }
} }

View File

@ -90,7 +90,6 @@ public:
virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) = 0; virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) = 0;
virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) = 0; virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) = 0;
virtual void FirstFrameLoaded(MediaInfo* aInfo) = 0;
virtual void RemoveMediaTracks() = 0; virtual void RemoveMediaTracks() = 0;
@ -178,53 +177,6 @@ class MetadataEventRunner : public nsRunnable
MetadataTags* mTags; MetadataTags* mTags;
}; };
class FirstFrameLoadedEventRunner : public nsRunnable
{
private:
nsRefPtr<AbstractMediaDecoder> mDecoder;
public:
FirstFrameLoadedEventRunner(AbstractMediaDecoder* aDecoder, MediaInfo* aInfo)
: mDecoder(aDecoder),
mInfo(aInfo)
{}
NS_IMETHOD Run() MOZ_OVERRIDE
{
mDecoder->FirstFrameLoaded(mInfo);
return NS_OK;
}
// The ownership is transferred to MediaDecoder.
MediaInfo* mInfo;
};
class MetadataUpdatedEventRunner : public nsRunnable
{
private:
nsRefPtr<AbstractMediaDecoder> mDecoder;
public:
MetadataUpdatedEventRunner(AbstractMediaDecoder* aDecoder, MediaInfo* aInfo, MetadataTags* aTags)
: mDecoder(aDecoder),
mInfo(aInfo),
mTags(aTags)
{}
NS_IMETHOD Run() MOZ_OVERRIDE
{
nsAutoPtr<MediaInfo> info(new MediaInfo());
*info = *mInfo;
mDecoder->MetadataLoaded(info.forget(), mTags);
mDecoder->FirstFrameLoaded(mInfo);
return NS_OK;
}
// The ownership is transferred to MediaDecoder.
MediaInfo* mInfo;
// The ownership is transferred to its owning element.
MetadataTags* mTags;
};
class RemoveMediaTracksEventRunner : public nsRunnable class RemoveMediaTracksEventRunner : public nsRunnable
{ {
public: public:

View File

@ -721,24 +721,6 @@ void MediaDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
Invalidate(); Invalidate();
mOwner->MetadataLoaded(aInfo, aTags); mOwner->MetadataLoaded(aInfo, aTags);
} }
}
void MediaDecoder::FirstFrameLoaded(MediaInfo* aInfo)
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown) {
return;
}
DECODER_LOG("FirstFrameLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d",
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
aInfo->HasAudio(), aInfo->HasVideo());
if (mPlayState == PLAY_STATE_LOADING && mIsDormant && !mIsExitingDormant) {
return;
}
mInfo = aInfo;
if (mOwner) { if (mOwner) {
mOwner->FirstFrameLoaded(); mOwner->FirstFrameLoaded();

View File

@ -67,9 +67,7 @@ The state machine has the following states:
DECODING_METADATA DECODING_METADATA
The media headers are being loaded, and things like framerate, etc are The media headers are being loaded, and things like framerate, etc are
being determined. being determined, and the first frame of audio/video data is being decoded.
DECODING_FIRSTFRAME
The first frame of audio/video data is being decoded.
DECODING DECODING
The decode has started. If the PlayState is PLAYING, the decode thread The decode has started. If the PlayState is PLAYING, the decode thread
should be alive and decoding video and audio frame, the audio thread should be alive and decoding video and audio frame, the audio thread
@ -106,36 +104,32 @@ Seek(double)
A state transition diagram: A state transition diagram:
|---<-- DECODING_METADATA ----->--------| DECODING_METADATA
| | | | |
Seek(t) v Shutdown() v | Shutdown()
| | | | |
-->--- DECODING_FIRSTFRAME |------->-----------------| v -->-------------------->--------------------------|
| | | |---------------->----->------------------------| v
| Shutdown() | DECODING | | | | |
| | | ^ v Seek(t) | | | |
v |-->----------------->--------------------------| | Play() | v | | |
|---------------->----->------------------------| v ^-----------<----SEEKING | v Complete v v
DECODING | | | | | | | | | | |
^ v Seek(t) | | | | | | | COMPLETED SHUTDOWN-<-|
| Play() | v | | | ^ ^ | |Shutdown() |
^-----------<----SEEKING | v Complete v v | | | >-------->-----^
| | | | | | | Play() |Seek(t) |Buffer() |
| | | COMPLETED SHUTDOWN-<-| -----------<--------<-------BUFFERING |
^ ^ | |Shutdown() | | ^
| | | >-------->-----^ v Shutdown() |
| Play() |Seek(t) |Buffer() | | |
-----------<--------<-------BUFFERING | ------------>-----|
| ^
v Shutdown() |
| |
------------>-----|
The following represents the states that the MediaDecoder object The following represents the states that the MediaDecoder object
can be in, and the valid states the MediaDecoderStateMachine can be in at that can be in, and the valid states the MediaDecoderStateMachine can be in at that
time: time:
player LOADING decoder DECODING_METADATA, DECODING_FIRSTFRAME player LOADING decoder DECODING_METADATA
player PLAYING decoder DECODING, BUFFERING, SEEKING, COMPLETED player PLAYING decoder DECODING, BUFFERING, SEEKING, COMPLETED
player PAUSED decoder DECODING, BUFFERING, SEEKING, COMPLETED player PAUSED decoder DECODING, BUFFERING, SEEKING, COMPLETED
player SEEKING decoder SEEKING player SEEKING decoder SEEKING
@ -791,10 +785,6 @@ public:
virtual void MetadataLoaded(MediaInfo* aInfo, virtual void MetadataLoaded(MediaInfo* aInfo,
MetadataTags* aTags); MetadataTags* aTags);
// Called when the first audio and/or video from the media file has been loaded
// by the state machine. Call on the main thread only.
virtual void FirstFrameLoaded(MediaInfo* aInfo);
// Called from MetadataLoaded(). Creates audio tracks and adds them to its // Called from MetadataLoaded(). Creates audio tracks and adds them to its
// owner's audio track list, and implies to video tracks respectively. // owner's audio track list, and implies to video tracks respectively.
// Call on the main thread only. // Call on the main thread only.
@ -804,6 +794,10 @@ public:
// the track list. Call on the main thread only. // the track list. Call on the main thread only.
virtual void RemoveMediaTracks() MOZ_OVERRIDE; virtual void RemoveMediaTracks() MOZ_OVERRIDE;
// Called when the first frame has been loaded.
// Call on the main thread only.
void FirstFrameLoaded();
// Returns true if the resource has been loaded. Acquires the monitor. // Returns true if the resource has been loaded. Acquires the monitor.
// Call from any thread. // Call from any thread.
virtual bool IsDataCachedToEndOfResource(); virtual bool IsDataCachedToEndOfResource();

View File

@ -101,10 +101,6 @@ public:
virtual nsresult ReadMetadata(MediaInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) = 0; MetadataTags** aTags) = 0;
// Fills aInfo with the latest cached data required to present the media,
// ReadUpdatedMetadata will always be called once ReadMetadata has succeeded.
virtual void ReadUpdatedMetadata(MediaInfo* aInfo) { };
// Requests the Reader to seek and call OnSeekCompleted on the callback // Requests the Reader to seek and call OnSeekCompleted on the callback
// once completed. // once completed.
// Moves the decode head to aTime microseconds. aStartTime and aEndTime // Moves the decode head to aTime microseconds. aStartTime and aEndTime

View File

@ -371,8 +371,7 @@ void MediaDecoderStateMachine::SendStreamData()
return; return;
} }
if (mState == DECODER_STATE_DECODING_METADATA || if (mState == DECODER_STATE_DECODING_METADATA) {
mState == DECODER_STATE_DECODING_FIRSTFRAME) {
return; return;
} }
@ -706,9 +705,9 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
(audio ? audio->mDiscontinuity : 0)); (audio ? audio->mDiscontinuity : 0));
switch (mState) { switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: { case DECODER_STATE_DECODING_METADATA: {
Push(audio.forget()); Push(audio.forget());
MaybeFinishDecodeFirstFrame(); MaybeFinishDecodeMetadata();
return; return;
} }
@ -771,7 +770,7 @@ MediaDecoderStateMachine::Push(AudioData* aSample)
// otherwise AdvanceFrame may pop the sample before we have a chance // otherwise AdvanceFrame may pop the sample before we have a chance
// to reach playing. // to reach playing.
AudioQueue().Push(aSample); AudioQueue().Push(aSample);
if (mState > DECODER_STATE_DECODING_FIRSTFRAME) { if (mState > DECODER_STATE_DECODING_METADATA) {
SendStreamData(); SendStreamData();
// The ready state can change when we've decoded data, so update the // The ready state can change when we've decoded data, so update the
// ready state, so that DOM events can fire. // ready state, so that DOM events can fire.
@ -789,7 +788,7 @@ MediaDecoderStateMachine::Push(VideoData* aSample)
// otherwise AdvanceFrame may pop the sample before we have a chance // otherwise AdvanceFrame may pop the sample before we have a chance
// to reach playing. // to reach playing.
VideoQueue().Push(aSample); VideoQueue().Push(aSample);
if (mState > DECODER_STATE_DECODING_FIRSTFRAME) { if (mState > DECODER_STATE_DECODING_METADATA) {
SendStreamData(); SendStreamData();
// The ready state can change when we've decoded data, so update the // The ready state can change when we've decoded data, so update the
// ready state, so that DOM events can fire. // ready state, so that DOM events can fire.
@ -840,8 +839,8 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
} }
isAudio ? AudioQueue().Finish() : VideoQueue().Finish(); isAudio ? AudioQueue().Finish() : VideoQueue().Finish();
switch (mState) { switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: { case DECODER_STATE_DECODING_METADATA: {
MaybeFinishDecodeFirstFrame(); MaybeFinishDecodeMetadata();
return; return;
} }
@ -884,14 +883,14 @@ MediaDecoderStateMachine::AcquireMonitorAndInvokeDecodeError()
} }
void void
MediaDecoderStateMachine::MaybeFinishDecodeFirstFrame() MediaDecoderStateMachine::MaybeFinishDecodeMetadata()
{ {
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if ((IsAudioDecoding() && AudioQueue().GetSize() == 0) || if ((IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
(IsVideoDecoding() && VideoQueue().GetSize() == 0)) { (IsVideoDecoding() && VideoQueue().GetSize() == 0)) {
return; return;
} }
if (NS_FAILED(FinishDecodeFirstFrame())) { if (NS_FAILED(FinishDecodeMetadata())) {
DecodeError(); DecodeError();
} }
} }
@ -909,9 +908,9 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
(video ? video->mDiscontinuity : 0)); (video ? video->mDiscontinuity : 0));
switch (mState) { switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: { case DECODER_STATE_DECODING_METADATA: {
Push(video.forget()); Push(video.forget());
MaybeFinishDecodeFirstFrame(); MaybeFinishDecodeMetadata();
return; return;
} }
@ -1222,7 +1221,6 @@ static const char* const gMachineStateStr[] = {
"NONE", "NONE",
"DECODING_METADATA", "DECODING_METADATA",
"WAIT_FOR_RESOURCES", "WAIT_FOR_RESOURCES",
"DECODING_FIRSTFRAME",
"DORMANT", "DORMANT",
"DECODING", "DECODING",
"SEEKING", "SEEKING",
@ -1529,55 +1527,12 @@ void MediaDecoderStateMachine::Seek(const SeekTarget& aTarget)
DECODER_WARN("Seek() function should not be called on a non-seekable state machine"); DECODER_WARN("Seek() function should not be called on a non-seekable state machine");
return; return;
} }
// MediaDecoder::mPlayState should be SEEKING while we seek, and // MediaDecoder::mPlayState should be SEEKING while we seek, and
// in that case MediaDecoder shouldn't be calling us. // in that case MediaDecoder shouldn't be calling us.
NS_ASSERTION(mState != DECODER_STATE_SEEKING, NS_ASSERTION(mState != DECODER_STATE_SEEKING,
"We shouldn't already be seeking"); "We shouldn't already be seeking");
NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA, NS_ASSERTION(mState >= DECODER_STATE_DECODING,
"We should have got duration already"); "We should have loaded metadata");
if (mState <= DECODER_STATE_DECODING_FIRSTFRAME) {
DECODER_LOG("Seek() Not Enough Data to continue at this stage, queuing seek");
mQueuedSeekTarget = aTarget;
return;
}
mQueuedSeekTarget.Reset();
StartSeek(aTarget);
}
void
MediaDecoderStateMachine::EnqueueStartQueuedSeekTask()
{
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::StartQueuedSeek);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}
void
MediaDecoderStateMachine::StartQueuedSeek()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (!mQueuedSeekTarget.IsValid()) {
return;
}
StartSeek(mQueuedSeekTarget);
mQueuedSeekTarget.Reset();
}
void
MediaDecoderStateMachine::StartSeek(const SeekTarget& aTarget)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
AssertCurrentThreadInMonitor();
MOZ_ASSERT(mState >= DECODER_STATE_DECODING);
if (mState == DECODER_STATE_SHUTDOWN) {
return;
}
// Bound the seek time to be inside the media range. // Bound the seek time to be inside the media range.
NS_ASSERTION(mStartTime != -1, "Should know start time by now"); NS_ASSERTION(mStartTime != -1, "Should know start time by now");
@ -1599,8 +1554,8 @@ MediaDecoderStateMachine::StartSeek(const SeekTarget& aTarget)
void MediaDecoderStateMachine::StopAudioThread() void MediaDecoderStateMachine::StopAudioThread()
{ {
NS_ASSERTION(OnDecodeThread() || OnStateMachineThread(), NS_ASSERTION(OnDecodeThread() ||
"Should be on decode thread or state machine thread"); OnStateMachineThread(), "Should be on decode thread or state machine thread");
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
if (mStopAudioThread) { if (mStopAudioThread) {
@ -1643,19 +1598,6 @@ MediaDecoderStateMachine::EnqueueDecodeMetadataTask()
return NS_OK; return NS_OK;
} }
nsresult
MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask()
{
AssertCurrentThreadInMonitor();
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
RefPtr<nsIRunnable> task(
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::CallDecodeFirstFrame));
nsresult rv = mDecodeTaskQueue->Dispatch(task);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
void void
MediaDecoderStateMachine::SetReaderIdle() MediaDecoderStateMachine::SetReaderIdle()
{ {
@ -1791,7 +1733,7 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
return NS_OK; return NS_OK;
} }
MOZ_ASSERT(mState > DECODER_STATE_DECODING_FIRSTFRAME); MOZ_ASSERT(mState > DECODER_STATE_DECODING_METADATA);
if (IsAudioDecoding() && !mAudioRequestPending && !mWaitingForDecoderSeek) { if (IsAudioDecoding() && !mAudioRequestPending && !mWaitingForDecoderSeek) {
RefPtr<nsIRunnable> task( RefPtr<nsIRunnable> task(
@ -1836,7 +1778,7 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
return NS_OK; return NS_OK;
} }
MOZ_ASSERT(mState > DECODER_STATE_DECODING_FIRSTFRAME); MOZ_ASSERT(mState > DECODER_STATE_DECODING_METADATA);
if (IsVideoDecoding() && !mVideoRequestPending && !mWaitingForDecoderSeek) { if (IsVideoDecoding() && !mVideoRequestPending && !mWaitingForDecoderSeek) {
RefPtr<nsIRunnable> task( RefPtr<nsIRunnable> task(
@ -1914,8 +1856,8 @@ bool MediaDecoderStateMachine::HasLowUndecodedData()
bool MediaDecoderStateMachine::HasLowUndecodedData(double aUsecs) bool MediaDecoderStateMachine::HasLowUndecodedData(double aUsecs)
{ {
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
NS_ASSERTION(mState > DECODER_STATE_DECODING_FIRSTFRAME, NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA,
"Must have loaded first frame for GetBuffered() to work"); "Must have loaded metadata for GetBuffered() to work");
bool reliable; bool reliable;
double bytesPerSecond = mDecoder->ComputePlaybackRate(&reliable); double bytesPerSecond = mDecoder->ComputePlaybackRate(&reliable);
@ -2025,55 +1967,6 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
mDecoder->StartProgressUpdates(); mDecoder->StartProgressUpdates();
mGotDurationFromMetaData = (GetDuration() != -1); mGotDurationFromMetaData = (GetDuration() != -1);
if (mGotDurationFromMetaData) {
// We have all the information required: duration and size
// Inform the element that we've loaded the metadata.
EnqueueLoadedMetadataEvent();
}
if (mState == DECODER_STATE_DECODING_METADATA) {
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
res = EnqueueDecodeFirstFrameTask();
if (NS_FAILED(res)) {
return NS_ERROR_FAILURE;
}
}
ScheduleStateMachine();
return NS_OK;
}
void
MediaDecoderStateMachine::EnqueueLoadedMetadataEvent()
{
nsAutoPtr<MediaInfo> info(new MediaInfo());
*info = mInfo;
nsCOMPtr<nsIRunnable> metadataLoadedEvent =
new MetadataEventRunner(mDecoder, info.forget(), mMetadataTags.forget());
NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL);
}
void
MediaDecoderStateMachine::CallDecodeFirstFrame()
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mState != DECODER_STATE_DECODING_FIRSTFRAME) {
return;
}
if (NS_FAILED(DecodeFirstFrame())) {
DECODER_WARN("Decode failed to start, shutting down decoder");
DecodeError();
}
}
nsresult
MediaDecoderStateMachine::DecodeFirstFrame()
{
AssertCurrentThreadInMonitor();
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
DECODER_LOG("DecodeFirstFrame started");
if (HasAudio()) { if (HasAudio()) {
RefPtr<nsIRunnable> decodeTask( RefPtr<nsIRunnable> decodeTask(
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DispatchAudioDecodeTaskIfNeeded)); NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DispatchAudioDecodeTaskIfNeeded));
@ -2087,11 +1980,11 @@ MediaDecoderStateMachine::DecodeFirstFrame()
if (mScheduler->IsRealTime()) { if (mScheduler->IsRealTime()) {
SetStartTime(0); SetStartTime(0);
nsresult res = FinishDecodeFirstFrame(); res = FinishDecodeMetadata();
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} else if (mDecodingFrozenAtStateMetadata) { } else if (mDecodingFrozenAtStateMetadata) {
SetStartTime(mStartTime); SetStartTime(mStartTime);
nsresult res = FinishDecodeFirstFrame(); res = FinishDecodeMetadata();
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} else { } else {
if (HasAudio()) { if (HasAudio()) {
@ -2108,11 +2001,11 @@ MediaDecoderStateMachine::DecodeFirstFrame()
} }
nsresult nsresult
MediaDecoderStateMachine::FinishDecodeFirstFrame() MediaDecoderStateMachine::FinishDecodeMetadata()
{ {
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread."); NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
DECODER_LOG("FinishDecodeFirstFrame"); DECODER_LOG("FinishDecodeMetadata");
if (mState == DECODER_STATE_SHUTDOWN) { if (mState == DECODER_STATE_SHUTDOWN) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -2151,34 +2044,19 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
mLowAudioThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR; mLowAudioThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
} }
// Get potentially updated metadata // Inform the element that we've loaded the metadata and the first frame.
{
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
mReader->ReadUpdatedMetadata(&mInfo);
}
nsAutoPtr<MediaInfo> info(new MediaInfo()); nsAutoPtr<MediaInfo> info(new MediaInfo());
*info = mInfo; *info = mInfo;
nsCOMPtr<nsIRunnable> event; nsCOMPtr<nsIRunnable> metadataLoadedEvent =
if (!mGotDurationFromMetaData) { new MetadataEventRunner(mDecoder, info.forget(), mMetadataTags.forget());
// We now have a duration, we can fire the LoadedMetadata and NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL);
// FirstFrame event.
event =
new MetadataUpdatedEventRunner(mDecoder,
info.forget(),
mMetadataTags.forget());
} else {
// Inform the element that we've loaded the first frame.
event =
new FirstFrameLoadedEventRunner(mDecoder, info.forget());
}
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
if (mState == DECODER_STATE_DECODING_FIRSTFRAME) { if (mState == DECODER_STATE_DECODING_METADATA) {
DECODER_LOG("Changed state from DECODING_METADATA to DECODING");
StartDecoding(); StartDecoding();
} }
// For very short media the first frame decode can decode the entire media. // For very short media the metadata decode can decode the entire media.
// So we need to check if this has occurred, else our decode pipeline won't // So we need to check if this has occurred, else our decode pipeline won't
// run (since it doesn't need to) and we won't detect end of stream. // run (since it doesn't need to) and we won't detect end of stream.
CheckIfDecodeComplete(); CheckIfDecodeComplete();
@ -2190,10 +2068,6 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
StartPlayback(); StartPlayback();
} }
if (mQueuedSeekTarget.IsValid()) {
EnqueueStartQueuedSeekTask();
}
return NS_OK; return NS_OK;
} }
@ -2340,7 +2214,6 @@ MediaDecoderStateMachine::SeekCompleted()
mDecoder->StartProgressUpdates(); mDecoder->StartProgressUpdates();
if (mState == DECODER_STATE_DECODING_METADATA || if (mState == DECODER_STATE_DECODING_METADATA ||
mState == DECODER_STATE_DECODING_FIRSTFRAME ||
mState == DECODER_STATE_DORMANT || mState == DECODER_STATE_DORMANT ||
mState == DECODER_STATE_SHUTDOWN) { mState == DECODER_STATE_SHUTDOWN) {
return; return;
@ -2526,11 +2399,6 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
return NS_OK; return NS_OK;
} }
case DECODER_STATE_DECODING_FIRSTFRAME: {
// DECODER_STATE_DECODING_FIRSTFRAME will be started by DecodeMetadata
return NS_OK;
}
case DECODER_STATE_DECODING: { case DECODER_STATE_DECODING: {
if (mDecoder->GetState() != MediaDecoder::PLAY_STATE_PLAYING && if (mDecoder->GetState() != MediaDecoder::PLAY_STATE_PLAYING &&
IsPlaying()) IsPlaying())

View File

@ -138,7 +138,6 @@ public:
DECODER_STATE_DECODING_NONE, DECODER_STATE_DECODING_NONE,
DECODER_STATE_DECODING_METADATA, DECODER_STATE_DECODING_METADATA,
DECODER_STATE_WAIT_FOR_RESOURCES, DECODER_STATE_WAIT_FOR_RESOURCES,
DECODER_STATE_DECODING_FIRSTFRAME,
DECODER_STATE_DORMANT, DECODER_STATE_DORMANT,
DECODER_STATE_DECODING, DECODER_STATE_DECODING,
DECODER_STATE_SEEKING, DECODER_STATE_SEEKING,
@ -199,22 +198,8 @@ public:
void Play(); void Play();
// Seeks to the decoder to aTarget asynchronously. // Seeks to the decoder to aTarget asynchronously.
// Must be called from the main thread.
void Seek(const SeekTarget& aTarget); void Seek(const SeekTarget& aTarget);
// Dispatches a task to the main thread to seek to mQueuedSeekTarget.
// This is threadsafe and can be called on any thread.
void EnqueueStartQueuedSeekTask();
// Seeks to the decoder to mQueuedSeekTarget asynchronously.
// Must be called from the main thread.
void StartQueuedSeek();
// Seeks to the decoder to aTarget asynchronously.
// Must be called from the main thread.
// The decoder monitor must be held with exactly one lock count.
void StartSeek(const SeekTarget& aTarget);
// Returns the current playback position in seconds. // Returns the current playback position in seconds.
// Called from the main thread to get the current frame time. The decoder // Called from the main thread to get the current frame time. The decoder
// monitor must be obtained before calling this. // monitor must be obtained before calling this.
@ -412,7 +397,7 @@ protected:
MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; } MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; } MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
nsresult FinishDecodeFirstFrame(); nsresult FinishDecodeMetadata();
RefPtr<MediaDataDecodedListener<MediaDecoderStateMachine>> mMediaDecodedListener; RefPtr<MediaDataDecodedListener<MediaDecoderStateMachine>> mMediaDecodedListener;
@ -541,16 +526,6 @@ protected:
// The decoder monitor must be held. // The decoder monitor must be held.
nsresult EnqueueDecodeMetadataTask(); nsresult EnqueueDecodeMetadataTask();
// Dispatches a LoadedMetadataEvent.
// This is threadsafe and can be called on any thread.
// The decoder monitor must be held.
void EnqueueLoadedMetadataEvent();
// Dispatches a task to the decode task queue to begin decoding content.
// This is threadsafe and can be called on any thread.
// The decoder monitor must be held.
nsresult EnqueueDecodeFirstFrameTask();
// Dispatches a task to the decode task queue to seek the decoder. // Dispatches a task to the decode task queue to seek the decoder.
// The decoder monitor must be held. // The decoder monitor must be held.
nsresult EnqueueDecodeSeekTask(); nsresult EnqueueDecodeSeekTask();
@ -608,16 +583,9 @@ protected:
// Wraps the call to DecodeMetadata(), signals a DecodeError() on failure. // Wraps the call to DecodeMetadata(), signals a DecodeError() on failure.
void CallDecodeMetadata(); void CallDecodeMetadata();
// Initiate first content decoding. Called on the decode thread. // Checks whether we're finished decoding metadata, and switches to DECODING
// The decoder monitor must be held with exactly one lock count. // state if so.
nsresult DecodeFirstFrame(); void MaybeFinishDecodeMetadata();
// Wraps the call to DecodeFirstFrame(), signals a DecodeError() on failure.
void CallDecodeFirstFrame();
// Checks whether we're finished decoding first audio and/or video packets,
// and switches to DECODING state if so.
void MaybeFinishDecodeFirstFrame();
// Seeks to mSeekTarget. Called on the decode thread. The decoder monitor // Seeks to mSeekTarget. Called on the decode thread. The decoder monitor
// must be held with exactly one lock count. // must be held with exactly one lock count.
@ -759,11 +727,6 @@ protected:
// this value. Accessed on main and decode thread. // this value. Accessed on main and decode thread.
SeekTarget mSeekTarget; SeekTarget mSeekTarget;
// Position to seek to in microseconds when DecodeFirstFrame completes.
// The decoder monitor lock must be obtained before reading or writing
// this value. Accessed on main and decode thread.
SeekTarget mQueuedSeekTarget;
// The position that we're currently seeking to. This differs from // The position that we're currently seeking to. This differs from
// mSeekTarget, as mSeekTarget is the target we'll seek to next, whereas // mSeekTarget, as mSeekTarget is the target we'll seek to next, whereas
// mCurrentSeekTarget is the position that the decode is in the process // mCurrentSeekTarget is the position that the decode is in the process

View File

@ -52,9 +52,9 @@ namespace mozilla {
NS_DispatchToMainThread(removeTracksEvent); NS_DispatchToMainThread(removeTracksEvent);
nsCOMPtr<nsIRunnable> metadataUpdatedEvent = nsCOMPtr<nsIRunnable> metadataUpdatedEvent =
new MetadataUpdatedEventRunner(aDecoder, new MetadataEventRunner(aDecoder,
metadata->mInfo.forget(), metadata->mInfo.forget(),
metadata->mTags.forget()); metadata->mTags.forget());
NS_DispatchToMainThread(metadataUpdatedEvent); NS_DispatchToMainThread(metadataUpdatedEvent);
delete mMetadataQueue.popFirst(); delete mMetadataQueue.popFirst();
metadata = mMetadataQueue.getFirst(); metadata = mMetadataQueue.getFirst();

View File

@ -395,6 +395,10 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
NS_ENSURE_TRUE(mAudio.mDecoder != nullptr, NS_ERROR_FAILURE); NS_ENSURE_TRUE(mAudio.mDecoder != nullptr, NS_ERROR_FAILURE);
nsresult rv = mAudio.mDecoder->Init(); nsresult rv = mAudio.mDecoder->Init();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Decode one audio frame to detect potentially incorrect channels count or
// sampling rate from demuxer.
Decode(kAudio);
} }
if (HasVideo()) { if (HasVideo()) {
@ -427,12 +431,6 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
return NS_OK; return NS_OK;
} }
void
MP4Reader::ReadUpdatedMetadata(MediaInfo* aInfo)
{
*aInfo = mInfo;
}
bool bool
MP4Reader::IsMediaSeekable() MP4Reader::IsMediaSeekable()
{ {

View File

@ -45,8 +45,6 @@ public:
virtual nsresult ReadMetadata(MediaInfo* aInfo, virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MOZ_OVERRIDE; MetadataTags** aTags) MOZ_OVERRIDE;
virtual void ReadUpdatedMetadata(MediaInfo* aInfo) MOZ_OVERRIDE;
virtual void Seek(int64_t aTime, virtual void Seek(int64_t aTime,
int64_t aStartTime, int64_t aStartTime,
int64_t aEndTime, int64_t aEndTime,

View File

@ -95,12 +95,6 @@ SourceBufferDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
MSE_DEBUG("SourceBufferDecoder(%p)::MetadataLoaded UNIMPLEMENTED", this); MSE_DEBUG("SourceBufferDecoder(%p)::MetadataLoaded UNIMPLEMENTED", this);
} }
void
SourceBufferDecoder::FirstFrameLoaded(MediaInfo* aInfo)
{
MSE_DEBUG("SourceBufferDecoder(%p)::FirstFrameLoaded UNIMPLEMENTED", this);
}
void void
SourceBufferDecoder::QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) SourceBufferDecoder::QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags)
{ {

View File

@ -48,7 +48,6 @@ public:
virtual ReentrantMonitor& GetReentrantMonitor() MOZ_FINAL MOZ_OVERRIDE; virtual ReentrantMonitor& GetReentrantMonitor() MOZ_FINAL MOZ_OVERRIDE;
virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE; virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE; virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
virtual void FirstFrameLoaded(MediaInfo* aInfo) MOZ_FINAL MOZ_OVERRIDE;
virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE; virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE; virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE; virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE;

View File

@ -57,10 +57,11 @@ MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio()
} }
void void
MediaOmxCommonDecoder::FirstFrameLoaded(MediaInfo* aInfo) MediaOmxCommonDecoder::MetadataLoaded(MediaInfo* aInfo,
MetadataTags* aTags)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MediaDecoder::FirstFrameLoaded(aInfo); MediaDecoder::MetadataLoaded(aInfo, aTags);
ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
if (!CheckDecoderCanOffloadAudio()) { if (!CheckDecoderCanOffloadAudio()) {

View File

@ -23,7 +23,8 @@ class MediaOmxCommonDecoder : public MediaDecoder
public: public:
MediaOmxCommonDecoder(); MediaOmxCommonDecoder();
virtual void FirstFrameLoaded(MediaInfo* aInfo); virtual void MetadataLoaded(MediaInfo* aInfo,
MetadataTags* aTags);
virtual void ChangeState(PlayState aState); virtual void ChangeState(PlayState aState);
virtual void ApplyStateToStateMachine(PlayState aState); virtual void ApplyStateToStateMachine(PlayState aState);
virtual void SetVolume(double aVolume); virtual void SetVolume(double aVolume);

View File

@ -145,12 +145,6 @@ BufferDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
// ignore // ignore
} }
void
BufferDecoder::FirstFrameLoaded(MediaInfo* aInfo)
{
// ignore
}
void void
BufferDecoder::QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) BufferDecoder::QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags)
{ {

View File

@ -60,7 +60,6 @@ public:
virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE; virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE; virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
virtual void FirstFrameLoaded(MediaInfo* aInfo) MOZ_FINAL MOZ_OVERRIDE;
virtual void RemoveMediaTracks() MOZ_FINAL MOZ_OVERRIDE; virtual void RemoveMediaTracks() MOZ_FINAL MOZ_OVERRIDE;