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.
This commit is contained in:
@ -9,6 +9,7 @@ public:
|
|||||||
virtual bool Capture() = 0;
|
virtual bool Capture() = 0;
|
||||||
virtual bool SetHMirror(bool enabled) = 0;
|
virtual bool SetHMirror(bool enabled) = 0;
|
||||||
virtual bool SetVFlip(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;
|
virtual std::string Explain(const std::string& question) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -41,6 +41,11 @@ Esp32Camera::~Esp32Camera() {
|
|||||||
esp_camera_fb_return(current_fb_);
|
esp_camera_fb_return(current_fb_);
|
||||||
current_fb_ = nullptr;
|
current_fb_ = nullptr;
|
||||||
}
|
}
|
||||||
|
if (encode_buf_) {
|
||||||
|
heap_caps_free(encode_buf_);
|
||||||
|
encode_buf_ = nullptr;
|
||||||
|
encode_buf_size_ = 0;
|
||||||
|
}
|
||||||
esp_camera_deinit();
|
esp_camera_deinit();
|
||||||
streaming_on_ = false;
|
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) {
|
if (current_fb_->format == PIXFORMAT_RGB565) {
|
||||||
size_t pixel_count = current_fb_->width * current_fb_->height;
|
size_t pixel_count = current_fb_->width * current_fb_->height;
|
||||||
size_t data_size = pixel_count * 2;
|
size_t data_size = pixel_count * 2;
|
||||||
|
|
||||||
uint8_t *preview_data = (uint8_t *)heap_caps_malloc(data_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
// Allocate or reallocate encode buffer if needed
|
||||||
if (preview_data == nullptr) {
|
if (encode_buf_size_ < data_size) {
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory for preview image");
|
if (encode_buf_) {
|
||||||
return false;
|
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 *src = (uint16_t *)current_fb_->buf;
|
||||||
uint16_t *dst = (uint16_t *)preview_data;
|
uint16_t *dst = (uint16_t *)encode_buf_;
|
||||||
for (size_t i = 0; i < pixel_count; i++) {
|
if (swap_bytes_enabled_) {
|
||||||
// Copy data from driver buffer to preview buffer with byte swapping
|
for (size_t i = 0; i < pixel_count; i++) {
|
||||||
dst[i] = __builtin_bswap16(src[i]);
|
dst[i] = __builtin_bswap16(src[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(encode_buf_, current_fb_->buf, data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display preview image
|
// Allocate separate buffer for preview display
|
||||||
auto display = dynamic_cast<LvglDisplay *>(Board::GetInstance().GetDisplay());
|
uint8_t *preview_data = (uint8_t *)heap_caps_malloc(data_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
if (display != nullptr) {
|
if (preview_data != nullptr) {
|
||||||
display->SetPreviewImage(std::make_unique<LvglAllocatedImage>(preview_data, data_size, current_fb_->width, current_fb_->height, current_fb_->width * 2, LV_COLOR_FORMAT_RGB565));
|
memcpy(preview_data, encode_buf_, data_size);
|
||||||
} else {
|
auto display = dynamic_cast<LvglDisplay *>(Board::GetInstance().GetDisplay());
|
||||||
heap_caps_free(preview_data);
|
if (display != nullptr) {
|
||||||
|
display->SetPreviewImage(std::make_unique<LvglAllocatedImage>(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) {
|
} else if (current_fb_->format == PIXFORMAT_JPEG) {
|
||||||
// JPEG format preview usually requires decoding, skip preview display for now, just log
|
// JPEG format preview usually requires decoding, skip preview display for now, just log
|
||||||
@ -126,6 +147,11 @@ bool Esp32Camera::SetVFlip(bool enabled) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Esp32Camera::SetSwapBytes(bool enabled) {
|
||||||
|
swap_bytes_enabled_ = enabled;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Esp32Camera::Explain(const std::string &question) {
|
std::string Esp32Camera::Explain(const std::string &question) {
|
||||||
if (explain_url_.empty()) {
|
if (explain_url_.empty()) {
|
||||||
throw std::runtime_error("Image explain URL or token is not set");
|
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;
|
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 {
|
[](void* arg, size_t index, const void* data, size_t len) -> size_t {
|
||||||
auto jpeg_queue = static_cast<QueueHandle_t>(arg);
|
auto jpeg_queue = static_cast<QueueHandle_t>(arg);
|
||||||
JpegChunk chunk = {.data = nullptr, .len = len};
|
JpegChunk chunk = {.data = nullptr, .len = len};
|
||||||
|
|||||||
@ -23,10 +23,13 @@ class Esp32Camera : public Camera
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool streaming_on_ = false;
|
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_url_;
|
||||||
std::string explain_token_;
|
std::string explain_token_;
|
||||||
std::thread encoder_thread_;
|
std::thread encoder_thread_;
|
||||||
camera_fb_t *current_fb_ = nullptr;
|
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:
|
public:
|
||||||
Esp32Camera(const camera_config_t &config);
|
Esp32Camera(const camera_config_t &config);
|
||||||
@ -36,5 +39,6 @@ public:
|
|||||||
virtual bool Capture() override;
|
virtual bool Capture() override;
|
||||||
virtual bool SetHMirror(bool enabled) override;
|
virtual bool SetHMirror(bool enabled) override;
|
||||||
virtual bool SetVFlip(bool enabled) override;
|
virtual bool SetVFlip(bool enabled) override;
|
||||||
|
virtual bool SetSwapBytes(bool enabled) override;
|
||||||
virtual std::string Explain(const std::string &question) override;
|
virtual std::string Explain(const std::string &question) override;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -22,9 +22,9 @@ dependencies:
|
|||||||
78/esp-wifi-connect: ~3.0.2
|
78/esp-wifi-connect: ~3.0.2
|
||||||
espressif/esp_audio_effects: ~1.2.1
|
espressif/esp_audio_effects: ~1.2.1
|
||||||
espressif/esp_audio_codec: ~2.4.1
|
espressif/esp_audio_codec: ~2.4.1
|
||||||
78/esp-ml307: ~3.6.2
|
78/esp-ml307: ~3.6.3
|
||||||
78/uart-eth-modem:
|
78/uart-eth-modem:
|
||||||
version: ~0.3.0
|
version: ~0.3.1
|
||||||
rules:
|
rules:
|
||||||
- if: target not in [esp32]
|
- if: target not in [esp32]
|
||||||
78/xiaozhi-fonts: ~1.6.0
|
78/xiaozhi-fonts: ~1.6.0
|
||||||
|
|||||||
Reference in New Issue
Block a user