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