DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (87e55ae73eb9)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
/* -*- 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/. */

#ifndef VIDEOFRAMECONTAINER_H_
#define VIDEOFRAMECONTAINER_H_

#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();

  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoFrameContainer)

 public:
  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) {
    SetCurrentFrames(aIntrinsicSize,
                     nsTArray<ImageContainer::NonOwningImage>());
  }

  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
  enum { INVALIDATE_DEFAULT, INVALIDATE_FORCE };
  void Invalidate() { InvalidateWithFlags(INVALIDATE_DEFAULT); }
  void InvalidateWithFlags(uint32_t aFlags);
  ImageContainer* GetImageContainer();
  void ForgetElement() { mOwner = nullptr; }

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

 protected:
  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

#endif /* VIDEOFRAMECONTAINER_H_ */