content/media/VideoFrameContainer.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "VideoFrameContainer.h"
michael@0 8
michael@0 9 #include "mozilla/dom/HTMLMediaElement.h"
michael@0 10 #include "nsIFrame.h"
michael@0 11 #include "nsDisplayList.h"
michael@0 12 #include "nsSVGEffects.h"
michael@0 13 #include "ImageContainer.h"
michael@0 14
michael@0 15 using namespace mozilla::layers;
michael@0 16
michael@0 17 namespace mozilla {
michael@0 18
michael@0 19 VideoFrameContainer::VideoFrameContainer(dom::HTMLMediaElement* aElement,
michael@0 20 already_AddRefed<ImageContainer> aContainer)
michael@0 21 : mElement(aElement),
michael@0 22 mImageContainer(aContainer), mMutex("nsVideoFrameContainer"),
michael@0 23 mIntrinsicSizeChanged(false), mImageSizeChanged(false)
michael@0 24 {
michael@0 25 NS_ASSERTION(aElement, "aElement must not be null");
michael@0 26 NS_ASSERTION(mImageContainer, "aContainer must not be null");
michael@0 27 }
michael@0 28
michael@0 29 VideoFrameContainer::~VideoFrameContainer()
michael@0 30 {}
michael@0 31
michael@0 32 void VideoFrameContainer::SetCurrentFrame(const gfxIntSize& aIntrinsicSize,
michael@0 33 Image* aImage,
michael@0 34 TimeStamp aTargetTime)
michael@0 35 {
michael@0 36 MutexAutoLock lock(mMutex);
michael@0 37
michael@0 38 if (aIntrinsicSize != mIntrinsicSize) {
michael@0 39 mIntrinsicSize = aIntrinsicSize;
michael@0 40 mIntrinsicSizeChanged = true;
michael@0 41 }
michael@0 42
michael@0 43 gfx::IntSize oldFrameSize = mImageContainer->GetCurrentSize();
michael@0 44 TimeStamp lastPaintTime = mImageContainer->GetPaintTime();
michael@0 45 if (!lastPaintTime.IsNull() && !mPaintTarget.IsNull()) {
michael@0 46 mPaintDelay = lastPaintTime - mPaintTarget;
michael@0 47 }
michael@0 48
michael@0 49 // When using the OMX decoder, destruction of the current image can indirectly
michael@0 50 // block on main thread I/O. If we let this happen while holding onto
michael@0 51 // |mImageContainer|'s lock, then when the main thread then tries to
michael@0 52 // composite it can then block on |mImageContainer|'s lock, causing a
michael@0 53 // deadlock. We use this hack to defer the destruction of the current image
michael@0 54 // until it is safe.
michael@0 55 nsRefPtr<Image> kungFuDeathGrip;
michael@0 56 kungFuDeathGrip = mImageContainer->LockCurrentImage();
michael@0 57 mImageContainer->UnlockCurrentImage();
michael@0 58
michael@0 59 mImageContainer->SetCurrentImage(aImage);
michael@0 60 gfx::IntSize newFrameSize = mImageContainer->GetCurrentSize();
michael@0 61 if (oldFrameSize != newFrameSize) {
michael@0 62 mImageSizeChanged = true;
michael@0 63 }
michael@0 64
michael@0 65 mPaintTarget = aTargetTime;
michael@0 66 }
michael@0 67
michael@0 68 void VideoFrameContainer::Reset()
michael@0 69 {
michael@0 70 ClearCurrentFrame(true);
michael@0 71 Invalidate();
michael@0 72 mIntrinsicSize = gfxIntSize(-1, -1);
michael@0 73 mPaintDelay = mozilla::TimeDuration();
michael@0 74 mPaintTarget = mozilla::TimeStamp();
michael@0 75 mImageContainer->ResetPaintCount();
michael@0 76 }
michael@0 77
michael@0 78 void VideoFrameContainer::ClearCurrentFrame(bool aResetSize)
michael@0 79 {
michael@0 80 MutexAutoLock lock(mMutex);
michael@0 81
michael@0 82 // See comment in SetCurrentFrame for the reasoning behind
michael@0 83 // using a kungFuDeathGrip here.
michael@0 84 nsRefPtr<Image> kungFuDeathGrip;
michael@0 85 kungFuDeathGrip = mImageContainer->LockCurrentImage();
michael@0 86 mImageContainer->UnlockCurrentImage();
michael@0 87
michael@0 88 mImageContainer->ClearAllImages();
michael@0 89 mImageSizeChanged = aResetSize;
michael@0 90 }
michael@0 91
michael@0 92 ImageContainer* VideoFrameContainer::GetImageContainer() {
michael@0 93 return mImageContainer;
michael@0 94 }
michael@0 95
michael@0 96
michael@0 97 double VideoFrameContainer::GetFrameDelay()
michael@0 98 {
michael@0 99 MutexAutoLock lock(mMutex);
michael@0 100 return mPaintDelay.ToSeconds();
michael@0 101 }
michael@0 102
michael@0 103 void VideoFrameContainer::InvalidateWithFlags(uint32_t aFlags)
michael@0 104 {
michael@0 105 NS_ASSERTION(NS_IsMainThread(), "Must call on main thread");
michael@0 106
michael@0 107 if (!mElement) {
michael@0 108 // Element has been destroyed
michael@0 109 return;
michael@0 110 }
michael@0 111
michael@0 112 nsIFrame* frame = mElement->GetPrimaryFrame();
michael@0 113 bool invalidateFrame = false;
michael@0 114
michael@0 115 {
michael@0 116 MutexAutoLock lock(mMutex);
michael@0 117
michael@0 118 // Get mImageContainerSizeChanged while holding the lock.
michael@0 119 invalidateFrame = mImageSizeChanged;
michael@0 120 mImageSizeChanged = false;
michael@0 121
michael@0 122 if (mIntrinsicSizeChanged) {
michael@0 123 mElement->UpdateMediaSize(mIntrinsicSize);
michael@0 124 mIntrinsicSizeChanged = false;
michael@0 125
michael@0 126 if (frame) {
michael@0 127 nsPresContext* presContext = frame->PresContext();
michael@0 128 nsIPresShell *presShell = presContext->PresShell();
michael@0 129 presShell->FrameNeedsReflow(frame,
michael@0 130 nsIPresShell::eStyleChange,
michael@0 131 NS_FRAME_IS_DIRTY);
michael@0 132 }
michael@0 133 }
michael@0 134 }
michael@0 135
michael@0 136 bool asyncInvalidate = mImageContainer &&
michael@0 137 mImageContainer->IsAsync() &&
michael@0 138 !(aFlags & INVALIDATE_FORCE);
michael@0 139
michael@0 140 if (frame) {
michael@0 141 if (invalidateFrame) {
michael@0 142 frame->InvalidateFrame();
michael@0 143 } else {
michael@0 144 frame->InvalidateLayer(nsDisplayItem::TYPE_VIDEO, nullptr,
michael@0 145 asyncInvalidate ? nsIFrame::UPDATE_IS_ASYNC : 0);
michael@0 146 }
michael@0 147 }
michael@0 148
michael@0 149 nsSVGEffects::InvalidateDirectRenderingObservers(mElement);
michael@0 150 }
michael@0 151
michael@0 152 }

mercurial