14VideoImpl::VideoImpl(
size_t pixelsPerFrame,
float fpsVideo,
15 size_t nFramesInBuffer)
16 : mPixelsPerFrame(pixelsPerFrame),
18 FrameInterpolatorPtr::New(
MAX(1, nFramesInBuffer), fpsVideo)) {}
20void VideoImpl::pause(uint32_t now) {
22 mTime = TimeWarpPtr::New(now);
26void VideoImpl::resume(uint32_t now) {
28 mTime = TimeWarpPtr::New(now);
33void VideoImpl::setTimeScale(
float timeScale) {
40void VideoImpl::setFade(uint32_t fadeInTime, uint32_t fadeOutTime) {
41 mFadeInTime = fadeInTime;
42 mFadeOutTime = fadeOutTime;
45bool VideoImpl::needsFrame(uint32_t now)
const {
47 bool out = mFrameInterpolator->needsFrame(now, &f1, &f2);
51VideoImpl::~VideoImpl() { end(); }
53void VideoImpl::begin(FileHandlePtr h) {
56 mStream = PixelStreamPtr::New(mPixelsPerFrame * kSizeRGB8);
61void VideoImpl::beginStream(ByteStreamPtr bs) {
63 mStream = PixelStreamPtr::New(mPixelsPerFrame * kSizeRGB8);
65 mStream->beginStream(bs);
69void VideoImpl::end() {
70 mFrameInterpolator->clear();
75bool VideoImpl::full()
const {
return mFrameInterpolator->getFrames()->full(); }
77bool VideoImpl::draw(uint32_t now,
Frame *frame) {
81int32_t VideoImpl::durationMicros()
const {
85 int32_t frames = mStream->framesRemaining();
89 uint32_t micros_per_frame =
90 mFrameInterpolator->getFrameTracker().microsecondsPerFrame();
91 return (frames * micros_per_frame);
94bool VideoImpl::draw(uint32_t now,
CRGB *
leds) {
96 mTime = TimeWarpPtr::New(now);
97 mTime->setSpeed(mTimeScale);
100 now = mTime->update(now);
105 bool ok = updateBufferIfNecessary(mPrevNow, now);
111 mFrameInterpolator->draw(now,
leds);
113 uint32_t time = mTime->time();
116 if (mFadeInTime || mFadeOutTime) {
118 if (time <= mFadeInTime) {
119 if (mFadeInTime == 0) {
124 }
else if (mFadeOutTime) {
125 int32_t frames_remaining = mStream->framesRemaining();
126 if (frames_remaining < 0) {
131 mFrameInterpolator->getFrameTracker();
132 uint32_t micros_per_frame =
134 uint32_t millis_left =
135 (frames_remaining * micros_per_frame) / 1000;
136 if (millis_left < mFadeOutTime) {
137 brightness = millis_left * 255 / mFadeOutTime;
144 for (
size_t i = 0; i < mPixelsPerFrame; ++i) {
148 for (
size_t i = 0; i < mPixelsPerFrame; ++i) {
156bool VideoImpl::updateBufferFromStream(uint32_t now) {
157 FASTLED_ASSERT(mTime,
"mTime is null");
162 if (mStream->atEnd()) {
166 uint32_t currFrameNumber = 0;
167 uint32_t nextFrameNumber = 0;
169 mFrameInterpolator->needsFrame(now, &currFrameNumber, &nextFrameNumber);
174 if (mFrameInterpolator->capacity() == 0) {
179 const bool has_current_frame = mFrameInterpolator->has(currFrameNumber);
180 const bool has_next_frame = mFrameInterpolator->has(nextFrameNumber);
183 if (!has_current_frame) {
184 frame_numbers.
push_back(currFrameNumber);
186 size_t capacity = mFrameInterpolator->
capacity();
187 if (capacity > 1 && !has_next_frame) {
188 frame_numbers.
push_back(nextFrameNumber);
191 for (
size_t i = 0; i < frame_numbers.
size(); ++i) {
192 FramePtr recycled_frame;
193 if (mFrameInterpolator->full()) {
194 uint32_t frame_to_erase = 0;
196 mFrameInterpolator->get_oldest_frame_number(&frame_to_erase);
201 recycled_frame = mFrameInterpolator->erase(frame_to_erase);
202 if (!recycled_frame) {
203 FASTLED_WARN(
"erase failed for frame: " << frame_to_erase);
207 uint32_t frame_to_fetch = frame_numbers[i];
208 if (!recycled_frame) {
210 recycled_frame = FramePtr::New(mPixelsPerFrame);
213 if (!mStream->readFrame(recycled_frame.get())) {
214 if (mStream->atEnd()) {
215 if (!mStream->rewind()) {
221 if (!mStream->readFrameAt(frame_to_fetch,
222 recycled_frame.get())) {
231 bool ok = mFrameInterpolator->
insert(frame_to_fetch, recycled_frame);
240bool VideoImpl::updateBufferFromFile(uint32_t now,
bool forward) {
241 uint32_t currFrameNumber = 0;
242 uint32_t nextFrameNumber = 0;
244 mFrameInterpolator->needsFrame(now, &currFrameNumber, &nextFrameNumber);
248 bool has_curr_frame = mFrameInterpolator->has(currFrameNumber);
249 bool has_next_frame = mFrameInterpolator->has(nextFrameNumber);
250 if (has_curr_frame && has_next_frame) {
253 if (mFrameInterpolator->capacity() == 0) {
259 if (!mFrameInterpolator->has(currFrameNumber)) {
260 frame_numbers.
push_back(currFrameNumber);
262 if (mFrameInterpolator->capacity() > 1 &&
263 !mFrameInterpolator->has(nextFrameNumber)) {
264 frame_numbers.
push_back(nextFrameNumber);
267 for (
size_t i = 0; i < frame_numbers.
size(); ++i) {
268 FramePtr recycled_frame;
269 if (mFrameInterpolator->full()) {
270 uint32_t frame_to_erase = 0;
273 ok = mFrameInterpolator->get_oldest_frame_number(
280 ok = mFrameInterpolator->get_newest_frame_number(
287 recycled_frame = mFrameInterpolator->erase(frame_to_erase);
288 if (!recycled_frame) {
289 FASTLED_WARN(
"erase failed for frame: " << frame_to_erase);
293 uint32_t frame_to_fetch = frame_numbers[i];
294 if (!recycled_frame) {
296 recycled_frame = FramePtr::New(mPixelsPerFrame);
300 if (!mStream->readFrameAt(frame_to_fetch, recycled_frame.get())) {
305 if (mStream->atEnd()) {
306 if (!mStream->rewind()) {
312 if (!mStream->readFrameAt(frame_to_fetch,
313 recycled_frame.get())) {
325 bool ok = mFrameInterpolator->
insert(frame_to_fetch, recycled_frame);
334bool VideoImpl::updateBufferIfNecessary(uint32_t prev, uint32_t now) {
335 const bool forward = now >= prev;
340 return updateBufferFromFile(now,
forward);
342 return updateBufferFromStream(now);
349bool VideoImpl::rewind() {
350 if (!mStream || !mStream->rewind()) {
353 mFrameInterpolator->clear();
TimeWarp timeScale(0, 1.0f)
UISlider brightness("Brightness", 255, 0, 255, 1)
constexpr size_t size() const
void push_back(const T &value)
constexpr size_t capacity() const
bool insert(iterator pos, const T &value)
uint32_t microsecondsPerFrame() const
Implements the FastLED namespace macros.
constexpr T && forward(typename remove_reference< T >::type &t) noexcept
Implements a simple red square effect for 2D LED grids.
@ Black
<div style='background:#000000;width:4em;height:4em;'></div>
Representation of an RGB pixel (Red, Green, Blue)