1#include "fx/video/frame_interpolator.h"
2#include "fx/detail/circular_buffer.h"
3#include "fx/detail/data_stream.h"
4#include "math_macros.h"
9FrameInterpolator::FrameInterpolator(
size_t nframes,
float fps)
10 : mFrames(MAX(1, nframes)), mInterval(fps) {
13bool FrameInterpolator::draw(uint32_t now,
Frame *dst) {
14 bool ok = draw(now, dst->rgb(), dst->alpha(), &now);
16 dst->setTimestamp(now);
21bool FrameInterpolator::draw(uint32_t now,
CRGB* leds, uint8_t* alpha, uint32_t* precise_timestamp) {
22 const Frame *frameMin =
nullptr;
23 const Frame *frameMax =
nullptr;
24 if (!selectFrames(now, &frameMin, &frameMax)) {
27 if (!frameMin || !frameMax) {
32 uint32_t total_duration = frameMax->getTimestamp() - frameMin->getTimestamp();
33 if (frameMin == frameMax || total_duration == 0) {
35 frameMax->draw(leds, alpha);
36 if (precise_timestamp) {
37 *precise_timestamp = frameMax->getTimestamp();
41 uint32_t elapsed = now - frameMin->getTimestamp();
42 uint8_t progress = (elapsed * 255) / total_duration;
44 Frame::interpolate(*frameMin, *frameMax, progress, leds, alpha);
45 if (precise_timestamp) {
46 *precise_timestamp = frameMin->getTimestamp() + elapsed;
51bool FrameInterpolator::addWithTimestamp(
const Frame &frame,
54 if (!mFrames.empty() && timestamp <= mFrames.back()->getTimestamp()) {
59 if (mFrames.empty()) {
61 FrameRef newFrame = FrameRef::New(frame.size(), !!frame.alpha());
62 newFrame->copy(frame);
63 newFrame->setTimestamp(timestamp);
64 mFrames.push_back(newFrame);
68 if (timestamp <= mFrames.front()->getTimestamp()) {
76 bool ok = mFrames.pop_back(&newFrame);
77 if (!ok || !newFrame) {
83 newFrame = FrameRef::New(frame.size(), !!frame.alpha());
85 newFrame->copy(frame);
86 newFrame->setTimestamp(timestamp);
89 mFrames.push_front(newFrame);
94bool FrameInterpolator::add(
const Frame &frame) {
95 return addWithTimestamp(frame, frame.getTimestamp());
98bool FrameInterpolator::selectFrames(uint32_t now,
const Frame **frameMin,
99 const Frame **frameMax)
const {
100 if (mFrames.empty()) {
101 *frameMin = *frameMax =
nullptr;
105 if (mFrames.size() == 1) {
106 *frameMin = *frameMax = mFrames.front().get();
111 if (now <= mFrames.back()->getTimestamp())
113 *frameMin = mFrames.back().get();
114 *frameMax = mFrames.back().get();
120 if (now >= mFrames.front()->getTimestamp()) {
121 Frame* cur = mFrames.front().get();
128 for (
size_t i = 0; i < mFrames.size() - 1; ++i) {
129 if (now <= mFrames[i]->getTimestamp() && mFrames[i + 1]->getTimestamp() <= now) {
130 *frameMax = mFrames[i].get();
131 *frameMin = mFrames[i + 1].get();
Representation of an RGB pixel (Red, Green, Blue)