Line data Source code
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/. */
6 :
7 : #ifndef VIDEOFRAMECONTAINER_H_
8 : #define VIDEOFRAMECONTAINER_H_
9 :
10 : #include "mozilla/Mutex.h"
11 : #include "mozilla/TimeStamp.h"
12 : #include "gfxPoint.h"
13 : #include "nsCOMPtr.h"
14 : #include "ImageContainer.h"
15 : #include "MediaSegment.h"
16 : #include "MediaStreamVideoSink.h"
17 : #include "VideoSegment.h"
18 :
19 : namespace mozilla {
20 :
21 : namespace dom {
22 : class HTMLMediaElement;
23 : } // namespace dom
24 :
25 : /**
26 : * This object is used in the decoder backend threads and the main thread
27 : * to manage the "current video frame" state. This state includes timing data
28 : * and an intrinsic size (see below).
29 : * This has to be a thread-safe object since it's accessed by resource decoders
30 : * and other off-main-thread components. So we can't put this state in the media
31 : * element itself ... well, maybe we could, but it could be risky and/or
32 : * confusing.
33 : */
34 : class VideoFrameContainer : public MediaStreamVideoSink {
35 : virtual ~VideoFrameContainer();
36 :
37 : public:
38 : typedef layers::ImageContainer ImageContainer;
39 : typedef layers::Image Image;
40 :
41 : VideoFrameContainer(dom::HTMLMediaElement* aElement,
42 : already_AddRefed<ImageContainer> aContainer);
43 :
44 : // Call on any thread
45 : virtual void SetCurrentFrames(const VideoSegment& aSegment) override;
46 : virtual void ClearFrames() override;
47 : void SetCurrentFrame(const gfx::IntSize& aIntrinsicSize, Image* aImage,
48 : const TimeStamp& aTargetTime);
49 : // Returns the last principalHandle we notified mElement about.
50 : PrincipalHandle GetLastPrincipalHandle();
51 : PrincipalHandle GetLastPrincipalHandleLocked();
52 : // We will notify mElement that aPrincipalHandle has been applied when all
53 : // FrameIDs prior to aFrameID have been flushed out.
54 : // aFrameID is ignored if aPrincipalHandle already is our pending principalHandle.
55 : void UpdatePrincipalHandleForFrameID(const PrincipalHandle& aPrincipalHandle,
56 : const ImageContainer::FrameID& aFrameID);
57 : void UpdatePrincipalHandleForFrameIDLocked(const PrincipalHandle& aPrincipalHandle,
58 : const ImageContainer::FrameID& aFrameID);
59 : void SetCurrentFrames(const gfx::IntSize& aIntrinsicSize,
60 : const nsTArray<ImageContainer::NonOwningImage>& aImages);
61 0 : void ClearCurrentFrame(const gfx::IntSize& aIntrinsicSize)
62 : {
63 0 : SetCurrentFrames(aIntrinsicSize, nsTArray<ImageContainer::NonOwningImage>());
64 0 : }
65 0 : VideoFrameContainer* AsVideoFrameContainer() override { return this; }
66 :
67 : void ClearCurrentFrame();
68 : // Make the current frame the only frame in the container, i.e. discard
69 : // all future frames.
70 : void ClearFutureFrames();
71 : // Time in seconds by which the last painted video frame was late by.
72 : // E.g. if the last painted frame should have been painted at time t,
73 : // but was actually painted at t+n, this returns n in seconds. Threadsafe.
74 : double GetFrameDelay();
75 :
76 : // Clear any resources that are not immediately necessary.
77 : void ClearCachedResources();
78 :
79 : // Returns a new frame ID for SetCurrentFrames(). The client must either
80 : // call this on only one thread or provide barriers. Do not use together
81 : // with SetCurrentFrame().
82 0 : ImageContainer::FrameID NewFrameID()
83 : {
84 0 : return ++mFrameID;
85 : }
86 :
87 : // Call on main thread
88 : enum {
89 : INVALIDATE_DEFAULT,
90 : INVALIDATE_FORCE
91 : };
92 0 : void Invalidate() override { InvalidateWithFlags(INVALIDATE_DEFAULT); }
93 : void InvalidateWithFlags(uint32_t aFlags);
94 : ImageContainer* GetImageContainer();
95 0 : void ForgetElement() { mElement = nullptr; }
96 :
97 : uint32_t GetDroppedImageCount() { return mImageContainer->GetDroppedImageCount(); }
98 :
99 : protected:
100 : void SetCurrentFramesLocked(const gfx::IntSize& aIntrinsicSize,
101 : const nsTArray<ImageContainer::NonOwningImage>& aImages);
102 :
103 : // Non-addreffed pointer to the element. The element calls ForgetElement
104 : // to clear this reference when the element is destroyed.
105 : dom::HTMLMediaElement* mElement;
106 : RefPtr<ImageContainer> mImageContainer;
107 :
108 : struct
109 0 : {
110 : // True when the Image size has changed since the last time Invalidate() was
111 : // called. When set, the next call to Invalidate() will ensure that the
112 : // frame is fully invalidated instead of just invalidating for the image change
113 : // in the ImageLayer.
114 : bool mImageSizeChanged = false;
115 : // The main thread mirror of the member of the same name below.
116 : gfx::IntSize mIntrinsicSize;
117 : // True when the intrinsic size has been changed by SetCurrentFrame() since
118 : // the last call to Invalidate().
119 : // The next call to Invalidate() will recalculate
120 : // and update the intrinsic size on the element, request a frame reflow and
121 : // then reset this flag.
122 : bool mIntrinsicSizeChanged = false;
123 : } mMainThreadState;
124 :
125 : // mMutex protects all the fields below.
126 : Mutex mMutex;
127 : // Once the frame is forced to black, we initialize mBlackImage for following
128 : // frames.
129 : RefPtr<Image> mBlackImage;
130 : // The intrinsic size is the ideal size which we should render the
131 : // ImageContainer's current Image at.
132 : // This can differ from the Image's actual size when the media resource
133 : // specifies that the Image should be stretched to have the correct aspect
134 : // ratio.
135 : gfx::IntSize mIntrinsicSize;
136 : // We maintain our own mFrameID which is auto-incremented at every
137 : // SetCurrentFrame() or NewFrameID() call.
138 : ImageContainer::FrameID mFrameID;
139 : // We record the last played video frame to avoid playing the frame again
140 : // with a different frame id.
141 : VideoFrame mLastPlayedVideoFrame;
142 : // The last PrincipalHandle we notified mElement about.
143 : PrincipalHandle mLastPrincipalHandle;
144 : // The PrincipalHandle the client has notified us is changing with FrameID
145 : // mFrameIDForPendingPrincipalHandle.
146 : PrincipalHandle mPendingPrincipalHandle;
147 : // The FrameID for which mPendingPrincipal is first valid.
148 : ImageContainer::FrameID mFrameIDForPendingPrincipalHandle;
149 :
150 : const RefPtr<AbstractThread> mMainThread;
151 : };
152 :
153 : } // namespace mozilla
154 :
155 : #endif /* VIDEOFRAMECONTAINER_H_ */
|