25 fl::u32
width = frame->width;
26 fl::u32
height = frame->height;
29 const fl::i32 YUV_TO_RGB_MATRIX[9] = {
36 for (fl::u32
x = 0;
x <
width;
x++) {
38 fl::u32 y_index =
y * frame->y.width +
x;
41 fl::u32 uv_index = uv_y * frame->cr.width + uv_x;
43 fl::i32 Y = frame->y.data[y_index] - 16;
44 fl::i32 U = frame->cb.data[uv_index] - 128;
45 fl::i32 V = frame->cr.data[uv_index] - 128;
48 fl::i32 R = (YUV_TO_RGB_MATRIX[0] * Y + YUV_TO_RGB_MATRIX[1] * U + YUV_TO_RGB_MATRIX[2] * V) / 1000;
49 fl::i32 G = (YUV_TO_RGB_MATRIX[3] * Y + YUV_TO_RGB_MATRIX[4] * U + YUV_TO_RGB_MATRIX[5] * V) / 1000;
50 fl::i32
B = (YUV_TO_RGB_MATRIX[6] * Y + YUV_TO_RGB_MATRIX[7] * U + YUV_TO_RGB_MATRIX[8] * V) / 1000;
53 R = R < 0 ? 0 : (R > 255 ? 255 : R);
54 G = G < 0 ? 0 : (G > 255 ? 255 : G);
55 B =
B < 0 ? 0 : (
B > 255 ? 255 :
B);
58 fl::u32 rgb_index = (
y *
width +
x) * 3;
59 rgb_buffer[rgb_index + 0] =
static_cast<fl::u8>(R);
60 rgb_buffer[rgb_index + 1] =
static_cast<fl::u8>(G);
61 rgb_buffer[rgb_index + 2] =
static_cast<fl::u8>(
B);
100 if (decoder && decoder->decoderData_ && frame) {
101 decoder->decoderData_->hasNewFrame =
true;
102 decoder->decoderData_->lastFrameTime = frame->time;
105 if (decoder->decoderData_->rgbFrameBuffer.get()) {
106 yuv_to_rgb(frame, decoder->decoderData_->rgbFrameBuffer.get());
116 if (!decoder || !samples || !decoder->config_.audioCallback) {
123 pcm.
reserve(samples->count * 2);
125 for (
unsigned i = 0; i < samples->count * 2; i++) {
126 float sample = samples->interleaved[i];
133 fl::u32 timestampMs =
static_cast<fl::u32
>(samples->time * 1000.0);
137 decoder->config_.audioCallback(audioSample);
156 setError(
"Invalid filebuf provided");
253 setError(
"No input stream available");
259 const fl::size CHUNK_SIZE = 8192;
265 bytesRead =
stream_->read(chunk, CHUNK_SIZE);
267 for (fl::size i = 0; i < bytesRead; ++i) {
271 }
while (bytesRead == CHUNK_SIZE);
273 if (tempBuffer.
empty()) {
274 setError(
"Empty input stream - no data available");
291 setError(
"Failed to create pl_mpeg decoder instance");
317 fl::size temp_buffer_size =
static_cast<fl::size
>(1920ul * 1080ul * 3ul);
327 setError(
"Failed to parse MPEG1 headers");
340 setError(
"Invalid video dimensions from MPEG1 stream");
394 fl::u32 timestampMs =
static_cast<fl::u32
>(
decoderData_->lastFrameTime * 1000.0);
469 config_.audioCallback = callback;
473 if (callback && !
config_.skipAudio) {
Frame getCurrentFrame() FL_NOEXCEPT override
bool begin(fl::filebuf_ptr stream) FL_NOEXCEPT override
int getAudioSampleRate() const FL_NOEXCEPT override
void allocateFrameBuffers() FL_NOEXCEPT
void setError(const fl::string &message) FL_NOEXCEPT
bool hasAudio() const FL_NOEXCEPT override
bool decodeNextFrame() FL_NOEXCEPT
bool hasMoreFrames() const FL_NOEXCEPT override
fl::shared_ptr< Frame > currentFrame_
Mpeg1DecoderData * decoderData_
void end() FL_NOEXCEPT override
SoftwareMpeg1Decoder(const Mpeg1Config &config) FL_NOEXCEPT
fl::u16 getFrameRate() const FL_NOEXCEPT
fl::u8 currentFrameIndex_
static void audioDecodeCallback(fl::third_party::plm_t *plm, fl::third_party::plm_samples_t *samples, void *user) FL_NOEXCEPT
void setAudioCallback(AudioFrameCallback callback) FL_NOEXCEPT override
fl::u16 getHeight() const FL_NOEXCEPT
fl::u32 getFrameCount() const FL_NOEXCEPT override
fl::u16 getWidth() const FL_NOEXCEPT
bool parseSequenceHeader() FL_NOEXCEPT
bool decodeFrame() FL_NOEXCEPT
bool decodePictureHeader() FL_NOEXCEPT
bool initializeDecoder() FL_NOEXCEPT
static void videoDecodeCallback(fl::third_party::plm_t *plm, fl::third_party::plm_frame_t *frame, void *user) FL_NOEXCEPT
bool hasError(fl::string *msg=nullptr) const FL_NOEXCEPT override
bool seek(fl::u32 frameIndex) FL_NOEXCEPT override
fl::vector< fl::shared_ptr< Frame > > frameBuffer_
void cleanupDecoder() FL_NOEXCEPT
DecodeResult decode() FL_NOEXCEPT override
fl::third_party::plm_t * plmpeg
fl::unique_ptr< fl::u8[]> inputBuffer
double targetFrameDuration
fl::unique_ptr< fl::u8[]> rgbFrameBuffer
fl::size size() const FL_NOEXCEPT
bool empty() const FL_NOEXCEPT
void reserve(fl::size n) FL_NOEXCEPT
void push_back(const T &value) FL_NOEXCEPT
void plm_set_video_decode_callback(plm_t *self, plm_video_decode_callback fp, void *user) FL_NOEXCEPT
void plm_decode(plm_t *self, double seconds) FL_NOEXCEPT
int plm_get_samplerate(plm_t *self) FL_NOEXCEPT
int plm_get_width(plm_t *self) FL_NOEXCEPT
int plm_get_height(plm_t *self) FL_NOEXCEPT
plm_t * plm_create_with_memory(uint8_t *bytes, size_t length, int free_when_done) FL_NOEXCEPT
void plm_set_audio_enabled(plm_t *self, int enabled) FL_NOEXCEPT
int plm_get_num_audio_streams(plm_t *self) FL_NOEXCEPT
void plm_set_loop(plm_t *self, int loop) FL_NOEXCEPT
void plm_set_audio_decode_callback(plm_t *self, plm_audio_decode_callback fp, void *user) FL_NOEXCEPT
double plm_get_framerate(plm_t *self) FL_NOEXCEPT
void plm_destroy(plm_t *self) FL_NOEXCEPT
int plm_has_headers(plm_t *self) FL_NOEXCEPT
static void yuv_to_rgb(const fl::third_party::plm_frame_t *frame, fl::u8 *rgb_buffer) FL_NOEXCEPT
int plm_has_ended(plm_t *self) FL_NOEXCEPT
void * memcpy(void *dest, const void *src, size_t n) FL_NOEXCEPT
FL_DISABLE_WARNING_PUSH unsigned char * B
CRGB sample(const CRGB *grid, const XYMap &xyMap, float x, float y, SampleMode mode)
Sample a pixel from a 2D CRGB grid at floating-point coordinates.
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
expected< T, E > result
Alias for expected (Rust-style naming)
fl::shared_ptr< filebuf > filebuf_ptr
fl::function< void(const audio::Sample &)> AudioFrameCallback
Base definition for an LED controller.