diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index 1d745c5eee5..ee8b3400051 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -185,8 +185,10 @@ public: gfxASurface* GetPrintSurface() { return mPrintSurface; } // Dispatch events - nsresult DispatchEvent(const nsAString& aName); - nsresult DispatchAsyncEvent(const nsAString& aName); + nsresult DispatchSimpleEvent(const nsAString& aName); + nsresult DispatchProgressEvent(const nsAString& aName); + nsresult DispatchAsyncSimpleEvent(const nsAString& aName); + nsresult DispatchAsyncProgressEvent(const nsAString& aName); nsresult DispatchAudioAvailableEvent(float* aFrameBuffer, PRUint32 aFrameBufferLength, PRUint64 aTime); diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 4cf3ad3b34d..b76a791f136 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -70,6 +70,7 @@ #include "nsEventDispatcher.h" #include "nsIDOMDocumentEvent.h" +#include "nsIDOMProgressEvent.h" #include "nsMediaError.h" #include "nsICategoryManager.h" #include "nsCharSeparatedTokenizer.h" @@ -191,10 +192,11 @@ class nsAsyncEventRunner : public nsMediaEvent { private: nsString mName; + PRPackedBool mProgress; public: - nsAsyncEventRunner(const nsAString& aName, nsHTMLMediaElement* aElement) : - nsMediaEvent(aElement), mName(aName) + nsAsyncEventRunner(const nsAString& aName, nsHTMLMediaElement* aElement, PRBool aProgress) : + nsMediaEvent(aElement), mName(aName), mProgress(aProgress) { } @@ -204,7 +206,9 @@ public: if (IsCancelled()) return NS_OK; - return mElement->DispatchEvent(mName); + return mProgress ? + mElement->DispatchProgressEvent(mName) : + mElement->DispatchSimpleEvent(mName); } }; @@ -486,7 +490,7 @@ void nsHTMLMediaElement::AbortExistingLoads() if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING || mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE) { - DispatchEvent(NS_LITERAL_STRING("abort")); + DispatchProgressEvent(NS_LITERAL_STRING("abort")); } mError = nsnull; @@ -509,9 +513,9 @@ void nsHTMLMediaElement::AbortExistingLoads() // will now be reported as 0. The playback position was non-zero when // we destroyed the decoder, so fire a timeupdate event so that the // change will be reflected in the controls. - DispatchAsyncEvent(NS_LITERAL_STRING("timeupdate")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("timeupdate")); } - DispatchEvent(NS_LITERAL_STRING("emptied")); + DispatchSimpleEvent(NS_LITERAL_STRING("emptied")); } // We may have changed mPaused, mAutoplaying, mNetworkState and other @@ -527,7 +531,7 @@ void nsHTMLMediaElement::NoSupportedMediaSourceError() mError = new nsMediaError(nsIDOMMediaError::MEDIA_ERR_SRC_NOT_SUPPORTED); mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE; - DispatchAsyncEvent(NS_LITERAL_STRING("error")); + DispatchAsyncProgressEvent(NS_LITERAL_STRING("error")); // This clears mDelayingLoadEvent, so AddRemoveSelfReference will be called ChangeDelayLoadStatus(PR_FALSE); } @@ -645,7 +649,7 @@ void nsHTMLMediaElement::SelectResource() mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING; // Load event was delayed, and still is, so no need to call // AddRemoveSelfReference, since it must still be held - DispatchAsyncEvent(NS_LITERAL_STRING("loadstart")); + DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart")); nsAutoString src; nsCOMPtr uri; @@ -797,7 +801,7 @@ void nsHTMLMediaElement::SuspendLoad(nsIURI* aURI) { mLoadIsSuspended = PR_TRUE; mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE; - DispatchAsyncEvent(NS_LITERAL_STRING("suspend")); + DispatchAsyncProgressEvent(NS_LITERAL_STRING("suspend")); ChangeDelayLoadStatus(PR_FALSE); } @@ -1033,7 +1037,7 @@ nsresult nsHTMLMediaElement::LoadWithChannel(nsIChannel *aChannel, return rv; } - DispatchAsyncEvent(NS_LITERAL_STRING("loadstart")); + DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart")); return NS_OK; } @@ -1057,7 +1061,7 @@ NS_IMETHODIMP nsHTMLMediaElement::MozLoadFrom(nsIDOMHTMLMediaElement* aOther) return rv; } - DispatchAsyncEvent(NS_LITERAL_STRING("loadstart")); + DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart")); return NS_OK; } @@ -1157,8 +1161,8 @@ NS_IMETHODIMP nsHTMLMediaElement::Pause() AddRemoveSelfReference(); if (!oldPaused) { - DispatchAsyncEvent(NS_LITERAL_STRING("timeupdate")); - DispatchAsyncEvent(NS_LITERAL_STRING("pause")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("timeupdate")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("pause")); } return NS_OK; @@ -1188,7 +1192,7 @@ NS_IMETHODIMP nsHTMLMediaElement::SetVolume(float aVolume) mAudioStream->SetVolume(mVolume); } - DispatchAsyncEvent(NS_LITERAL_STRING("volumechange")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("volumechange")); return NS_OK; } @@ -1258,7 +1262,7 @@ NS_IMETHODIMP nsHTMLMediaElement::SetMuted(PRBool aMuted) mAudioStream->SetVolume(mMuted ? 0.0 : mVolume); } - DispatchAsyncEvent(NS_LITERAL_STRING("volumechange")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("volumechange")); return NS_OK; } @@ -1381,15 +1385,15 @@ NS_IMETHODIMP nsHTMLMediaElement::Play() // seek to the effective start. // TODO: The playback rate must be set to the default playback rate. if (mPaused) { - DispatchAsyncEvent(NS_LITERAL_STRING("play")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("play")); switch (mReadyState) { case nsIDOMHTMLMediaElement::HAVE_METADATA: case nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA: - DispatchAsyncEvent(NS_LITERAL_STRING("waiting")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("waiting")); break; case nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA: case nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA: - DispatchAsyncEvent(NS_LITERAL_STRING("playing")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("playing")); break; } } @@ -1945,8 +1949,8 @@ void nsHTMLMediaElement::MetadataLoaded(PRUint32 aChannels, PRUint32 aRate) mChannels = aChannels; mRate = aRate; ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA); - DispatchAsyncEvent(NS_LITERAL_STRING("durationchange")); - DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("durationchange")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("loadedmetadata")); } void nsHTMLMediaElement::FirstFrameLoaded(PRBool aResourceFullyLoaded) @@ -1972,9 +1976,9 @@ void nsHTMLMediaElement::ResourceLoaded() AddRemoveSelfReference(); ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA); // Ensure a progress event is dispatched at the end of download. - DispatchAsyncEvent(NS_LITERAL_STRING("progress")); + DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress")); // The download has stopped. - DispatchAsyncEvent(NS_LITERAL_STRING("suspend")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("suspend")); } void nsHTMLMediaElement::NetworkError() @@ -2000,10 +2004,10 @@ void nsHTMLMediaElement::Error(PRUint16 aErrorCode) "Only use nsIDOMMediaError codes!"); mError = new nsMediaError(aErrorCode); mBegun = PR_FALSE; - DispatchAsyncEvent(NS_LITERAL_STRING("error")); + DispatchAsyncProgressEvent(NS_LITERAL_STRING("error")); if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) { mNetworkState = nsIDOMHTMLMediaElement::NETWORK_EMPTY; - DispatchAsyncEvent(NS_LITERAL_STRING("emptied")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("emptied")); } else { mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE; } @@ -2017,20 +2021,20 @@ void nsHTMLMediaElement::PlaybackEnded() // We changed the state of IsPlaybackEnded which can affect AddRemoveSelfReference AddRemoveSelfReference(); - DispatchAsyncEvent(NS_LITERAL_STRING("ended")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("ended")); } void nsHTMLMediaElement::SeekStarted() { - DispatchAsyncEvent(NS_LITERAL_STRING("seeking")); - DispatchAsyncEvent(NS_LITERAL_STRING("timeupdate")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("seeking")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("timeupdate")); } void nsHTMLMediaElement::SeekCompleted() { mPlayingBeforeSeek = PR_FALSE; SetPlayedOrSeeked(PR_TRUE); - DispatchAsyncEvent(NS_LITERAL_STRING("seeked")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("seeked")); // We changed whether we're seeking so we need to AddRemoveSelfReference AddRemoveSelfReference(); } @@ -2040,7 +2044,7 @@ void nsHTMLMediaElement::DownloadSuspended() if (mBegun) { mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE; AddRemoveSelfReference(); - DispatchAsyncEvent(NS_LITERAL_STRING("suspend")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("suspend")); } } @@ -2055,7 +2059,7 @@ void nsHTMLMediaElement::DownloadResumed() void nsHTMLMediaElement::DownloadStalled() { if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING) { - DispatchAsyncEvent(NS_LITERAL_STRING("stalled")); + DispatchAsyncProgressEvent(NS_LITERAL_STRING("stalled")); } } @@ -2078,7 +2082,7 @@ void nsHTMLMediaElement::UpdateReadyStateForData(NextFrameStatus aNextFrame) if (aNextFrame != NEXT_FRAME_AVAILABLE) { ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA); if (!mWaitingFired && aNextFrame == NEXT_FRAME_UNAVAILABLE_BUFFERING) { - DispatchAsyncEvent(NS_LITERAL_STRING("waiting")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("waiting")); mWaitingFired = PR_TRUE; } return; @@ -2128,14 +2132,14 @@ void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState) // Handle raising of "waiting" event during seek (see 4.8.10.9) if (mPlayingBeforeSeek && oldState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA) { - DispatchAsyncEvent(NS_LITERAL_STRING("waiting")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("waiting")); } if (oldState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA && mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA && !mLoadedFirstFrame) { - DispatchAsyncEvent(NS_LITERAL_STRING("loadeddata")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("loadeddata")); mLoadedFirstFrame = PR_TRUE; } @@ -2145,7 +2149,7 @@ void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState) if (oldState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA && mReadyState >= nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA) { - DispatchAsyncEvent(NS_LITERAL_STRING("canplay")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("canplay")); } if (mReadyState == nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) { @@ -2155,12 +2159,12 @@ void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState) if (oldState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA && mReadyState >= nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA && IsPotentiallyPlaying()) { - DispatchAsyncEvent(NS_LITERAL_STRING("playing")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("playing")); } if (oldState < nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) { - DispatchAsyncEvent(NS_LITERAL_STRING("canplaythrough")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("canplaythrough")); } } @@ -2183,7 +2187,7 @@ void nsHTMLMediaElement::NotifyAutoplayDataReady() SetPlayedOrSeeked(PR_TRUE); mDecoder->Play(); } - DispatchAsyncEvent(NS_LITERAL_STRING("play")); + DispatchAsyncSimpleEvent(NS_LITERAL_STRING("play")); } } @@ -2240,9 +2244,9 @@ nsresult nsHTMLMediaElement::DispatchAudioAvailableEvent(float* aFrameBuffer, return target->DispatchEvent(event, &dummy); } -nsresult nsHTMLMediaElement::DispatchEvent(const nsAString& aName) +nsresult nsHTMLMediaElement::DispatchSimpleEvent(const nsAString& aName) { - LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching event %s", this, + LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching simple event %s", this, NS_ConvertUTF16toUTF8(aName).get())); return nsContentUtils::DispatchTrustedEvent(GetOwnerDoc(), @@ -2252,16 +2256,55 @@ nsresult nsHTMLMediaElement::DispatchEvent(const nsAString& aName) PR_TRUE); } -nsresult nsHTMLMediaElement::DispatchAsyncEvent(const nsAString& aName) +nsresult nsHTMLMediaElement::DispatchAsyncSimpleEvent(const nsAString& aName) { - LOG_EVENT(PR_LOG_DEBUG, ("%p Queuing event %s", this, - NS_ConvertUTF16toUTF8(aName).get())); + LOG_EVENT(PR_LOG_DEBUG, ("%p Queuing simple event %s", this, NS_ConvertUTF16toUTF8(aName).get())); - nsCOMPtr event = new nsAsyncEventRunner(aName, this); + nsCOMPtr event = new nsAsyncEventRunner(aName, this, PR_FALSE); NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); return NS_OK; } +nsresult nsHTMLMediaElement::DispatchAsyncProgressEvent(const nsAString& aName) +{ + LOG_EVENT(PR_LOG_DEBUG, ("%p Queuing progress event %s", this, NS_ConvertUTF16toUTF8(aName).get())); + + nsCOMPtr event = new nsAsyncEventRunner(aName, this, PR_TRUE); + NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); + return NS_OK; +} + +nsresult nsHTMLMediaElement::DispatchProgressEvent(const nsAString& aName) +{ + nsCOMPtr docEvent(do_QueryInterface(GetOwnerDoc())); + nsCOMPtr target(do_QueryInterface(static_cast(this))); + NS_ENSURE_TRUE(docEvent && target, NS_ERROR_INVALID_ARG); + + nsCOMPtr event; + nsresult rv = docEvent->CreateEvent(NS_LITERAL_STRING("ProgressEvent"), getter_AddRefs(event)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr progressEvent(do_QueryInterface(event)); + NS_ENSURE_TRUE(progressEvent, NS_ERROR_FAILURE); + + PRInt64 totalBytes = 0; + PRUint64 downloadPosition = 0; + if (mDecoder) { + nsMediaDecoder::Statistics stats = mDecoder->GetStatistics(); + totalBytes = stats.mTotalBytes; + downloadPosition = stats.mDownloadPosition; + } + rv = progressEvent->InitProgressEvent(aName, PR_TRUE, PR_TRUE, + totalBytes >= 0, downloadPosition, totalBytes); + NS_ENSURE_SUCCESS(rv, rv); + + LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching progress event %s", this, + NS_ConvertUTF16toUTF8(aName).get())); + + PRBool dummy; + return target->DispatchEvent(event, &dummy); +} + PRBool nsHTMLMediaElement::IsPotentiallyPlaying() const { // TODO: @@ -2531,9 +2574,7 @@ nsresult nsHTMLMediaElement::GetBuffered(nsIDOMTimeRanges** aBuffered) nsTimeRanges* ranges = new nsTimeRanges(); NS_ADDREF(*aBuffered = ranges); if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA && mDecoder) { - // If GetBuffered fails we ignore the error result and just return the - // time ranges we found up till the error. - mDecoder->GetBuffered(ranges); + return mDecoder->GetBuffered(ranges); } return NS_OK; } diff --git a/content/media/nsBuiltinDecoder.cpp b/content/media/nsBuiltinDecoder.cpp index bdef0ea9027..2baa2870267 100644 --- a/content/media/nsBuiltinDecoder.cpp +++ b/content/media/nsBuiltinDecoder.cpp @@ -359,7 +359,7 @@ void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels, else if (mElement) { // Resource was loaded during metadata loading, when progress // events are being ignored. Fire the final progress event. - mElement->DispatchAsyncEvent(NS_LITERAL_STRING("progress")); + mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress")); } // Only inform the element of FirstFrameLoaded if not doing a load() in order @@ -773,7 +773,7 @@ void nsBuiltinDecoder::PlaybackPositionChanged() Invalidate(); if (mElement && lastTime != mCurrentTime) { - mElement->DispatchEvent(NS_LITERAL_STRING("timeupdate")); + mElement->DispatchSimpleEvent(NS_LITERAL_STRING("timeupdate")); } } @@ -788,7 +788,7 @@ void nsBuiltinDecoder::DurationChanged() if (mElement && oldDuration != mDuration) { LOG(PR_LOG_DEBUG, ("%p duration changed to %lldms", this, mDuration)); - mElement->DispatchEvent(NS_LITERAL_STRING("durationchange")); + mElement->DispatchSimpleEvent(NS_LITERAL_STRING("durationchange")); } } diff --git a/content/media/nsMediaDecoder.cpp b/content/media/nsMediaDecoder.cpp index 9925fb5efa4..64bbeff52a3 100644 --- a/content/media/nsMediaDecoder.cpp +++ b/content/media/nsMediaDecoder.cpp @@ -200,7 +200,7 @@ void nsMediaDecoder::Progress(PRBool aTimer) now - mProgressTime >= TimeDuration::FromMilliseconds(PROGRESS_MS)) && !mDataTime.IsNull() && now - mDataTime <= TimeDuration::FromMilliseconds(PROGRESS_MS)) { - mElement->DispatchAsyncEvent(NS_LITERAL_STRING("progress")); + mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("progress")); mProgressTime = now; } diff --git a/content/media/ogg/nsOggReader.cpp b/content/media/ogg/nsOggReader.cpp index a3c5aeb6015..4daadeb7478 100644 --- a/content/media/ogg/nsOggReader.cpp +++ b/content/media/ogg/nsOggReader.cpp @@ -284,10 +284,14 @@ nsresult nsOggReader::ReadMetadata() // Theora spec these can be considered the 'primary' bitstreams for playback. // Extract the metadata needed from these streams. // Set a default callback period for if we have no video data - if (mTheoraState && mTheoraState->Init()) { - gfxIntSize sz(mTheoraState->mInfo.pic_width, - mTheoraState->mInfo.pic_height); - mDecoder->SetVideoData(sz, mTheoraState->mPixelAspectRatio, nsnull); + if (mTheoraState) { + if (mTheoraState->Init()) { + gfxIntSize sz(mTheoraState->mInfo.pic_width, + mTheoraState->mInfo.pic_height); + mDecoder->SetVideoData(sz, mTheoraState->mPixelAspectRatio, nsnull); + } else { + mTheoraState = nsnull; + } } if (mVorbisState) { mVorbisState->Init(); @@ -906,7 +910,7 @@ PRInt64 nsOggReader::FindEndTime(PRInt64 aEndOffset, // We need more data if we've not encountered a page we've seen before, // or we've read to the end of file. if (mustBackOff || readHead == aEndOffset) { - if (endTime != -1 || readStartOffset == 0) { + if (endTime != -1) { // We have encountered a page before, or we're at the end of file. break; } @@ -1538,16 +1542,6 @@ nsresult nsOggReader::SeekBisection(PRInt64 aTarget, nsresult nsOggReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime) { NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); - - // HasAudio and HasVideo are not used here as they take a lock and cause - // a deadlock. Accessing mInfo doesn't require a lock - it doesn't change - // after metadata is read and GetBuffered isn't called before metadata is - // read. - if (!mInfo.mHasVideo && !mInfo.mHasAudio) { - // No need to search through the file if there are no audio or video tracks - return NS_OK; - } - nsMediaStream* stream = mDecoder->GetCurrentStream(); // Traverse across the buffered byte ranges, determining the time ranges @@ -1610,16 +1604,6 @@ nsresult nsOggReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime) startTime = codecState->Time(granulepos) - aStartTime; NS_ASSERTION(startTime > 0, "Must have positive start time"); } - else if(codecState) { - // Page is for an inactive stream, skip it. - startOffset += page.header_len + page.body_len; - continue; - } - else { - // Page is for a stream we don't know about (possibly a chained - // ogg), return an error. - return PAGE_SYNC_ERROR; - } } if (startTime != -1) { diff --git a/content/media/test/test_progress.html b/content/media/test/test_progress.html index 2056b6b7811..1bd2e9d7b45 100644 --- a/content/media/test/test_progress.html +++ b/content/media/test/test_progress.html @@ -17,6 +17,10 @@ var manager = new MediaTestManager; function do_progress(e) { var v = e.target; ok(!v._finished, "Check no progress events after completed for " + v._name); + ok(e.lengthComputable, "Check progress lengthComputable for " + v._name); + v._last_progress_total = e.loaded; + ok(e.loaded <= e.total, "Check progress in bounds: " + e.loaded + " for " + v._name); + is(e.total, v._size, "Check progress total for " + v._name); } function do_ended(e) { @@ -35,7 +39,9 @@ function startTest(test, token) { v.src = test.name; v.autoplay = true; v._name = test.name; + v._size = test.size; v._finished = false; + v._last_progress_total = 0; v.addEventListener("ended", do_ended, false); v.addEventListener("progress", do_progress, false); document.body.appendChild(v); diff --git a/content/media/wave/nsWaveDecoder.cpp b/content/media/wave/nsWaveDecoder.cpp index c9df589d233..1324ad18f09 100644 --- a/content/media/wave/nsWaveDecoder.cpp +++ b/content/media/wave/nsWaveDecoder.cpp @@ -1678,7 +1678,7 @@ nsWaveDecoder::PlaybackPositionChanged() if (mElement && lastTime != mCurrentTime) { UpdateReadyStateForData(); - mElement->DispatchEvent(NS_LITERAL_STRING("timeupdate")); + mElement->DispatchSimpleEvent(NS_LITERAL_STRING("timeupdate")); } } diff --git a/toolkit/content/widgets/videocontrols.xml b/toolkit/content/widgets/videocontrols.xml index 85a2cde727a..bff881f57d0 100644 --- a/toolkit/content/widgets/videocontrols.xml +++ b/toolkit/content/widgets/videocontrols.xml @@ -368,8 +368,8 @@ // fully loaded. (If it's still loading, it will fire a progress event // and we'll figure out the exact state then.) this.bufferBar.setAttribute("max", 100); - if (this.video.readyState >= this.video.HAVE_METADATA) - this.showBuffered(); + if (this.video.networkState == this.video.NETWORK_LOADED) + this.bufferBar.setAttribute("value", 100); else this.bufferBar.setAttribute("value", 0); @@ -458,7 +458,15 @@ this.durationChange(duration); break; case "progress": - this.showBuffered(); + var loaded = aEvent.loaded; + var total = aEvent.total; + this.log("+++ load, " + loaded + " of " + total); + // When the source is streaming, the value of .total is -1. Set the + // progress bar to the maximum, since it's not useful. + if (total == -1) + total = loaded; + this.bufferBar.max = total; + this.bufferBar.value = loaded; this.setupStatusFader(); break; case "suspend": @@ -500,10 +508,6 @@ this.bufferBar.value = 0; break; case "seeking": - this.showBuffered(); - this.statusIcon.setAttribute("type", "throbber"); - this.setupStatusFader(); - break; case "waiting": this.statusIcon.setAttribute("type", "throbber"); this.setupStatusFader(); @@ -595,53 +599,6 @@ this.scrubber.value = currentTime; }, - showBuffered : function() { - function bsearch(haystack, needle, cmp) { - var length = haystack.length; - var low = 0; - var high = length; - while (high - low > 1) { - var probe = low + ((high - low) >> 1); - var r = cmp(haystack, probe, needle); - if (r == 0) { - low = probe; - break; - } else if (r > 0) { - low = probe + 1; - } else { - high = probe; - } - } - return low < length ? low : -1; - } - - function bufferedCompare(buffered, i, time) { - if (time > buffered.end(i)) { - return 1; - } else if (time >= buffered.start(i)) { - return 0; - } - return -1; - } - - var duration = Math.round(this.video.duration * 1000); - if (isNaN(duration)) - duration = this.maxCurrentTimeSeen; - - // Find the range that the current play position is in and use that - // range for bufferBar. At some point we may support multiple ranges - // displayed in the bar. - var currentTime = this.video.currentTime; - var buffered = this.video.buffered; - var index = bsearch(buffered, currentTime, bufferedCompare); - var endTime = 0; - if (index >= 0) { - endTime = Math.round(buffered.end(index) * 1000); - } - this.bufferBar.max = duration; - this.bufferBar.value = endTime; - }, - onVolumeMouseInOut : function (event) { // Ignore events caused by transitions between mute button and volumeStack, // or between nodes inside these two elements.