Arduino_libraries/FastLED/tests/test_frame_interpolator.cpp

285 lines
11 KiB
C++

// g++ --std=c++11 test.cpp
#include "test.h"
#include "test.h"
#include "fx/frame.h"
#include "fx/video/frame_interpolator.h"
#include "fl/namespace.h"
#include "fl/namespace.h"
FASTLED_USING_NAMESPACE
#if 0
TEST_CASE("FrameInterpolator::selectFrames") {
SUBCASE("Empty interpolator") {
FrameInterpolator interpolator(5, -1);
const Frame *selected1;
const Frame *selected2;
CHECK_FALSE(interpolator.selectFrames(0, &selected1, &selected2));
}
SUBCASE("2 frame interpolator before") {
// Create an interpolator with capacity for 2 frames
FrameInterpolator interpolator(2, -1);
// Create some test frames with different timestamps
FrameRef frame1 = FrameRef::New(10, false); // 10 pixels, no alpha
FrameRef frame2 = FrameRef::New(10, false);
// Add frames with timestamps
CHECK(interpolator.push_front(frame1, 0, 1000));
CHECK(interpolator.push_front(frame2, 1, 2000));
const Frame *selected1;
const Frame *selected2;
// Falls between two frames->
bool selected = interpolator.selectFrames(0, &selected1, &selected2);
CHECK(selected);
CHECK(selected1);
CHECK(selected2);
// Now check that it's the same frame.
CHECK(selected1 == selected2);
// now check that the timestamp of the first frame is less than the
// timestamp of the second frame
CHECK(selected1->getTimestamp() == 1000);
CHECK(selected2->getTimestamp() == 1000);
}
SUBCASE("2 frame interpolator between") {
// Create an interpolator with capacity for 2 frames
FrameInterpolator interpolator(2, -1);
// Create some test frames with different timestamps
FrameRef frame1 = FrameRef::New(10, false); // 10 pixels, no alpha
FrameRef frame2 = FrameRef::New(10, false);
// Add frames with timestamps
//CHECK(interpolator.addWithTimestamp(frame1, 0));
//CHECK(interpolator.addWithTimestamp(frame2, 1000));
CHECK(interpolator.push_front(frame1, 0, 1000));
CHECK(interpolator.push_front(frame2, 1, 2000));
const Frame *selected1;
const Frame *selected2;
// Falls between two frames->
bool selected = interpolator.selectFrames(500, &selected1, &selected2);
CHECK(selected);
CHECK(selected1);
CHECK(selected2);
// now check that the frames are different
CHECK(selected1 != selected2);
// now check that the timestamp of the first frame is less than the
// timestamp of the second frame
CHECK(selected1->getTimestamp() == 0);
CHECK(selected2->getTimestamp() == 1000);
}
SUBCASE("2 frame interpolator after") {
// Create an interpolator with capacity for 2 frames
FrameInterpolator interpolator(2, -1);
// Create some test frames with different timestamps
FrameRef frame1 = FrameRef::New(10, false); // 10 pixels, no alpha
FrameRef frame2 = FrameRef::New(10, false);
// Add frames with timestamps
CHECK(interpolator.push_front(frame1, 0, 0));
CHECK(interpolator.push_front(frame2, 1, 1000));
const Frame *selected1;
const Frame *selected2;
// Falls between two frames->
bool selected = interpolator.selectFrames(1500, &selected1, &selected2);
CHECK(selected);
CHECK(selected1);
CHECK(selected2);
// now check that the frames are different
CHECK(selected1 == selected2);
// now check that the timestamp of the first frame is less than the
// timestamp of the second frame
CHECK(selected1->getTimestamp() == 1000);
CHECK(selected2->getTimestamp() == 1000);
}
}
TEST_CASE("FrameInterpolator::addWithTimestamp") {
SUBCASE("add first frame") {
FrameInterpolator interpolator(5, -1);
FrameRef frame = FrameRef::New(10, false);
CHECK(interpolator.push_front(frame, 0, 1000));
FrameInterpolator::FrameBuffer* frames = interpolator.getFrames();
CHECK_EQ(frames->size(), 1);
CHECK_EQ(frames->front().frame->getTimestamp(), 1000);
}
SUBCASE("add second frame which is before first frame and should be rejected") {
FrameInterpolator interpolator(5, -1);
FrameRef frame1 = FrameRef::New(10, false);
FrameRef frame2 = FrameRef::New(10, false);
CHECK(interpolator.push_front(frame1, 0, 1000));
CHECK_FALSE(interpolator.push_front(frame2, 1, 500));
FrameInterpolator::FrameBuffer* frames = interpolator.getFrames();
CHECK_EQ(frames->size(), 1);
CHECK_EQ(frames->front().frame->getTimestamp(), 1000);
}
SUBCASE("add second frame which has the same timestamp as first frame and should be rejected") {
FrameInterpolator interpolator(5, -1);
FrameRef frame1 = FrameRef::New(10, false);
FrameRef frame2 = FrameRef::New(10, false);
CHECK(interpolator.push_front(frame1, 0, 1000));
CHECK_FALSE(interpolator.push_front(frame2, 1, 1000));
FrameInterpolator::FrameBuffer* frames = interpolator.getFrames();
CHECK_EQ(frames->size(), 1);
CHECK_EQ(frames->front().frame->getTimestamp(), 1000);
}
SUBCASE("add second frame which is after first frame and should be accepted") {
FrameInterpolator interpolator(5, -1);
FrameRef frame1 = FrameRef::New(10, false);
FrameRef frame2 = FrameRef::New(10, false);
CHECK(interpolator.push_front(frame1, 0, 1000));
CHECK(interpolator.push_front(frame2, 1, 1500));
FrameInterpolator::FrameBuffer* frames = interpolator.getFrames();
CHECK_EQ(frames->size(), 2);
CHECK_EQ(frames->front().frame->getTimestamp(), 1500);
CHECK_EQ(frames->back().frame->getTimestamp(), 1000);
}
}
TEST_CASE("FrameInterpolator::addWithTimestamp and overflow") {
SUBCASE("add two frames and check time") {
FrameInterpolator interpolator(2, -1);
FrameRef frame = FrameRef::New(10, false);
CHECK(interpolator.push_front(frame, 0, 1000));
CHECK(interpolator.push_front(frame, 1, 2000));
CHECK(interpolator.push_front(frame, 2, 3000));
FrameInterpolator::FrameBuffer* frames = interpolator.getFrames();
CHECK_EQ(frames->size(), 2);
CHECK_EQ(frames->front().frame->getTimestamp(), 3000);
CHECK_EQ(frames->back().frame->getTimestamp(), 2000);
}
SUBCASE("add two frames and check that Frame object was recycled") {
FrameInterpolator interpolator(2, -1);
FrameInterpolator::FrameBuffer* frames = interpolator.getFrames();
CHECK_EQ(2, frames->capacity());
CHECK_EQ(0, frames->size());
FrameRef frame = FrameRef::New(2, false);
CHECK(interpolator.push_front(frame, 0, 1000));
CHECK_EQ(2, frames->capacity());
CHECK_EQ(1, frames->size());
CHECK(interpolator.push_front(frame, 1, 2000));
CHECK_EQ(2, frames->capacity());
CHECK_EQ(2, frames->size());
CHECK(frames->full());
Frame* frameThatShouldBeRecycled = frames->back().frame.get();
CHECK(interpolator.push_front(frame, 2, 3000));
CHECK_EQ(frames->size(), 2);
CHECK_EQ(frames->front().frame->getTimestamp(), 3000);
// check pointers are equal
CHECK(frames->front().frame == frameThatShouldBeRecycled);
}
}
TEST_CASE("FrameInterpolator::draw") {
SUBCASE("Empty interpolator") {
FrameInterpolator interpolator(5, -1);
FrameRef frame = FrameRef::New(10, false);
FrameRef dst = FrameRef::New(10, false);
CHECK_FALSE(interpolator.draw(0, dst.get()));
}
SUBCASE("Add one frame and check that we will draw with that") {
FrameInterpolator interpolator(5, -1);
FrameRef frame = FrameRef::New(10, false);
CHECK(interpolator.push_front(frame, 0, 1000));
FrameRef dst = FrameRef::New(10, false);
CHECK(interpolator.draw(0, dst.get()));
CHECK_EQ(dst->getTimestamp(), 1000);
CHECK(interpolator.draw(2000, dst.get()));
CHECK_EQ(dst->getTimestamp(), 1000);
}
SUBCASE("Add two frames and check behavior for drawing before, between and after") {
FrameInterpolator interpolator(5, -1);
FrameRef frame1 = FrameRef::New(10, false);
FrameRef frame2 = FrameRef::New(10, false);
CHECK(interpolator.push_front(frame1, 0, 1000));
CHECK(interpolator.push_front(frame2, 1, 2000));
FrameRef dst = FrameRef::New(10, false);
CHECK(interpolator.draw(0, dst.get()));
CHECK_EQ(dst->getTimestamp(), 1000);
CHECK(interpolator.draw(1500, dst.get()));
CHECK_EQ(dst->getTimestamp(), 1500);
CHECK(interpolator.draw(2500, dst.get()));
CHECK_EQ(dst->getTimestamp(), 2000);
}
SUBCASE("Add three frames and check behavior for drawing before, between 0&1, between 1&2 and after") {
FrameInterpolator interpolator(5, -1);
FrameRef frame1 = FrameRef::New(10, false);
FrameRef frame2 = FrameRef::New(10, false);
FrameRef frame3 = FrameRef::New(10, false);
CHECK(interpolator.push_front(frame1, 0, 1000));
CHECK(interpolator.push_front(frame2, 1, 2000));
CHECK(interpolator.push_front(frame3, 2, 3000));
FrameRef dst = FrameRef::New(10, false);
CHECK(interpolator.draw(0, dst.get()));
CHECK_EQ(dst->getTimestamp(), 1000);
// now check what happens when we draw exactly at 1000
CHECK(interpolator.draw(1000, dst.get()));
CHECK_EQ(dst->getTimestamp(), 1000);
CHECK(interpolator.draw(1500, dst.get()));
CHECK_EQ(dst->getTimestamp(), 1500);
// now check what happens when we draw exactly at 2000
CHECK(interpolator.draw(2000, dst.get()));
CHECK_EQ(dst->getTimestamp(), 2000);
CHECK(interpolator.draw(2500, dst.get()));
CHECK_EQ(dst->getTimestamp(), 2500);
CHECK(interpolator.draw(3500, dst.get()));
CHECK_EQ(dst->getTimestamp(), 3000);
}
SUBCASE("Check that the draw command interpolates between two added frames when queried from the middle") {
FrameInterpolator interpolator(5, -1);
FrameRef frame1 = FrameRef::New(10, false);
FrameRef frame2 = FrameRef::New(10, false);
// frame 1 is all red
for (int i = 0; i < 10; i++) {
frame1->rgb()[i] = CRGB::Red;
}
// frame 2 is all blue
for (int i = 0; i < 10; i++) {
frame2->rgb()[i] = CRGB::Blue;
}
CHECK(interpolator.push_front(frame1, 0, 1000));
CHECK(interpolator.push_front(frame2, 1, 2000));
FrameRef dst = FrameRef::New(10, false);
CHECK(interpolator.draw(1500, dst.get()));
CHECK_EQ(dst->getTimestamp(), 1500);
// now check that the frame is interpolated between red and blue
for (int i = 0; i < 10; i++) {
CHECK(dst->rgb()[i] == CRGB(128, 0, 127));
}
}
}
#endif