author L10n Bumper Bot <>
Mon, 16 Sep 2019 19:00:33 +0000
changeset 551834 7eb35c46cab3137a924125ed12ca57c1c1eb8db0
parent 524474 81d85b9029903a05648fd609d4f425b0add12c6c
permissions -rw-r--r--
no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD cy -> 6a7cdd024e02 dsb -> cab0e87b192c el -> a0b719920c5f es-AR -> 1e278f18da1b es-ES -> 8780b8a6011c fr -> a13f3f38a5fd he -> f234e0677624 id -> e4f1e01168f1 pt-BR -> 06bdbe8a2c1e sv-SE -> 7d70d2a61a02 vi -> b04561b91eae zh-CN -> 819842cd6fda

/* -*- 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 */


#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"
#include "gfxPoint.h"
#include "nsCOMPtr.h"
#include "ImageContainer.h"
#include "MediaSegment.h"
#include "VideoSegment.h"

namespace mozilla {

class MediaDecoderOwner;

 * This object is used in the decoder backend threads and the main thread
 * to manage the "current video frame" state. This state includes timing data
 * and an intrinsic size (see below).
 * This has to be a thread-safe object since it's accessed by resource decoders
 * and other off-main-thread components. So we can't put this state in the media
 * element itself ... well, maybe we could, but it could be risky and/or
 * confusing.
class VideoFrameContainer {
  virtual ~VideoFrameContainer();


  typedef layers::ImageContainer ImageContainer;
  typedef layers::Image Image;

  VideoFrameContainer(MediaDecoderOwner* aOwner,
                      already_AddRefed<ImageContainer> aContainer);

  void SetCurrentFrame(const gfx::IntSize& aIntrinsicSize, Image* aImage,
                       const TimeStamp& aTargetTime);
  // Returns the last principalHandle we notified mElement about.
  PrincipalHandle GetLastPrincipalHandle();
  PrincipalHandle GetLastPrincipalHandleLocked();
  // We will notify mElement that aPrincipalHandle has been applied when all
  // FrameIDs prior to aFrameID have been flushed out.
  // aFrameID is ignored if aPrincipalHandle already is our pending
  // principalHandle.
  void UpdatePrincipalHandleForFrameID(const PrincipalHandle& aPrincipalHandle,
                                       const ImageContainer::FrameID& aFrameID);
  void UpdatePrincipalHandleForFrameIDLocked(
      const PrincipalHandle& aPrincipalHandle,
      const ImageContainer::FrameID& aFrameID);
  void SetCurrentFrames(
      const gfx::IntSize& aIntrinsicSize,
      const nsTArray<ImageContainer::NonOwningImage>& aImages);
  void ClearCurrentFrame(const gfx::IntSize& aIntrinsicSize) {

  void ClearCurrentFrame();
  // Make the current frame the only frame in the container, i.e. discard
  // all future frames.
  void ClearFutureFrames();
  // Time in seconds by which the last painted video frame was late by.
  // E.g. if the last painted frame should have been painted at time t,
  // but was actually painted at t+n, this returns n in seconds. Threadsafe.
  double GetFrameDelay();

  // Clear any resources that are not immediately necessary.
  void ClearCachedResources();

  // Returns a new frame ID for SetCurrentFrames().  The client must either
  // call this on only one thread or provide barriers.  Do not use together
  // with SetCurrentFrame().
  ImageContainer::FrameID NewFrameID() { return ++mFrameID; }

  // Call on main thread
  void Invalidate() { InvalidateWithFlags(INVALIDATE_DEFAULT); }
  void InvalidateWithFlags(uint32_t aFlags);
  ImageContainer* GetImageContainer();
  void ForgetElement() { mOwner = nullptr; }

  uint32_t GetDroppedImageCount() {
    return mImageContainer->GetDroppedImageCount();

  void SetCurrentFramesLocked(
      const gfx::IntSize& aIntrinsicSize,
      const nsTArray<ImageContainer::NonOwningImage>& aImages);

  // Non-addreffed pointer to the owner. The ownenr calls ForgetElement
  // to clear this reference when the owner is destroyed.
  MediaDecoderOwner* mOwner;
  RefPtr<ImageContainer> mImageContainer;

  struct {
    // True when the Image size has changed since the last time Invalidate() was
    // called. When set, the next call to Invalidate() will ensure that the
    // frame is fully invalidated instead of just invalidating for the image
    // change in the ImageLayer.
    bool mImageSizeChanged = false;
    // The main thread mirror of the member of the same name below.
    gfx::IntSize mIntrinsicSize;
    // True when the intrinsic size has been changed by SetCurrentFrame() since
    // the last call to Invalidate().
    // The next call to Invalidate() will recalculate
    // and update the intrinsic size on the element, request a frame reflow and
    // then reset this flag.
    bool mIntrinsicSizeChanged = false;
  } mMainThreadState;

  // mMutex protects all the fields below.
  Mutex mMutex;
  // The intrinsic size is the ideal size which we should render the
  // ImageContainer's current Image at.
  // This can differ from the Image's actual size when the media resource
  // specifies that the Image should be stretched to have the correct aspect
  // ratio.
  gfx::IntSize mIntrinsicSize;
  // We maintain our own mFrameID which is auto-incremented at every
  // SetCurrentFrame() or NewFrameID() call.
  ImageContainer::FrameID mFrameID;
  // The last PrincipalHandle we notified mElement about.
  PrincipalHandle mLastPrincipalHandle;
  // The PrincipalHandle the client has notified us is changing with FrameID
  // mFrameIDForPendingPrincipalHandle.
  PrincipalHandle mPendingPrincipalHandle;
  // The FrameID for which mPendingPrincipal is first valid.
  ImageContainer::FrameID mFrameIDForPendingPrincipalHandle;

  const RefPtr<AbstractThread> mMainThread;

}  // namespace mozilla