FastLED 3.9.7
Loading...
Searching...
No Matches
video_impl.cpp
1
2
3
4#include "video_impl.h"
5
6#include "fl/dbg.h"
7#include "fl/math_macros.h"
8#include "fl/namespace.h"
9
10
11#define DBG FASTLED_DBG
12
13using namespace fl;
14
15namespace fl {
16
17VideoImpl::VideoImpl(size_t pixelsPerFrame, float fpsVideo,
18 size_t nFramesInBuffer)
19 : mPixelsPerFrame(pixelsPerFrame),
20 mFrameInterpolator(
21 FrameInterpolatorPtr::New(MAX(1, nFramesInBuffer), fpsVideo)) {}
22
23void VideoImpl::pause(uint32_t now) {
24 if (!mTimeScale) {
25 mTimeScale = TimeScalePtr::New(now);
26 }
27 mTimeScale->pause(now);
28}
29void VideoImpl::resume(uint32_t now) {
30 if (!mTimeScale) {
31 mTimeScale = TimeScalePtr::New(now);
32 }
33 mTimeScale->resume(now);
34}
35
36void VideoImpl::setTimeScale(float timeScale) {
37 if (!mTimeScale) {
38 mTimeScale = TimeScalePtr::New(0, timeScale);
39 }
40 mTimeScale->setScale(timeScale);
41}
42
43bool VideoImpl::needsFrame(uint32_t now) const {
44 uint32_t f1, f2;
45 bool out = mFrameInterpolator->needsFrame(now, &f1, &f2);
46 return out;
47}
48
49VideoImpl::~VideoImpl() { end(); }
50
51void VideoImpl::begin(FileHandlePtr h) {
52 end();
53 // Removed setStartTime call
54 mStream = PixelStreamPtr::New(mPixelsPerFrame * kSizeRGB8);
55 mStream->begin(h);
56 mPrevNow = 0;
57}
58
59void VideoImpl::beginStream(ByteStreamPtr bs) {
60 end();
61 mStream = PixelStreamPtr::New(mPixelsPerFrame * kSizeRGB8);
62 // Removed setStartTime call
63 mStream->beginStream(bs);
64 mPrevNow = 0;
65}
66
67void VideoImpl::end() {
68 mFrameInterpolator->clear();
69 // Removed resetFrameCounter and setStartTime calls
70 mStream.reset();
71}
72
73bool VideoImpl::full() const { return mFrameInterpolator->getFrames()->full(); }
74
75bool VideoImpl::draw(uint32_t now, Frame *frame) {
76 //DBG("draw with now = " << now);
77 if (!mStream) {
78 DBG("no stream");
79 return false;
80 }
81 updateBufferIfNecessary(mPrevNow, now);
82 mPrevNow = now;
83 if (!frame) {
84 return false;
85 }
86 bool ok = mFrameInterpolator->draw(now, frame);
87 return ok;
88}
89
90bool VideoImpl::draw(uint32_t now, CRGB *leds) {
91 //DBG("draw with now = " << now);
92 if (!mTimeScale) {
93 mTimeScale = TimeScalePtr::New(now);
94 }
95 now = mTimeScale->update(now);
96 if (!mStream) {
97 DBG("no stream");
98 return false;
99 }
100 bool ok = updateBufferIfNecessary(mPrevNow, now);
101 mPrevNow = now;
102 if (!ok) {
103 DBG("updateBufferIfNecessary failed");
104 return false;
105 }
106 mFrameInterpolator->draw(now, leds);
107 return true;
108}
109
110
111bool VideoImpl::updateBufferFromStream(uint32_t now) {
112 if (!mStream) {
113 FASTLED_DBG("no stream");
114 return false;
115 }
116 if (mStream->atEnd()) {
117 return false;
118 }
119
120 uint32_t currFrameNumber = 0;
121 uint32_t nextFrameNumber = 0;
122 bool needs_frame = mFrameInterpolator->needsFrame(now, &currFrameNumber, &nextFrameNumber);
123 if (!needs_frame) {
124 return true;
125 }
126
127 if (mFrameInterpolator->capacity() == 0) {
128 DBG("capacity == 0");
129 return false;
130 }
131
132 const bool has_current_frame = mFrameInterpolator->has(currFrameNumber);
133 const bool has_next_frame = mFrameInterpolator->has(nextFrameNumber);
134
135 fl::FixedVector<uint32_t, 2> frame_numbers;
136 if (!has_current_frame) {
137 frame_numbers.push_back(currFrameNumber);
138 }
139 size_t capacity = mFrameInterpolator->capacity();
140 if (capacity > 1 && !has_next_frame) {
141 frame_numbers.push_back(nextFrameNumber);
142 }
143
144 for (size_t i = 0; i < frame_numbers.size(); ++i) {
145 FramePtr recycled_frame;
146 if (mFrameInterpolator->full()) {
147 uint32_t frame_to_erase = 0;
148 bool ok = mFrameInterpolator->get_oldest_frame_number(&frame_to_erase);
149 if (!ok) {
150 DBG("get_oldest_frame_number failed");
151 return false;
152 }
153 recycled_frame = mFrameInterpolator->erase(frame_to_erase);
154 if (!recycled_frame) {
155 DBG("erase failed for frame: " << frame_to_erase);
156 return false;
157 }
158 }
159 uint32_t frame_to_fetch = frame_numbers[i];
160 if (!recycled_frame) {
161 // Happens when we are not full and we need to allocate a new frame.
162 recycled_frame = FramePtr::New(mPixelsPerFrame);
163 }
164
165 if (!mStream->readFrame(recycled_frame.get())) {
166 if (mStream->atEnd()) {
167 if (!mStream->rewind()) {
168 DBG("rewind failed");
169 return false;
170 }
171 mTimeScale->reset(now);
172 frame_to_fetch = 0;
173 if (!mStream->readFrameAt(frame_to_fetch, recycled_frame.get())) {
174 DBG("readFrameAt failed");
175 return false;
176 }
177 } else {
178 DBG("We failed for some other reason");
179 return false;
180 }
181 }
182 bool ok = mFrameInterpolator->insert(frame_to_fetch, recycled_frame);
183 if (!ok) {
184 DBG("insert failed");
185 return false;
186 }
187 }
188 return true;
189}
190
191bool VideoImpl::updateBufferFromFile(uint32_t now, bool forward) {
192 uint32_t currFrameNumber = 0;
193 uint32_t nextFrameNumber = 0;
194 bool needs_frame = mFrameInterpolator->needsFrame(now, &currFrameNumber, &nextFrameNumber);
195 if (!needs_frame) {
196 return true;
197 }
198 bool has_curr_frame = mFrameInterpolator->has(currFrameNumber);
199 bool has_next_frame = mFrameInterpolator->has(nextFrameNumber);
200 if (has_curr_frame && has_next_frame) {
201 return true;
202 }
203 if (mFrameInterpolator->capacity() == 0) {
204 DBG("capacity == 0");
205 return false;
206 }
207
208 fl::FixedVector<uint32_t, 2> frame_numbers;
209 if (!mFrameInterpolator->has(currFrameNumber)) {
210 frame_numbers.push_back(currFrameNumber);
211 }
212 if (mFrameInterpolator->capacity() > 1 && !mFrameInterpolator->has(nextFrameNumber)) {
213 frame_numbers.push_back(nextFrameNumber);
214 }
215
216 for (size_t i = 0; i < frame_numbers.size(); ++i) {
217 FramePtr recycled_frame;
218 if (mFrameInterpolator->full()) {
219 uint32_t frame_to_erase = 0;
220 bool ok = false;
221 if (forward) {
222 ok = mFrameInterpolator->get_oldest_frame_number(&frame_to_erase);
223 if (!ok) {
224 DBG("get_oldest_frame_number failed");
225 return false;
226 }
227 } else {
228 ok = mFrameInterpolator->get_newest_frame_number(&frame_to_erase);
229 if (!ok) {
230 DBG("get_newest_frame_number failed");
231 return false;
232 }
233 }
234 recycled_frame = mFrameInterpolator->erase(frame_to_erase);
235 if (!recycled_frame) {
236 DBG("erase failed for frame: " << frame_to_erase);
237 return false;
238 }
239 }
240 uint32_t frame_to_fetch = frame_numbers[i];
241 if (!recycled_frame) {
242 // Happens when we are not full and we need to allocate a new frame.
243 recycled_frame = FramePtr::New(mPixelsPerFrame);
244 }
245
246 do { // only to use break
247 if (!mStream->readFrameAt(frame_to_fetch, recycled_frame.get())) {
248 if (!forward) {
249 // nothing more we can do, we can't go negative.
250 return false;
251 }
252 if (mStream->atEnd()) {
253 if (!mStream->rewind()) { // Is this still
254 DBG("rewind failed");
255 return false;
256 }
257 mTimeScale->reset(now);
258 frame_to_fetch = 0;
259 if (!mStream->readFrameAt(frame_to_fetch, recycled_frame.get())) {
260 DBG("readFrameAt failed");
261 return false;
262 }
263 break; // we have the frame, so we can break out of the loop
264 }
265 DBG("We failed for some other reason");
266 return false;
267 }
268 break;
269 } while (false);
270
271 bool ok = mFrameInterpolator->insert(frame_to_fetch, recycled_frame);
272 if (!ok) {
273 DBG("insert failed");
274 return false;
275 }
276 }
277 return true;
278}
279
280bool VideoImpl::updateBufferIfNecessary(uint32_t prev, uint32_t now) {
281 const bool forward = now >= prev;
282
283 PixelStream::Type type = mStream->getType();
284 switch (type) {
285 case PixelStream::kFile:
286 return updateBufferFromFile(now, forward);
287 case PixelStream::kStreaming:
288 return updateBufferFromStream(now);
289 default:
290 DBG("Unknown type: " << type);
291 return false;
292 }
293}
294
295bool VideoImpl::rewind() {
296 if (!mStream || !mStream->rewind()) {
297 return false;
298 }
299 mFrameInterpolator->clear();
300 return true;
301}
302
303} // namespace fl
Implements the FastLED namespace macros.
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:54