12VideoImpl::VideoImpl(
size_t pixelsPerFrame,
float fpsVideo,
13 size_t nFramesInBuffer)
14 : mPixelsPerFrame(pixelsPerFrame),
18void VideoImpl::pause(fl::u32 now) {
24void VideoImpl::resume(fl::u32 now) {
31void VideoImpl::setTimeScale(
float timeScale) {
38void VideoImpl::setFade(fl::u32 fadeInTime, fl::u32 fadeOutTime) {
39 mFadeInTime = fadeInTime;
40 mFadeOutTime = fadeOutTime;
43bool VideoImpl::needsFrame(fl::u32 now)
const {
45 bool out = mFrameInterpolator->needsFrame(now, &f1, &f2);
49VideoImpl::~VideoImpl() {
end(); }
51void VideoImpl::begin(FileHandlePtr h) {
59void VideoImpl::beginStream(ByteStreamPtr bs) {
63 mStream->beginStream(bs);
67void VideoImpl::end() {
68 mFrameInterpolator->clear();
73bool VideoImpl::full()
const {
return mFrameInterpolator->getFrames()->full(); }
75bool VideoImpl::draw(fl::u32 now, Frame *frame) {
76 return draw(now, frame->rgb());
79int32_t VideoImpl::durationMicros()
const {
83 int32_t frames = mStream->framesRemaining();
87 fl::u32 micros_per_frame =
88 mFrameInterpolator->getFrameTracker().microsecondsPerFrame();
89 return (frames * micros_per_frame);
92bool VideoImpl::draw(fl::u32 now,
CRGB *
leds) {
95 mTime->setSpeed(mTimeScale);
98 now = mTime->update(now);
103 bool ok = updateBufferIfNecessary(mPrevNow, now);
109 mFrameInterpolator->draw(now,
leds);
111 fl::u32
time = mTime->time();
114 if (mFadeInTime || mFadeOutTime) {
116 if (time <= mFadeInTime) {
117 if (mFadeInTime == 0) {
122 }
else if (mFadeOutTime) {
123 int32_t frames_remaining = mStream->framesRemaining();
124 if (frames_remaining < 0) {
128 FrameTracker &frame_tracker =
129 mFrameInterpolator->getFrameTracker();
130 fl::u32 micros_per_frame =
131 frame_tracker.microsecondsPerFrame();
132 fl::u32 millis_left =
133 (frames_remaining * micros_per_frame) / 1000;
134 if (millis_left < mFadeOutTime) {
135 brightness = millis_left * 255 / mFadeOutTime;
142 for (
size_t i = 0; i < mPixelsPerFrame; ++i) {
146 for (
size_t i = 0; i < mPixelsPerFrame; ++i) {
154bool VideoImpl::updateBufferFromStream(fl::u32 now) {
155 FASTLED_ASSERT(mTime,
"mTime is null");
160 if (mStream->atEnd()) {
164 fl::u32 currFrameNumber = 0;
165 fl::u32 nextFrameNumber = 0;
167 mFrameInterpolator->needsFrame(now, &currFrameNumber, &nextFrameNumber);
172 if (mFrameInterpolator->capacity() == 0) {
177 const bool has_current_frame = mFrameInterpolator->has(currFrameNumber);
178 const bool has_next_frame = mFrameInterpolator->has(nextFrameNumber);
181 if (!has_current_frame) {
182 frame_numbers.
push_back(currFrameNumber);
184 size_t capacity = mFrameInterpolator->
capacity();
185 if (capacity > 1 && !has_next_frame) {
186 frame_numbers.
push_back(nextFrameNumber);
189 for (
size_t i = 0; i < frame_numbers.
size(); ++i) {
190 FramePtr recycled_frame;
191 if (mFrameInterpolator->full()) {
192 fl::u32 frame_to_erase = 0;
194 mFrameInterpolator->get_oldest_frame_number(&frame_to_erase);
199 recycled_frame = mFrameInterpolator->erase(frame_to_erase);
200 if (!recycled_frame) {
201 FASTLED_WARN(
"erase failed for frame: " << frame_to_erase);
205 fl::u32 frame_to_fetch = frame_numbers[i];
206 if (!recycled_frame) {
211 if (!mStream->readFrame(recycled_frame.get())) {
212 if (mStream->atEnd()) {
213 if (!mStream->rewind()) {
219 if (!mStream->readFrameAt(frame_to_fetch,
220 recycled_frame.get())) {
229 bool ok = mFrameInterpolator->
insert(frame_to_fetch, recycled_frame);
238bool VideoImpl::updateBufferFromFile(fl::u32 now,
bool forward) {
239 fl::u32 currFrameNumber = 0;
240 fl::u32 nextFrameNumber = 0;
242 mFrameInterpolator->needsFrame(now, &currFrameNumber, &nextFrameNumber);
246 bool has_curr_frame = mFrameInterpolator->has(currFrameNumber);
247 bool has_next_frame = mFrameInterpolator->has(nextFrameNumber);
248 if (has_curr_frame && has_next_frame) {
251 if (mFrameInterpolator->capacity() == 0) {
257 if (!mFrameInterpolator->has(currFrameNumber)) {
258 frame_numbers.
push_back(currFrameNumber);
260 if (mFrameInterpolator->capacity() > 1 &&
261 !mFrameInterpolator->has(nextFrameNumber)) {
262 frame_numbers.
push_back(nextFrameNumber);
265 for (
size_t i = 0; i < frame_numbers.
size(); ++i) {
266 FramePtr recycled_frame;
267 if (mFrameInterpolator->full()) {
268 fl::u32 frame_to_erase = 0;
271 ok = mFrameInterpolator->get_oldest_frame_number(
278 ok = mFrameInterpolator->get_newest_frame_number(
285 recycled_frame = mFrameInterpolator->erase(frame_to_erase);
286 if (!recycled_frame) {
287 FASTLED_WARN(
"erase failed for frame: " << frame_to_erase);
291 fl::u32 frame_to_fetch = frame_numbers[i];
292 if (!recycled_frame) {
298 if (!mStream->readFrameAt(frame_to_fetch, recycled_frame.get())) {
303 if (mStream->atEnd()) {
304 if (!mStream->rewind()) {
310 if (!mStream->readFrameAt(frame_to_fetch,
311 recycled_frame.get())) {
323 bool ok = mFrameInterpolator->
insert(frame_to_fetch, recycled_frame);
332bool VideoImpl::updateBufferIfNecessary(fl::u32 prev, fl::u32 now) {
333 const bool forward = now >= prev;
335 PixelStream::Type type = mStream->getType();
337 case PixelStream::kFile:
338 return updateBufferFromFile(now, forward);
339 case PixelStream::kStreaming:
340 return updateBufferFromStream(now);
347bool VideoImpl::rewind() {
348 if (!mStream || !mStream->rewind()) {
351 mFrameInterpolator->clear();
TimeWarp timeScale(0, 1.0f)
UISlider brightness("Brightness", 128, 0, 255, 1)
constexpr fl::size size() const
constexpr fl::size capacity() const
void push_back(const T &value)
bool insert(iterator pos, const T &value)
Implements the FastLED namespace macros.
constexpr T * end(T(&array)[N]) noexcept
fl::u32 time()
Universal millisecond timer - returns milliseconds since system startup.
shared_ptr< T > make_shared(Args &&... args)
constexpr T && forward(typename remove_reference< T >::type &t) noexcept
@ Black
<div style='background:#000000;width:4em;height:4em;'></div>
Representation of an RGB pixel (Red, Green, Blue)