From 4a0b3c6969d5bd34105d9012079caf5a6c8f74cb Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Fri, 27 Sep 2019 12:15:33 +0200 Subject: [PATCH 01/11] added rgb888 format output. Also added more inerfaces in frame class --- src/esp32cam.cpp | 1 + src/internal/config.cpp | 8 ++++++++ src/internal/config.hpp | 5 +++++ src/internal/frame.cpp | 18 ++++++++++-------- src/internal/frame.hpp | 30 +++++++++++++++++++++++++++++- 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/esp32cam.cpp b/src/esp32cam.cpp index 0b3ca67..66884ed 100644 --- a/src/esp32cam.cpp +++ b/src/esp32cam.cpp @@ -79,6 +79,7 @@ CameraClass::streamMjpeg(Client& client, const StreamMjpegConfig& cfg) break; } client.print("\r\n--" BOUNDARY "\r\n"); + yield(); } return nFrames; #undef BOUNDARY diff --git a/src/internal/config.cpp b/src/internal/config.cpp index 9ae4c26..188f930 100644 --- a/src/internal/config.cpp +++ b/src/internal/config.cpp @@ -78,6 +78,14 @@ Config::setRgb() return *this; } +Config& +Config::setRgb888() +{ + m_cfg->pixel_format = PIXFORMAT_RGB888; + return *this; +} + + Config& Config::setYuv() { diff --git a/src/internal/config.hpp b/src/internal/config.hpp index ed9a82b..e0f6499 100644 --- a/src/internal/config.hpp +++ b/src/internal/config.hpp @@ -36,6 +36,11 @@ class Config */ Config& setRgb(); + /** \brief Change pixel format to RGB888. + */ + Config& + setRgb888(); + /** \brief Change pixel format to YUV422. */ Config& setYuv(); diff --git a/src/internal/frame.cpp b/src/internal/frame.cpp index 8957d7c..d2b17c5 100644 --- a/src/internal/frame.cpp +++ b/src/internal/frame.cpp @@ -38,23 +38,25 @@ Frame::releaseFb() } } -bool -Frame::writeTo(Print& os, int timeout) -{ +bool Frame::writeTo(Print& os, int timeout) { + return writeToImpl(&os, timeout, nullptr); +} +bool Frame::writeTo(Print* os, int timeout) { return writeToImpl(os, timeout, nullptr); } -bool -Frame::writeTo(Client& os, int timeout) -{ +bool Frame::writeTo(Client& os, int timeout) { + return writeToImpl(&os, timeout, &os); +} +bool Frame::writeTo(Client* os, int timeout) { return writeToImpl(os, timeout, &os); } bool -Frame::writeToImpl(Print& os, int timeout, Client* client) +Frame::writeToImpl(Print* os, int timeout, Client* client) { auto startTime = millis(); - for (size_t i = 0; i < m_size; i += os.write(&m_data[i], m_size - i)) { + for (size_t i = 0; i < m_size; i += os->write(&m_data[i], m_size - i)) { if (millis() - startTime > static_cast(timeout) || (client != nullptr && !client->connected())) { return false; diff --git a/src/internal/frame.hpp b/src/internal/frame.hpp index badb3eb..420d23a 100644 --- a/src/internal/frame.hpp +++ b/src/internal/frame.hpp @@ -7,6 +7,15 @@ class Client; class Print; +#if defined(ESP8266) +# include +# include +#endif +#if defined(ESP32) +# include +# include +#endif + namespace esp32cam { /** \brief A frame of picture. @@ -52,6 +61,14 @@ class Frame */ bool writeTo(Client& os, int timeout = 10000); + /** \brief Write frame buffer to \p os . + * \param os output socket. + * \param timeout total time limit in millis. + * \retval true writing completed. + * \retval false writing disrupted by timeout or socket error. + */ + bool writeTo(AsyncClient& os, int timeout = 10000); + public: // conversion bool isJpeg() const; @@ -65,9 +82,19 @@ class Frame return m_pixFormat == PIXFORMAT_BMP; } + int + getPixFormat() + { + return m_pixFormat; + } + /** \brief Convert frame to BMP. */ bool toBmp(); +/** \we converted the buffer ourself outside the lib and need to set it! + */ + void + setData(uint8_t* newdata, size_t newsize, bool bIsBmp); private: Frame(); @@ -76,8 +103,9 @@ class Frame bool writeToImpl(Print& os, int timeout, Client* client); + bool writeToImpl(int timeout, AsyncClient* client); + void releaseFb(); - private: class CameraFbT; ///< camera_fb_t CameraFbT* m_fb = nullptr; From 9e503dd5d95fd6d7e3f6431f3f5132dddac8e87f Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Mon, 14 Oct 2019 09:14:54 +0200 Subject: [PATCH 02/11] Added support for streaming mjpeg and asyncclient --- src/esp32cam.cpp | 49 +++++++++++++++++++++++++++++++++++++----- src/esp32cam.h | 13 ++++++----- src/internal/frame.cpp | 29 ++++++++++++++++--------- src/internal/frame.hpp | 5 +++-- 4 files changed, 74 insertions(+), 22 deletions(-) diff --git a/src/esp32cam.cpp b/src/esp32cam.cpp index 66884ed..86e1519 100644 --- a/src/esp32cam.cpp +++ b/src/esp32cam.cpp @@ -3,6 +3,9 @@ #include #include +#define BOUNDARY "e8b8c539-047d-4777-a985-fbba6edff11e" +// #undef BOUNDARY + namespace esp32cam { CameraClass Camera; @@ -49,10 +52,7 @@ CameraClass::capture() return std::unique_ptr(new Frame(fb)); } -int -CameraClass::streamMjpeg(Client& client, const StreamMjpegConfig& cfg) -{ -#define BOUNDARY "e8b8c539-047d-4777-a985-fbba6edff11e" +int CameraClass::streamMjpeg(Client& client, const StreamMjpegConfig& cfg) { client.print("HTTP/1.1 200 OK\r\n" "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" "\r\n"); @@ -82,7 +82,46 @@ CameraClass::streamMjpeg(Client& client, const StreamMjpegConfig& cfg) yield(); } return nFrames; -#undef BOUNDARY } +/* +Cloned function for ASYNCCLIENT +*/ +int CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) { + client.write("HTTP/1.1 200 OK\r\n" + "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" + "\r\n"); + auto lastCapture = millis(); + int nFrames; + for (nFrames = 0; cfg.maxFrames < 0 || nFrames < cfg.maxFrames; ++nFrames) { + auto now = millis(); + auto sinceLastCapture = now - lastCapture; + if (static_cast(sinceLastCapture) < cfg.minInterval) { + delay(cfg.minInterval - sinceLastCapture); + } + lastCapture = millis(); + + auto frame = capture(); + if (frame == nullptr) { + break; + } + + char szTmp[256]; + size_t stLen = snprintf_P(szTmp, 256, PSTR( + "Content-Type: image/jpeg\r\n" + "Content-Length: %d\r\n" + "\r\n"), static_cast(frame->size()) + ); + client.write((const char*) szTmp, stLen); + if (!frame->writeTo(client, cfg.frameTimeout)) { + break; + } + client.write("\r\n--" BOUNDARY "\r\n"); + yield(); + } + return nFrames; +} + + + } // namespace esp32cam diff --git a/src/esp32cam.h b/src/esp32cam.h index b84a5ae..6c90f01 100644 --- a/src/esp32cam.h +++ b/src/esp32cam.h @@ -48,14 +48,17 @@ class CameraClass * \pre The camera has been initialized to JPEG mode. * \return number of frames streamed. */ - int - streamMjpeg(Client& client, const StreamMjpegConfig& cfg); + int streamMjpeg(Client& client, const StreamMjpegConfig& cfg); + int streamMjpeg(Client& client) { + return streamMjpeg(client, StreamMjpegConfig()); + } - int - streamMjpeg(Client& client) - { + int streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg); + int streamMjpeg(AsyncClient& client) { return streamMjpeg(client, StreamMjpegConfig()); } + + }; extern CameraClass Camera; diff --git a/src/internal/frame.cpp b/src/internal/frame.cpp index d2b17c5..92f0ecc 100644 --- a/src/internal/frame.cpp +++ b/src/internal/frame.cpp @@ -39,24 +39,20 @@ Frame::releaseFb() } bool Frame::writeTo(Print& os, int timeout) { - return writeToImpl(&os, timeout, nullptr); -} -bool Frame::writeTo(Print* os, int timeout) { return writeToImpl(os, timeout, nullptr); } bool Frame::writeTo(Client& os, int timeout) { - return writeToImpl(&os, timeout, &os); -} -bool Frame::writeTo(Client* os, int timeout) { return writeToImpl(os, timeout, &os); } -bool -Frame::writeToImpl(Print* os, int timeout, Client* client) -{ +bool Frame::writeTo(AsyncClient& os, int timeout) { + return writeToImpl(timeout, &os); +} + +bool Frame::writeToImpl(Print& os, int timeout, Client* client) { auto startTime = millis(); - for (size_t i = 0; i < m_size; i += os->write(&m_data[i], m_size - i)) { + for (size_t i = 0; i < m_size; i += os.write(&m_data[i], m_size - i)) { if (millis() - startTime > static_cast(timeout) || (client != nullptr && !client->connected())) { return false; @@ -66,6 +62,19 @@ Frame::writeToImpl(Print* os, int timeout, Client* client) return true; } +bool Frame::writeToImpl(int timeout, AsyncClient* client) { + auto startTime = millis(); + for (size_t i = 0; i < m_size; i += client->write((const char*) &m_data[i], m_size - i)) { + if (millis() - startTime > static_cast(timeout) || + (client != nullptr && !client->connected())) { + return false; + } + yield(); + } + return true; +} + + bool Frame::isJpeg() const { diff --git a/src/internal/frame.hpp b/src/internal/frame.hpp index 420d23a..3866dca 100644 --- a/src/internal/frame.hpp +++ b/src/internal/frame.hpp @@ -103,9 +103,10 @@ class Frame bool writeToImpl(Print& os, int timeout, Client* client); - bool writeToImpl(int timeout, AsyncClient* client); - + bool writeToImpl(int timeout, AsyncClient* client); + void releaseFb(); + private: class CameraFbT; ///< camera_fb_t CameraFbT* m_fb = nullptr; From 6135241a0e8626180b3ec6a05c6deee227d1b90d Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Tue, 15 Oct 2019 07:51:50 +0200 Subject: [PATCH 03/11] forcing send in async mode --- src/internal/frame.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/internal/frame.cpp b/src/internal/frame.cpp index 92f0ecc..8924e84 100644 --- a/src/internal/frame.cpp +++ b/src/internal/frame.cpp @@ -69,6 +69,8 @@ bool Frame::writeToImpl(int timeout, AsyncClient* client) { (client != nullptr && !client->connected())) { return false; } + // Force send now + client->send(); yield(); } return true; From d739cf4f13ab4f7f2bfdcddd6d172306af41d2a5 Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Tue, 15 Oct 2019 13:02:19 +0200 Subject: [PATCH 04/11] Added static member functions to control camera sensor properties fixed code style --- src/esp32cam.cpp | 223 +++++++++++++++++++++++++++++++++++++++-- src/esp32cam.h | 100 ++++++++++++++++++ src/internal/frame.cpp | 15 ++- src/internal/frame.hpp | 8 +- 4 files changed, 331 insertions(+), 15 deletions(-) diff --git a/src/esp32cam.cpp b/src/esp32cam.cpp index 86e1519..be9a90b 100644 --- a/src/esp32cam.cpp +++ b/src/esp32cam.cpp @@ -42,6 +42,218 @@ CameraClass::changeResolution(const Resolution& resolution, int sleepFor) return true; } +bool +CameraClass::changeContrast(int ilevel) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_contrast(sensor, ilevel) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeBrightness(int ilevel) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_brightness(sensor, ilevel) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeSaturation(int ilevel) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_saturation(sensor, ilevel) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeSpecialEffect(int ilevel) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_special_effect(sensor, ilevel) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeWbMode(int ilevel) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_wb_mode(sensor, ilevel) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeAeLevels(int ilevel) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_ae_level(sensor, ilevel)) { + return true; + } else + return false; +} + +bool +CameraClass::changAgcGain(int ilevel) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_agc_gain(sensor, ilevel) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changGainceilingSensor(int iGainCeiling) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if ((gainceiling_t)iGainCeiling < GAINCEILING_2X || + (gainceiling_t)iGainCeiling > GAINCEILING_128X) { + return false; + } + + if (sensor->set_gainceiling(sensor, (gainceiling_t)iGainCeiling) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeGaincontrol(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_gain_ctrl(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeColorbar(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_colorbar(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeWhitebalance(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_whitebal(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeQuality(int iQuality) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (iQuality < 0 || + iQuality > 63) { + return false; + } + + if (sensor->set_quality(sensor, iQuality) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changAec2(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_aec2(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changeAecValue(int iValue) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (iValue < 0 || + iValue > 1200) { + return false; + } + + if (sensor->set_agc_gain(sensor, iValue) == 0) { + return true; + } else + return false; +} + + std::unique_ptr CameraClass::capture() { @@ -52,7 +264,8 @@ CameraClass::capture() return std::unique_ptr(new Frame(fb)); } -int CameraClass::streamMjpeg(Client& client, const StreamMjpegConfig& cfg) { +int +CameraClass::streamMjpeg(Client& client, const StreamMjpegConfig& cfg) { client.print("HTTP/1.1 200 OK\r\n" "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" "\r\n"); @@ -84,10 +297,8 @@ int CameraClass::streamMjpeg(Client& client, const StreamMjpegConfig& cfg) { return nFrames; } -/* -Cloned function for ASYNCCLIENT -*/ -int CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) { +int +CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) { client.write("HTTP/1.1 200 OK\r\n" "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" "\r\n"); @@ -122,6 +333,4 @@ int CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) return nFrames; } - - } // namespace esp32cam diff --git a/src/esp32cam.h b/src/esp32cam.h index 6c90f01..0362f3a 100644 --- a/src/esp32cam.h +++ b/src/esp32cam.h @@ -29,6 +29,101 @@ class CameraClass bool changeResolution(const Resolution& resolution, int sleepFor = 500); + /** \brief Change Sensor Contrast level + * must be -2 to +2, default 0 + */ + bool + changeContrast(int ilevel); + + /** \brief Change Brightness level + * \param ilevel must be -2 to +2, default 0 + */ + bool + changeBrightness(int ilevel); + + /** \brief Change Saturation level + * \param ilevel must be -2 to +2, default 0 + */ + bool + changeSaturation(int ilevel); + + /** \brief Change SpecialEffect + * \param ilevel must be > 0 && <= NUM_SPECIAL_EFFECTS, default 0 + * \ 1 = no effect + * \ 2 = negative + * \ 3 = black and white + * \ 4 = reddish + * \ 5 = greenish + * \ 6 = blue + * \ 7 = retro + */ + bool + changeSpecialEffect(int ilevel); + + /** \brief Change WbMode + * \param ilevel must be > 0 && <= NUM_WB_MODES, default 0 + * \ 0 = default + * \ 1 = sunny + * \ 2 = cloudy + * \ 3 = office + * \ 4 = home + */ + bool + changeWbMode(int ilevel); + + /** \brief Change AE Levels + * \param ilevel must be -2 to +2, default 0 + */ + bool + changeAeLevels(int ilevel); + + /** \brief Change AGC Gain + * \param ilevel must be >= 0 and <= 30, default 30 + */ + bool + changAgcGain(int ilevel); + + /** \brief Change Gainceiling + * \param ilevel must be within ENUM gainceiling_t + */ + bool + changGainceilingSensor(int iGainCeiling); + + /** \brief Enable/Disable Gaincontrol + * \param iGainCeiling must be between GAINCEILING_2X and GAINCEILING_128X + */ + bool + changeGaincontrol(int iEnable); + + /** \brief Enable/Disable Testing Colorbar + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changeColorbar(int iEnable); + + /** \brief Enable/Disable Whitebalance + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changeWhitebalance(int iEnable); + + /** \brief Change JPEG Quality + * \param iEnable iQuality must be within 0 and 63 + */ + bool changeQuality(int iQuality); + + /** \brief Change AEC Value + * \param iEnable iValue must be 0 to 1200, default 0 + */ + bool + changeAecValue(int iValue); + + /** \brief Enable/Disable Auto/Manual Exposure control + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changAec2(int iEnable); + /** \brief Capture a frame of picture. */ std::unique_ptr @@ -53,6 +148,11 @@ class CameraClass return streamMjpeg(client, StreamMjpegConfig()); } + /** \brief Stream Motion JPEG. + * \Function cloned for AsyncClient + * \pre The camera has been initialized to JPEG mode. + * \return number of frames streamed. + */ int streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg); int streamMjpeg(AsyncClient& client) { return streamMjpeg(client, StreamMjpegConfig()); diff --git a/src/internal/frame.cpp b/src/internal/frame.cpp index 8924e84..42cf470 100644 --- a/src/internal/frame.cpp +++ b/src/internal/frame.cpp @@ -38,19 +38,23 @@ Frame::releaseFb() } } -bool Frame::writeTo(Print& os, int timeout) { +bool +Frame::writeTo(Print& os, int timeout) { return writeToImpl(os, timeout, nullptr); } -bool Frame::writeTo(Client& os, int timeout) { +bool +Frame::writeTo(Client& os, int timeout) { return writeToImpl(os, timeout, &os); } -bool Frame::writeTo(AsyncClient& os, int timeout) { +bool +Frame::writeTo(AsyncClient& os, int timeout) { return writeToImpl(timeout, &os); } -bool Frame::writeToImpl(Print& os, int timeout, Client* client) { +bool +Frame::writeToImpl(Print& os, int timeout, Client* client) { auto startTime = millis(); for (size_t i = 0; i < m_size; i += os.write(&m_data[i], m_size - i)) { if (millis() - startTime > static_cast(timeout) || @@ -62,7 +66,8 @@ bool Frame::writeToImpl(Print& os, int timeout, Client* client) { return true; } -bool Frame::writeToImpl(int timeout, AsyncClient* client) { +bool +Frame::writeToImpl(int timeout, AsyncClient* client) { auto startTime = millis(); for (size_t i = 0; i < m_size; i += client->write((const char*) &m_data[i], m_size - i)) { if (millis() - startTime > static_cast(timeout) || diff --git a/src/internal/frame.hpp b/src/internal/frame.hpp index 3866dca..fec0c83 100644 --- a/src/internal/frame.hpp +++ b/src/internal/frame.hpp @@ -51,7 +51,8 @@ class Frame * \retval true writing completed. * \retval false writing disrupted by timeout. */ - bool writeTo(Print& os, int timeout = 10000); + bool + writeTo(Print& os, int timeout = 10000); /** \brief Write frame buffer to \p os . * \param os output socket. @@ -67,8 +68,9 @@ class Frame * \retval true writing completed. * \retval false writing disrupted by timeout or socket error. */ - bool writeTo(AsyncClient& os, int timeout = 10000); - + bool + writeTo(AsyncClient& os, int timeout = 10000); + public: // conversion bool isJpeg() const; From 1763f2f3b3897fcb75c1446d93dfd65ca9c3974b Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Fri, 10 Jan 2020 12:33:43 +0100 Subject: [PATCH 05/11] added function to set AwbGainControl --- src/esp32cam.cpp | 15 +++++++++++++++ src/esp32cam.h | 10 ++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/esp32cam.cpp b/src/esp32cam.cpp index be9a90b..490da82 100644 --- a/src/esp32cam.cpp +++ b/src/esp32cam.cpp @@ -159,6 +159,21 @@ CameraClass::changGainceilingSensor(int iGainCeiling) return false; } +bool +CameraClass::changeAwbGainControl(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_awb_gain(sensor, iEnable) == 0) { + return true; + } else + return false; +} + + bool CameraClass::changeGaincontrol(int iEnable) { diff --git a/src/esp32cam.h b/src/esp32cam.h index 0362f3a..0130ede 100644 --- a/src/esp32cam.h +++ b/src/esp32cam.h @@ -84,13 +84,19 @@ class CameraClass changAgcGain(int ilevel); /** \brief Change Gainceiling - * \param ilevel must be within ENUM gainceiling_t + * \param iGainCeiling must be between GAINCEILING_2X and GAINCEILING_128X */ bool changGainceilingSensor(int iGainCeiling); + /** \brief Enable/Disable Awb GainControl + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changeAwbGainControl(int iEnable); + /** \brief Enable/Disable Gaincontrol - * \param iGainCeiling must be between GAINCEILING_2X and GAINCEILING_128X + * \param iEnable must be 0(disable) or 1 (enable) */ bool changeGaincontrol(int iEnable); From 12370f55654ddf65997115b1e08666c6c2ef1e12 Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Wed, 23 Sep 2020 16:57:25 +0200 Subject: [PATCH 06/11] add control for v / h mirror - Add function to change frequence - Add function to overwrite frame data buffer which I need to convert JPG to BMP using PSRAM! --- src/esp32cam.cpp | 27 +++++++++++++++++++++++++++ src/esp32cam.h | 14 +++++++++++++- src/internal/config.cpp | 7 +++++++ src/internal/config.hpp | 6 ++++++ src/internal/frame.cpp | 8 ++++++++ src/internal/frame.hpp | 5 +++++ 6 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/esp32cam.cpp b/src/esp32cam.cpp index 490da82..d0a5865 100644 --- a/src/esp32cam.cpp +++ b/src/esp32cam.cpp @@ -268,6 +268,33 @@ CameraClass::changeAecValue(int iValue) return false; } +bool +CameraClass::changHMirror(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_hmirror(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changVFlip(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_vflip(sensor, iEnable) == 0) { + return true; + } else + return false; +} std::unique_ptr CameraClass::capture() diff --git a/src/esp32cam.h b/src/esp32cam.h index 0130ede..f17337d 100644 --- a/src/esp32cam.h +++ b/src/esp32cam.h @@ -129,7 +129,19 @@ class CameraClass */ bool changAec2(int iEnable); - + + /** \brief Enable/Disable horizontal mirror + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changHMirror(int iEnable); + + /** \brief Enable/Disable vertical mirror + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changVFlip(int iEnable); + /** \brief Capture a frame of picture. */ std::unique_ptr diff --git a/src/internal/config.cpp b/src/internal/config.cpp index 188f930..fed90a1 100644 --- a/src/internal/config.cpp +++ b/src/internal/config.cpp @@ -108,4 +108,11 @@ Config::setJpeg(int quality) return *this; } +Config& +Config::setFreqHz(int freq) +{ + m_cfg->xclk_freq_hz = freq; + return *this; +} + } // namespace esp32cam diff --git a/src/internal/config.hpp b/src/internal/config.hpp index e0f6499..22e8785 100644 --- a/src/internal/config.hpp +++ b/src/internal/config.hpp @@ -54,6 +54,12 @@ class Config */ Config& setJpeg(int quality); + /** \brief Change xclk freq hz + * \param Change xclk freq hz default 20000000 + */ + Config& + setFreqHz(int freq); + private: class CameraConfigT; ///< camera_config_t CameraConfigT* m_cfg; diff --git a/src/internal/frame.cpp b/src/internal/frame.cpp index 42cf470..cb1aba6 100644 --- a/src/internal/frame.cpp +++ b/src/internal/frame.cpp @@ -88,6 +88,14 @@ Frame::isJpeg() const return m_pixFormat == PIXFORMAT_JPEG; } +void +Frame::setData(uint8_t* newdata, size_t newsize, bool bIsBmp) { + releaseFb(); + m_data = newdata; + m_size = newsize; + m_pixFormat = (bIsBmp ? PIXFORMAT_BMP : PIXFORMAT_JPEG); +} + bool Frame::toJpeg(int quality) { diff --git a/src/internal/frame.hpp b/src/internal/frame.hpp index fec0c83..80c5978 100644 --- a/src/internal/frame.hpp +++ b/src/internal/frame.hpp @@ -98,6 +98,11 @@ class Frame void setData(uint8_t* newdata, size_t newsize, bool bIsBmp); + /** \we converted the buffer ourself outside the lib and need to set it! + */ + void + setData(uint8_t* newdata, size_t newsize, bool bIsBmp); + private: Frame(); From ac169f06b3c41ea09884ed7cf7c34a88170ccabc Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Wed, 23 Sep 2020 17:02:56 +0200 Subject: [PATCH 07/11] add functions to set new sensor features - white pixel correction - black pixel correction - denoise control - lens correction - raw gamma - changeFrequence of Cam Sensor from 10 to 20 mhz - AutoExposurecontrol - Dcw - AsyncClient: Handle Client Disconnect from Outside - fix merge conflicts --- src/esp32cam.cpp | 147 ++++++++++++++++++++++++++++++++++-- src/esp32cam.h | 69 ++++++++++++++--- src/internal/frame.hpp | 6 +- src/internal/resolution.cpp | 2 +- src/internal/resolution.hpp | 2 +- 5 files changed, 201 insertions(+), 25 deletions(-) diff --git a/src/esp32cam.cpp b/src/esp32cam.cpp index d0a5865..9b4c5f5 100644 --- a/src/esp32cam.cpp +++ b/src/esp32cam.cpp @@ -42,6 +42,25 @@ CameraClass::changeResolution(const Resolution& resolution, int sleepFor) return true; } +bool +CameraClass::changeFrequence(int iMhz) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + int iLedTimer = 0; + int ret = 0; + sensor->xclk_freq_hz = iMhz * 1000000U; +// ret = xclk_timer_conf(iLedTimer, sensor->xclk_freq_hz); + // if (sensor->set_xclk(sensor, iLedTimer, iMhz) != 0) { + if (ret != 0) { + return false; + } else + return true; +} + bool CameraClass::changeContrast(int ilevel) { @@ -158,7 +177,7 @@ CameraClass::changGainceilingSensor(int iGainCeiling) } else return false; } - + bool CameraClass::changeAwbGainControl(int iEnable) { @@ -262,7 +281,7 @@ CameraClass::changeAecValue(int iValue) return false; } - if (sensor->set_agc_gain(sensor, iValue) == 0) { + if (sensor->set_aec_value(sensor, iValue) == 0) { return true; } else return false; @@ -296,6 +315,105 @@ CameraClass::changVFlip(int iEnable) return false; } +bool +CameraClass::changBPC(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_bpc(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changWPC(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_wpc(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changDenoise(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_denoise(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changLenc(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_lenc(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changRawGMA(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_raw_gma(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changAutoExposurecontrol(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_exposure_ctrl(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +bool +CameraClass::changDcw(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_dcw(sensor, iEnable) == 0) { + return true; + } else + return false; +} + + std::unique_ptr CameraClass::capture() { @@ -346,6 +464,7 @@ CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) { "\r\n"); auto lastCapture = millis(); int nFrames; + int nNullFrames = 0; for (nFrames = 0; cfg.maxFrames < 0 || nFrames < cfg.maxFrames; ++nFrames) { auto now = millis(); auto sinceLastCapture = now - lastCapture; @@ -356,8 +475,16 @@ CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) { auto frame = capture(); if (frame == nullptr) { - break; - } + nNullFrames++; + if (nNullFrames > 10) + break; + else { + // delay(100); // Delay short period! + continue; + } + } else { + nNullFrames = 0; + } char szTmp[256]; size_t stLen = snprintf_P(szTmp, 256, PSTR( @@ -365,10 +492,14 @@ CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) { "Content-Length: %d\r\n" "\r\n"), static_cast(frame->size()) ); - client.write((const char*) szTmp, stLen); - if (!frame->writeTo(client, cfg.frameTimeout)) { - break; - } + if (!client.disconnected()) { + client.write((const char*) szTmp, stLen); + if (!frame->writeTo(client, cfg.frameTimeout)) { + break; + } + } else { + break; + } client.write("\r\n--" BOUNDARY "\r\n"); yield(); } diff --git a/src/esp32cam.h b/src/esp32cam.h index f17337d..b178c3a 100644 --- a/src/esp32cam.h +++ b/src/esp32cam.h @@ -8,6 +8,16 @@ namespace esp32cam { +struct StreamMjpegConfig +{ +/// minimum interval between frame captures. +int minInterval = 0; +/// maximum number of frames before disconnecting. +int maxFrames = -1; +/// time limit of writing one frame in millis. +int frameTimeout = 10000; +}; + class CameraClass { public: @@ -29,6 +39,13 @@ class CameraClass bool changeResolution(const Resolution& resolution, int sleepFor = 500); + /** \brief Change camera resolution. + * \pre Change Camera Frequence Clock + * \param iMhz new Frequence, must be in MHZ + */ + bool + changeFrequence(int iMhz); + /** \brief Change Sensor Contrast level * must be -2 to +2, default 0 */ @@ -76,6 +93,12 @@ class CameraClass */ bool changeAeLevels(int ilevel); + + /** \brief Enable/Disable AEC (Auto Exposure Control) + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changAutoExposurecontrol(int iEnable); /** \brief Change AGC Gain * \param ilevel must be >= 0 and <= 30, default 30 @@ -141,22 +164,48 @@ class CameraClass */ bool changVFlip(int iEnable); + + /** \brief Enable/Disable black pixel correction + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changBPC(int iEnable); + + /** \brief Enable/Disable white pixel correction + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changWPC(int iEnable); + + /** \brief Enable/Disable Denoise Control + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changDenoise(int iEnable); + + /** \brief Enable/Disable Lenc Correction + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changLenc(int iEnable); + + /** \brief Enable/Disable RAW Gamma + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changRawGMA(int iEnable); + + /** \brief Enable/Disable DCW + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changDcw(int iEnable); /** \brief Capture a frame of picture. */ std::unique_ptr capture(); - struct StreamMjpegConfig - { - /// minimum interval between frame captures. - int minInterval = 0; - /// maximum number of frames before disconnecting. - int maxFrames = -1; - /// time limit of writing one frame in millis. - int frameTimeout = 10000; - }; - /** \brief Stream Motion JPEG. * \pre The camera has been initialized to JPEG mode. * \return number of frames streamed. diff --git a/src/internal/frame.hpp b/src/internal/frame.hpp index 80c5978..c2feb50 100644 --- a/src/internal/frame.hpp +++ b/src/internal/frame.hpp @@ -93,11 +93,7 @@ class Frame /** \brief Convert frame to BMP. */ bool toBmp(); -/** \we converted the buffer ourself outside the lib and need to set it! - */ - void - setData(uint8_t* newdata, size_t newsize, bool bIsBmp); - + /** \we converted the buffer ourself outside the lib and need to set it! */ void diff --git a/src/internal/resolution.cpp b/src/internal/resolution.cpp index 0e9eb38..2a7e731 100644 --- a/src/internal/resolution.cpp +++ b/src/internal/resolution.cpp @@ -40,4 +40,4 @@ Resolution::find(int minWidth, int minHeight) return res; } -} // namespace esp32cam +} // namespace esp32cam \ No newline at end of file diff --git a/src/internal/resolution.hpp b/src/internal/resolution.hpp index 8a609e7..653562c 100644 --- a/src/internal/resolution.hpp +++ b/src/internal/resolution.hpp @@ -35,4 +35,4 @@ class Resolution } // namespace esp32cam -#endif // ESP32CAM_RESOLUTION_HPP +#endif // ESP32CAM_RESOLUTION_HPP \ No newline at end of file From c61dc47d9d85f95e32731eaf0c851b1797119783 Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Thu, 3 Dec 2020 08:57:02 +0100 Subject: [PATCH 08/11] esp32-camera: fix compatibility issue caused by commit ae32d52c see commit: https://github.com/espressif/esp32-camera/commit/ae32d52cc27136d3b37ebcb4efc187dcdeb5fdf0#diff-a00662a8f0e0727f691f0ff27d0dd00a3721195193dad7b9b3dffb3f4d8591cc --- src/internal/resolution.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/resolution.cpp b/src/internal/resolution.cpp index 2a7e731..330eebe 100644 --- a/src/internal/resolution.cpp +++ b/src/internal/resolution.cpp @@ -16,7 +16,7 @@ Resolution::getWidth() const if (!isValid()) { return -1; } - return ::resolution[m_frameSize][0]; + return ::resolution[m_frameSize].width; } int @@ -25,7 +25,7 @@ Resolution::getHeight() const if (!isValid()) { return -1; } - return ::resolution[m_frameSize][1]; + return ::resolution[m_frameSize].height; } Resolution From 0ce16c20ad9c0f34195e9a359de0dc10beaa9d6c Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Thu, 3 Dec 2020 14:29:04 +0100 Subject: [PATCH 09/11] Add lastEspErr variable to store esp32 camera api return values In order to get more details on API failure reason, the return error code needs to be stored and evaluated. --- src/esp32cam.cpp | 6 ++++-- src/esp32cam.h | 4 ++++ src/internal/frame.hpp | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/esp32cam.cpp b/src/esp32cam.cpp index 9b4c5f5..bbd53e7 100644 --- a/src/esp32cam.cpp +++ b/src/esp32cam.cpp @@ -13,13 +13,15 @@ CameraClass Camera; bool CameraClass::begin(const Config& config) { - return esp_camera_init(reinterpret_cast(config.m_cfg)) == ESP_OK; + lastEspErr = esp_camera_init(reinterpret_cast(config.m_cfg)); + return (lastEspErr == ESP_OK ? true : false); } bool CameraClass::end() { - return esp_camera_deinit() == ESP_OK; + lastEspErr = esp_camera_deinit(); + return (lastEspErr == ESP_OK ? true : false); } bool diff --git a/src/esp32cam.h b/src/esp32cam.h index b178c3a..0d9c704 100644 --- a/src/esp32cam.h +++ b/src/esp32cam.h @@ -225,6 +225,10 @@ class CameraClass return streamMjpeg(client, StreamMjpegConfig()); } + /** \brief Return value for esp API calls + * \Store last api return value here useful for error handling! + */ + esp_err_t lastEspErr; }; diff --git a/src/internal/frame.hpp b/src/internal/frame.hpp index c2feb50..f613958 100644 --- a/src/internal/frame.hpp +++ b/src/internal/frame.hpp @@ -94,7 +94,8 @@ class Frame */ bool toBmp(); - /** \we converted the buffer ourself outside the lib and need to set it! + /** \brief Assign buffer from outside + * \We converted the buffer ourself outside the lib and need to set it! */ void setData(uint8_t* newdata, size_t newsize, bool bIsBmp); From 33e5c93294909356d5bb6b0ee6abb632e67f556e Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Tue, 8 Dec 2020 14:52:02 +0100 Subject: [PATCH 10/11] Changed yields to taskyield, added Abort flag to StreamMjpegConfig Use bAbort flag to cancel streaming from outside task --- src/esp32cam.cpp | 17 +++++++++-------- src/esp32cam.h | 8 ++++---- src/internal/frame.cpp | 3 +-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/esp32cam.cpp b/src/esp32cam.cpp index bbd53e7..c2f3572 100644 --- a/src/esp32cam.cpp +++ b/src/esp32cam.cpp @@ -454,24 +454,23 @@ CameraClass::streamMjpeg(Client& client, const StreamMjpegConfig& cfg) { break; } client.print("\r\n--" BOUNDARY "\r\n"); - yield(); } return nFrames; } int -CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) { +CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig* cfg) { client.write("HTTP/1.1 200 OK\r\n" "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" "\r\n"); auto lastCapture = millis(); int nFrames; int nNullFrames = 0; - for (nFrames = 0; cfg.maxFrames < 0 || nFrames < cfg.maxFrames; ++nFrames) { + for (nFrames = 0; cfg->maxFrames < 0 || nFrames < cfg->maxFrames; ++nFrames) { auto now = millis(); auto sinceLastCapture = now - lastCapture; - if (static_cast(sinceLastCapture) < cfg.minInterval) { - delay(cfg.minInterval - sinceLastCapture); + if (static_cast(sinceLastCapture) < cfg->minInterval) { + delay(cfg->minInterval - sinceLastCapture); } lastCapture = millis(); @@ -481,7 +480,6 @@ CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) { if (nNullFrames > 10) break; else { - // delay(100); // Delay short period! continue; } } else { @@ -496,14 +494,17 @@ CameraClass::streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg) { ); if (!client.disconnected()) { client.write((const char*) szTmp, stLen); - if (!frame->writeTo(client, cfg.frameTimeout)) { + if (!frame->writeTo(client, cfg->frameTimeout)) { break; } } else { break; } client.write("\r\n--" BOUNDARY "\r\n"); - yield(); + taskYIELD(); + + if (cfg->bAbort) + break; } return nFrames; } diff --git a/src/esp32cam.h b/src/esp32cam.h index 0d9c704..90c8239 100644 --- a/src/esp32cam.h +++ b/src/esp32cam.h @@ -16,6 +16,9 @@ int minInterval = 0; int maxFrames = -1; /// time limit of writing one frame in millis. int frameTimeout = 10000; +/// Abort flags +bool bAbort = false; + }; class CameraClass @@ -220,10 +223,7 @@ class CameraClass * \pre The camera has been initialized to JPEG mode. * \return number of frames streamed. */ - int streamMjpeg(AsyncClient& client, const StreamMjpegConfig& cfg); - int streamMjpeg(AsyncClient& client) { - return streamMjpeg(client, StreamMjpegConfig()); - } + int streamMjpeg(AsyncClient& client, const StreamMjpegConfig* cfg); /** \brief Return value for esp API calls * \Store last api return value here useful for error handling! diff --git a/src/internal/frame.cpp b/src/internal/frame.cpp index cb1aba6..e096598 100644 --- a/src/internal/frame.cpp +++ b/src/internal/frame.cpp @@ -61,7 +61,6 @@ Frame::writeToImpl(Print& os, int timeout, Client* client) { (client != nullptr && !client->connected())) { return false; } - yield(); } return true; } @@ -76,7 +75,7 @@ Frame::writeToImpl(int timeout, AsyncClient* client) { } // Force send now client->send(); - yield(); + taskYIELD(); } return true; } From 2035e41890f8904809da5b7a6ef5b3c34f87d401 Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Tue, 13 Jun 2023 12:40:41 +0200 Subject: [PATCH 11/11] testing change zoom and fixing freertos.h include --- src/esp32cam.cpp | 129 ++++++++++++++++++++++++++++++++++++++++- src/esp32cam.h | 39 ++++++++++++- src/internal/frame.cpp | 2 +- src/internal/frame.hpp | 2 +- 4 files changed, 168 insertions(+), 4 deletions(-) diff --git a/src/esp32cam.cpp b/src/esp32cam.cpp index c2f3572..f0c24d9 100644 --- a/src/esp32cam.cpp +++ b/src/esp32cam.cpp @@ -1,4 +1,4 @@ -#include "esp32cam.h" +#include "esp32cam.h" #include #include @@ -415,6 +415,133 @@ CameraClass::changDcw(int iEnable) return false; } +bool +CameraClass::changeZoom(int iEnable) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + // sensor->status.aec2 = enable; + if (sensor->set_reg(sensor, 0x12 /*COM7*/, 0xFF, iEnable?0x04/*COM7_ZOOM_EN*/:0) == 0) { +// if (sensor->set_reg(sensor, 0x01 /*BANK_SENSOR*/, 0x12 /*COM7*/, iEnable?0x04/*COM7_ZOOM_EN*/:0) == 0) { +// if (sensor->set_zoom(sensor, iEnable) == 0) { + return true; + } else + return false; +} + +int +CameraClass::getBandMode() +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + return sensor->get_reg(sensor, 0x3C0C, 0x01); +} + +bool +CameraClass::changeBandMode(int ilevel) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + // OV3660 registers + if ( ilevel == 0 ) { + // Auto Mode: Enable 0x3004[2] + if (sensor->set_reg(sensor, 0x3a00, 0x32, 0x32) == 0 && + sensor->set_reg(sensor, 0x3004, 0x04, 0x04) == 0 && + sensor->set_reg(sensor, 0x3c00, 0x04, 0x00) == 0 /* 60Hz? */ ) + return true; + else + return false; + } else { + // Manual Mode: Disable registers + if (sensor->set_reg(sensor, 0x3a00, 0x32, 0x00) == 0 && + sensor->set_reg(sensor, 0x3004, 0x04, 0x00) == 0 ) { + if ( ilevel == 1 ) { +// TESTING sensor->set_reg(sensor, 0x5000, 0x20, 0x20); + // 50 HZ + if (sensor->set_reg(sensor, 0x3c00, 0x04, 0x04) == 0) { + sensor->set_reg(sensor, 0x3a08, 0x00, 0x00);//50HZ BAND WIDTH + sensor->set_reg(sensor, 0x3a09, 0xeb, 0xeb);//50HZ BAND WIDTH + sensor->set_reg(sensor, 0x3a0e, 0x06, 0x06);//50HZ MAX BAND + + sensor->set_reg(sensor, 0x3C0C, 0x01, 0x01); + return true; + } else + return false; + } else { +// TESTING sensor->set_reg(sensor, 0x5000, 0x20, 0x00); + // 60 HZ + if (sensor->set_reg(sensor, 0x3c00, 0x04, 0x00) == 0) { + sensor->set_reg(sensor, 0x3a0a, 0x00, 0x00);//60HZ BAND WIDTH + sensor->set_reg(sensor, 0x3a0b, 0xc4, 0xc4);//60HZ BAND WIDTH + sensor->set_reg(sensor, 0x3a0d, 0x08, 0x08);//60HZ MAX BAND + + sensor->set_reg(sensor, 0x3C0C, 0x01, 0x00); + return true; + } else + return false; + } + } else { + return false; + } + } + + /* OV3660 + {0x3a00, 0x38}, //BIT[5]:1,banding function enable;bit[2] night mode disable + // /******if use 50HZ banding remove, refer to below setting******** + {0x3c00, 0x04}, //BIT[2]:1,ENABLE 50HZ + {0x3a14, 0x06}, //NIGHT MODE CEILING, 50HZ + {0x3a15, 0x6d}, //NIGHT MODE CEILING, 50HZ + {0x3a08, 0x00}, //50HZ BAND WIDTH + {0x3a09, 0xeb}, //50HZ BAND WIDTH + {0x3a0e, 0x06}, //50HZ MAX BAND + + {0x380e, 0x06}, + {0x380f, 0x6d}, //inset 81 dummy lines for banding filter//1c + // /******if use 60HZ banding remove, refer to below setting******** + + //{0x3c00, 0x00}, //BIT[2]:0,ENABLE 50HZ + {0x3a02, 0x06}, //NIGHT MODE CEILING, 60HZ + {0x3a03, 0x6d}, //NIGHT MODE CEILING, 60HZ + {0x3a0a, 0x00}, //60HZ BAND WIDTH + {0x3a0b, 0xc4}, //60HZ BAND WIDTH + {0x3a0d, 0x08}, //60HZ MAX BAND + + 0x3004[2] = 1 = AUTO + 0x3004[2] = 0 = MANUAL + 0X3C0C[0] = 0 = 60hz + 0X3C0C[0] = 1 = 50hz + */ +} + +bool +CameraClass::changePll(int iMul, int iPre, int iPclk) +{ + sensor_t* sensor = esp_camera_sensor_get(); + if (sensor == nullptr) { + return false; + } + + if (sensor->set_pll( sensor, + false, + iMul, + 1, + iPre, + false, + 0, + true, + iPclk) == 0) { + return true; + } else + return false; +} + std::unique_ptr CameraClass::capture() diff --git a/src/esp32cam.h b/src/esp32cam.h index 90c8239..88a586b 100644 --- a/src/esp32cam.h +++ b/src/esp32cam.h @@ -203,7 +203,44 @@ class CameraClass */ bool changDcw(int iEnable); - + + /** \brief Enable/Disable COM7_ZOOM_EN + * \param iEnable must be 0(disable) or 1 (enable) + */ + bool + changeZoom(int iEnable); + + /** \brief Get detectedBandMode Light Frequence Detection (Antiflicker) + * return + * \ 0 = 60hz + * \ 1 = 50hz + */ + int + getBandMode(void); + + /** \brief Change BandMode Light Frequewnce Detection (Antiflicker) + * \param ilevel must be > 0 && <= NUM_SPECIAL_EFFECTS, default 0 + * \ 0 = AUTO + * \ 1 = MANUAL 50hz + * \ 2 = MANUAL 60hz + */ + bool + changeBandMode(int ilevel); + + /** \brief TODO + * \param iMul + * \param iPclk + * \param iPre + * \ is set to 50hz or 60hz. + */ + bool + changePll(int iMul, int iPre, int iPclk); + + /** \brief Set Double Clock Mode for ov2640 + */ + bool + setDoubleClk(); + /** \brief Capture a frame of picture. */ std::unique_ptr diff --git a/src/internal/frame.cpp b/src/internal/frame.cpp index e096598..ea5be07 100644 --- a/src/internal/frame.cpp +++ b/src/internal/frame.cpp @@ -92,7 +92,7 @@ Frame::setData(uint8_t* newdata, size_t newsize, bool bIsBmp) { releaseFb(); m_data = newdata; m_size = newsize; - m_pixFormat = (bIsBmp ? PIXFORMAT_BMP : PIXFORMAT_JPEG); + m_pixFormat = (int)(bIsBmp ? PIXFORMAT_BMP : PIXFORMAT_JPEG); } bool diff --git a/src/internal/frame.hpp b/src/internal/frame.hpp index f613958..2226b54 100644 --- a/src/internal/frame.hpp +++ b/src/internal/frame.hpp @@ -12,7 +12,7 @@ class Print; # include #endif #if defined(ESP32) -# include +# include "freertos/FreeRTOS.h" # include #endif