From 37110a9d05a199efeff6ca3bb590427a354d0df2 Mon Sep 17 00:00:00 2001 From: Xiaoxia Date: Mon, 2 Feb 2026 15:33:32 +0800 Subject: [PATCH] Fix: esp32camera pixel byte order and uart-uhci compiling error (#1728) * Fix: uart-uhci compiling errors * Enhance Esp32Camera functionality by adding optional byte swapping for RGB565 format. Introduce SetSwapBytes method to enable/disable byte order swapping, and update Capture method to utilize an encode buffer for improved memory management and performance during image processing. --- main/boards/common/camera.h | 1 + main/boards/common/esp32_camera.cc | 66 ++++++++++++++++++++++-------- main/boards/common/esp32_camera.h | 4 ++ main/idf_component.yml | 4 +- 4 files changed, 57 insertions(+), 18 deletions(-) diff --git a/main/boards/common/camera.h b/main/boards/common/camera.h index 75c780c1..09a6a3e7 100644 --- a/main/boards/common/camera.h +++ b/main/boards/common/camera.h @@ -9,6 +9,7 @@ public: virtual bool Capture() = 0; virtual bool SetHMirror(bool enabled) = 0; virtual bool SetVFlip(bool enabled) = 0; + virtual bool SetSwapBytes(bool enabled) { return false; } // Optional, default no-op virtual std::string Explain(const std::string& question) = 0; }; diff --git a/main/boards/common/esp32_camera.cc b/main/boards/common/esp32_camera.cc index 60a5050a..76eaaabd 100644 --- a/main/boards/common/esp32_camera.cc +++ b/main/boards/common/esp32_camera.cc @@ -41,6 +41,11 @@ Esp32Camera::~Esp32Camera() { esp_camera_fb_return(current_fb_); current_fb_ = nullptr; } + if (encode_buf_) { + heap_caps_free(encode_buf_); + encode_buf_ = nullptr; + encode_buf_size_ = 0; + } esp_camera_deinit(); streaming_on_ = false; } @@ -72,30 +77,46 @@ bool Esp32Camera::Capture() { } } - // Perform byte swapping for RGB565 format and prepare preview image + // Prepare encode buffer for RGB565 format (with optional byte swapping) if (current_fb_->format == PIXFORMAT_RGB565) { size_t pixel_count = current_fb_->width * current_fb_->height; size_t data_size = pixel_count * 2; - uint8_t *preview_data = (uint8_t *)heap_caps_malloc(data_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (preview_data == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for preview image"); - return false; + // Allocate or reallocate encode buffer if needed + if (encode_buf_size_ < data_size) { + if (encode_buf_) { + heap_caps_free(encode_buf_); + } + encode_buf_ = (uint8_t *)heap_caps_malloc(data_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (encode_buf_ == nullptr) { + ESP_LOGE(TAG, "Failed to allocate memory for encode buffer"); + encode_buf_size_ = 0; + return false; + } + encode_buf_size_ = data_size; } + // Copy data to encode buffer with optional byte swapping uint16_t *src = (uint16_t *)current_fb_->buf; - uint16_t *dst = (uint16_t *)preview_data; - for (size_t i = 0; i < pixel_count; i++) { - // Copy data from driver buffer to preview buffer with byte swapping - dst[i] = __builtin_bswap16(src[i]); + uint16_t *dst = (uint16_t *)encode_buf_; + if (swap_bytes_enabled_) { + for (size_t i = 0; i < pixel_count; i++) { + dst[i] = __builtin_bswap16(src[i]); + } + } else { + memcpy(encode_buf_, current_fb_->buf, data_size); } - // Display preview image - auto display = dynamic_cast(Board::GetInstance().GetDisplay()); - if (display != nullptr) { - display->SetPreviewImage(std::make_unique(preview_data, data_size, current_fb_->width, current_fb_->height, current_fb_->width * 2, LV_COLOR_FORMAT_RGB565)); - } else { - heap_caps_free(preview_data); + // Allocate separate buffer for preview display + uint8_t *preview_data = (uint8_t *)heap_caps_malloc(data_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (preview_data != nullptr) { + memcpy(preview_data, encode_buf_, data_size); + auto display = dynamic_cast(Board::GetInstance().GetDisplay()); + if (display != nullptr) { + display->SetPreviewImage(std::make_unique(preview_data, data_size, current_fb_->width, current_fb_->height, current_fb_->width * 2, LV_COLOR_FORMAT_RGB565)); + } else { + heap_caps_free(preview_data); + } } } else if (current_fb_->format == PIXFORMAT_JPEG) { // JPEG format preview usually requires decoding, skip preview display for now, just log @@ -126,6 +147,11 @@ bool Esp32Camera::SetVFlip(bool enabled) { return true; } +bool Esp32Camera::SetSwapBytes(bool enabled) { + swap_bytes_enabled_ = enabled; + return true; +} + std::string Esp32Camera::Explain(const std::string &question) { if (explain_url_.empty()) { throw std::runtime_error("Image explain URL or token is not set"); @@ -172,7 +198,15 @@ std::string Esp32Camera::Explain(const std::string &question) { return; } - bool ok = image_to_jpeg_cb(current_fb_->buf, current_fb_->len, w, h, enc_fmt, 80, + // Use encode buffer for RGB565, otherwise use original frame buffer + uint8_t *jpeg_src_buf = current_fb_->buf; + size_t jpeg_src_len = current_fb_->len; + if (current_fb_->format == PIXFORMAT_RGB565 && encode_buf_ != nullptr) { + jpeg_src_buf = encode_buf_; + jpeg_src_len = encode_buf_size_; + } + + bool ok = image_to_jpeg_cb(jpeg_src_buf, jpeg_src_len, w, h, enc_fmt, 80, [](void* arg, size_t index, const void* data, size_t len) -> size_t { auto jpeg_queue = static_cast(arg); JpegChunk chunk = {.data = nullptr, .len = len}; diff --git a/main/boards/common/esp32_camera.h b/main/boards/common/esp32_camera.h index 308578bc..e2fb0712 100644 --- a/main/boards/common/esp32_camera.h +++ b/main/boards/common/esp32_camera.h @@ -23,10 +23,13 @@ class Esp32Camera : public Camera { private: bool streaming_on_ = false; + bool swap_bytes_enabled_ = true; // Swap pixel byte order for RGB565, enabled by default std::string explain_url_; std::string explain_token_; std::thread encoder_thread_; camera_fb_t *current_fb_ = nullptr; + uint8_t *encode_buf_ = nullptr; // Buffer for JPEG encoding (with optional byte swap) + size_t encode_buf_size_ = 0; public: Esp32Camera(const camera_config_t &config); @@ -36,5 +39,6 @@ public: virtual bool Capture() override; virtual bool SetHMirror(bool enabled) override; virtual bool SetVFlip(bool enabled) override; + virtual bool SetSwapBytes(bool enabled) override; virtual std::string Explain(const std::string &question) override; }; diff --git a/main/idf_component.yml b/main/idf_component.yml index ffb07923..3194e38f 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -22,9 +22,9 @@ dependencies: 78/esp-wifi-connect: ~3.0.2 espressif/esp_audio_effects: ~1.2.1 espressif/esp_audio_codec: ~2.4.1 - 78/esp-ml307: ~3.6.2 + 78/esp-ml307: ~3.6.3 78/uart-eth-modem: - version: ~0.3.0 + version: ~0.3.1 rules: - if: target not in [esp32] 78/xiaozhi-fonts: ~1.6.0