FastLED 3.9.15
Loading...
Searching...
No Matches
file_system_codecs.cpp.hpp
Go to the documentation of this file.
1// ok no header
6
8#include "fl/codec/idecoder.h"
9#include "fl/codec/jpeg.h"
10#include "fl/codec/mp3.h"
11#include "fl/codec/mpeg1.h"
12#include "fl/log/log.h"
13#include "fl/math/math.h"
14#include "fl/stl/vector.h"
15#include "fl/stl/cstring.h"
16
17namespace fl {
18
19// filebuf wrapper for MPEG1 decoded frame stream
20class Mpeg1FileHandle : public filebuf {
21private:
22 IDecoderPtr mDecoder;
24 fl::size mFrameSize;
25 fl::size mCurrentPos;
28
31 if (!mDecoder->hasMoreFrames()) { mHasValidFrame = false; return false; }
32 DecodeResult result = mDecoder->decode();
34 Frame decodedFrame = mDecoder->getCurrentFrame();
36 mCurrentPos = 0; mHasValidFrame = true; return true;
37 } else { mHasValidFrame = false; return false; }
38 }
39 return mHasValidFrame;
40 }
41
42public:
43 Mpeg1FileHandle(IDecoderPtr decoder, fl::size pixelsPerFrame, const char* path)
44 : mDecoder(decoder), mCurrentFrame(nullptr), mFrameSize(pixelsPerFrame * 3),
46 bool is_open() const override { return mDecoder != nullptr; }
47 void close() override { if (mDecoder) mDecoder->end(); }
48 fl::size_t read(char* dst, fl::size_t bytesToRead) override {
49 if (!mDecoder || !mHasValidFrame) return 0;
50 fl::size totalRead = 0;
51 while (bytesToRead > 0 && mHasValidFrame) {
52 fl::size rem = mFrameSize - mCurrentPos;
53 if (rem == 0) { if (!decodeNextFrameIfNeeded()) break; rem = mFrameSize - mCurrentPos; }
54 fl::size toRead = fl::min(bytesToRead, rem);
55 if (toRead > 0 && mCurrentFrame && mCurrentFrame->rgb().data()) {
56 fl::memcpy(dst + totalRead, (fl::u8*)mCurrentFrame->rgb().data() + mCurrentPos, toRead);
57 mCurrentPos += toRead; totalRead += toRead; bytesToRead -= toRead;
58 } else break;
59 }
60 return totalRead;
61 }
62 using filebuf::read;
63 fl::size_t write(const char*, fl::size_t) override { return 0; }
64 fl::size_t tell() override { return 0; }
65 bool seek(fl::size_t, seek_dir) override { return false; }
66 using filebuf::seek;
67 fl::size_t size() const override { return 0; }
68 const char* path() const override { return mPath.c_str(); }
69 bool is_eof() const override { return !mHasValidFrame && !mDecoder->hasMoreFrames(); }
70 bool has_error() const override { return false; }
71 void clear_error() override {}
72 int error_code() const override { return 0; }
73 const char* error_message() const override { return "No error"; }
74 bool available() const override { return mHasValidFrame || mDecoder->hasMoreFrames(); }
75 fl::size_t bytes_left() const override {
76 if (!mHasValidFrame) return 0;
77 return (mCurrentPos < mFrameSize) ? (mFrameSize - mCurrentPos) : 0;
78 }
79};
80
81Video FileSystem::openMpeg1Video(const char *path, fl::size pixelsPerFrame, float fps,
82 fl::size nFrameHistory) {
83 Video video(pixelsPerFrame, fps, nFrameHistory);
84 fl::ifstream file = openRead(path);
85 if (!file.is_open()) { video.setError(fl::string("Could not open MPEG1 file: ").append(path)); return video; }
86 Mpeg1Config config;
88 config.targetFps = static_cast<fl::u16>(fps);
89 config.looping = false;
90 config.skipAudio = true;
91 fl::string error_message;
92 IDecoderPtr decoder = Mpeg1::createDecoder(config, &error_message);
93 if (!decoder) { video.setError(fl::string("Failed to create MPEG1 decoder: ").append(error_message)); return video; }
94 if (!decoder->begin(file.rdbuf())) {
95 fl::string decoder_error; decoder->hasError(&decoder_error);
96 video.setError(fl::string("Failed to initialize MPEG1 decoder: ").append(decoder_error)); return video;
97 }
98 fl::shared_ptr<Mpeg1FileHandle> mpeg1Stream = fl::make_shared<Mpeg1FileHandle>(decoder, pixelsPerFrame, path);
99 if (!video.begin(mpeg1Stream)) { video.setError(fl::string("Failed to initialize video with MPEG1 stream")); return video; }
100 return video;
101}
102
103FramePtr FileSystem::loadJpeg(const char *path, const JpegConfig &config,
104 fl::string *error_message) {
105 fl::ifstream file = openRead(path);
106 if (!file.is_open()) {
107 if (error_message) { *error_message = "Failed to open file: "; error_message->append(path); }
108 FL_WARN("Failed to open JPEG file: " << path); return FramePtr();
109 }
110 fl::size fileSize = file.size();
111 if (fileSize == 0) {
112 if (error_message) { *error_message = "File is empty: "; error_message->append(path); }
113 file.close(); return FramePtr();
114 }
115 fl::vector<u8> buffer;
116 buffer.reserve(fileSize); buffer.resize(fileSize);
117 fl::size bytesRead = 0;
118 while (bytesRead < fileSize && file.available()) {
119 fl::size chunkSize = min<fl::size>(4096, fileSize - bytesRead);
120 fl::size n = file.read(buffer.data() + bytesRead, chunkSize);
121 if (n == 0) break;
122 bytesRead += n;
123 }
124 file.close();
125 if (bytesRead != fileSize) {
126 if (error_message) {
127 *error_message = "Failed to read complete file. Expected ";
128 error_message->append(static_cast<u32>(fileSize));
129 error_message->append(" bytes, got ");
130 error_message->append(static_cast<u32>(bytesRead));
131 }
132 FL_WARN("Failed to read complete JPEG file: " << path); return FramePtr();
133 }
134 fl::span<const u8> jpegData(buffer.data(), buffer.size());
135 FramePtr frame = Jpeg::decode(config, jpegData, error_message);
136 if (!frame && error_message && error_message->empty()) {
137 *error_message = "Failed to decode JPEG from file: "; error_message->append(path);
138 }
139 return frame;
140}
141
142fl::Mp3DecoderPtr FileSystem::openMp3(const char *path, fl::string *error_message) {
143 fl::ifstream file = openRead(path);
144 if (!file.is_open()) {
145 if (error_message) { *error_message = "Failed to open file: "; error_message->append(path); }
146 FL_WARN("Failed to open MP3 file: " << path); return fl::Mp3DecoderPtr();
147 }
148 fl::Mp3DecoderPtr decoder = fl::Mp3::createDecoder(error_message);
149 if (!decoder->begin(file.rdbuf())) {
150 fl::string decoder_error; decoder->hasError(&decoder_error);
151 if (error_message) { *error_message = "Failed to initialize MP3 decoder: "; error_message->append(decoder_error); }
152 FL_WARN("Failed to initialize MP3 decoder for: " << path); return fl::Mp3DecoderPtr();
153 }
154 return decoder;
155}
156
157} // namespace fl
Video openMpeg1Video(const char *path, fl::size pixelsPerFrame, float fps=30.0f, fl::size nFrameHistory=0)
fl::ifstream openRead(const char *path)
fl::Mp3DecoderPtr openMp3(const char *path, fl::string *error_message=nullptr)
FramePtr loadJpeg(const char *path, const JpegConfig &config=JpegConfig(), fl::string *error_message=nullptr)
static bool decode(const JpegConfig &config, fl::span< const fl::u8 > data, Frame *frame, fl::string *error_message=nullptr)
Definition jpeg.cpp.hpp:296
static Mp3DecoderPtr createDecoder(fl::string *error_message=nullptr)
Definition mp3.cpp.hpp:400
bool begin(fl::filebuf_ptr stream)
Definition mp3.cpp.hpp:367
bool hasError(fl::string *msg=nullptr) const
Definition mp3.cpp.hpp:379
static IDecoderPtr createDecoder(const Mpeg1Config &config, fl::string *error_message=nullptr)
Definition mpeg1.cpp.hpp:8
bool available() const override
fl::size_t read(char *dst, fl::size_t bytesToRead) override
fl::size_t tell() override
Mpeg1FileHandle(IDecoderPtr decoder, fl::size pixelsPerFrame, const char *path)
bool is_eof() const override
const char * error_message() const override
bool is_open() const override
fl::size_t bytes_left() const override
fl::size_t size() const override
fl::shared_ptr< Frame > mCurrentFrame
bool seek(fl::size_t, seek_dir) override
int error_code() const override
fl::size_t write(const char *, fl::size_t) override
bool has_error() const override
const char * path() const override
bool empty() const FL_NOEXCEPT
virtual bool seek(fl::size_t pos, seek_dir dir)=0
virtual fl::size_t read(char *buffer, fl::size_t count)=0
bool available() const
Definition fstream.h:161
fl::size_t size() const
Definition fstream.h:146
ifstream & read(char *buffer, fl::size_t count)
bool is_open() const
Definition fstream.h:111
filebuf_ptr rdbuf() const
Definition fstream.h:143
string & append(const bitset_fixed< N > &bs) FL_NOEXCEPT
Definition string.h:284
fl::size size() const FL_NOEXCEPT
T * data() FL_NOEXCEPT
Definition vector.h:619
void reserve(fl::size n) FL_NOEXCEPT
Definition vector.h:591
void resize(fl::size n) FL_NOEXCEPT
Definition vector.h:593
#define FL_WARN(X)
Definition log.h:276
Centralized logging categories for FastLED hardware interfaces and subsystems.
unsigned char u8
Definition s16x16x4.h:132
__SIZE_TYPE__ size_t
Definition s16x16x4.h:16
FL_DISABLE_WARNING_PUSH U constexpr common_type_t< T, U > min(T a, U b) FL_NOEXCEPT
Definition math.h:71
void * memcpy(void *dest, const void *src, size_t n) FL_NOEXCEPT
seek_dir
Definition file_handle.h:19
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:414
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
third_party::Mpeg1Config Mpeg1Config
Definition mpeg1.h:29
DecodeResult
Definition idecoder.h:18
fl::shared_ptr< Mp3Decoder > Mp3DecoderPtr
Definition file_system.h:19
Base definition for an LED controller.
Definition crgb.hpp:179