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