Bug 449156 - Implement HTMLVideoElement.poster, with correct reftests. r+=doublec,jst, sr+=roc

This commit is contained in:
Chris Pearce 2009-06-26 19:25:17 +12:00
parent d4c3dad091
commit 21a86f06aa
33 changed files with 560 additions and 33 deletions

View File

@ -64,7 +64,7 @@ interface nsIURI;
* sufficient, when combined with the imageBlockingStatus information.)
*/
[scriptable, uuid(7744c6d3-5c60-4b7b-a526-4fe9d5ac7e97)]
[scriptable, uuid(e036857e-3417-4812-a5f2-89668a616781)]
interface nsIImageLoadingContent : imgIDecoderObserver
{
/**
@ -167,4 +167,12 @@ interface nsIImageLoadingContent : imgIDecoderObserver
* @throws NS_ERROR_NOT_AVAILABLE if there is no current URI to reload
*/
void forceReload();
/**
* Enables/disables image state forcing. When |aForce| is PR_TRUE, we force
* nsImageLoadingContent::ImageState() to return |aState|. Call again with |aForce|
* as PR_FALSE to revert ImageState() to its original behaviour.
*/
void forceImageState(in boolean aForce, in long aState);
};

View File

@ -109,7 +109,8 @@ nsImageLoadingContent::nsImageLoadingContent()
// mBroken starts out true, since an image without a URI is broken....
mBroken(PR_TRUE),
mUserDisabled(PR_FALSE),
mSuppressed(PR_FALSE)
mSuppressed(PR_FALSE),
mIsImageStateForced(PR_FALSE)
{
if (!nsContentUtils::GetImgLoader()) {
mLoadingEnabled = PR_FALSE;
@ -617,10 +618,18 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
return NS_OK;
}
nsresult
nsImageLoadingContent::ForceImageState(PRBool aForce, PRInt32 aState)
{
mIsImageStateForced = aForce;
mForcedImageState = aState;
return NS_OK;
}
PRInt32
nsImageLoadingContent::ImageState() const
{
return
return mIsImageStateForced ? mForcedImageState :
(mBroken * NS_EVENT_STATE_BROKEN) |
(mUserDisabled * NS_EVENT_STATE_USERDISABLED) |
(mSuppressed * NS_EVENT_STATE_SUPPRESSED) |

View File

@ -260,10 +260,21 @@ private:
*/
ImageObserver mObserverList;
/**
* When mIsImageStateForced is true, this holds the ImageState that we'll
* return in ImageState().
*/
PRInt32 mForcedImageState;
PRInt16 mImageBlockingStatus;
PRPackedBool mLoadingEnabled : 1;
PRPackedBool mStartingLoad : 1;
/**
* When true, we return mForcedImageState from ImageState().
*/
PRPackedBool mIsImageStateForced : 1;
/**
* The state we had the last time we checked whether we needed to notify the
* document of a state change. These are maintained by UpdateImageState.

View File

@ -256,11 +256,24 @@ public:
*/
already_AddRefed<nsILoadGroup> GetDocumentLoadGroup();
/**
* Returns PR_TRUE if the media has played or completed a seek.
* Used by video frame to determine whether to paint the poster.
*/
PRBool GetPlayedOrSeeked() { return mHasPlayedOrSeeked; }
protected:
class MediaLoadListener;
class LoadNextSourceEvent;
class SelectResourceEvent;
/**
* Changes mHasPlayedOrSeeked to aValue. If mHasPlayedOrSeeked changes
* we'll force a reflow so that the video frame gets reflowed to reflect
* the poster hiding or showing immediately.
*/
void SetPlayedOrSeeked(PRBool aValue);
/**
* Create a decoder for the given aMIMEType. Returns false if we
* were unable to create the decoder.
@ -469,4 +482,8 @@ protected:
// PR_TRUE if we are allowed to suspend the decoder because we were paused,
// autobuffer and autoplay were not set, and we loaded the first frame.
PRPackedBool mAllowSuspendAfterFirstFrame;
// PR_TRUE if we've played or completed a seek. We use this to determine
// when the poster frame should be shown.
PRPackedBool mHasPlayedOrSeeked;
};

View File

@ -413,6 +413,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Load()
{
if (mIsRunningLoadMethod)
return NS_OK;
SetPlayedOrSeeked(PR_FALSE);
mIsRunningLoadMethod = PR_TRUE;
AbortExistingLoads();
QueueSelectResourceTask();
@ -784,7 +785,8 @@ nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParse
mDelayingLoadEvent(PR_FALSE),
mIsRunningSelectResource(PR_FALSE),
mSuspendedAfterFirstFrame(PR_FALSE),
mAllowSuspendAfterFirstFrame(PR_TRUE)
mAllowSuspendAfterFirstFrame(PR_TRUE),
mHasPlayedOrSeeked(PR_FALSE)
{
RegisterFreezableElement();
}
@ -813,9 +815,29 @@ void nsHTMLMediaElement::StopSuspendingAfterFirstFrame()
}
}
void nsHTMLMediaElement::SetPlayedOrSeeked(PRBool aValue)
{
if (aValue == mHasPlayedOrSeeked)
return;
mHasPlayedOrSeeked = aValue;
// Force a reflow so that the poster frame hides or shows immediately.
nsIDocument *doc = GetDocument();
if (!doc) return;
nsIPresShell *presShell = doc->GetPrimaryShell();
if (!presShell) return;
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
if (!frame) return;
presShell->FrameNeedsReflow(frame,
nsIPresShell::eTreeChange,
NS_FRAME_IS_DIRTY);
}
NS_IMETHODIMP nsHTMLMediaElement::Play()
{
StopSuspendingAfterFirstFrame();
SetPlayedOrSeeked(PR_TRUE);
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
nsresult rv = Load();
@ -1204,6 +1226,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
mDecoder->SetVolume(mMuted ? 0.0 : mVolume);
if (!mPaused) {
SetPlayedOrSeeked(PR_TRUE);
rv = mDecoder->Play();
}
@ -1301,6 +1324,7 @@ void nsHTMLMediaElement::SeekStarted()
void nsHTMLMediaElement::SeekCompleted()
{
mPlayingBeforeSeek = PR_FALSE;
SetPlayedOrSeeked(PR_TRUE);
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("seeked"));
}
@ -1454,6 +1478,7 @@ void nsHTMLMediaElement::NotifyAutoplayDataReady()
mAutoplayEnabled) {
mPaused = PR_FALSE;
if (mDecoder) {
SetPlayedOrSeeked(PR_TRUE);
mDecoder->Play();
}
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("play"));

View File

@ -158,3 +158,5 @@ nsHTMLVideoElement::GetAttributeMappingFunction() const
{
return &MapAttributesIntoRule;
}
NS_IMPL_URI_ATTR(nsHTMLVideoElement, Poster, poster)

View File

@ -48,12 +48,13 @@
* @status UNDER_DEVELOPMENT
*/
[scriptable, uuid(4e3f05a5-ca9b-4576-af7f-b1d4038e6eb3)]
[scriptable, uuid(edf468dc-42eb-4494-920b-56a315172640)]
interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement
{
attribute long width;
attribute long height;
readonly attribute unsigned long videoWidth;
readonly attribute unsigned long videoHeight;
attribute DOMString poster;
};

View File

@ -55,6 +55,8 @@
#include "nsContentCreatorFunctions.h"
#include "nsBoxLayoutState.h"
#include "nsBoxFrame.h"
#include "nsImageFrame.h"
#include "nsIImageLoadingContent.h"
#ifdef ACCESSIBILITY
#include "nsIServiceManager.h"
@ -87,20 +89,50 @@ NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
nsresult
nsVideoFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements)
{
nsNodeInfoManager *nodeInfoManager = GetContent()->GetCurrentDoc()->NodeInfoManager();
nsCOMPtr<nsINodeInfo> nodeInfo;
if (HasVideoElement()) {
// Create an anonymous image element as a child to hold the poster
// image. We may not have a poster image now, but one could be added
// before we load, or on a subsequent load.
nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::img,
nsnull,
kNameSpaceID_None);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
mPosterImage = NS_NewHTMLImageElement(nodeInfo);
NS_ENSURE_TRUE(mPosterImage, NS_ERROR_OUT_OF_MEMORY);
// Set the nsImageLoadingContent::ImageState() to 0. This means that the
// image will always report its state as 0, so it will never be reframed
// to show frames for loading or the broken image icon. This is important,
// as the image is native anonymous, and so can't be reframed (currently).
nsCOMPtr<nsIImageLoadingContent> imgContent = do_QueryInterface(mPosterImage);
NS_ENSURE_TRUE(imgContent, NS_ERROR_FAILURE);
imgContent->ForceImageState(PR_TRUE, 0);
nsresult res = UpdatePosterSource(PR_FALSE);
NS_ENSURE_SUCCESS(res,res);
if (!aElements.AppendElement(mPosterImage))
return NS_ERROR_OUT_OF_MEMORY;
}
// Set up "videocontrols" XUL element which will be XBL-bound to the
// actual controls.
nsPresContext* presContext = PresContext();
nsNodeInfoManager *nodeInfoManager =
presContext->Document()->NodeInfoManager();
nsCOMPtr<nsINodeInfo> nodeInfo;
nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::videocontrols, nsnull,
nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::videocontrols,
nsnull,
kNameSpaceID_XUL);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = NS_NewElement(getter_AddRefs(mVideoControls), kNameSpaceID_XUL, nodeInfo, PR_FALSE);
nsresult rv = NS_NewElement(getter_AddRefs(mVideoControls),
kNameSpaceID_XUL,
nodeInfo,
PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
if (!aElements.AppendElement(mVideoControls))
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -108,6 +140,7 @@ void
nsVideoFrame::Destroy()
{
nsContentUtils::DestroyAnonymousContent(&mVideoControls);
nsContentUtils::DestroyAnonymousContent(&mPosterImage);
nsContainerFrame::Destroy();
}
@ -179,16 +212,46 @@ nsVideoFrame::Reflow(nsPresContext* aPresContext,
aMetrics.width += mBorderPadding.left + mBorderPadding.right;
aMetrics.height += mBorderPadding.top + mBorderPadding.bottom;
nsIFrame* child = mFrames.FirstChild();
if (child) {
NS_ASSERTION(child->GetContent() == mVideoControls,
"What is this child doing here?");
nsBoxLayoutState boxState(PresContext(), aReflowState.rendContext);
nsBoxFrame::LayoutChildAt(boxState, child,
nsRect(mBorderPadding.left, mBorderPadding.top,
aReflowState.ComputedWidth(), aReflowState.ComputedHeight()));
// Reflow the child frames. We may have up to two, an image frame
// which is the poster, and a box frame, which is the video controls.
for (nsIFrame *child = mFrames.FirstChild();
child;
child = child->GetNextSibling()) {
if (child->GetType() == nsGkAtoms::imageFrame) {
// Reflow the poster frame.
nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
nsHTMLReflowMetrics kidDesiredSize;
nsSize availableSize = nsSize(aReflowState.availableWidth,
aReflowState.availableHeight);
nsHTMLReflowState kidReflowState(aPresContext,
aReflowState,
imageFrame,
availableSize,
aMetrics.width,
aMetrics.height);
if (ShouldDisplayPoster()) {
kidReflowState.SetComputedWidth(aReflowState.ComputedWidth());
kidReflowState.SetComputedHeight(aReflowState.ComputedHeight());
} else {
kidReflowState.SetComputedWidth(0);
kidReflowState.SetComputedHeight(0);
}
ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowState,
mBorderPadding.left, mBorderPadding.top, 0, aStatus);
FinishReflowChild(imageFrame, aPresContext,
&kidReflowState, kidDesiredSize,
mBorderPadding.left, mBorderPadding.top, 0);
} else if (child->GetType() == nsGkAtoms::boxFrame) {
// Reflow the video controls frame.
nsBoxLayoutState boxState(PresContext(), aReflowState.rendContext);
nsBoxFrame::LayoutChildAt(boxState,
child,
nsRect(mBorderPadding.left,
mBorderPadding.top,
aReflowState.ComputedWidth(),
aReflowState.ComputedHeight()));
}
}
aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height);
FinishAndStoreOverflow(&aMetrics);
@ -233,16 +296,30 @@ nsVideoFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
if (HasVideoData()) {
if (!ShouldDisplayPoster() && HasVideoData()) {
rv = aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayGeneric(this, ::PaintVideo, "Video"));
NS_ENSURE_SUCCESS(rv, rv);
}
nsIFrame *kid = mFrames.FirstChild();
if (kid) {
rv = kid->BuildDisplayListForStackingContext(aBuilder, aDirtyRect - kid->GetOffsetTo(this), aLists.Content());
// Add child frames to display list. We expect up to two children, an image
// frame for the poster, and the box frame for the video controls.
for (nsIFrame *child = mFrames.FirstChild();
child;
child = child->GetNextSibling()) {
if (child->GetType() == nsGkAtoms::imageFrame && ShouldDisplayPoster()) {
rv = child->BuildDisplayListForStackingContext(aBuilder,
aDirtyRect - child->GetOffsetTo(this),
aLists.Content());
NS_ENSURE_SUCCESS(rv,rv);
} else if (child->GetType() == nsGkAtoms::boxFrame) {
rv = child->BuildDisplayListForStackingContext(aBuilder,
aDirtyRect - child->GetOffsetTo(this),
aLists.Content());
NS_ENSURE_SUCCESS(rv,rv);
}
return rv;
}
return NS_OK;
}
nsIAtom*
@ -317,11 +394,49 @@ nsSize nsVideoFrame::GetIntrinsicRatio()
return GetIntrinsicSize(nsnull);
}
PRBool nsVideoFrame::ShouldDisplayPoster()
{
if (!HasVideoElement())
return PR_FALSE;
nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent());
if (element->GetPlayedOrSeeked() && HasVideoData())
return PR_FALSE;
nsCOMPtr<nsIImageLoadingContent> imgContent = do_QueryInterface(mPosterImage);
NS_ENSURE_TRUE(imgContent, PR_FALSE);
nsCOMPtr<imgIRequest> request;
nsresult res = imgContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
getter_AddRefs(request));
if (NS_FAILED(res) || !request) {
return PR_FALSE;
}
PRUint32 status = 0;
res = request->GetImageStatus(&status);
if (NS_FAILED(res) || (status & imgIRequest::STATUS_ERROR))
return PR_FALSE;
return PR_TRUE;
}
nsSize nsVideoFrame::GetIntrinsicSize(nsIRenderingContext *aRenderingContext)
{
// Defaulting size to 300x150 if no size given.
nsIntSize size(300,150);
if (ShouldDisplayPoster()) {
// Use the poster image frame's size.
nsIFrame *child = mFrames.FirstChild();
if (child && child->GetType() == nsGkAtoms::imageFrame) {
nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
nsSize imgsize;
imageFrame->GetIntrinsicImageSize(imgsize);
return imgsize;
}
}
if (!HasVideoData()) {
if (!aRenderingContext || !mFrames.FirstChild()) {
// We just want our intrinsic ratio, but audio elements need no
@ -332,21 +447,57 @@ nsSize nsVideoFrame::GetIntrinsicSize(nsIRenderingContext *aRenderingContext)
// Ask the controls frame what its preferred height is
nsBoxLayoutState boxState(PresContext(), aRenderingContext, 0);
nscoord prefHeight = mFrames.FirstChild()->GetPrefSize(boxState).height;
nscoord prefHeight = mFrames.LastChild()->GetPrefSize(boxState).height;
return nsSize(nsPresContext::CSSPixelsToAppUnits(size.width), prefHeight);
}
nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent());
if (element) {
size = element->GetVideoSize(size);
}
return nsSize(nsPresContext::CSSPixelsToAppUnits(size.width),
nsPresContext::CSSPixelsToAppUnits(size.height));
}
nsresult
nsVideoFrame::UpdatePosterSource(PRBool aNotify)
{
NS_ASSERTION(HasVideoElement(), "Only call this on <video> elements.");
nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent());
nsAutoString posterStr;
element->GetPoster(posterStr);
nsresult res = mPosterImage->SetAttr(kNameSpaceID_None,
nsGkAtoms::src,
posterStr,
aNotify);
NS_ENSURE_SUCCESS(res,res);
return NS_OK;
}
NS_IMETHODIMP
nsVideoFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aAttribute == nsGkAtoms::poster) {
nsresult res = UpdatePosterSource(PR_TRUE);
NS_ENSURE_SUCCESS(res,res);
}
return nsContainerFrame::AttributeChanged(aNameSpaceID,
aAttribute,
aModType);
}
PRBool nsVideoFrame::HasVideoElement() {
nsCOMPtr<nsIDOMHTMLVideoElement> videoDomElement = do_QueryInterface(mContent);
return videoDomElement != nsnull;
}
PRBool nsVideoFrame::HasVideoData()
{
nsCOMPtr<nsIDOMHTMLVideoElement> videoElem = do_QueryInterface(mContent);
return videoElem != nsnull;
if (!HasVideoElement())
return PR_FALSE;
nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent());
nsIntSize size = element->GetVideoSize(nsIntSize(0,0));
return size != nsIntSize(0,0);
}

View File

@ -63,6 +63,10 @@ public:
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
void PaintVideo(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, nsPoint aPt);
@ -101,14 +105,33 @@ public:
#endif
protected:
// Returns true if there is video data to render. Can return false
// when we're the frame for an audio element.
// Returns PR_TRUE if we're rendering for a video element. We still create
// nsVideoFrame to render controls for an audio element.
PRBool HasVideoElement();
// Returns PR_TRUE if there is video data to render. Can return false
// when we're the frame for an audio element, or we've created a video
// element for a media which is audio-only.
PRBool HasVideoData();
// Returns PR_TRUE if we should display the poster. Note that once we show
// a video frame, the poster will never be displayed again.
PRBool ShouldDisplayPoster();
// Sets the mPosterImage's src attribute to be the video's poster attribute,
// if we're the frame for a video element.
nsresult UpdatePosterSource(PRBool aNotify);
virtual ~nsVideoFrame();
nsMargin mBorderPadding;
// Anonymous child which is bound via XBL to the video controls.
nsCOMPtr<nsIContent> mVideoControls;
// Anonymous child which is the image element of the poster frame.
nsCOMPtr<nsIContent> mPosterImage;
};
#endif /* nsVideoFrame_h___ */

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<body style="background:white;">
<!-- Test if poster frame displays correctly when poster is different size. -->
<video src="black140x100.ogv" poster="blue250x200.png"></video>
</body>
</html>

View File

@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<!-- Test: Create video, add poster, load. Should display poster. -->
<script>
function runTest() {
var v = document.createElement('video');
v.addEventListener('loadeddata', function(){setTimeout(function(){document.documentElement.className = '';}, 0);}, false);
v.id = 'v';
v.src = "black140x100.ogv";
v.poster = "blue250x200.png";
v.autobuffer = true;
document.body.appendChild(v);
}
</script>
<body style="background:white;" onload="runTest();">
</body>
</html>

View File

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<!-- Test: Create video, load. Add poster frame, load again, poster should show. -->
<script>
function runTest() {
var v = document.createElement('video');
var endTest = function() {
setTimeout(function(){document.documentElement.className = '';}, 0);
};
var addPoster = function() {
v.removeEventListener('loadeddata', addPoster, false);
v.poster = "blue250x200.png";
v.addEventListener('loadeddata', endTest, false);
v.load();
};
v.addEventListener('loadeddata', addPoster, false);
v.id = 'v';
v.src = "black140x100.ogv";
v.autobuffer = true;
document.body.appendChild(v);
}
</script>
<body style="background:white;" onload="runTest();">
</body>
</html>

View File

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<!-- Test: Create video, load, play. Add poster frame, load again, poster should show. -->
<script>
function runTest() {
var v = document.createElement('video');
var endTest = function() {
setTimeout(function(){document.documentElement.className = '';}, 0);
};
var play =
function() {
v.removeEventListener('loadeddata', play, false);
v.play();
}
var addPoster = function() {
v.removeEventListener('playing', addPoster,false);
v.poster = "blue250x200.png";
v.addEventListener('loadeddata', endTest, false);
v.load();
};
v.addEventListener('loadeddata',
play,
false);
v.addEventListener('playing',
addPoster,
false);
v.id = 'v';
v.src = "black140x100.ogv";
v.autobuffer = true;
document.body.appendChild(v);
}
</script>
<body style="background:white;" onload="runTest();">
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE HTML>
<html>
<body style="background:white;">
<!-- Test that poster is stretched by css styling. -->
<video src="black140x100.ogv" poster="blue250x200.png" style="width: 400px; height: 300px;"></video>
</body>
</html>

View File

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<!-- Test: Create video, load, wait for video frame to show, add poster
attribute, poster should show. -->
<script>
function runTest() {
var v = document.createElement('video');
var loadeddata =
function() {
setTimeout(function() {v.poster = "blue250x200.png";}, 100);
setTimeout(function() {document.documentElement.className = '';}, 150);
};
v.addEventListener('loadeddata',
loadeddata,
false);
v.id = 'v';
v.src = "black140x100.ogv";
v.autobuffer = true;
document.body.appendChild(v);
}
</script>
<body style="background:white;" onload="runTest();">
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<!-- Test that poster is correctly laid out inside borders. Also test that
poster frames smaller than video don't have the video frame drawn behind
them etc. -->
<body style="background:white;">
<video src="black140x100.ogv"
poster="green70x30.png"
autobuffer
style="border: solid blue 2px;">
</video>
</body>
</html>

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<body style="background:white;">
<!-- Test if poster frame with invalid poster displays video frame. -->
<video src="black140x100.ogv" poster="not-a-valid-file"></video>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<body style="background:white;">
<!-- Test if poster hides after playing with autoplay. -->
<video src="black140x100.ogv"
poster="blue250x200.png"
autobuffer
autoplay
onplaying="setTimeout(function(){document.documentElement.className = '';},0);"></video>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<body style="background:white;">
<!-- Test if we show video frame after removing valid poster. -->
<video src="black140x100.ogv"
autobuffer
id="v"
onload="document.getElementById('v').poster = ''; setTimeout(function(){document.documentElement.className = '';}, 0);"
poster="blue250x200.png"></video>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<body style="background:white;">
<!-- Test to ensure that changing the poster after video has painted its first
frame doesn't render the poster. The video frame should not change to the
poster, since it's already painted its first video frame. -->
<video src="black140x100.ogv"
autobuffer
id="v"
autoplay
onended="document.getElementById('v').poster = 'blue250x200.png'; setTimeout(function(){document.documentElement.className = '';},0);"></video>
</body>
</html>

View File

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<body style="background:white;">
<!-- Test that poster frame should hide after completing a seek. -->
<video src="black140x100.ogv"
autobuffer
id="v"
onloadeddata="var v = document.getElementById('v'); v.currentTime = v.duration;"
onseeked="setTimeout(function(){document.documentElement.className = '';}, 0);"
poster="blue250x200.png"></video>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<body style="background:white;">
<!-- Test that poster frame changes when you change the poster attribute. -->
<video src="black140x100.ogv"
autobuffer
id="v"
onload="document.getElementById('v').poster = 'red160x120.png'; setTimeout(function(){document.documentElement.className = '';}, 0);"
poster="blue250x200.png"></video>
</body>
</html>

View File

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<body style="background:white;">
<!-- Test if poster hides after playing with play() call. -->
<video src="black140x100.ogv"
poster="blue250x200.png"
id="v"
autobuffer
onloadeddata="document.getElementById('v').play();"
onplaying="setTimeout(function(){document.documentElement.className = '';}, 0);"></video>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html class="reftest-wait">
<body style="background:white;" >
<!-- Test that poster displays all the time when <video> is showing an audio-only media. -->
<video src="../../../content/media/test/bug461281.ogg"
poster="blue250x200.png"
id="v"
autobuffer
autoplay
onended="setTimeout(function(){document.documentElement.className = '';},0);">
</video>
</body>
</html>

View File

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html>
<body style="background:white;">
<video src="black140x100.ogv" autobuffer></video>
</body>
</html>

View File

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html>
<body style="background:white;">
<img src="blue250x200.png" alt="poster">
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE HTML>
<html>
<body style="background:white;">
<img src="blue250x200.png" style="width: 400px; height: 300px;">
</body>
</html>

View File

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html>
<body style="background:white;">
<img src="green70x30.png" alt="poster" style="border: solid blue 2px;">
</body>
</html>

View File

@ -0,0 +1,6 @@
<!DOCTYPE HTML>
<html>
<body style="background:white;">
<img src="red160x120.png" alt="poster">
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

View File

@ -15,3 +15,18 @@ HTTP(..) == offset-1.xhtml offset-1-ref.html
random HTTP(..) == object-aspect-ratio-2a.xhtml aspect-ratio-2-ref.html
random HTTP(..) == object-aspect-ratio-2b.xhtml aspect-ratio-2-ref.html
skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") HTTP(..) == zoomed-1.xhtml zoomed-1-ref.html
== poster-1.html poster-ref-blue250x200.html
== poster-2.html poster-ref-black140x100.html
== poster-3.html poster-ref-black140x100.html
== poster-4.html poster-ref-black140x100.html
== poster-5.html poster-ref-black140x100.html
== poster-6.html poster-ref-black140x100.html
== poster-7.html poster-ref-red160x120.html
== poster-8.html poster-ref-black140x100.html
== poster-9.html poster-ref-blue250x200.html
== poster-10.html poster-ref-blue250x200.html
== poster-11.html poster-ref-blue250x200.html
== poster-12.html poster-ref-blue250x200.html
== poster-13.html poster-ref-blue400x300.html
== poster-14.html poster-ref-blue250x200.html
== poster-15.html poster-ref-green70x30.html