3#if defined(USE_ESP_IDF) && defined(USE_SENDSPIN_ARTWORK)
13static constexpr uint32_t TRANSITION_ACK_TIMEOUT_ID = 0;
17static constexpr uint32_t TRANSITION_ACK_WARNING_MS = 10000;
22 if (frame_size == 0) {
25 ESP_LOGE(TAG,
"Cannot decode artwork at %dx%d", this->
width_, this->
height_);
34 ESP_LOGE(TAG,
"Could not allocate %zu bytes for an artwork frame. Largest free block: %zu", frame_size,
36 for (uint8_t *&allocated : this->buffers_) {
45 memset(
buffer, 0, frame_size);
55 this->
parent_->add_image_decode_callback(
56 [
this](uint8_t slot,
const uint8_t *data,
size_t length, sendspin::SendspinImageFormat) {
57 if (slot == this->
slot_)
60 this->
parent_->add_image_display_callback([
this](uint8_t slot,
uint32_t lateness_ms) {
61 if (slot == this->
slot_)
64 this->
parent_->add_image_clear_callback([
this](uint8_t slot) {
65 if (slot == this->
slot_)
109 ESP_LOGE(TAG,
"Could not start decode");
113 size_t total_consumed = 0;
114 while (total_consumed <
length) {
118 ESP_LOGE(TAG,
"Decode failed at offset %zu (result %d)", total_consumed, consumed);
121 total_consumed += consumed;
125 ESP_LOGE(TAG,
"Could not finalize decode");
168 this->
set_timeout(TRANSITION_ACK_TIMEOUT_ID, TRANSITION_ACK_WARNING_MS, [
this]() {
171 "Slot %u: displayed artwork was never acknowledged; no new artwork will arrive until "
172 "sendspin.image.transition_finished runs or the stream is cleared",
237 " Dimensions: %dx%d\n"
238 " Frame buffers: 2 x %zu bytes\n"
239 " Transition image: %s",
void mark_failed()
Mark this component as failed.
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
void defer(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call with a const char* name.
Helper class that wraps a mutex with a RAII-style API.
An STL allocator that uses SPI or internal RAM.
void deallocate(T *p, size_t n)
size_t get_max_free_block_size() const
Return the maximum size block this allocator could allocate.
bool begin_decode(size_t expected_size=0, ImageFormat format=AUTO)
Begin decoding an image.
size_t get_buffer_size(int width, int height) const
Get the buffer size in bytes needed for a picture of the given dimensions.
bool end_decode()
Complete the decoding process.
int feed_data(uint8_t *data, size_t len)
Feed data to the decoder.
void release()
Release the image buffer and free its memory, ending any decode session.
bool set_external_buffer(uint8_t *buffer, int width, int height)
Decode into a buffer the caller owns, instead of one allocated here.
bool decoded_into(const uint8_t *buffer) const
True when the decode ended with the given buffer still in place.
void set_frame(const uint8_t *data, int width, int height)
void set_showing_artwork(bool showing_artwork)
Records whether the frame on show is real artwork rather than the black it starts as.
LazyCallbackManager< void()> image_error_callback_
void on_display_(uint32_t lateness_ms)
ArtworkDecodeSink decode_sink_
void transition_finished()
Signals that the display transition for the last frame has finished.
ArtworkImageView * current_image_
void on_decode_(const uint8_t *data, size_t length)
void apply_frames_(bool transition_is_artwork)
void finish_transition_()
void dump_config() override
LazyCallbackManager< void()> image_clear_callback_
bool decode_frame_(const uint8_t *data, size_t length, const uint8_t *target)
ArtworkImageView * transition_image_
LazyCallbackManager< void(uint32_t)> image_display_callback_
std::array< uint8_t *, 2 > buffers_
ESPHOME_LOG_TAG(TAG, "sendspin.image")