/src/mozilla-central/image/AnimationFrameBuffer.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | #ifndef mozilla_image_AnimationFrameBuffer_h |
7 | | #define mozilla_image_AnimationFrameBuffer_h |
8 | | |
9 | | #include "ISurfaceProvider.h" |
10 | | |
11 | | namespace mozilla { |
12 | | namespace image { |
13 | | |
14 | | /** |
15 | | * An AnimationFrameBuffer owns the frames outputted by an animated image |
16 | | * decoder as well as directing its owner on how to drive the decoder, |
17 | | * whether to produce more or to stop. |
18 | | * |
19 | | * Based upon its given configuration parameters, it will retain up to a |
20 | | * certain number of frames in the buffer before deciding to discard previous |
21 | | * frames, and relying upon the decoder to recreate older frames when the |
22 | | * animation loops. It will also request that the decoder stop producing more |
23 | | * frames when the display of the frames are far behind -- this allows other |
24 | | * tasks and images which require decoding to take execution priority. |
25 | | * |
26 | | * The desire is that smaller animated images should be kept completely in |
27 | | * memory while larger animated images should only keep a certain number of |
28 | | * frames to minimize our memory footprint at the cost of CPU. |
29 | | */ |
30 | | class AnimationFrameBuffer final |
31 | | { |
32 | | public: |
33 | | AnimationFrameBuffer(); |
34 | | |
35 | | /** |
36 | | * Configure the frame buffer with a particular threshold and batch size. Note |
37 | | * that the frame buffer may adjust the given values. |
38 | | * |
39 | | * @param aThreshold Maximum number of frames that may be stored in the frame |
40 | | * buffer before it may discard already displayed frames. |
41 | | * Once exceeded, it will discard the previous frame to the |
42 | | * current frame whenever Advance is called. It always |
43 | | * retains the first frame. |
44 | | * |
45 | | * @param aBatch Number of frames we request to be decoded each time it |
46 | | * decides we need more. |
47 | | * |
48 | | * @param aStartFrame The starting frame for the animation. The frame buffer |
49 | | * will auto-advance (and thus keep the decoding pipeline |
50 | | * going) until it has reached this frame. Useful when the |
51 | | * animation was progressing, but the surface was |
52 | | * discarded, and we had to redecode. |
53 | | */ |
54 | | void Initialize(size_t aThreshold, size_t aBatch, size_t aStartFrame); |
55 | | |
56 | | /** |
57 | | * Access a specific frame from the frame buffer. It should generally access |
58 | | * frames in sequential order, increasing in tandem with AdvanceTo calls. The |
59 | | * first frame may be accessed at any time. The access order should start with |
60 | | * the same value as that given in Initialize (aStartFrame). |
61 | | * |
62 | | * @param aFrame The frame index to access. |
63 | | * |
64 | | * @returns The frame, if available. |
65 | | */ |
66 | | imgFrame* Get(size_t aFrame); |
67 | | |
68 | | /** |
69 | | * Inserts a frame into the frame buffer. If it has yet to fully decode the |
70 | | * animated image yet, then it will append the frame to its internal buffer. |
71 | | * If it has been fully decoded, it will replace the next frame in its buffer |
72 | | * with the given frame. |
73 | | * |
74 | | * Once we have a sufficient number of frames buffered relative to the |
75 | | * currently displayed frame, it will return false to indicate the caller |
76 | | * should stop decoding. |
77 | | * |
78 | | * @param aFrame The frame to insert into the buffer. |
79 | | * |
80 | | * @returns True if the decoder should decode another frame. |
81 | | */ |
82 | | bool Insert(RawAccessFrameRef&& aFrame); |
83 | | |
84 | | /** |
85 | | * This should be called after the last frame has been inserted. If the buffer |
86 | | * is discarding old frames, it may request more frames to be decoded. In this |
87 | | * case that means the decoder should start again from the beginning. This |
88 | | * return value should be used in preference to that of the Insert call. |
89 | | * |
90 | | * @returns True if the decoder should decode another frame. |
91 | | */ |
92 | | bool MarkComplete(); |
93 | | |
94 | | /** |
95 | | * Advance the currently displayed frame of the frame buffer. If it reaches |
96 | | * the end, it will loop back to the beginning. It should not be called unless |
97 | | * a call to Get has returned a valid frame for the next frame index. |
98 | | * |
99 | | * As we advance, the number of frames we have buffered ahead of the current |
100 | | * will shrink. Once that becomes too few, we will request a batch-sized set |
101 | | * of frames to be decoded from the decoder. |
102 | | * |
103 | | * @param aExpectedFrame The frame we expect to have advanced to. This is |
104 | | * used for confirmation purposes (e.g. asserts). |
105 | | * |
106 | | * @returns True if the caller should restart the decoder. |
107 | | */ |
108 | | bool AdvanceTo(size_t aExpectedFrame); |
109 | | |
110 | | /** |
111 | | * Resets the currently displayed frame of the frame buffer to the beginning. |
112 | | * If the buffer is discarding old frames, it will actually discard all frames |
113 | | * besides the first. |
114 | | * |
115 | | * @returns True if the caller should restart the decoder. |
116 | | */ |
117 | | bool Reset(); |
118 | | |
119 | | /** |
120 | | * @returns True if frames post-advance may be discarded and redecoded on |
121 | | * demand, else false. |
122 | | */ |
123 | 0 | bool MayDiscard() const { return mFrames.Length() > mThreshold; } |
124 | | |
125 | | /** |
126 | | * @returns True if the frame buffer was ever marked as complete. This implies |
127 | | * that the total number of frames is known and may be gotten from |
128 | | * Frames().Length(). |
129 | | */ |
130 | 0 | bool SizeKnown() const { return mSizeKnown; } |
131 | | |
132 | | /** |
133 | | * @returns True if encountered an error during redecode which should cause |
134 | | * the caller to stop inserting frames. |
135 | | */ |
136 | 0 | bool HasRedecodeError() const { return mRedecodeError; } |
137 | | |
138 | | /** |
139 | | * @returns The current frame index we have advanced to. |
140 | | */ |
141 | 0 | size_t Displayed() const { return mGetIndex; } |
142 | | |
143 | | /** |
144 | | * @returns Outstanding frames desired from the decoder. |
145 | | */ |
146 | 0 | size_t PendingDecode() const { return mPending; } |
147 | | |
148 | | /** |
149 | | * @returns Outstanding frames to advance internally. |
150 | | */ |
151 | 0 | size_t PendingAdvance() const { return mAdvance; } |
152 | | |
153 | | /** |
154 | | * @returns Number of frames we request to be decoded each time it decides we |
155 | | * need more. |
156 | | */ |
157 | 0 | size_t Batch() const { return mBatch; } |
158 | | |
159 | | /** |
160 | | * @returns Maximum number of frames before we start discarding previous |
161 | | * frames post-advance. |
162 | | */ |
163 | 0 | size_t Threshold() const { return mThreshold; } |
164 | | |
165 | | /** |
166 | | * @returns The frames of this animation, in order. May contain empty indices. |
167 | | */ |
168 | 0 | const nsTArray<RawAccessFrameRef>& Frames() const { return mFrames; } |
169 | | |
170 | | private: |
171 | | bool AdvanceInternal(); |
172 | | |
173 | | /// The frames of this animation, in order, but may have holes if discarding. |
174 | | nsTArray<RawAccessFrameRef> mFrames; |
175 | | |
176 | | // The maximum number of frames we can have before discarding. |
177 | | size_t mThreshold; |
178 | | |
179 | | // The minimum number of frames that we want buffered ahead of the display. |
180 | | size_t mBatch; |
181 | | |
182 | | // The number of frames to decode before we stop. |
183 | | size_t mPending; |
184 | | |
185 | | // The number of frames we need to auto-advance to synchronize with the caller. |
186 | | size_t mAdvance; |
187 | | |
188 | | // The mFrames index in which to insert the next decoded frame. |
189 | | size_t mInsertIndex; |
190 | | |
191 | | // The mFrames index that we have advanced to. |
192 | | size_t mGetIndex; |
193 | | |
194 | | // True if the total number of frames is known. |
195 | | bool mSizeKnown; |
196 | | |
197 | | // True if we encountered an error while redecoding. |
198 | | bool mRedecodeError; |
199 | | }; |
200 | | |
201 | | } // namespace image |
202 | | } // namespace mozilla |
203 | | |
204 | | #endif // mozilla_image_AnimationFrameBuffer_h |