content/media/VideoFrameContainer.cpp

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial