2012-02-14 20:35:01 -08:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "VideoFrameContainer.h"
|
|
|
|
|
|
|
|
#include "nsHTMLMediaElement.h"
|
|
|
|
#include "nsIFrame.h"
|
|
|
|
#include "nsDisplayList.h"
|
|
|
|
#include "nsSVGEffects.h"
|
2012-08-20 21:06:46 -07:00
|
|
|
#include "ImageContainer.h"
|
2012-02-14 20:35:01 -08:00
|
|
|
|
|
|
|
using namespace mozilla::layers;
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
2012-08-20 21:06:46 -07:00
|
|
|
VideoFrameContainer::VideoFrameContainer(nsHTMLMediaElement* aElement,
|
|
|
|
already_AddRefed<ImageContainer> aContainer)
|
|
|
|
: mElement(aElement),
|
|
|
|
mImageContainer(aContainer), mMutex("nsVideoFrameContainer"),
|
|
|
|
mIntrinsicSizeChanged(false), mImageSizeChanged(false),
|
|
|
|
mNeedInvalidation(true)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aElement, "aElement must not be null");
|
|
|
|
NS_ASSERTION(mImageContainer, "aContainer must not be null");
|
|
|
|
}
|
|
|
|
|
|
|
|
VideoFrameContainer::~VideoFrameContainer()
|
|
|
|
{}
|
|
|
|
|
2012-02-14 20:35:01 -08:00
|
|
|
void VideoFrameContainer::SetCurrentFrame(const gfxIntSize& aIntrinsicSize,
|
|
|
|
Image* aImage,
|
|
|
|
TimeStamp aTargetTime)
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
|
|
|
if (aIntrinsicSize != mIntrinsicSize) {
|
|
|
|
mIntrinsicSize = aIntrinsicSize;
|
|
|
|
mIntrinsicSizeChanged = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfxIntSize oldFrameSize = mImageContainer->GetCurrentSize();
|
|
|
|
TimeStamp lastPaintTime = mImageContainer->GetPaintTime();
|
|
|
|
if (!lastPaintTime.IsNull() && !mPaintTarget.IsNull()) {
|
|
|
|
mPaintDelay = lastPaintTime - mPaintTarget;
|
|
|
|
}
|
2012-09-26 21:33:43 -07:00
|
|
|
|
|
|
|
// When using the OMX decoder, destruction of the current image can indirectly
|
|
|
|
// block on main thread I/O. If we let this happen while holding onto
|
|
|
|
// |mImageContainer|'s lock, then when the main thread then tries to
|
|
|
|
// composite it can then block on |mImageContainer|'s lock, causing a
|
|
|
|
// deadlock. We use this hack to defer the destruction of the current image
|
|
|
|
// until it is safe.
|
|
|
|
nsRefPtr<Image> kungFuDeathGrip;
|
|
|
|
kungFuDeathGrip = mImageContainer->LockCurrentImage();
|
|
|
|
mImageContainer->UnlockCurrentImage();
|
|
|
|
|
2012-02-14 20:35:01 -08:00
|
|
|
mImageContainer->SetCurrentImage(aImage);
|
|
|
|
gfxIntSize newFrameSize = mImageContainer->GetCurrentSize();
|
|
|
|
if (oldFrameSize != newFrameSize) {
|
|
|
|
mImageSizeChanged = true;
|
2013-01-23 15:08:16 -08:00
|
|
|
mNeedInvalidation = true;
|
2012-02-14 20:35:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
mPaintTarget = aTargetTime;
|
|
|
|
}
|
|
|
|
|
2012-12-27 07:21:30 -08:00
|
|
|
void VideoFrameContainer::Reset()
|
|
|
|
{
|
|
|
|
ClearCurrentFrame(true);
|
|
|
|
Invalidate();
|
2013-02-04 06:21:44 -08:00
|
|
|
mIntrinsicSize = gfxIntSize(-1, -1);
|
2013-01-31 06:41:05 -08:00
|
|
|
mPaintDelay = mozilla::TimeDuration();
|
|
|
|
mPaintTarget = mozilla::TimeStamp();
|
2012-12-27 07:21:30 -08:00
|
|
|
mImageContainer->ResetPaintCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoFrameContainer::ClearCurrentFrame(bool aResetSize)
|
2012-09-26 21:33:43 -07:00
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
|
|
|
// See comment in SetCurrentFrame for the reasoning behind
|
|
|
|
// using a kungFuDeathGrip here.
|
|
|
|
nsRefPtr<Image> kungFuDeathGrip;
|
|
|
|
kungFuDeathGrip = mImageContainer->LockCurrentImage();
|
|
|
|
mImageContainer->UnlockCurrentImage();
|
|
|
|
|
|
|
|
mImageContainer->SetCurrentImage(nullptr);
|
2012-12-27 07:21:30 -08:00
|
|
|
mImageSizeChanged = aResetSize;
|
2012-10-19 17:18:31 -07:00
|
|
|
|
|
|
|
// We removed the current image so we will have to invalidate once
|
|
|
|
// again to setup the ImageContainer <-> Compositor pair.
|
|
|
|
mNeedInvalidation = true;
|
2012-09-26 21:33:43 -07:00
|
|
|
}
|
|
|
|
|
2012-08-20 21:06:46 -07:00
|
|
|
ImageContainer* VideoFrameContainer::GetImageContainer() {
|
|
|
|
return mImageContainer;
|
|
|
|
}
|
|
|
|
|
Backout b3a8618f901c (bug 829042), 34a9ef8f929d (bug 822933), 4c1215cefbab (bug 826349), 70bb7f775178 (bug 825325), e9c8447fb197 (bug 828713), eb6ebf01eafe (bug 828901), f1f3ef647920 (bug 825329), f9d7b5722d4f (bug 825329), 5add564d4546 (bug 819377), 55e93d1fa972 (bug 804875), f14639a3461e (bug 804875), 23456fc21052 (bug 814308) for Windows pgo-only mochitest-1 media test timeouts on a CLOSED TREE
2013-01-16 07:16:23 -08:00
|
|
|
|
2012-02-14 20:35:01 -08:00
|
|
|
double VideoFrameContainer::GetFrameDelay()
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
return mPaintDelay.ToSeconds();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoFrameContainer::Invalidate()
|
|
|
|
{
|
|
|
|
NS_ASSERTION(NS_IsMainThread(), "Must call on main thread");
|
2012-08-10 08:42:53 -07:00
|
|
|
|
|
|
|
if (!mNeedInvalidation) {
|
|
|
|
return;
|
|
|
|
}
|
2012-10-19 17:18:31 -07:00
|
|
|
|
|
|
|
if (mImageContainer &&
|
|
|
|
mImageContainer->IsAsync() &&
|
2013-01-23 15:08:16 -08:00
|
|
|
mImageContainer->HasCurrentImage() &&
|
|
|
|
!mIntrinsicSizeChanged) {
|
2012-08-10 08:42:53 -07:00
|
|
|
mNeedInvalidation = false;
|
|
|
|
}
|
|
|
|
|
2012-02-14 20:35:01 -08:00
|
|
|
if (!mElement) {
|
|
|
|
// Element has been destroyed
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame* frame = mElement->GetPrimaryFrame();
|
|
|
|
bool invalidateFrame = false;
|
|
|
|
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
|
|
|
// Get mImageContainerSizeChanged while holding the lock.
|
|
|
|
invalidateFrame = mImageSizeChanged;
|
|
|
|
mImageSizeChanged = false;
|
|
|
|
|
|
|
|
if (mIntrinsicSizeChanged) {
|
|
|
|
mElement->UpdateMediaSize(mIntrinsicSize);
|
|
|
|
mIntrinsicSizeChanged = false;
|
|
|
|
|
|
|
|
if (frame) {
|
|
|
|
nsPresContext* presContext = frame->PresContext();
|
|
|
|
nsIPresShell *presShell = presContext->PresShell();
|
|
|
|
presShell->FrameNeedsReflow(frame,
|
|
|
|
nsIPresShell::eStyleChange,
|
|
|
|
NS_FRAME_IS_DIRTY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frame) {
|
|
|
|
if (invalidateFrame) {
|
2012-08-28 22:39:31 -07:00
|
|
|
frame->InvalidateFrame();
|
2012-02-14 20:35:01 -08:00
|
|
|
} else {
|
2012-08-28 22:47:18 -07:00
|
|
|
frame->InvalidateLayer(nsDisplayItem::TYPE_VIDEO);
|
2012-02-14 20:35:01 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsSVGEffects::InvalidateDirectRenderingObservers(mElement);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|