197 lines
5.0 KiB
C++
197 lines
5.0 KiB
C++
|
|
#include "fx/video/pixel_stream.h"
|
|
#include "fl/dbg.h"
|
|
#include "fl/namespace.h"
|
|
|
|
#ifndef INT32_MAX
|
|
#define INT32_MAX 0x7fffffff
|
|
#endif
|
|
|
|
#define DBG FASTLED_DBG
|
|
|
|
using fl::ByteStreamPtr;
|
|
using fl::FileHandlePtr;
|
|
|
|
namespace fl {
|
|
|
|
PixelStream::PixelStream(int bytes_per_frame)
|
|
: mbytesPerFrame(bytes_per_frame), mUsingByteStream(false) {}
|
|
|
|
PixelStream::~PixelStream() { close(); }
|
|
|
|
bool PixelStream::begin(FileHandlePtr h) {
|
|
close();
|
|
mFileHandle = h;
|
|
mUsingByteStream = false;
|
|
return mFileHandle->available();
|
|
}
|
|
|
|
bool PixelStream::beginStream(ByteStreamPtr s) {
|
|
close();
|
|
mByteStream = s;
|
|
mUsingByteStream = true;
|
|
return mByteStream->available(mbytesPerFrame);
|
|
}
|
|
|
|
void PixelStream::close() {
|
|
if (!mUsingByteStream && mFileHandle) {
|
|
mFileHandle.reset();
|
|
}
|
|
mByteStream.reset();
|
|
mFileHandle.reset();
|
|
}
|
|
|
|
int32_t PixelStream::bytesPerFrame() { return mbytesPerFrame; }
|
|
|
|
bool PixelStream::readPixel(CRGB *dst) {
|
|
if (mUsingByteStream) {
|
|
return mByteStream->read(&dst->r, 1) && mByteStream->read(&dst->g, 1) &&
|
|
mByteStream->read(&dst->b, 1);
|
|
} else {
|
|
return mFileHandle->read(&dst->r, 1) && mFileHandle->read(&dst->g, 1) &&
|
|
mFileHandle->read(&dst->b, 1);
|
|
}
|
|
}
|
|
|
|
bool PixelStream::available() const {
|
|
if (mUsingByteStream) {
|
|
return mByteStream->available(mbytesPerFrame);
|
|
} else {
|
|
return mFileHandle->available();
|
|
}
|
|
}
|
|
|
|
bool PixelStream::atEnd() const {
|
|
if (mUsingByteStream) {
|
|
return false;
|
|
} else {
|
|
return !mFileHandle->available();
|
|
}
|
|
}
|
|
|
|
bool PixelStream::readFrame(Frame *frame) {
|
|
if (!frame) {
|
|
return false;
|
|
}
|
|
if (!mUsingByteStream) {
|
|
if (!framesRemaining()) {
|
|
return false;
|
|
}
|
|
size_t n = mFileHandle->readCRGB(frame->rgb(), mbytesPerFrame / 3);
|
|
DBG("pos: " << mFileHandle->pos());
|
|
return n * 3 == size_t(mbytesPerFrame);
|
|
}
|
|
size_t n = mByteStream->readCRGB(frame->rgb(), mbytesPerFrame / 3);
|
|
return n * 3 == size_t(mbytesPerFrame);
|
|
}
|
|
|
|
bool PixelStream::hasFrame(fl::u32 frameNumber) {
|
|
if (mUsingByteStream) {
|
|
// ByteStream doesn't support seeking
|
|
DBG("Not implemented and therefore always returns true");
|
|
return true;
|
|
} else {
|
|
size_t total_bytes = mFileHandle->size();
|
|
return frameNumber * mbytesPerFrame < total_bytes;
|
|
}
|
|
}
|
|
|
|
bool PixelStream::readFrameAt(fl::u32 frameNumber, Frame *frame) {
|
|
// DBG("read frame at " << frameNumber);
|
|
if (mUsingByteStream) {
|
|
// ByteStream doesn't support seeking
|
|
FASTLED_DBG("ByteStream doesn't support seeking");
|
|
return false;
|
|
} else {
|
|
// DBG("mbytesPerFrame: " << mbytesPerFrame);
|
|
mFileHandle->seek(frameNumber * mbytesPerFrame);
|
|
if (mFileHandle->bytesLeft() == 0) {
|
|
return false;
|
|
}
|
|
size_t read =
|
|
mFileHandle->readCRGB(frame->rgb(), mbytesPerFrame / 3) * 3;
|
|
// DBG("read: " << read);
|
|
// DBG("pos: " << mFileHandle->Position());
|
|
|
|
bool ok = int(read) == mbytesPerFrame;
|
|
if (!ok) {
|
|
DBG("readFrameAt failed - read: "
|
|
<< read << ", mbytesPerFrame: " << mbytesPerFrame << ", frame:"
|
|
<< frameNumber << ", left: " << mFileHandle->bytesLeft());
|
|
}
|
|
return ok;
|
|
}
|
|
}
|
|
|
|
int32_t PixelStream::framesRemaining() const {
|
|
if (mbytesPerFrame == 0)
|
|
return 0;
|
|
int32_t bytes_left = bytesRemaining();
|
|
if (bytes_left <= 0) {
|
|
return 0;
|
|
}
|
|
return bytes_left / mbytesPerFrame;
|
|
}
|
|
|
|
int32_t PixelStream::framesDisplayed() const {
|
|
if (mUsingByteStream) {
|
|
// ByteStream doesn't have a concept of total size, so we can't
|
|
// calculate this
|
|
return -1;
|
|
} else {
|
|
int32_t bytes_played = mFileHandle->pos();
|
|
return bytes_played / mbytesPerFrame;
|
|
}
|
|
}
|
|
|
|
int32_t PixelStream::bytesRemaining() const {
|
|
if (mUsingByteStream) {
|
|
return INT32_MAX;
|
|
} else {
|
|
return mFileHandle->bytesLeft();
|
|
}
|
|
}
|
|
|
|
int32_t PixelStream::bytesRemainingInFrame() const {
|
|
return bytesRemaining() % mbytesPerFrame;
|
|
}
|
|
|
|
bool PixelStream::rewind() {
|
|
if (mUsingByteStream) {
|
|
// ByteStream doesn't support rewinding
|
|
return false;
|
|
} else {
|
|
mFileHandle->seek(0);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
PixelStream::Type PixelStream::getType() const {
|
|
return mUsingByteStream ? Type::kStreaming : Type::kFile;
|
|
}
|
|
|
|
size_t PixelStream::readBytes(uint8_t *dst, size_t len) {
|
|
uint16_t bytesRead = 0;
|
|
if (mUsingByteStream) {
|
|
while (bytesRead < len && mByteStream->available(len)) {
|
|
// use pop_front()
|
|
if (mByteStream->read(dst + bytesRead, 1)) {
|
|
bytesRead++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
while (bytesRead < len && mFileHandle->available()) {
|
|
if (mFileHandle->read(dst + bytesRead, 1)) {
|
|
bytesRead++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return bytesRead;
|
|
}
|
|
|
|
} // namespace fl
|