Coverage Report

Created: 2018-09-25 14:53

/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