author | Ryan VanderMeulen <ryanvm@gmail.com> |
Mon, 06 Oct 2014 13:44:28 -0400 | |
changeset 209033 | b2d92cb448730745ab54c54167cd423ae8347469 |
parent 209032 | 8f91f44a4e3ec476466fb56ab2faff603bb76957 |
child 209034 | 8be54e6c4dcd2f69d8c27ab6038e828dee126f63 |
push id | 1 |
push user | root |
push date | Mon, 20 Oct 2014 17:29:22 +0000 |
bugs | 879717 |
milestone | 35.0a1 |
backs out | 353aee81348432381174cb0957fc8f84661dc8c1 cd7d8b93923f3fe80129955917d78e83ebce5da8 78b01186ff855234e43e2968afc9fd3bbc7e354b 29f4a39efc29b864b0d61009ad536f57b2a2d66d |
--- a/content/html/content/public/HTMLMediaElement.h +++ b/content/html/content/public/HTMLMediaElement.h @@ -1008,19 +1008,16 @@ protected: // These events get re-dispatched when the bfcache is exited. nsTArray<nsString> mPendingEvents; // Media loading flags. See: // http://www.whatwg.org/specs/web-apps/current-work/#video) nsMediaNetworkState mNetworkState; nsMediaReadyState mReadyState; - // Last value passed from codec or stream source to UpdateReadyStateForData. - NextFrameStatus mLastNextFrameStatus; - enum LoadAlgorithmState { // No load algorithm instance is waiting for a source to be added to the // media in order to continue loading. NOT_WAITING, // We've run the load algorithm, and we tried all source children of the // media element, and failed to load any successfully. We're waiting for // another source element to be added to the media element, and will try // to load any such element when its added.
--- a/content/html/content/src/HTMLMediaElement.cpp +++ b/content/html/content/src/HTMLMediaElement.cpp @@ -66,18 +66,16 @@ #include "nsURIHashKey.h" #include "nsJSUtils.h" #include "MediaStreamGraph.h" #include "nsIScriptError.h" #include "nsHostObjectProtocolHandler.h" #include "mozilla/dom/MediaSource.h" #include "MediaMetadataManager.h" #include "MediaSourceDecoder.h" -#include "AudioStreamTrack.h" -#include "VideoStreamTrack.h" #include "AudioChannelService.h" #include "mozilla/dom/power/PowerManagerService.h" #include "mozilla/dom/WakeLock.h" #include "mozilla/dom/AudioTrack.h" #include "mozilla/dom/AudioTrackList.h" @@ -661,20 +659,17 @@ void HTMLMediaElement::AbortExistingLoad mLoadedDataFired = false; mAutoplaying = true; mIsLoadingFromSourceChildren = false; mSuspendedAfterFirstFrame = false; mAllowSuspendAfterFirstFrame = true; mHaveQueuedSelectResource = false; mSuspendedForPreloadNone = false; mDownloadSuspendedByCache = false; - mHasAudio = false; - mHasVideo = false; mSourcePointer = nullptr; - mLastNextFrameStatus = NEXT_FRAME_UNINITIALIZED; mTags = nullptr; if (mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) { NS_ASSERTION(!mDecoder && !mSrcStream, "How did someone setup a new stream/decoder already?"); ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY); ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING); mPaused = true; @@ -1987,17 +1982,16 @@ HTMLMediaElement::LookupMediaElementURIT } HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) : nsGenericHTMLElement(aNodeInfo), mSrcStreamListener(nullptr), mCurrentLoadID(0), mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY), mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING), - mLastNextFrameStatus(NEXT_FRAME_UNINITIALIZED), mLoadWaitStatus(NOT_WAITING), mVolume(1.0), mPreloadAction(PRELOAD_UNDEFINED), mMediaSize(-1,-1), mLastCurrentTime(0.0), mFragmentStart(-1.0), mFragmentEnd(-1.0), mDefaultPlaybackRate(1.0), @@ -2829,43 +2823,32 @@ void HTMLMediaElement::SetupSrcMediaStre mSrcStreamListener = new StreamListener(this); GetSrcMediaStream()->AddListener(mSrcStreamListener); if (mPaused) { GetSrcMediaStream()->ChangeExplicitBlockerCount(1); } if (mPausedForInactiveDocumentOrChannel) { GetSrcMediaStream()->ChangeExplicitBlockerCount(1); } - - nsAutoTArray<nsRefPtr<AudioStreamTrack>,1> audioTracks; - aStream->GetAudioTracks(audioTracks); - nsAutoTArray<nsRefPtr<VideoStreamTrack>,1> videoTracks; - aStream->GetVideoTracks(videoTracks); - - // Clear aTags, but set mHasAudio and mHasVideo - MediaInfo mediaInfo; - mediaInfo.mAudio.mHasAudio = !audioTracks.IsEmpty(); - mediaInfo.mVideo.mHasVideo = !videoTracks.IsEmpty(); - MetadataLoaded(&mediaInfo, nullptr); - - DispatchAsyncEvent(NS_LITERAL_STRING("suspend")); - mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE; - ChangeDelayLoadStatus(false); GetSrcMediaStream()->AddAudioOutput(this); GetSrcMediaStream()->SetAudioOutputVolume(this, float(mMuted ? 0.0 : mVolume)); VideoFrameContainer* container = GetVideoFrameContainer(); if (container) { GetSrcMediaStream()->AddVideoOutput(container); } // Note: we must call DisconnectTrackListListeners(...) before dropping // mSrcStream mSrcStream->ConstructMediaTracks(AudioTracks(), VideoTracks()); + ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA); + DispatchAsyncEvent(NS_LITERAL_STRING("durationchange")); + DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata")); + ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE); AddRemoveSelfReference(); // FirstFrameLoaded() will be called when the stream has current data. } void HTMLMediaElement::EndSrcMediaStreamPlayback() { MediaStream* stream = GetSrcMediaStream(); if (stream) { @@ -2928,29 +2911,23 @@ void HTMLMediaElement::MetadataLoaded(co // delete the VideoFrameContainer. This happens when the src is changed to an // audio only file. if (!aInfo->HasVideo() && mVideoFrameContainer) { // call ForgetElement() such that callbacks from |mVideoFrameContainer| // won't reach us anymore. mVideoFrameContainer->ForgetElement(); mVideoFrameContainer = nullptr; } - - if (IsVideo()) { - // Update the screen wakelock in case mHasVideo changed - NotifyOwnerDocumentActivityChanged(); - } } void HTMLMediaElement::FirstFrameLoaded() { NS_ASSERTION(!mSuspendedAfterFirstFrame, "Should not have already suspended"); ChangeDelayLoadStatus(false); - UpdateReadyStateForData(NEXT_FRAME_UNAVAILABLE); if (mDecoder && mAllowSuspendAfterFirstFrame && mPaused && !HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) && mPreloadAction == HTMLMediaElement::PRELOAD_METADATA) { mSuspendedAfterFirstFrame = true; mDecoder->Suspend(); } } @@ -3103,18 +3080,16 @@ void HTMLMediaElement::DownloadStalled() bool HTMLMediaElement::ShouldCheckAllowOrigin() { return mCORSMode != CORS_NONE; } void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatus aNextFrame) { - mLastNextFrameStatus = aNextFrame; - if (mReadyState < nsIDOMHTMLMediaElement::HAVE_METADATA) { // aNextFrame might have a next frame because the decoder can advance // on its own thread before MetadataLoaded gets a chance to run. // The arrival of more data can't change us out of this readyState. return; } if (aNextFrame == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING) { @@ -3131,24 +3106,16 @@ void HTMLMediaElement::UpdateReadyStateF // this transition if the decoder is in ended state; the readyState // should remain at HAVE_CURRENT_DATA in this case. // Note that this state transition includes the case where we finished // downloaded the whole data stream. ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA); return; } - if (mReadyState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA && mHasVideo) { - VideoFrameContainer* container = GetVideoFrameContainer(); - if (container && mMediaSize == nsIntSize(-1,-1)) { - // No frame has been set yet. Don't advance. - return; - } - } - if (aNextFrame != MediaDecoderOwner::NEXT_FRAME_AVAILABLE) { ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA); if (!mWaitingFired && aNextFrame == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING) { FireTimeUpdate(false); DispatchAsyncEvent(NS_LITERAL_STRING("waiting")); mWaitingFired = true; } return; @@ -3279,24 +3246,24 @@ void HTMLMediaElement::ChangeNetworkStat } else if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE && !mError) { // Fire 'suspend' event when entering NETWORK_IDLE and no error presented. DispatchAsyncEvent(NS_LITERAL_STRING("suspend")); } } bool HTMLMediaElement::CanActivateAutoplay() { - // For stream inputs, we activate autoplay on HAVE_METADATA because + // For stream inputs, we activate autoplay on HAVE_CURRENT_DATA because // this element itself might be blocking the stream from making progress by // being paused. return !mPausedForInactiveDocumentOrChannel && mAutoplaying && mPaused && ((mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) || - (mSrcStream && mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA)) && + (mSrcStream && mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA)) && HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) && mAutoplayEnabled && !IsEditable(); } void HTMLMediaElement::CheckAutoplayDataReady() { if (CanActivateAutoplay()) { @@ -3315,24 +3282,34 @@ void HTMLMediaElement::CheckAutoplayData GetSrcMediaStream()->ChangeExplicitBlockerCount(-1); } DispatchAsyncEvent(NS_LITERAL_STRING("play")); } } VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer() { - if (mVideoFrameContainer) - return mVideoFrameContainer; + // If we have loaded the metadata, and the size of the video is still + // (-1, -1), the media has no video. Don't go a create a video frame + // container. + if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA && + mMediaSize == nsIntSize(-1, -1)) { + return nullptr; + } // Only video frames need an image container. if (!IsVideo()) { return nullptr; } + mHasVideo = true; + + if (mVideoFrameContainer) + return mVideoFrameContainer; + mVideoFrameContainer = new VideoFrameContainer(this, LayerManager::CreateAsynchronousImageContainer()); return mVideoFrameContainer; } nsresult HTMLMediaElement::DispatchEvent(const nsAString& aName) { @@ -3430,17 +3407,16 @@ void HTMLMediaElement::NotifyDecoderPrin OutputMediaStream* ms = &mOutputStreams[i]; ms->mStream->CombineWithPrincipal(principal); } } void HTMLMediaElement::UpdateMediaSize(nsIntSize size) { mMediaSize = size; - UpdateReadyStateForData(mLastNextFrameStatus); } void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendEvents) { if (aPauseElement != mPausedForInactiveDocumentOrChannel) { mPausedForInactiveDocumentOrChannel = aPauseElement; if (aPauseElement) { #ifdef MOZ_EME
--- a/content/media/test/mochitest.ini +++ b/content/media/test/mochitest.ini @@ -314,17 +314,16 @@ skip-if = buildapp == 'mulet' || os == ' [test_bug465498.html] [test_bug493187.html] [test_bug495145.html] [test_bug495300.html] [test_bug654550.html] [test_bug686942.html] [test_bug726904.html] [test_bug874897.html] -[test_bug879717.html] [test_bug883173.html] [test_bug895091.html] [test_bug895305.html] [test_bug919265.html] [test_bug957847.html] [test_bug1018933.html] [test_can_play_type.html] [test_can_play_type_mpeg.html]
deleted file mode 100644 --- a/content/media/test/test_bug879717.html +++ /dev/null @@ -1,65 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test for bug 879717, check that a video element can be drawn into a canvas directly on 'play' event</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> -</head> -<body> -<video id="v1" autoplay /> -<video id="v2" autoplay /> -<canvas id="c1" /> -<canvas id="c2" /> -<pre id="test"> -<script class="testbody" type="text/javascript"> -SimpleTest.waitForExplicitFinish(); - -var media = getPlayableVideo(gSmallTests); - -var checkDrawImage = function(video, canvas, name) { - var exception = null; - var exceptionName = "nothing"; - try { - var ctx = canvas.getContext('2d'); - ctx.drawImage(video, 0, 0, canvas.width, canvas.height); - } catch (e) { - exception = e; - exceptionName = e.name; - } - ok(exception === null || video.ended, - "drawImage shouldn't throw an exception on play of " + name + ", got " + exceptionName); -}; - -if (media == null) { - todo(false, "No media supported."); - SimpleTest.finish(); -} else { - v1.src = media.name; - v2.mozSrcObject = v1.mozCaptureStream(); - - var v1Tested = false; - var v2Tested = false; - - v1.addEventListener('play', function() { - checkDrawImage(v1, c1, media.name); - - v1Tested = true; - if (v2Tested) { - SimpleTest.finish(); - } - }); - - v2.addEventListener('play', function() { - checkDrawImage(v2, c2, "stream of " + media.name); - - v2Tested = true; - if (v1Tested) { - SimpleTest.finish(); - } - }); -} -</script> -</pre> -</body> -</html>