summaryrefslogtreecommitdiffstats
path: root/dom/media/VideoFrameContainer.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/VideoFrameContainer.h')
-rw-r--r--dom/media/VideoFrameContainer.h147
1 files changed, 147 insertions, 0 deletions
diff --git a/dom/media/VideoFrameContainer.h b/dom/media/VideoFrameContainer.h
new file mode 100644
index 000000000..b5c84e760
--- /dev/null
+++ b/dom/media/VideoFrameContainer.h
@@ -0,0 +1,147 @@
+/* -*- 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 "MediaStreamVideoSink.h"
+#include "VideoSegment.h"
+
+namespace mozilla {
+
+namespace dom {
+class HTMLMediaElement;
+} // namespace dom
+
+/**
+ * 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 : public MediaStreamVideoSink {
+ virtual ~VideoFrameContainer();
+
+public:
+ typedef layers::ImageContainer ImageContainer;
+ typedef layers::Image Image;
+
+ VideoFrameContainer(dom::HTMLMediaElement* aElement,
+ already_AddRefed<ImageContainer> aContainer);
+
+ // Call on any thread
+ virtual void SetCurrentFrames(const VideoSegment& aSegment) override;
+ virtual void ClearFrames() override;
+ 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>());
+ }
+ VideoFrameContainer* AsVideoFrameContainer() override { return this; }
+
+ 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() override { InvalidateWithFlags(INVALIDATE_DEFAULT); }
+ void InvalidateWithFlags(uint32_t aFlags);
+ ImageContainer* GetImageContainer();
+ void ForgetElement() { mElement = nullptr; }
+
+ uint32_t GetDroppedImageCount() { return mImageContainer->GetDroppedImageCount(); }
+
+protected:
+ void SetCurrentFramesLocked(const gfx::IntSize& aIntrinsicSize,
+ const nsTArray<ImageContainer::NonOwningImage>& aImages);
+
+ // Non-addreffed pointer to the element. The element calls ForgetElement
+ // to clear this reference when the element is destroyed.
+ dom::HTMLMediaElement* mElement;
+ RefPtr<ImageContainer> mImageContainer;
+
+ // mMutex protects all the fields below.
+ Mutex mMutex;
+ // Once the frame is forced to black, we initialize mBlackImage for following
+ // frames.
+ RefPtr<Image> mBlackImage;
+ // 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;
+ // We record the last played video frame to avoid playing the frame again
+ // with a different frame id.
+ VideoFrame mLastPlayedVideoFrame;
+ // 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;
+ // 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;
+ // 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;
+};
+
+} // namespace mozilla
+
+#endif /* VIDEOFRAMECONTAINER_H_ */