├── .gitmodules ├── Arduino-IDE ├── README.md ├── esp32-cam-rtos-allframes │ ├── .gitignore │ ├── CMakeLists.txt │ ├── Kconfig │ ├── LICENSE │ ├── README.md │ ├── cam_hal.c │ ├── cam_hal.h │ ├── camera_common.h │ ├── camera_pins.h │ ├── component.mk │ ├── esp32-cam-rtos-allframes.ino │ ├── esp32-camera-master.zip │ ├── esp_camera.c │ ├── esp_camera.h │ ├── esp_jpg_decode.c │ ├── esp_jpg_decode.h │ ├── img_converters.h │ ├── jpge.cpp │ ├── jpge.h │ ├── library.json │ ├── ll_cam.c │ ├── ll_cam.h │ ├── nt99141.c │ ├── nt99141.h │ ├── nt99141_regs.h │ ├── nt99141_settings.h │ ├── ov2640.c │ ├── ov2640.h │ ├── ov2640_regs.h │ ├── ov2640_settings.h │ ├── ov3660.c │ ├── ov3660.h │ ├── ov3660_regs.h │ ├── ov3660_settings.h │ ├── ov5640.c │ ├── ov5640.h │ ├── ov5640_regs.h │ ├── ov5640_settings.h │ ├── ov7670.c │ ├── ov7670.h │ ├── ov7670_regs.h │ ├── ov7725.c │ ├── ov7725.h │ ├── ov7725_regs.h │ ├── sccb.c │ ├── sccb.h │ ├── sensor.c │ ├── sensor.h │ ├── to_bmp.c │ ├── to_jpg.cpp │ ├── xclk.c │ ├── xclk.h │ ├── yuv.c │ └── yuv.h ├── esp32-cam-rtos │ ├── .gitignore │ ├── CMakeLists.txt │ ├── Kconfig │ ├── LICENSE │ ├── README.md │ ├── cam_hal.c │ ├── cam_hal.h │ ├── camera_common.h │ ├── camera_pins.h │ ├── component.mk │ ├── esp32-cam-rtos.ino │ ├── esp32-camera-master.zip │ ├── esp_camera.c │ ├── esp_camera.h │ ├── esp_jpg_decode.c │ ├── esp_jpg_decode.h │ ├── img_converters.h │ ├── jpge.cpp │ ├── jpge.h │ ├── library.json │ ├── ll_cam.c │ ├── ll_cam.h │ ├── nt99141.c │ ├── nt99141.h │ ├── nt99141_regs.h │ ├── nt99141_settings.h │ ├── ov2640.c │ ├── ov2640.h │ ├── ov2640_regs.h │ ├── ov2640_settings.h │ ├── ov3660.c │ ├── ov3660.h │ ├── ov3660_regs.h │ ├── ov3660_settings.h │ ├── ov5640.c │ ├── ov5640.h │ ├── ov5640_regs.h │ ├── ov5640_settings.h │ ├── ov7670.c │ ├── ov7670.h │ ├── ov7670_regs.h │ ├── ov7725.c │ ├── ov7725.h │ ├── ov7725_regs.h │ ├── sccb.c │ ├── sccb.h │ ├── sensor.c │ ├── sensor.h │ ├── to_bmp.c │ ├── to_jpg.cpp │ ├── xclk.c │ ├── xclk.h │ ├── yuv.c │ └── yuv.h └── esp32-cam │ ├── .gitignore │ ├── CMakeLists.txt │ ├── Kconfig │ ├── LICENSE │ ├── README.md │ ├── cam_hal.c │ ├── cam_hal.h │ ├── camera_common.h │ ├── camera_pins.h │ ├── component.mk │ ├── esp32-cam.ino │ ├── esp32-camera-master.zip │ ├── esp_camera.c │ ├── esp_camera.h │ ├── esp_jpg_decode.c │ ├── esp_jpg_decode.h │ ├── img_converters.h │ ├── jpge.cpp │ ├── jpge.h │ ├── library.json │ ├── ll_cam.c │ ├── ll_cam.h │ ├── nt99141.c │ ├── nt99141.h │ ├── nt99141_regs.h │ ├── nt99141_settings.h │ ├── ov2640.c │ ├── ov2640.h │ ├── ov2640_regs.h │ ├── ov2640_settings.h │ ├── ov3660.c │ ├── ov3660.h │ ├── ov3660_regs.h │ ├── ov3660_settings.h │ ├── ov5640.c │ ├── ov5640.h │ ├── ov5640_regs.h │ ├── ov5640_settings.h │ ├── ov7670.c │ ├── ov7670.h │ ├── ov7670_regs.h │ ├── ov7725.c │ ├── ov7725.h │ ├── ov7725_regs.h │ ├── sccb.c │ ├── sccb.h │ ├── sensor.c │ ├── sensor.h │ ├── to_bmp.c │ ├── to_jpg.cpp │ ├── xclk.c │ ├── xclk.h │ ├── yuv.c │ └── yuv.h ├── LICENSE.txt ├── PlatformIO ├── README.md └── esp32-cam-rtos-pio │ ├── .gitignore │ ├── .vscode │ ├── extensions.json │ └── settings.json │ ├── CMakeLists.txt │ ├── ai-thinker-cam.csv │ ├── boards │ ├── ai-thinker-cam.json │ ├── esp-eye.json │ └── freenove-wrover-cam.json │ ├── dependencies.lock │ ├── esp-eye.csv │ ├── esp32-cam-rtos-pio.code-workspace │ ├── files │ └── camera_pins.ods │ ├── freenove-wrover-cam.csv │ ├── include │ ├── camera_pins.h │ ├── credentials.h │ ├── definitions.h │ ├── logging.h │ ├── references.h │ └── streaming.h │ ├── lib │ ├── ArduinoLog │ │ ├── library.json │ │ └── src │ │ │ ├── ArduinoLog.cpp │ │ │ └── ArduinoLog.h │ └── AverageFilter │ │ ├── LICENSE.txt │ │ ├── README.md │ │ ├── keywords.txt │ │ ├── library.json │ │ └── src │ │ └── AverageFilter.h │ ├── platformio.ini │ ├── sdkconfig.ai-thinker-cam │ ├── sdkconfig.ai-thinker-cam-debug │ ├── sdkconfig.ai-thinker-cam-debug.old │ ├── sdkconfig.esp-eye │ ├── sdkconfig.esp-eye-debug │ ├── sdkconfig.esp-eye-debug.old │ ├── sdkconfig.freenove-wrover-cam │ ├── src │ ├── CMakeLists.txt │ ├── logging.cpp │ ├── main.cpp │ ├── streaming.cpp │ ├── streaming_all_frames.cpp │ ├── streaming_multiclient_queue.cpp │ └── streaming_multiclient_task.cpp │ └── test │ └── README └── README.md /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "PlatformIO/esp32-cam-rtos-pio/components/esp32-camera"] 2 | path = PlatformIO/esp32-cam-rtos-pio/components/esp32-camera 3 | url = https://github.com/espressif/esp32-camera.git 4 | -------------------------------------------------------------------------------- /Arduino-IDE/README.md: -------------------------------------------------------------------------------- 1 | # MJPEG Multiclient Streaming Server 2 | 3 | ## With latest ESP-CAM drivers 4 | **Full story:** https://www.hackster.io/anatoli-arkhipenko/multi-client-mjpeg-streaming-from-esp32-47768f 5 | 6 | **Video:** https://youtu.be/bsAVJSZeSmc 7 | 8 | 9 | 10 | **Updated on 2021-07-01:** 11 | 12 | - OP updated to account for recent repo changes by Espressif 13 | 14 | - Recompiled with ESP32 Arduino Core 1.0.6 15 | 16 | - Updated with latest ESP CAM drivers 17 | 18 | 19 | 20 | ### Contents: 21 | 22 | #### esp32-cam folder: 23 | 24 | MJPEG Multiclient Streaming Server using RTOS queue to serve video to clients. 25 | 26 | The problem with this approach is that the slowest connected client slows it down for everyone. 27 | 28 | #### esp32-cam-rtos folder: 29 | 30 | MJPEG Multiclient Streaming Server using dedicated RTOS tasks to serve video to clients. 31 | 32 | This solves the problem of slowest client as every client is served independently based on their bandwidth. Slow clients are just not getting all the frames. 33 | 34 | #### esp32-cam-allframes folder: 35 | 36 | MJPEG Multiclient Streaming Server using dedicated RTOS tasks to serve video to clients. 37 | 38 | All captured frames are stored in PSRAM (until you run out of memory) and served to individual clients one after another, so every client is guaranteed to get all frames in order, at their own pace (good for recording without frame drops) 39 | 40 | 41 | 42 | ### DISCLAIMER: 43 | 44 | The repository should compile and work **AS-IS** as of the date stated above. Espressif is actively working on the camera drivers, and their **future updates may break the procedure below**. Please report the broken process providing as much information as possible, definitely the make and model of your camera device, version of the Arduino Core and IDE used. 45 | 46 | Remember, this is a hack, a POC and a test. This is **NOT GUARANTEED** to work on all ESP32-based devices. The performance could be different depending on the make, brand and manufacturer of your camera. 47 | 48 | Please do not demand fixes and updates - you are welcome to take this repo as a baseline and improve upon it. 49 | 50 | *Have fun!* 51 | 52 | 53 | 54 | ### Procedure: 55 | 56 | Use this process **ONLY** if you want to update to the very latest drivers. 57 | 58 | **Remember**: updating to the latest drivers may break the code dependencies and require investigation / code changes. 59 | 60 | 1. Clone or pull this repo locally using GIT 61 | 62 | 2. **Use AS-IS (in Arduino IDE) for guaranteed results.** If you feel adventurous and brave - proceed to step 3. 63 | 64 | 3. Download latest ZIP file from https://github.com/espressif/esp32-camera.git into the esp32-cam subfolder 65 | 66 | 4. In the archive: delete `examples` and `test` folders 67 | 68 | 5. Delete **ALL FILES** in the sketch folder (from step 1) except `esp32-cam*.ino` and `camera_pins.h` 69 | 70 | 6. In the archive: switch to subfolder `esp32-camera-master/target` and delete subfolders for `esp32s2` and `esp32s3` - I have not tested with those ones 71 | 72 | 7. unzip using `unzip -jo esp32-camera-master.zip` command. This will place all files in the same folder in a flat file structure 73 | 74 | 75 | 76 | **NOTE:** please observe the `-jo` flag: the sketch assumes all files are in the same folder and will overwrite the existing old files without asking for confirmation. 77 | 78 | 79 | 80 | In **esp32-cam.ino** sketch select your camera pin assignment. 81 | 82 | The choices are: 83 | 84 | - CAMERA_MODEL_WROVER_KIT 85 | 86 | - CAMERA_MODEL_ESP_EYE 87 | 88 | - CAMERA_MODEL_M5STACK_PSRAM 89 | 90 | - CAMERA_MODEL_M5STACK_WIDE 91 | 92 | - CAMERA_MODEL_AI_THINKER 93 | 94 | 95 | 96 | Compile the **esp32-cam.ino** sketch using the following settings: 97 | 98 | - ESP32 Dev Module 99 | - CPU Freq: 240 100 | - Flash Freq: 80 101 | - Flash mode: QIO 102 | - Flash Size: 4Mb 103 | - Partition: Default, Minimal SPIFFS (or any other that would fit the sketch) 104 | - PSRAM: **Enabled** 105 | 106 | 107 | 108 | ### Results: 109 | 110 | I was able to run multiple browser windows, multiple VLC windows and connect multiple Blynk video widgets (max: 10) to ESP-EYE chip. The delay on the browser window was almost unnoticeable. In VLC you notice a 1 second delay due to buffering. Blynk performance all depends on the phone, so no comments there. 111 | 112 | This is incredible considering the size of this thing! The camera on ESP-EYE is actually quite good. 113 | 114 | ### Enjoy! 115 | 116 | 117 | 118 | ------ 119 | 120 | ##### Other repositories that may be of interest 121 | 122 | ###### ESP32 MJPEG streaming server servicing a single client: 123 | 124 | https://github.com/arkhipenko/esp32-cam-mjpeg 125 | 126 | 127 | 128 | ###### ESP32 MJPEG streaming server servicing multiple clients (FreeRTOS based): 129 | 130 | https://github.com/arkhipenko/esp32-cam-mjpeg-multiclient 131 | 132 | 133 | 134 | ###### ESP32 MJPEG streaming server servicing multiple clients (FreeRTOS based) with the latest camera drivers from espressif. 135 | 136 | https://github.com/arkhipenko/esp32-mjpeg-multiclient-espcam-drivers 137 | 138 | 139 | 140 | ###### Cooperative multitasking library: 141 | 142 | https://github.com/arkhipenko/TaskScheduler 143 | 144 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") 2 | set(COMPONENT_SRCS 3 | driver/esp_camera.c 4 | driver/cam_hal.c 5 | driver/sccb.c 6 | driver/sensor.c 7 | sensors/ov2640.c 8 | sensors/ov3660.c 9 | sensors/ov5640.c 10 | sensors/ov7725.c 11 | sensors/ov7670.c 12 | sensors/nt99141.c 13 | conversions/yuv.c 14 | conversions/to_jpg.cpp 15 | conversions/to_bmp.c 16 | conversions/jpge.cpp 17 | conversions/esp_jpg_decode.c 18 | ) 19 | 20 | set(COMPONENT_ADD_INCLUDEDIRS 21 | driver/include 22 | conversions/include 23 | ) 24 | 25 | set(COMPONENT_PRIV_INCLUDEDIRS 26 | driver/private_include 27 | sensors/private_include 28 | conversions/private_include 29 | target/private_include 30 | ) 31 | 32 | if(IDF_TARGET STREQUAL "esp32") 33 | list(APPEND COMPONENT_SRCS 34 | target/xclk.c 35 | target/esp32/ll_cam.c 36 | ) 37 | endif() 38 | 39 | if(IDF_TARGET STREQUAL "esp32s2") 40 | list(APPEND COMPONENT_SRCS 41 | target/xclk.c 42 | target/esp32s2/ll_cam.c 43 | target/esp32s2/tjpgd.c 44 | ) 45 | 46 | list(APPEND COMPONENT_PRIV_INCLUDEDIRS 47 | target/esp32s2/private_include 48 | ) 49 | endif() 50 | 51 | if(IDF_TARGET STREQUAL "esp32s3") 52 | list(APPEND COMPONENT_SRCS 53 | target/esp32s3/ll_cam.c 54 | ) 55 | endif() 56 | 57 | set(COMPONENT_REQUIRES driver) 58 | set(COMPONENT_PRIV_REQUIRES freertos nvs_flash) 59 | 60 | register_component() 61 | endif() 62 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/Kconfig: -------------------------------------------------------------------------------- 1 | menu "Camera configuration" 2 | 3 | config OV7670_SUPPORT 4 | bool "Support OV7670 VGA" 5 | default y 6 | help 7 | Enable this option if you want to use the OV7670. 8 | Disable this option to save memory. 9 | 10 | config OV7725_SUPPORT 11 | bool "Support OV7725 SVGA" 12 | default n 13 | help 14 | Enable this option if you want to use the OV7725. 15 | Disable this option to save memory. 16 | 17 | config NT99141_SUPPORT 18 | bool "Support NT99141 HD" 19 | default y 20 | help 21 | Enable this option if you want to use the NT99141. 22 | Disable this option to save memory. 23 | 24 | config OV2640_SUPPORT 25 | bool "Support OV2640 2MP" 26 | default y 27 | help 28 | Enable this option if you want to use the OV2640. 29 | Disable this option to save memory. 30 | 31 | config OV3660_SUPPORT 32 | bool "Support OV3660 3MP" 33 | default y 34 | help 35 | Enable this option if you want to use the OV3360. 36 | Disable this option to save memory. 37 | 38 | config OV5640_SUPPORT 39 | bool "Support OV5640 5MP" 40 | default y 41 | help 42 | Enable this option if you want to use the OV5640. 43 | Disable this option to save memory. 44 | 45 | choice SCCB_HARDWARE_I2C_PORT 46 | bool "I2C peripheral to use for SCCB" 47 | default SCCB_HARDWARE_I2C_PORT1 48 | 49 | config SCCB_HARDWARE_I2C_PORT0 50 | bool "I2C0" 51 | config SCCB_HARDWARE_I2C_PORT1 52 | bool "I2C1" 53 | 54 | endchoice 55 | 56 | choice CAMERA_TASK_PINNED_TO_CORE 57 | bool "Camera task pinned to core" 58 | default CAMERA_CORE0 59 | help 60 | Pin the camera handle task to a certain core(0/1). It can also be done automatically choosing NO_AFFINITY. 61 | 62 | config CAMERA_CORE0 63 | bool "CORE0" 64 | config CAMERA_CORE1 65 | bool "CORE1" 66 | config CAMERA_NO_AFFINITY 67 | bool "NO_AFFINITY" 68 | 69 | endchoice 70 | 71 | endmenu 72 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/cam_hal.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include "esp_camera.h" 18 | 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /** 25 | * @brief Uninitialize the lcd_cam module 26 | * 27 | * @param handle Provide handle pointer to release resources 28 | * 29 | * @return 30 | * - ESP_OK Success 31 | * - ESP_FAIL Uninitialize fail 32 | */ 33 | esp_err_t cam_deinit(void); 34 | 35 | /** 36 | * @brief Initialize the lcd_cam module 37 | * 38 | * @param config Configurations - see lcd_cam_config_t struct 39 | * 40 | * @return 41 | * - ESP_OK Success 42 | * - ESP_ERR_INVALID_ARG Parameter error 43 | * - ESP_ERR_NO_MEM No memory to initialize lcd_cam 44 | * - ESP_FAIL Initialize fail 45 | */ 46 | esp_err_t cam_init(const camera_config_t *config); 47 | 48 | esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint8_t sensor_pid); 49 | 50 | void cam_stop(void); 51 | 52 | void cam_start(void); 53 | 54 | camera_fb_t *cam_take(TickType_t timeout); 55 | 56 | void cam_give(camera_fb_t *dma_buffer); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/camera_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "esp_err.h" 7 | #include "esp_intr_alloc.h" 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/semphr.h" 10 | #include "freertos/task.h" 11 | #include "esp_camera.h" 12 | #include "sensor.h" 13 | 14 | #include "esp_system.h" 15 | #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ 16 | #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 17 | #include "esp32/rom/lldesc.h" 18 | #elif CONFIG_IDF_TARGET_ESP32S2 // ESP32-S2 19 | #include "esp32s2/rom/lldesc.h" 20 | #elif CONFIG_IDF_TARGET_ESP32S3 // ESP32-S3 21 | #include "esp32s3/rom/lldesc.h" 22 | #else 23 | #error Target CONFIG_IDF_TARGET is not supported 24 | #endif 25 | #else // ESP32 Before IDF 4.0 26 | #include "rom/lldesc.h" 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/camera_pins.h: -------------------------------------------------------------------------------- 1 | 2 | #if defined(CAMERA_MODEL_WROVER_KIT) 3 | #define PWDN_GPIO_NUM -1 4 | #define RESET_GPIO_NUM -1 5 | #define XCLK_GPIO_NUM 21 6 | #define SIOD_GPIO_NUM 26 7 | #define SIOC_GPIO_NUM 27 8 | 9 | #define Y9_GPIO_NUM 35 10 | #define Y8_GPIO_NUM 34 11 | #define Y7_GPIO_NUM 39 12 | #define Y6_GPIO_NUM 36 13 | #define Y5_GPIO_NUM 19 14 | #define Y4_GPIO_NUM 18 15 | #define Y3_GPIO_NUM 5 16 | #define Y2_GPIO_NUM 4 17 | #define VSYNC_GPIO_NUM 25 18 | #define HREF_GPIO_NUM 23 19 | #define PCLK_GPIO_NUM 22 20 | 21 | #elif defined(CAMERA_MODEL_ESP_EYE) 22 | #define PWDN_GPIO_NUM -1 23 | #define RESET_GPIO_NUM -1 24 | #define XCLK_GPIO_NUM 4 25 | #define SIOD_GPIO_NUM 18 26 | #define SIOC_GPIO_NUM 23 27 | 28 | #define Y9_GPIO_NUM 36 29 | #define Y8_GPIO_NUM 37 30 | #define Y7_GPIO_NUM 38 31 | #define Y6_GPIO_NUM 39 32 | #define Y5_GPIO_NUM 35 33 | #define Y4_GPIO_NUM 14 34 | #define Y3_GPIO_NUM 13 35 | #define Y2_GPIO_NUM 34 36 | #define VSYNC_GPIO_NUM 5 37 | #define HREF_GPIO_NUM 27 38 | #define PCLK_GPIO_NUM 25 39 | 40 | #elif defined(CAMERA_MODEL_M5STACK_PSRAM) 41 | #define PWDN_GPIO_NUM -1 42 | #define RESET_GPIO_NUM 15 43 | #define XCLK_GPIO_NUM 27 44 | #define SIOD_GPIO_NUM 25 45 | #define SIOC_GPIO_NUM 23 46 | 47 | #define Y9_GPIO_NUM 19 48 | #define Y8_GPIO_NUM 36 49 | #define Y7_GPIO_NUM 18 50 | #define Y6_GPIO_NUM 39 51 | #define Y5_GPIO_NUM 5 52 | #define Y4_GPIO_NUM 34 53 | #define Y3_GPIO_NUM 35 54 | #define Y2_GPIO_NUM 32 55 | #define VSYNC_GPIO_NUM 22 56 | #define HREF_GPIO_NUM 26 57 | #define PCLK_GPIO_NUM 21 58 | 59 | #elif defined(CAMERA_MODEL_M5STACK_WIDE) 60 | #define PWDN_GPIO_NUM -1 61 | #define RESET_GPIO_NUM 15 62 | #define XCLK_GPIO_NUM 27 63 | #define SIOD_GPIO_NUM 22 64 | #define SIOC_GPIO_NUM 23 65 | 66 | #define Y9_GPIO_NUM 19 67 | #define Y8_GPIO_NUM 36 68 | #define Y7_GPIO_NUM 18 69 | #define Y6_GPIO_NUM 39 70 | #define Y5_GPIO_NUM 5 71 | #define Y4_GPIO_NUM 34 72 | #define Y3_GPIO_NUM 35 73 | #define Y2_GPIO_NUM 32 74 | #define VSYNC_GPIO_NUM 25 75 | #define HREF_GPIO_NUM 26 76 | #define PCLK_GPIO_NUM 21 77 | 78 | #elif defined(CAMERA_MODEL_AI_THINKER) 79 | #define PWDN_GPIO_NUM 32 80 | #define RESET_GPIO_NUM -1 81 | #define XCLK_GPIO_NUM 0 82 | #define SIOD_GPIO_NUM 26 83 | #define SIOC_GPIO_NUM 27 84 | 85 | #define Y9_GPIO_NUM 35 86 | #define Y8_GPIO_NUM 34 87 | #define Y7_GPIO_NUM 39 88 | #define Y6_GPIO_NUM 36 89 | #define Y5_GPIO_NUM 21 90 | #define Y4_GPIO_NUM 19 91 | #define Y3_GPIO_NUM 18 92 | #define Y2_GPIO_NUM 5 93 | #define VSYNC_GPIO_NUM 25 94 | #define HREF_GPIO_NUM 23 95 | #define PCLK_GPIO_NUM 22 96 | 97 | #else 98 | #error "Camera model not selected" 99 | #endif 100 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_ADD_INCLUDEDIRS := driver/include conversions/include 2 | COMPONENT_PRIV_INCLUDEDIRS := driver/private_include conversions/private_include sensors/private_include target/private_include 3 | COMPONENT_SRCDIRS := driver conversions sensors target target/esp32 4 | CXXFLAGS += -fno-rtti 5 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/esp32-camera-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arkhipenko/esp32-mjpeg-multiclient-espcam-drivers/b9451ebb6dff814bc0bebbd1850a411915e78eff/Arduino-IDE/esp32-cam-rtos-allframes/esp32-camera-master.zip -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/esp_jpg_decode.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "esp_jpg_decode.h" 15 | 16 | #include "esp_system.h" 17 | #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ 18 | #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 19 | #include "esp32/rom/tjpgd.h" 20 | #elif CONFIG_IDF_TARGET_ESP32S2 21 | #include "tjpgd.h" 22 | #elif CONFIG_IDF_TARGET_ESP32S3 23 | #include "esp32s3/rom/tjpgd.h" 24 | #else 25 | #error Target CONFIG_IDF_TARGET is not supported 26 | #endif 27 | #else // ESP32 Before IDF 4.0 28 | #include "rom/tjpgd.h" 29 | #endif 30 | 31 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 32 | #include "esp32-hal-log.h" 33 | #define TAG "" 34 | #else 35 | #include "esp_log.h" 36 | static const char* TAG = "esp_jpg_decode"; 37 | #endif 38 | 39 | typedef struct { 40 | jpg_scale_t scale; 41 | jpg_reader_cb reader; 42 | jpg_writer_cb writer; 43 | void * arg; 44 | size_t len; 45 | size_t index; 46 | } esp_jpg_decoder_t; 47 | 48 | static const char * jd_errors[] = { 49 | "Succeeded", 50 | "Interrupted by output function", 51 | "Device error or wrong termination of input stream", 52 | "Insufficient memory pool for the image", 53 | "Insufficient stream input buffer", 54 | "Parameter error", 55 | "Data format error", 56 | "Right format but not supported", 57 | "Not supported JPEG standard" 58 | }; 59 | 60 | static uint32_t _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect) 61 | { 62 | uint16_t x = rect->left; 63 | uint16_t y = rect->top; 64 | uint16_t w = rect->right + 1 - x; 65 | uint16_t h = rect->bottom + 1 - y; 66 | uint8_t *data = (uint8_t *)bitmap; 67 | 68 | esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; 69 | 70 | if (jpeg->writer) { 71 | return jpeg->writer(jpeg->arg, x, y, w, h, data); 72 | } 73 | return 0; 74 | } 75 | 76 | static uint32_t _jpg_read(JDEC *decoder, uint8_t *buf, uint32_t len) 77 | { 78 | esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; 79 | if (jpeg->len && len > (jpeg->len - jpeg->index)) { 80 | len = jpeg->len - jpeg->index; 81 | } 82 | if (len) { 83 | len = jpeg->reader(jpeg->arg, jpeg->index, buf, len); 84 | if (!len) { 85 | ESP_LOGE(TAG, "Read Fail at %u/%u", jpeg->index, jpeg->len); 86 | } 87 | jpeg->index += len; 88 | } 89 | return len; 90 | } 91 | 92 | esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg) 93 | { 94 | static uint8_t work[3100]; 95 | JDEC decoder; 96 | esp_jpg_decoder_t jpeg; 97 | 98 | jpeg.len = len; 99 | jpeg.reader = reader; 100 | jpeg.writer = writer; 101 | jpeg.arg = arg; 102 | jpeg.scale = scale; 103 | jpeg.index = 0; 104 | 105 | JRESULT jres = jd_prepare(&decoder, _jpg_read, work, 3100, &jpeg); 106 | if(jres != JDR_OK){ 107 | ESP_LOGE(TAG, "JPG Header Parse Failed! %s", jd_errors[jres]); 108 | return ESP_FAIL; 109 | } 110 | 111 | uint16_t output_width = decoder.width / (1 << (uint8_t)(jpeg.scale)); 112 | uint16_t output_height = decoder.height / (1 << (uint8_t)(jpeg.scale)); 113 | 114 | //output start 115 | writer(arg, 0, 0, output_width, output_height, NULL); 116 | //output write 117 | jres = jd_decomp(&decoder, _jpg_write, (uint8_t)jpeg.scale); 118 | //output end 119 | writer(arg, output_width, output_height, output_width, output_height, NULL); 120 | 121 | if (jres != JDR_OK) { 122 | ESP_LOGE(TAG, "JPG Decompression Failed! %s", jd_errors[jres]); 123 | return ESP_FAIL; 124 | } 125 | //check if all data has been consumed. 126 | if (len && jpeg.index < len) { 127 | _jpg_read(&decoder, NULL, len - jpeg.index); 128 | } 129 | 130 | return ESP_OK; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/esp_jpg_decode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _ESP_JPG_DECODE_H_ 15 | #define _ESP_JPG_DECODE_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include "esp_err.h" 25 | 26 | typedef enum { 27 | JPG_SCALE_NONE, 28 | JPG_SCALE_2X, 29 | JPG_SCALE_4X, 30 | JPG_SCALE_8X, 31 | JPG_SCALE_MAX = JPG_SCALE_8X 32 | } jpg_scale_t; 33 | 34 | typedef size_t (* jpg_reader_cb)(void * arg, size_t index, uint8_t *buf, size_t len); 35 | typedef bool (* jpg_writer_cb)(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data); 36 | 37 | esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif /* _ESP_JPG_DECODE_H_ */ 44 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/img_converters.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _IMG_CONVERTERS_H_ 15 | #define _IMG_CONVERTERS_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include "esp_camera.h" 25 | #include "esp_jpg_decode.h" 26 | 27 | typedef size_t (* jpg_out_cb)(void * arg, size_t index, const void* data, size_t len); 28 | 29 | /** 30 | * @brief Convert image buffer to JPEG 31 | * 32 | * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format 33 | * @param src_len Length in bytes of the source buffer 34 | * @param width Width in pixels of the source image 35 | * @param height Height in pixels of the source image 36 | * @param format Format of the source image 37 | * @param quality JPEG quality of the resulting image 38 | * @param cp Callback to be called to write the bytes of the output JPEG 39 | * @param arg Pointer to be passed to the callback 40 | * 41 | * @return true on success 42 | */ 43 | bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg); 44 | 45 | /** 46 | * @brief Convert camera frame buffer to JPEG 47 | * 48 | * @param fb Source camera frame buffer 49 | * @param quality JPEG quality of the resulting image 50 | * @param cp Callback to be called to write the bytes of the output JPEG 51 | * @param arg Pointer to be passed to the callback 52 | * 53 | * @return true on success 54 | */ 55 | bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg); 56 | 57 | /** 58 | * @brief Convert image buffer to JPEG buffer 59 | * 60 | * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format 61 | * @param src_len Length in bytes of the source buffer 62 | * @param width Width in pixels of the source image 63 | * @param height Height in pixels of the source image 64 | * @param format Format of the source image 65 | * @param quality JPEG quality of the resulting image 66 | * @param out Pointer to be populated with the address of the resulting buffer. 67 | * You MUST free the pointer once you are done with it. 68 | * @param out_len Pointer to be populated with the length of the output buffer 69 | * 70 | * @return true on success 71 | */ 72 | bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len); 73 | 74 | /** 75 | * @brief Convert camera frame buffer to JPEG buffer 76 | * 77 | * @param fb Source camera frame buffer 78 | * @param quality JPEG quality of the resulting image 79 | * @param out Pointer to be populated with the address of the resulting buffer 80 | * @param out_len Pointer to be populated with the length of the output buffer 81 | * 82 | * @return true on success 83 | */ 84 | bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len); 85 | 86 | /** 87 | * @brief Convert image buffer to BMP buffer 88 | * 89 | * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format 90 | * @param src_len Length in bytes of the source buffer 91 | * @param width Width in pixels of the source image 92 | * @param height Height in pixels of the source image 93 | * @param format Format of the source image 94 | * @param out Pointer to be populated with the address of the resulting buffer 95 | * @param out_len Pointer to be populated with the length of the output buffer 96 | * 97 | * @return true on success 98 | */ 99 | bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len); 100 | 101 | /** 102 | * @brief Convert camera frame buffer to BMP buffer 103 | * 104 | * @param fb Source camera frame buffer 105 | * @param out Pointer to be populated with the address of the resulting buffer 106 | * @param out_len Pointer to be populated with the length of the output buffer 107 | * 108 | * @return true on success 109 | */ 110 | bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len); 111 | 112 | /** 113 | * @brief Convert image buffer to RGB888 buffer (used for face detection) 114 | * 115 | * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format 116 | * @param src_len Length in bytes of the source buffer 117 | * @param format Format of the source image 118 | * @param rgb_buf Pointer to the output buffer (width * height * 3) 119 | * 120 | * @return true on success 121 | */ 122 | bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf); 123 | 124 | bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale); 125 | 126 | #ifdef __cplusplus 127 | } 128 | #endif 129 | 130 | #endif /* _IMG_CONVERTERS_H_ */ 131 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/jpge.h: -------------------------------------------------------------------------------- 1 | // jpge.h - C++ class for JPEG compression. 2 | // Public domain, Rich Geldreich 3 | // Alex Evans: Added RGBA support, linear memory allocator. 4 | #ifndef JPEG_ENCODER_H 5 | #define JPEG_ENCODER_H 6 | 7 | namespace jpge 8 | { 9 | typedef unsigned char uint8; 10 | typedef signed short int16; 11 | typedef signed int int32; 12 | typedef unsigned short uint16; 13 | typedef unsigned int uint32; 14 | typedef unsigned int uint; 15 | 16 | // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common. 17 | enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 }; 18 | 19 | // JPEG compression parameters structure. 20 | struct params { 21 | inline params() : m_quality(85), m_subsampling(H2V2) { } 22 | 23 | inline bool check() const { 24 | if ((m_quality < 1) || (m_quality > 100)) { 25 | return false; 26 | } 27 | if ((uint)m_subsampling > (uint)H2V2) { 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | // Quality: 1-100, higher is better. Typical values are around 50-95. 34 | int m_quality; 35 | 36 | // m_subsampling: 37 | // 0 = Y (grayscale) only 38 | // 1 = H1V1 subsampling (YCbCr 1x1x1, 3 blocks per MCU) 39 | // 2 = H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU) 40 | // 3 = H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common) 41 | subsampling_t m_subsampling; 42 | }; 43 | 44 | // Output stream abstract class - used by the jpeg_encoder class to write to the output stream. 45 | // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts. 46 | class output_stream { 47 | public: 48 | virtual ~output_stream() { }; 49 | virtual bool put_buf(const void* Pbuf, int len) = 0; 50 | virtual uint get_size() const = 0; 51 | }; 52 | 53 | // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions. 54 | class jpeg_encoder { 55 | public: 56 | jpeg_encoder(); 57 | ~jpeg_encoder(); 58 | 59 | // Initializes the compressor. 60 | // pStream: The stream object to use for writing compressed data. 61 | // params - Compression parameters structure, defined above. 62 | // width, height - Image dimensions. 63 | // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data. 64 | // Returns false on out of memory or if a stream write fails. 65 | bool init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params = params()); 66 | 67 | // Call this method with each source scanline. 68 | // width * src_channels bytes per scanline is expected (RGB or Y format). 69 | // You must call with NULL after all scanlines are processed to finish compression. 70 | // Returns false on out of memory or if a stream write fails. 71 | bool process_scanline(const void* pScanline); 72 | 73 | // Deinitializes the compressor, freeing any allocated memory. May be called at any time. 74 | void deinit(); 75 | 76 | private: 77 | jpeg_encoder(const jpeg_encoder &); 78 | jpeg_encoder &operator =(const jpeg_encoder &); 79 | 80 | typedef int32 sample_array_t; 81 | enum { JPGE_OUT_BUF_SIZE = 512 }; 82 | 83 | output_stream *m_pStream; 84 | params m_params; 85 | uint8 m_num_components; 86 | uint8 m_comp_h_samp[3], m_comp_v_samp[3]; 87 | int m_image_x, m_image_y, m_image_bpp, m_image_bpl; 88 | int m_image_x_mcu, m_image_y_mcu; 89 | int m_image_bpl_xlt, m_image_bpl_mcu; 90 | int m_mcus_per_row; 91 | int m_mcu_x, m_mcu_y; 92 | uint8 *m_mcu_lines[16]; 93 | uint8 m_mcu_y_ofs; 94 | sample_array_t m_sample_array[64]; 95 | int16 m_coefficient_array[64]; 96 | 97 | int m_last_dc_val[3]; 98 | uint8 m_out_buf[JPGE_OUT_BUF_SIZE]; 99 | uint8 *m_pOut_buf; 100 | uint m_out_buf_left; 101 | uint32 m_bit_buffer; 102 | uint m_bits_in; 103 | uint8 m_pass_num; 104 | bool m_all_stream_writes_succeeded; 105 | 106 | bool jpg_open(int p_x_res, int p_y_res, int src_channels); 107 | 108 | void flush_output_buffer(); 109 | void put_bits(uint bits, uint len); 110 | 111 | void emit_byte(uint8 i); 112 | void emit_word(uint i); 113 | void emit_marker(int marker); 114 | 115 | void emit_jfif_app0(); 116 | void emit_dqt(); 117 | void emit_sof(); 118 | void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag); 119 | void emit_dhts(); 120 | void emit_sos(); 121 | 122 | void compute_quant_table(int32 *dst, const int16 *src); 123 | void load_quantized_coefficients(int component_num); 124 | 125 | void load_block_8_8_grey(int x); 126 | void load_block_8_8(int x, int y, int c); 127 | void load_block_16_8(int x, int c); 128 | void load_block_16_8_8(int x, int c); 129 | 130 | void code_coefficients_pass_two(int component_num); 131 | void code_block(int component_num); 132 | 133 | void process_mcu_row(); 134 | bool process_end_of_image(); 135 | void load_mcu(const void* src); 136 | void clear(); 137 | void init(); 138 | }; 139 | 140 | } // namespace jpge 141 | 142 | #endif // JPEG_ENCODER 143 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esp32-camera", 3 | "version": "1.0.0", 4 | "keywords": "esp32, camera, espressif, esp32-cam", 5 | "description": "ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/espressif/esp32-camera" 9 | }, 10 | "frameworks": "espidf", 11 | "platforms": "*", 12 | "build": { 13 | "flags": [ 14 | "-Idriver/include", 15 | "-Iconversions/include", 16 | "-Idriver/private_include", 17 | "-Iconversions/private_include", 18 | "-Isensors/private_include", 19 | "-Itarget/private_include", 20 | "-fno-rtti" 21 | ], 22 | "includeDir": ".", 23 | "srcDir": ".", 24 | "srcFilter": ["-<*>", "+", "+", "+"] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/ll_cam.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "sdkconfig.h" 19 | #if CONFIG_IDF_TARGET_ESP32 20 | #if ESP_IDF_VERSION_MAJOR >= 4 21 | #include "esp32/rom/lldesc.h" 22 | #else 23 | #include "rom/lldesc.h" 24 | #endif 25 | #elif CONFIG_IDF_TARGET_ESP32S2 26 | #include "esp32s2/rom/lldesc.h" 27 | #elif CONFIG_IDF_TARGET_ESP32S3 28 | #include "esp32s3/rom/lldesc.h" 29 | #endif 30 | #include "esp_log.h" 31 | #include "esp_camera.h" 32 | #include "camera_common.h" 33 | #include "freertos/FreeRTOS.h" 34 | #include "freertos/queue.h" 35 | #include "freertos/task.h" 36 | #include "freertos/semphr.h" 37 | 38 | #define CAMERA_DBG_PIN_ENABLE 0 39 | #if CAMERA_DBG_PIN_ENABLE 40 | #if CONFIG_IDF_TARGET_ESP32 41 | #define DBG_PIN_NUM 26 42 | #else 43 | #define DBG_PIN_NUM 7 44 | #endif 45 | #include "hal/gpio_ll.h" 46 | #define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v) 47 | #else 48 | #define DBG_PIN_SET(v) 49 | #endif 50 | 51 | #define CAM_CHECK(a, str, ret) if (!(a)) { \ 52 | ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ 53 | return (ret); \ 54 | } 55 | 56 | #define CAM_CHECK_GOTO(a, str, lab) if (!(a)) { \ 57 | ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ 58 | goto lab; \ 59 | } 60 | 61 | #define LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE (4092) 62 | 63 | typedef enum { 64 | CAM_IN_SUC_EOF_EVENT = 0, 65 | CAM_VSYNC_EVENT 66 | } cam_event_t; 67 | 68 | typedef enum { 69 | CAM_STATE_IDLE = 0, 70 | CAM_STATE_READ_BUF = 1, 71 | } cam_state_t; 72 | 73 | typedef struct { 74 | camera_fb_t fb; 75 | uint8_t en; 76 | //for RGB/YUV modes 77 | lldesc_t *dma; 78 | size_t fb_offset; 79 | } cam_frame_t; 80 | 81 | typedef struct { 82 | uint32_t dma_bytes_per_item; 83 | uint32_t dma_buffer_size; 84 | uint32_t dma_half_buffer_size; 85 | uint32_t dma_half_buffer_cnt; 86 | uint32_t dma_node_buffer_size; 87 | uint32_t dma_node_cnt; 88 | uint32_t frame_copy_cnt; 89 | 90 | //for JPEG mode 91 | lldesc_t *dma; 92 | uint8_t *dma_buffer; 93 | 94 | cam_frame_t *frames; 95 | 96 | QueueHandle_t event_queue; 97 | QueueHandle_t frame_buffer_queue; 98 | TaskHandle_t task_handle; 99 | intr_handle_t cam_intr_handle; 100 | 101 | uint8_t dma_num;//ESP32-S3 102 | intr_handle_t dma_intr_handle;//ESP32-S3 103 | 104 | uint8_t jpeg_mode; 105 | uint8_t vsync_pin; 106 | uint8_t vsync_invert; 107 | uint32_t frame_cnt; 108 | uint32_t recv_size; 109 | bool swap_data; 110 | bool psram_mode; 111 | 112 | //for RGB/YUV modes 113 | uint16_t width; 114 | uint16_t height; 115 | uint8_t in_bytes_per_pixel; 116 | uint8_t fb_bytes_per_pixel; 117 | uint32_t fb_size; 118 | 119 | cam_state_t state; 120 | } cam_obj_t; 121 | 122 | 123 | bool ll_cam_stop(cam_obj_t *cam); 124 | bool ll_cam_start(cam_obj_t *cam, int frame_pos); 125 | esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config); 126 | void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en); 127 | esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config); 128 | esp_err_t ll_cam_init_isr(cam_obj_t *cam); 129 | void ll_cam_do_vsync(cam_obj_t *cam); 130 | uint8_t ll_cam_get_dma_align(cam_obj_t *cam); 131 | bool ll_cam_dma_sizes(cam_obj_t *cam); 132 | size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len); 133 | esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint8_t sensor_pid); 134 | 135 | // implemented in cam_hal 136 | void ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType_t * HPTaskAwoken); 137 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/nt99141.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * NT99141 driver. 7 | * 8 | */ 9 | #ifndef __NT99141_H__ 10 | #define __NT99141_H__ 11 | 12 | #include "sensor.h" 13 | 14 | int NT99141_init(sensor_t *sensor); 15 | 16 | #endif // __NT99141_H__ 17 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/ov2640.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV2640 driver. 7 | * 8 | */ 9 | #ifndef __OV2640_H__ 10 | #define __OV2640_H__ 11 | #include "sensor.h" 12 | int ov2640_init(sensor_t *sensor); 13 | #endif // __OV2640_H__ 14 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/ov3660.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV3660 driver. 7 | * 8 | */ 9 | #ifndef __OV3660_H__ 10 | #define __OV3660_H__ 11 | 12 | #include "sensor.h" 13 | 14 | int ov3660_init(sensor_t *sensor); 15 | 16 | #endif // __OV3660_H__ 17 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/ov5640.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __OV5640_H__ 3 | #define __OV5640_H__ 4 | 5 | #include "sensor.h" 6 | 7 | int ov5640_init(sensor_t *sensor); 8 | 9 | #endif // __OV5640_H__ 10 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/ov7670.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * author: Juan Schiavoni 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7670 driver. 7 | * 8 | */ 9 | #ifndef __OV7670_H__ 10 | #define __OV7670_H__ 11 | #include "sensor.h" 12 | 13 | int ov7670_init(sensor_t *sensor); 14 | #endif // __OV7670_H__ 15 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/ov7725.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7725 driver. 7 | * 8 | */ 9 | #ifndef __OV7725_H__ 10 | #define __OV7725_H__ 11 | #include "sensor.h" 12 | 13 | int ov7725_init(sensor_t *sensor); 14 | #endif // __OV7725_H__ 15 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/sccb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver. 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "sccb.h" 14 | #include "sensor.h" 15 | #include 16 | #include "sdkconfig.h" 17 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 18 | #include "esp32-hal-log.h" 19 | #else 20 | #include "esp_log.h" 21 | static const char* TAG = "sccb"; 22 | #endif 23 | 24 | #define LITTLETOBIG(x) ((x<<8)|(x>>8)) 25 | 26 | #include "driver/i2c.h" 27 | 28 | #define SCCB_FREQ 100000 /*!< I2C master frequency*/ 29 | #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ 30 | #define READ_BIT I2C_MASTER_READ /*!< I2C master read */ 31 | #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ 32 | #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ 33 | #define ACK_VAL 0x0 /*!< I2C ack value */ 34 | #define NACK_VAL 0x1 /*!< I2C nack value */ 35 | #if CONFIG_SCCB_HARDWARE_I2C_PORT1 36 | const int SCCB_I2C_PORT = 1; 37 | #else 38 | const int SCCB_I2C_PORT = 0; 39 | #endif 40 | 41 | int SCCB_Init(int pin_sda, int pin_scl) 42 | { 43 | ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl); 44 | i2c_config_t conf; 45 | memset(&conf, 0, sizeof(i2c_config_t)); 46 | conf.mode = I2C_MODE_MASTER; 47 | conf.sda_io_num = pin_sda; 48 | conf.sda_pullup_en = GPIO_PULLUP_ENABLE; 49 | conf.scl_io_num = pin_scl; 50 | conf.scl_pullup_en = GPIO_PULLUP_ENABLE; 51 | conf.master.clk_speed = SCCB_FREQ; 52 | 53 | i2c_param_config(SCCB_I2C_PORT, &conf); 54 | i2c_driver_install(SCCB_I2C_PORT, conf.mode, 0, 0, 0); 55 | return 0; 56 | } 57 | 58 | int SCCB_Deinit(void) 59 | { 60 | return i2c_driver_delete(SCCB_I2C_PORT); 61 | } 62 | 63 | uint8_t SCCB_Probe(void) 64 | { 65 | uint8_t slave_addr = 0x0; 66 | // for (size_t i = 1; i < 0x80; i++) { 67 | // i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 68 | // i2c_master_start(cmd); 69 | // i2c_master_write_byte(cmd, ( i << 1 ) | WRITE_BIT, ACK_CHECK_EN); 70 | // i2c_master_stop(cmd); 71 | // esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 72 | // i2c_cmd_link_delete(cmd); 73 | // if( ret == ESP_OK) { 74 | // ESP_LOGW(TAG, "Found I2C Device at 0x%02X", i); 75 | // } 76 | // } 77 | for (size_t i = 0; i < CAMERA_MODEL_MAX; i++) { 78 | if (slave_addr == camera_sensor[i].sccb_addr) { 79 | continue; 80 | } 81 | slave_addr = camera_sensor[i].sccb_addr; 82 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 83 | i2c_master_start(cmd); 84 | i2c_master_write_byte(cmd, ( slave_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 85 | i2c_master_stop(cmd); 86 | esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 87 | i2c_cmd_link_delete(cmd); 88 | if( ret == ESP_OK) { 89 | return slave_addr; 90 | } 91 | } 92 | return 0; 93 | } 94 | 95 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg) 96 | { 97 | uint8_t data=0; 98 | esp_err_t ret = ESP_FAIL; 99 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 100 | i2c_master_start(cmd); 101 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 102 | i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); 103 | i2c_master_stop(cmd); 104 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 105 | i2c_cmd_link_delete(cmd); 106 | if(ret != ESP_OK) return -1; 107 | cmd = i2c_cmd_link_create(); 108 | i2c_master_start(cmd); 109 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); 110 | i2c_master_read_byte(cmd, &data, NACK_VAL); 111 | i2c_master_stop(cmd); 112 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 113 | i2c_cmd_link_delete(cmd); 114 | if(ret != ESP_OK) { 115 | ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); 116 | } 117 | return data; 118 | } 119 | 120 | uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data) 121 | { 122 | esp_err_t ret = ESP_FAIL; 123 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 124 | i2c_master_start(cmd); 125 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 126 | i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); 127 | i2c_master_write_byte(cmd, data, ACK_CHECK_EN); 128 | i2c_master_stop(cmd); 129 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 130 | i2c_cmd_link_delete(cmd); 131 | if(ret != ESP_OK) { 132 | ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); 133 | } 134 | return ret == ESP_OK ? 0 : -1; 135 | } 136 | 137 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg) 138 | { 139 | uint8_t data=0; 140 | esp_err_t ret = ESP_FAIL; 141 | uint16_t reg_htons = LITTLETOBIG(reg); 142 | uint8_t *reg_u8 = (uint8_t *)®_htons; 143 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 144 | i2c_master_start(cmd); 145 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 146 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 147 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 148 | i2c_master_stop(cmd); 149 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 150 | i2c_cmd_link_delete(cmd); 151 | if(ret != ESP_OK) return -1; 152 | cmd = i2c_cmd_link_create(); 153 | i2c_master_start(cmd); 154 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); 155 | i2c_master_read_byte(cmd, &data, NACK_VAL); 156 | i2c_master_stop(cmd); 157 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 158 | i2c_cmd_link_delete(cmd); 159 | if(ret != ESP_OK) { 160 | ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data); 161 | } 162 | return data; 163 | } 164 | 165 | uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data) 166 | { 167 | static uint16_t i = 0; 168 | esp_err_t ret = ESP_FAIL; 169 | uint16_t reg_htons = LITTLETOBIG(reg); 170 | uint8_t *reg_u8 = (uint8_t *)®_htons; 171 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 172 | i2c_master_start(cmd); 173 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 174 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 175 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 176 | i2c_master_write_byte(cmd, data, ACK_CHECK_EN); 177 | i2c_master_stop(cmd); 178 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 179 | i2c_cmd_link_delete(cmd); 180 | if(ret != ESP_OK) { 181 | ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++); 182 | } 183 | return ret == ESP_OK ? 0 : -1; 184 | } 185 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/sccb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver. 7 | * 8 | */ 9 | #ifndef __SCCB_H__ 10 | #define __SCCB_H__ 11 | #include 12 | int SCCB_Init(int pin_sda, int pin_scl); 13 | int SCCB_Deinit(void); 14 | uint8_t SCCB_Probe(); 15 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg); 16 | uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data); 17 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg); 18 | uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data); 19 | #endif // __SCCB_H__ 20 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/sensor.c: -------------------------------------------------------------------------------- 1 | #include "sensor.h" 2 | 3 | const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = { 4 | {CAMERA_OV7725, OV7725_SCCB_ADDR, OV7725_PID, FRAMESIZE_VGA}, 5 | {CAMERA_OV2640, OV2640_SCCB_ADDR, OV2640_PID, FRAMESIZE_UXGA}, 6 | {CAMERA_OV3660, OV3660_SCCB_ADDR, OV3660_PID, FRAMESIZE_QXGA}, 7 | {CAMERA_OV5640, OV5640_SCCB_ADDR, OV5640_PID, FRAMESIZE_QSXGA}, 8 | {CAMERA_OV7670, OV7670_SCCB_ADDR, OV7670_PID, FRAMESIZE_VGA}, 9 | {CAMERA_NT99141, NT99141_SCCB_ADDR, NT99141_PID, FRAMESIZE_HD}, 10 | }; 11 | 12 | const resolution_info_t resolution[FRAMESIZE_INVALID] = { 13 | { 96, 96, ASPECT_RATIO_1X1 }, /* 96x96 */ 14 | { 160, 120, ASPECT_RATIO_4X3 }, /* QQVGA */ 15 | { 176, 144, ASPECT_RATIO_5X4 }, /* QCIF */ 16 | { 240, 176, ASPECT_RATIO_4X3 }, /* HQVGA */ 17 | { 240, 240, ASPECT_RATIO_1X1 }, /* 240x240 */ 18 | { 320, 240, ASPECT_RATIO_4X3 }, /* QVGA */ 19 | { 400, 296, ASPECT_RATIO_4X3 }, /* CIF */ 20 | { 480, 320, ASPECT_RATIO_3X2 }, /* HVGA */ 21 | { 640, 480, ASPECT_RATIO_4X3 }, /* VGA */ 22 | { 800, 600, ASPECT_RATIO_4X3 }, /* SVGA */ 23 | { 1024, 768, ASPECT_RATIO_4X3 }, /* XGA */ 24 | { 1280, 720, ASPECT_RATIO_16X9 }, /* HD */ 25 | { 1280, 1024, ASPECT_RATIO_5X4 }, /* SXGA */ 26 | { 1600, 1200, ASPECT_RATIO_4X3 }, /* UXGA */ 27 | // 3MP Sensors 28 | { 1920, 1080, ASPECT_RATIO_16X9 }, /* FHD */ 29 | { 720, 1280, ASPECT_RATIO_9X16 }, /* Portrait HD */ 30 | { 864, 1536, ASPECT_RATIO_9X16 }, /* Portrait 3MP */ 31 | { 2048, 1536, ASPECT_RATIO_4X3 }, /* QXGA */ 32 | // 5MP Sensors 33 | { 2560, 1440, ASPECT_RATIO_16X9 }, /* QHD */ 34 | { 2560, 1600, ASPECT_RATIO_16X10 }, /* WQXGA */ 35 | { 1088, 1920, ASPECT_RATIO_9X16 }, /* Portrait FHD */ 36 | { 2560, 1920, ASPECT_RATIO_4X3 }, /* QSXGA */ 37 | }; 38 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/xclk.c: -------------------------------------------------------------------------------- 1 | #include "driver/gpio.h" 2 | #include "driver/ledc.h" 3 | #include "esp_err.h" 4 | #include "esp_log.h" 5 | #include "esp_system.h" 6 | #include "xclk.h" 7 | 8 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 9 | #include "esp32-hal-log.h" 10 | #else 11 | #include "esp_log.h" 12 | static const char* TAG = "camera_xclk"; 13 | #endif 14 | 15 | esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz) 16 | { 17 | ledc_timer_config_t timer_conf; 18 | timer_conf.duty_resolution = LEDC_TIMER_1_BIT; 19 | timer_conf.freq_hz = xclk_freq_hz; 20 | #if CONFIG_IDF_TARGET_ESP32 21 | timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE; 22 | #else 23 | timer_conf.speed_mode = LEDC_LOW_SPEED_MODE; 24 | #endif 25 | #if ESP_IDF_VERSION_MAJOR >= 4 26 | timer_conf.clk_cfg = LEDC_AUTO_CLK; 27 | #endif 28 | timer_conf.timer_num = (ledc_timer_t)ledc_timer; 29 | esp_err_t err = ledc_timer_config(&timer_conf); 30 | if (err != ESP_OK) { 31 | ESP_LOGE(TAG, "ledc_timer_config failed for freq %d, rc=%x", xclk_freq_hz, err); 32 | } 33 | return err; 34 | } 35 | 36 | esp_err_t camera_enable_out_clock(camera_config_t* config) 37 | { 38 | periph_module_enable(PERIPH_LEDC_MODULE); 39 | 40 | esp_err_t err = xclk_timer_conf(config->ledc_timer, config->xclk_freq_hz); 41 | if (err != ESP_OK) { 42 | ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err); 43 | return err; 44 | } 45 | 46 | ledc_channel_config_t ch_conf; 47 | ch_conf.gpio_num = config->pin_xclk; 48 | #if CONFIG_IDF_TARGET_ESP32 49 | ch_conf.speed_mode = LEDC_HIGH_SPEED_MODE; 50 | #else 51 | ch_conf.speed_mode = LEDC_LOW_SPEED_MODE; 52 | #endif 53 | ch_conf.channel = config->ledc_channel; 54 | ch_conf.intr_type = LEDC_INTR_DISABLE; 55 | ch_conf.timer_sel = config->ledc_timer; 56 | ch_conf.duty = 1; 57 | ch_conf.hpoint = 0; 58 | err = ledc_channel_config(&ch_conf); 59 | if (err != ESP_OK) { 60 | ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err); 61 | return err; 62 | } 63 | return ESP_OK; 64 | } 65 | 66 | void camera_disable_out_clock() 67 | { 68 | periph_module_disable(PERIPH_LEDC_MODULE); 69 | } 70 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/xclk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "camera_common.h" 4 | 5 | esp_err_t camera_enable_out_clock(); 6 | 7 | void camera_disable_out_clock(); 8 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos-allframes/yuv.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _CONVERSIONS_YUV_H_ 15 | #define _CONVERSIONS_YUV_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | 23 | void yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* _CONVERSIONS_YUV_H_ */ 30 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") 2 | set(COMPONENT_SRCS 3 | driver/esp_camera.c 4 | driver/cam_hal.c 5 | driver/sccb.c 6 | driver/sensor.c 7 | sensors/ov2640.c 8 | sensors/ov3660.c 9 | sensors/ov5640.c 10 | sensors/ov7725.c 11 | sensors/ov7670.c 12 | sensors/nt99141.c 13 | conversions/yuv.c 14 | conversions/to_jpg.cpp 15 | conversions/to_bmp.c 16 | conversions/jpge.cpp 17 | conversions/esp_jpg_decode.c 18 | ) 19 | 20 | set(COMPONENT_ADD_INCLUDEDIRS 21 | driver/include 22 | conversions/include 23 | ) 24 | 25 | set(COMPONENT_PRIV_INCLUDEDIRS 26 | driver/private_include 27 | sensors/private_include 28 | conversions/private_include 29 | target/private_include 30 | ) 31 | 32 | if(IDF_TARGET STREQUAL "esp32") 33 | list(APPEND COMPONENT_SRCS 34 | target/xclk.c 35 | target/esp32/ll_cam.c 36 | ) 37 | endif() 38 | 39 | if(IDF_TARGET STREQUAL "esp32s2") 40 | list(APPEND COMPONENT_SRCS 41 | target/xclk.c 42 | target/esp32s2/ll_cam.c 43 | target/esp32s2/tjpgd.c 44 | ) 45 | 46 | list(APPEND COMPONENT_PRIV_INCLUDEDIRS 47 | target/esp32s2/private_include 48 | ) 49 | endif() 50 | 51 | if(IDF_TARGET STREQUAL "esp32s3") 52 | list(APPEND COMPONENT_SRCS 53 | target/esp32s3/ll_cam.c 54 | ) 55 | endif() 56 | 57 | set(COMPONENT_REQUIRES driver) 58 | set(COMPONENT_PRIV_REQUIRES freertos nvs_flash) 59 | 60 | register_component() 61 | endif() 62 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/Kconfig: -------------------------------------------------------------------------------- 1 | menu "Camera configuration" 2 | 3 | config OV7670_SUPPORT 4 | bool "Support OV7670 VGA" 5 | default y 6 | help 7 | Enable this option if you want to use the OV7670. 8 | Disable this option to save memory. 9 | 10 | config OV7725_SUPPORT 11 | bool "Support OV7725 SVGA" 12 | default n 13 | help 14 | Enable this option if you want to use the OV7725. 15 | Disable this option to save memory. 16 | 17 | config NT99141_SUPPORT 18 | bool "Support NT99141 HD" 19 | default y 20 | help 21 | Enable this option if you want to use the NT99141. 22 | Disable this option to save memory. 23 | 24 | config OV2640_SUPPORT 25 | bool "Support OV2640 2MP" 26 | default y 27 | help 28 | Enable this option if you want to use the OV2640. 29 | Disable this option to save memory. 30 | 31 | config OV3660_SUPPORT 32 | bool "Support OV3660 3MP" 33 | default y 34 | help 35 | Enable this option if you want to use the OV3360. 36 | Disable this option to save memory. 37 | 38 | config OV5640_SUPPORT 39 | bool "Support OV5640 5MP" 40 | default y 41 | help 42 | Enable this option if you want to use the OV5640. 43 | Disable this option to save memory. 44 | 45 | choice SCCB_HARDWARE_I2C_PORT 46 | bool "I2C peripheral to use for SCCB" 47 | default SCCB_HARDWARE_I2C_PORT1 48 | 49 | config SCCB_HARDWARE_I2C_PORT0 50 | bool "I2C0" 51 | config SCCB_HARDWARE_I2C_PORT1 52 | bool "I2C1" 53 | 54 | endchoice 55 | 56 | choice CAMERA_TASK_PINNED_TO_CORE 57 | bool "Camera task pinned to core" 58 | default CAMERA_CORE0 59 | help 60 | Pin the camera handle task to a certain core(0/1). It can also be done automatically choosing NO_AFFINITY. 61 | 62 | config CAMERA_CORE0 63 | bool "CORE0" 64 | config CAMERA_CORE1 65 | bool "CORE1" 66 | config CAMERA_NO_AFFINITY 67 | bool "NO_AFFINITY" 68 | 69 | endchoice 70 | 71 | endmenu 72 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/cam_hal.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include "esp_camera.h" 18 | 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /** 25 | * @brief Uninitialize the lcd_cam module 26 | * 27 | * @param handle Provide handle pointer to release resources 28 | * 29 | * @return 30 | * - ESP_OK Success 31 | * - ESP_FAIL Uninitialize fail 32 | */ 33 | esp_err_t cam_deinit(void); 34 | 35 | /** 36 | * @brief Initialize the lcd_cam module 37 | * 38 | * @param config Configurations - see lcd_cam_config_t struct 39 | * 40 | * @return 41 | * - ESP_OK Success 42 | * - ESP_ERR_INVALID_ARG Parameter error 43 | * - ESP_ERR_NO_MEM No memory to initialize lcd_cam 44 | * - ESP_FAIL Initialize fail 45 | */ 46 | esp_err_t cam_init(const camera_config_t *config); 47 | 48 | esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint8_t sensor_pid); 49 | 50 | void cam_stop(void); 51 | 52 | void cam_start(void); 53 | 54 | camera_fb_t *cam_take(TickType_t timeout); 55 | 56 | void cam_give(camera_fb_t *dma_buffer); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/camera_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "esp_err.h" 7 | #include "esp_intr_alloc.h" 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/semphr.h" 10 | #include "freertos/task.h" 11 | #include "esp_camera.h" 12 | #include "sensor.h" 13 | 14 | #include "esp_system.h" 15 | #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ 16 | #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 17 | #include "esp32/rom/lldesc.h" 18 | #elif CONFIG_IDF_TARGET_ESP32S2 // ESP32-S2 19 | #include "esp32s2/rom/lldesc.h" 20 | #elif CONFIG_IDF_TARGET_ESP32S3 // ESP32-S3 21 | #include "esp32s3/rom/lldesc.h" 22 | #else 23 | #error Target CONFIG_IDF_TARGET is not supported 24 | #endif 25 | #else // ESP32 Before IDF 4.0 26 | #include "rom/lldesc.h" 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/camera_pins.h: -------------------------------------------------------------------------------- 1 | 2 | #if defined(CAMERA_MODEL_WROVER_KIT) 3 | #define PWDN_GPIO_NUM -1 4 | #define RESET_GPIO_NUM -1 5 | #define XCLK_GPIO_NUM 21 6 | #define SIOD_GPIO_NUM 26 7 | #define SIOC_GPIO_NUM 27 8 | 9 | #define Y9_GPIO_NUM 35 10 | #define Y8_GPIO_NUM 34 11 | #define Y7_GPIO_NUM 39 12 | #define Y6_GPIO_NUM 36 13 | #define Y5_GPIO_NUM 19 14 | #define Y4_GPIO_NUM 18 15 | #define Y3_GPIO_NUM 5 16 | #define Y2_GPIO_NUM 4 17 | #define VSYNC_GPIO_NUM 25 18 | #define HREF_GPIO_NUM 23 19 | #define PCLK_GPIO_NUM 22 20 | 21 | #elif defined(CAMERA_MODEL_ESP_EYE) 22 | #define PWDN_GPIO_NUM -1 23 | #define RESET_GPIO_NUM -1 24 | #define XCLK_GPIO_NUM 4 25 | #define SIOD_GPIO_NUM 18 26 | #define SIOC_GPIO_NUM 23 27 | 28 | #define Y9_GPIO_NUM 36 29 | #define Y8_GPIO_NUM 37 30 | #define Y7_GPIO_NUM 38 31 | #define Y6_GPIO_NUM 39 32 | #define Y5_GPIO_NUM 35 33 | #define Y4_GPIO_NUM 14 34 | #define Y3_GPIO_NUM 13 35 | #define Y2_GPIO_NUM 34 36 | #define VSYNC_GPIO_NUM 5 37 | #define HREF_GPIO_NUM 27 38 | #define PCLK_GPIO_NUM 25 39 | 40 | #elif defined(CAMERA_MODEL_M5STACK_PSRAM) 41 | #define PWDN_GPIO_NUM -1 42 | #define RESET_GPIO_NUM 15 43 | #define XCLK_GPIO_NUM 27 44 | #define SIOD_GPIO_NUM 25 45 | #define SIOC_GPIO_NUM 23 46 | 47 | #define Y9_GPIO_NUM 19 48 | #define Y8_GPIO_NUM 36 49 | #define Y7_GPIO_NUM 18 50 | #define Y6_GPIO_NUM 39 51 | #define Y5_GPIO_NUM 5 52 | #define Y4_GPIO_NUM 34 53 | #define Y3_GPIO_NUM 35 54 | #define Y2_GPIO_NUM 32 55 | #define VSYNC_GPIO_NUM 22 56 | #define HREF_GPIO_NUM 26 57 | #define PCLK_GPIO_NUM 21 58 | 59 | #elif defined(CAMERA_MODEL_M5STACK_WIDE) 60 | #define PWDN_GPIO_NUM -1 61 | #define RESET_GPIO_NUM 15 62 | #define XCLK_GPIO_NUM 27 63 | #define SIOD_GPIO_NUM 22 64 | #define SIOC_GPIO_NUM 23 65 | 66 | #define Y9_GPIO_NUM 19 67 | #define Y8_GPIO_NUM 36 68 | #define Y7_GPIO_NUM 18 69 | #define Y6_GPIO_NUM 39 70 | #define Y5_GPIO_NUM 5 71 | #define Y4_GPIO_NUM 34 72 | #define Y3_GPIO_NUM 35 73 | #define Y2_GPIO_NUM 32 74 | #define VSYNC_GPIO_NUM 25 75 | #define HREF_GPIO_NUM 26 76 | #define PCLK_GPIO_NUM 21 77 | 78 | #elif defined(CAMERA_MODEL_AI_THINKER) 79 | #define PWDN_GPIO_NUM 32 80 | #define RESET_GPIO_NUM -1 81 | #define XCLK_GPIO_NUM 0 82 | #define SIOD_GPIO_NUM 26 83 | #define SIOC_GPIO_NUM 27 84 | 85 | #define Y9_GPIO_NUM 35 86 | #define Y8_GPIO_NUM 34 87 | #define Y7_GPIO_NUM 39 88 | #define Y6_GPIO_NUM 36 89 | #define Y5_GPIO_NUM 21 90 | #define Y4_GPIO_NUM 19 91 | #define Y3_GPIO_NUM 18 92 | #define Y2_GPIO_NUM 5 93 | #define VSYNC_GPIO_NUM 25 94 | #define HREF_GPIO_NUM 23 95 | #define PCLK_GPIO_NUM 22 96 | 97 | #else 98 | #error "Camera model not selected" 99 | #endif 100 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_ADD_INCLUDEDIRS := driver/include conversions/include 2 | COMPONENT_PRIV_INCLUDEDIRS := driver/private_include conversions/private_include sensors/private_include target/private_include 3 | COMPONENT_SRCDIRS := driver conversions sensors target target/esp32 4 | CXXFLAGS += -fno-rtti 5 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/esp32-camera-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arkhipenko/esp32-mjpeg-multiclient-espcam-drivers/b9451ebb6dff814bc0bebbd1850a411915e78eff/Arduino-IDE/esp32-cam-rtos/esp32-camera-master.zip -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/esp_jpg_decode.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "esp_jpg_decode.h" 15 | 16 | #include "esp_system.h" 17 | #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ 18 | #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 19 | #include "esp32/rom/tjpgd.h" 20 | #elif CONFIG_IDF_TARGET_ESP32S2 21 | #include "tjpgd.h" 22 | #elif CONFIG_IDF_TARGET_ESP32S3 23 | #include "esp32s3/rom/tjpgd.h" 24 | #else 25 | #error Target CONFIG_IDF_TARGET is not supported 26 | #endif 27 | #else // ESP32 Before IDF 4.0 28 | #include "rom/tjpgd.h" 29 | #endif 30 | 31 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 32 | #include "esp32-hal-log.h" 33 | #define TAG "" 34 | #else 35 | #include "esp_log.h" 36 | static const char* TAG = "esp_jpg_decode"; 37 | #endif 38 | 39 | typedef struct { 40 | jpg_scale_t scale; 41 | jpg_reader_cb reader; 42 | jpg_writer_cb writer; 43 | void * arg; 44 | size_t len; 45 | size_t index; 46 | } esp_jpg_decoder_t; 47 | 48 | static const char * jd_errors[] = { 49 | "Succeeded", 50 | "Interrupted by output function", 51 | "Device error or wrong termination of input stream", 52 | "Insufficient memory pool for the image", 53 | "Insufficient stream input buffer", 54 | "Parameter error", 55 | "Data format error", 56 | "Right format but not supported", 57 | "Not supported JPEG standard" 58 | }; 59 | 60 | static uint32_t _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect) 61 | { 62 | uint16_t x = rect->left; 63 | uint16_t y = rect->top; 64 | uint16_t w = rect->right + 1 - x; 65 | uint16_t h = rect->bottom + 1 - y; 66 | uint8_t *data = (uint8_t *)bitmap; 67 | 68 | esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; 69 | 70 | if (jpeg->writer) { 71 | return jpeg->writer(jpeg->arg, x, y, w, h, data); 72 | } 73 | return 0; 74 | } 75 | 76 | static uint32_t _jpg_read(JDEC *decoder, uint8_t *buf, uint32_t len) 77 | { 78 | esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; 79 | if (jpeg->len && len > (jpeg->len - jpeg->index)) { 80 | len = jpeg->len - jpeg->index; 81 | } 82 | if (len) { 83 | len = jpeg->reader(jpeg->arg, jpeg->index, buf, len); 84 | if (!len) { 85 | ESP_LOGE(TAG, "Read Fail at %u/%u", jpeg->index, jpeg->len); 86 | } 87 | jpeg->index += len; 88 | } 89 | return len; 90 | } 91 | 92 | esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg) 93 | { 94 | static uint8_t work[3100]; 95 | JDEC decoder; 96 | esp_jpg_decoder_t jpeg; 97 | 98 | jpeg.len = len; 99 | jpeg.reader = reader; 100 | jpeg.writer = writer; 101 | jpeg.arg = arg; 102 | jpeg.scale = scale; 103 | jpeg.index = 0; 104 | 105 | JRESULT jres = jd_prepare(&decoder, _jpg_read, work, 3100, &jpeg); 106 | if(jres != JDR_OK){ 107 | ESP_LOGE(TAG, "JPG Header Parse Failed! %s", jd_errors[jres]); 108 | return ESP_FAIL; 109 | } 110 | 111 | uint16_t output_width = decoder.width / (1 << (uint8_t)(jpeg.scale)); 112 | uint16_t output_height = decoder.height / (1 << (uint8_t)(jpeg.scale)); 113 | 114 | //output start 115 | writer(arg, 0, 0, output_width, output_height, NULL); 116 | //output write 117 | jres = jd_decomp(&decoder, _jpg_write, (uint8_t)jpeg.scale); 118 | //output end 119 | writer(arg, output_width, output_height, output_width, output_height, NULL); 120 | 121 | if (jres != JDR_OK) { 122 | ESP_LOGE(TAG, "JPG Decompression Failed! %s", jd_errors[jres]); 123 | return ESP_FAIL; 124 | } 125 | //check if all data has been consumed. 126 | if (len && jpeg.index < len) { 127 | _jpg_read(&decoder, NULL, len - jpeg.index); 128 | } 129 | 130 | return ESP_OK; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/esp_jpg_decode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _ESP_JPG_DECODE_H_ 15 | #define _ESP_JPG_DECODE_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include "esp_err.h" 25 | 26 | typedef enum { 27 | JPG_SCALE_NONE, 28 | JPG_SCALE_2X, 29 | JPG_SCALE_4X, 30 | JPG_SCALE_8X, 31 | JPG_SCALE_MAX = JPG_SCALE_8X 32 | } jpg_scale_t; 33 | 34 | typedef size_t (* jpg_reader_cb)(void * arg, size_t index, uint8_t *buf, size_t len); 35 | typedef bool (* jpg_writer_cb)(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data); 36 | 37 | esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif /* _ESP_JPG_DECODE_H_ */ 44 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/img_converters.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _IMG_CONVERTERS_H_ 15 | #define _IMG_CONVERTERS_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include "esp_camera.h" 25 | #include "esp_jpg_decode.h" 26 | 27 | typedef size_t (* jpg_out_cb)(void * arg, size_t index, const void* data, size_t len); 28 | 29 | /** 30 | * @brief Convert image buffer to JPEG 31 | * 32 | * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format 33 | * @param src_len Length in bytes of the source buffer 34 | * @param width Width in pixels of the source image 35 | * @param height Height in pixels of the source image 36 | * @param format Format of the source image 37 | * @param quality JPEG quality of the resulting image 38 | * @param cp Callback to be called to write the bytes of the output JPEG 39 | * @param arg Pointer to be passed to the callback 40 | * 41 | * @return true on success 42 | */ 43 | bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg); 44 | 45 | /** 46 | * @brief Convert camera frame buffer to JPEG 47 | * 48 | * @param fb Source camera frame buffer 49 | * @param quality JPEG quality of the resulting image 50 | * @param cp Callback to be called to write the bytes of the output JPEG 51 | * @param arg Pointer to be passed to the callback 52 | * 53 | * @return true on success 54 | */ 55 | bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg); 56 | 57 | /** 58 | * @brief Convert image buffer to JPEG buffer 59 | * 60 | * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format 61 | * @param src_len Length in bytes of the source buffer 62 | * @param width Width in pixels of the source image 63 | * @param height Height in pixels of the source image 64 | * @param format Format of the source image 65 | * @param quality JPEG quality of the resulting image 66 | * @param out Pointer to be populated with the address of the resulting buffer. 67 | * You MUST free the pointer once you are done with it. 68 | * @param out_len Pointer to be populated with the length of the output buffer 69 | * 70 | * @return true on success 71 | */ 72 | bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len); 73 | 74 | /** 75 | * @brief Convert camera frame buffer to JPEG buffer 76 | * 77 | * @param fb Source camera frame buffer 78 | * @param quality JPEG quality of the resulting image 79 | * @param out Pointer to be populated with the address of the resulting buffer 80 | * @param out_len Pointer to be populated with the length of the output buffer 81 | * 82 | * @return true on success 83 | */ 84 | bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len); 85 | 86 | /** 87 | * @brief Convert image buffer to BMP buffer 88 | * 89 | * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format 90 | * @param src_len Length in bytes of the source buffer 91 | * @param width Width in pixels of the source image 92 | * @param height Height in pixels of the source image 93 | * @param format Format of the source image 94 | * @param out Pointer to be populated with the address of the resulting buffer 95 | * @param out_len Pointer to be populated with the length of the output buffer 96 | * 97 | * @return true on success 98 | */ 99 | bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len); 100 | 101 | /** 102 | * @brief Convert camera frame buffer to BMP buffer 103 | * 104 | * @param fb Source camera frame buffer 105 | * @param out Pointer to be populated with the address of the resulting buffer 106 | * @param out_len Pointer to be populated with the length of the output buffer 107 | * 108 | * @return true on success 109 | */ 110 | bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len); 111 | 112 | /** 113 | * @brief Convert image buffer to RGB888 buffer (used for face detection) 114 | * 115 | * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format 116 | * @param src_len Length in bytes of the source buffer 117 | * @param format Format of the source image 118 | * @param rgb_buf Pointer to the output buffer (width * height * 3) 119 | * 120 | * @return true on success 121 | */ 122 | bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf); 123 | 124 | bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale); 125 | 126 | #ifdef __cplusplus 127 | } 128 | #endif 129 | 130 | #endif /* _IMG_CONVERTERS_H_ */ 131 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/jpge.h: -------------------------------------------------------------------------------- 1 | // jpge.h - C++ class for JPEG compression. 2 | // Public domain, Rich Geldreich 3 | // Alex Evans: Added RGBA support, linear memory allocator. 4 | #ifndef JPEG_ENCODER_H 5 | #define JPEG_ENCODER_H 6 | 7 | namespace jpge 8 | { 9 | typedef unsigned char uint8; 10 | typedef signed short int16; 11 | typedef signed int int32; 12 | typedef unsigned short uint16; 13 | typedef unsigned int uint32; 14 | typedef unsigned int uint; 15 | 16 | // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common. 17 | enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 }; 18 | 19 | // JPEG compression parameters structure. 20 | struct params { 21 | inline params() : m_quality(85), m_subsampling(H2V2) { } 22 | 23 | inline bool check() const { 24 | if ((m_quality < 1) || (m_quality > 100)) { 25 | return false; 26 | } 27 | if ((uint)m_subsampling > (uint)H2V2) { 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | // Quality: 1-100, higher is better. Typical values are around 50-95. 34 | int m_quality; 35 | 36 | // m_subsampling: 37 | // 0 = Y (grayscale) only 38 | // 1 = H1V1 subsampling (YCbCr 1x1x1, 3 blocks per MCU) 39 | // 2 = H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU) 40 | // 3 = H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common) 41 | subsampling_t m_subsampling; 42 | }; 43 | 44 | // Output stream abstract class - used by the jpeg_encoder class to write to the output stream. 45 | // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts. 46 | class output_stream { 47 | public: 48 | virtual ~output_stream() { }; 49 | virtual bool put_buf(const void* Pbuf, int len) = 0; 50 | virtual uint get_size() const = 0; 51 | }; 52 | 53 | // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions. 54 | class jpeg_encoder { 55 | public: 56 | jpeg_encoder(); 57 | ~jpeg_encoder(); 58 | 59 | // Initializes the compressor. 60 | // pStream: The stream object to use for writing compressed data. 61 | // params - Compression parameters structure, defined above. 62 | // width, height - Image dimensions. 63 | // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data. 64 | // Returns false on out of memory or if a stream write fails. 65 | bool init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params = params()); 66 | 67 | // Call this method with each source scanline. 68 | // width * src_channels bytes per scanline is expected (RGB or Y format). 69 | // You must call with NULL after all scanlines are processed to finish compression. 70 | // Returns false on out of memory or if a stream write fails. 71 | bool process_scanline(const void* pScanline); 72 | 73 | // Deinitializes the compressor, freeing any allocated memory. May be called at any time. 74 | void deinit(); 75 | 76 | private: 77 | jpeg_encoder(const jpeg_encoder &); 78 | jpeg_encoder &operator =(const jpeg_encoder &); 79 | 80 | typedef int32 sample_array_t; 81 | enum { JPGE_OUT_BUF_SIZE = 512 }; 82 | 83 | output_stream *m_pStream; 84 | params m_params; 85 | uint8 m_num_components; 86 | uint8 m_comp_h_samp[3], m_comp_v_samp[3]; 87 | int m_image_x, m_image_y, m_image_bpp, m_image_bpl; 88 | int m_image_x_mcu, m_image_y_mcu; 89 | int m_image_bpl_xlt, m_image_bpl_mcu; 90 | int m_mcus_per_row; 91 | int m_mcu_x, m_mcu_y; 92 | uint8 *m_mcu_lines[16]; 93 | uint8 m_mcu_y_ofs; 94 | sample_array_t m_sample_array[64]; 95 | int16 m_coefficient_array[64]; 96 | 97 | int m_last_dc_val[3]; 98 | uint8 m_out_buf[JPGE_OUT_BUF_SIZE]; 99 | uint8 *m_pOut_buf; 100 | uint m_out_buf_left; 101 | uint32 m_bit_buffer; 102 | uint m_bits_in; 103 | uint8 m_pass_num; 104 | bool m_all_stream_writes_succeeded; 105 | 106 | bool jpg_open(int p_x_res, int p_y_res, int src_channels); 107 | 108 | void flush_output_buffer(); 109 | void put_bits(uint bits, uint len); 110 | 111 | void emit_byte(uint8 i); 112 | void emit_word(uint i); 113 | void emit_marker(int marker); 114 | 115 | void emit_jfif_app0(); 116 | void emit_dqt(); 117 | void emit_sof(); 118 | void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag); 119 | void emit_dhts(); 120 | void emit_sos(); 121 | 122 | void compute_quant_table(int32 *dst, const int16 *src); 123 | void load_quantized_coefficients(int component_num); 124 | 125 | void load_block_8_8_grey(int x); 126 | void load_block_8_8(int x, int y, int c); 127 | void load_block_16_8(int x, int c); 128 | void load_block_16_8_8(int x, int c); 129 | 130 | void code_coefficients_pass_two(int component_num); 131 | void code_block(int component_num); 132 | 133 | void process_mcu_row(); 134 | bool process_end_of_image(); 135 | void load_mcu(const void* src); 136 | void clear(); 137 | void init(); 138 | }; 139 | 140 | } // namespace jpge 141 | 142 | #endif // JPEG_ENCODER 143 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esp32-camera", 3 | "version": "1.0.0", 4 | "keywords": "esp32, camera, espressif, esp32-cam", 5 | "description": "ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/espressif/esp32-camera" 9 | }, 10 | "frameworks": "espidf", 11 | "platforms": "*", 12 | "build": { 13 | "flags": [ 14 | "-Idriver/include", 15 | "-Iconversions/include", 16 | "-Idriver/private_include", 17 | "-Iconversions/private_include", 18 | "-Isensors/private_include", 19 | "-Itarget/private_include", 20 | "-fno-rtti" 21 | ], 22 | "includeDir": ".", 23 | "srcDir": ".", 24 | "srcFilter": ["-<*>", "+", "+", "+"] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/ll_cam.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "sdkconfig.h" 19 | #if CONFIG_IDF_TARGET_ESP32 20 | #if ESP_IDF_VERSION_MAJOR >= 4 21 | #include "esp32/rom/lldesc.h" 22 | #else 23 | #include "rom/lldesc.h" 24 | #endif 25 | #elif CONFIG_IDF_TARGET_ESP32S2 26 | #include "esp32s2/rom/lldesc.h" 27 | #elif CONFIG_IDF_TARGET_ESP32S3 28 | #include "esp32s3/rom/lldesc.h" 29 | #endif 30 | #include "esp_log.h" 31 | #include "esp_camera.h" 32 | #include "camera_common.h" 33 | #include "freertos/FreeRTOS.h" 34 | #include "freertos/queue.h" 35 | #include "freertos/task.h" 36 | #include "freertos/semphr.h" 37 | 38 | #define CAMERA_DBG_PIN_ENABLE 0 39 | #if CAMERA_DBG_PIN_ENABLE 40 | #if CONFIG_IDF_TARGET_ESP32 41 | #define DBG_PIN_NUM 26 42 | #else 43 | #define DBG_PIN_NUM 7 44 | #endif 45 | #include "hal/gpio_ll.h" 46 | #define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v) 47 | #else 48 | #define DBG_PIN_SET(v) 49 | #endif 50 | 51 | #define CAM_CHECK(a, str, ret) if (!(a)) { \ 52 | ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ 53 | return (ret); \ 54 | } 55 | 56 | #define CAM_CHECK_GOTO(a, str, lab) if (!(a)) { \ 57 | ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ 58 | goto lab; \ 59 | } 60 | 61 | #define LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE (4092) 62 | 63 | typedef enum { 64 | CAM_IN_SUC_EOF_EVENT = 0, 65 | CAM_VSYNC_EVENT 66 | } cam_event_t; 67 | 68 | typedef enum { 69 | CAM_STATE_IDLE = 0, 70 | CAM_STATE_READ_BUF = 1, 71 | } cam_state_t; 72 | 73 | typedef struct { 74 | camera_fb_t fb; 75 | uint8_t en; 76 | //for RGB/YUV modes 77 | lldesc_t *dma; 78 | size_t fb_offset; 79 | } cam_frame_t; 80 | 81 | typedef struct { 82 | uint32_t dma_bytes_per_item; 83 | uint32_t dma_buffer_size; 84 | uint32_t dma_half_buffer_size; 85 | uint32_t dma_half_buffer_cnt; 86 | uint32_t dma_node_buffer_size; 87 | uint32_t dma_node_cnt; 88 | uint32_t frame_copy_cnt; 89 | 90 | //for JPEG mode 91 | lldesc_t *dma; 92 | uint8_t *dma_buffer; 93 | 94 | cam_frame_t *frames; 95 | 96 | QueueHandle_t event_queue; 97 | QueueHandle_t frame_buffer_queue; 98 | TaskHandle_t task_handle; 99 | intr_handle_t cam_intr_handle; 100 | 101 | uint8_t dma_num;//ESP32-S3 102 | intr_handle_t dma_intr_handle;//ESP32-S3 103 | 104 | uint8_t jpeg_mode; 105 | uint8_t vsync_pin; 106 | uint8_t vsync_invert; 107 | uint32_t frame_cnt; 108 | uint32_t recv_size; 109 | bool swap_data; 110 | bool psram_mode; 111 | 112 | //for RGB/YUV modes 113 | uint16_t width; 114 | uint16_t height; 115 | uint8_t in_bytes_per_pixel; 116 | uint8_t fb_bytes_per_pixel; 117 | uint32_t fb_size; 118 | 119 | cam_state_t state; 120 | } cam_obj_t; 121 | 122 | 123 | bool ll_cam_stop(cam_obj_t *cam); 124 | bool ll_cam_start(cam_obj_t *cam, int frame_pos); 125 | esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config); 126 | void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en); 127 | esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config); 128 | esp_err_t ll_cam_init_isr(cam_obj_t *cam); 129 | void ll_cam_do_vsync(cam_obj_t *cam); 130 | uint8_t ll_cam_get_dma_align(cam_obj_t *cam); 131 | bool ll_cam_dma_sizes(cam_obj_t *cam); 132 | size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len); 133 | esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint8_t sensor_pid); 134 | 135 | // implemented in cam_hal 136 | void ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType_t * HPTaskAwoken); 137 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/nt99141.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * NT99141 driver. 7 | * 8 | */ 9 | #ifndef __NT99141_H__ 10 | #define __NT99141_H__ 11 | 12 | #include "sensor.h" 13 | 14 | int NT99141_init(sensor_t *sensor); 15 | 16 | #endif // __NT99141_H__ 17 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/ov2640.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV2640 driver. 7 | * 8 | */ 9 | #ifndef __OV2640_H__ 10 | #define __OV2640_H__ 11 | #include "sensor.h" 12 | int ov2640_init(sensor_t *sensor); 13 | #endif // __OV2640_H__ 14 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/ov3660.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV3660 driver. 7 | * 8 | */ 9 | #ifndef __OV3660_H__ 10 | #define __OV3660_H__ 11 | 12 | #include "sensor.h" 13 | 14 | int ov3660_init(sensor_t *sensor); 15 | 16 | #endif // __OV3660_H__ 17 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/ov5640.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __OV5640_H__ 3 | #define __OV5640_H__ 4 | 5 | #include "sensor.h" 6 | 7 | int ov5640_init(sensor_t *sensor); 8 | 9 | #endif // __OV5640_H__ 10 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/ov7670.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * author: Juan Schiavoni 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7670 driver. 7 | * 8 | */ 9 | #ifndef __OV7670_H__ 10 | #define __OV7670_H__ 11 | #include "sensor.h" 12 | 13 | int ov7670_init(sensor_t *sensor); 14 | #endif // __OV7670_H__ 15 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/ov7725.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7725 driver. 7 | * 8 | */ 9 | #ifndef __OV7725_H__ 10 | #define __OV7725_H__ 11 | #include "sensor.h" 12 | 13 | int ov7725_init(sensor_t *sensor); 14 | #endif // __OV7725_H__ 15 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/sccb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver. 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "sccb.h" 14 | #include "sensor.h" 15 | #include 16 | #include "sdkconfig.h" 17 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 18 | #include "esp32-hal-log.h" 19 | #else 20 | #include "esp_log.h" 21 | static const char* TAG = "sccb"; 22 | #endif 23 | 24 | #define LITTLETOBIG(x) ((x<<8)|(x>>8)) 25 | 26 | #include "driver/i2c.h" 27 | 28 | #define SCCB_FREQ 100000 /*!< I2C master frequency*/ 29 | #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ 30 | #define READ_BIT I2C_MASTER_READ /*!< I2C master read */ 31 | #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ 32 | #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ 33 | #define ACK_VAL 0x0 /*!< I2C ack value */ 34 | #define NACK_VAL 0x1 /*!< I2C nack value */ 35 | #if CONFIG_SCCB_HARDWARE_I2C_PORT1 36 | const int SCCB_I2C_PORT = 1; 37 | #else 38 | const int SCCB_I2C_PORT = 0; 39 | #endif 40 | 41 | int SCCB_Init(int pin_sda, int pin_scl) 42 | { 43 | ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl); 44 | i2c_config_t conf; 45 | memset(&conf, 0, sizeof(i2c_config_t)); 46 | conf.mode = I2C_MODE_MASTER; 47 | conf.sda_io_num = pin_sda; 48 | conf.sda_pullup_en = GPIO_PULLUP_ENABLE; 49 | conf.scl_io_num = pin_scl; 50 | conf.scl_pullup_en = GPIO_PULLUP_ENABLE; 51 | conf.master.clk_speed = SCCB_FREQ; 52 | 53 | i2c_param_config(SCCB_I2C_PORT, &conf); 54 | i2c_driver_install(SCCB_I2C_PORT, conf.mode, 0, 0, 0); 55 | return 0; 56 | } 57 | 58 | int SCCB_Deinit(void) 59 | { 60 | return i2c_driver_delete(SCCB_I2C_PORT); 61 | } 62 | 63 | uint8_t SCCB_Probe(void) 64 | { 65 | uint8_t slave_addr = 0x0; 66 | // for (size_t i = 1; i < 0x80; i++) { 67 | // i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 68 | // i2c_master_start(cmd); 69 | // i2c_master_write_byte(cmd, ( i << 1 ) | WRITE_BIT, ACK_CHECK_EN); 70 | // i2c_master_stop(cmd); 71 | // esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 72 | // i2c_cmd_link_delete(cmd); 73 | // if( ret == ESP_OK) { 74 | // ESP_LOGW(TAG, "Found I2C Device at 0x%02X", i); 75 | // } 76 | // } 77 | for (size_t i = 0; i < CAMERA_MODEL_MAX; i++) { 78 | if (slave_addr == camera_sensor[i].sccb_addr) { 79 | continue; 80 | } 81 | slave_addr = camera_sensor[i].sccb_addr; 82 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 83 | i2c_master_start(cmd); 84 | i2c_master_write_byte(cmd, ( slave_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 85 | i2c_master_stop(cmd); 86 | esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 87 | i2c_cmd_link_delete(cmd); 88 | if( ret == ESP_OK) { 89 | return slave_addr; 90 | } 91 | } 92 | return 0; 93 | } 94 | 95 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg) 96 | { 97 | uint8_t data=0; 98 | esp_err_t ret = ESP_FAIL; 99 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 100 | i2c_master_start(cmd); 101 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 102 | i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); 103 | i2c_master_stop(cmd); 104 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 105 | i2c_cmd_link_delete(cmd); 106 | if(ret != ESP_OK) return -1; 107 | cmd = i2c_cmd_link_create(); 108 | i2c_master_start(cmd); 109 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); 110 | i2c_master_read_byte(cmd, &data, NACK_VAL); 111 | i2c_master_stop(cmd); 112 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 113 | i2c_cmd_link_delete(cmd); 114 | if(ret != ESP_OK) { 115 | ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); 116 | } 117 | return data; 118 | } 119 | 120 | uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data) 121 | { 122 | esp_err_t ret = ESP_FAIL; 123 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 124 | i2c_master_start(cmd); 125 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 126 | i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); 127 | i2c_master_write_byte(cmd, data, ACK_CHECK_EN); 128 | i2c_master_stop(cmd); 129 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 130 | i2c_cmd_link_delete(cmd); 131 | if(ret != ESP_OK) { 132 | ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); 133 | } 134 | return ret == ESP_OK ? 0 : -1; 135 | } 136 | 137 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg) 138 | { 139 | uint8_t data=0; 140 | esp_err_t ret = ESP_FAIL; 141 | uint16_t reg_htons = LITTLETOBIG(reg); 142 | uint8_t *reg_u8 = (uint8_t *)®_htons; 143 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 144 | i2c_master_start(cmd); 145 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 146 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 147 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 148 | i2c_master_stop(cmd); 149 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 150 | i2c_cmd_link_delete(cmd); 151 | if(ret != ESP_OK) return -1; 152 | cmd = i2c_cmd_link_create(); 153 | i2c_master_start(cmd); 154 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); 155 | i2c_master_read_byte(cmd, &data, NACK_VAL); 156 | i2c_master_stop(cmd); 157 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 158 | i2c_cmd_link_delete(cmd); 159 | if(ret != ESP_OK) { 160 | ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data); 161 | } 162 | return data; 163 | } 164 | 165 | uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data) 166 | { 167 | static uint16_t i = 0; 168 | esp_err_t ret = ESP_FAIL; 169 | uint16_t reg_htons = LITTLETOBIG(reg); 170 | uint8_t *reg_u8 = (uint8_t *)®_htons; 171 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 172 | i2c_master_start(cmd); 173 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 174 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 175 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 176 | i2c_master_write_byte(cmd, data, ACK_CHECK_EN); 177 | i2c_master_stop(cmd); 178 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 179 | i2c_cmd_link_delete(cmd); 180 | if(ret != ESP_OK) { 181 | ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++); 182 | } 183 | return ret == ESP_OK ? 0 : -1; 184 | } 185 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/sccb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver. 7 | * 8 | */ 9 | #ifndef __SCCB_H__ 10 | #define __SCCB_H__ 11 | #include 12 | int SCCB_Init(int pin_sda, int pin_scl); 13 | int SCCB_Deinit(void); 14 | uint8_t SCCB_Probe(); 15 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg); 16 | uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data); 17 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg); 18 | uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data); 19 | #endif // __SCCB_H__ 20 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/sensor.c: -------------------------------------------------------------------------------- 1 | #include "sensor.h" 2 | 3 | const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = { 4 | {CAMERA_OV7725, OV7725_SCCB_ADDR, OV7725_PID, FRAMESIZE_VGA}, 5 | {CAMERA_OV2640, OV2640_SCCB_ADDR, OV2640_PID, FRAMESIZE_UXGA}, 6 | {CAMERA_OV3660, OV3660_SCCB_ADDR, OV3660_PID, FRAMESIZE_QXGA}, 7 | {CAMERA_OV5640, OV5640_SCCB_ADDR, OV5640_PID, FRAMESIZE_QSXGA}, 8 | {CAMERA_OV7670, OV7670_SCCB_ADDR, OV7670_PID, FRAMESIZE_VGA}, 9 | {CAMERA_NT99141, NT99141_SCCB_ADDR, NT99141_PID, FRAMESIZE_HD}, 10 | }; 11 | 12 | const resolution_info_t resolution[FRAMESIZE_INVALID] = { 13 | { 96, 96, ASPECT_RATIO_1X1 }, /* 96x96 */ 14 | { 160, 120, ASPECT_RATIO_4X3 }, /* QQVGA */ 15 | { 176, 144, ASPECT_RATIO_5X4 }, /* QCIF */ 16 | { 240, 176, ASPECT_RATIO_4X3 }, /* HQVGA */ 17 | { 240, 240, ASPECT_RATIO_1X1 }, /* 240x240 */ 18 | { 320, 240, ASPECT_RATIO_4X3 }, /* QVGA */ 19 | { 400, 296, ASPECT_RATIO_4X3 }, /* CIF */ 20 | { 480, 320, ASPECT_RATIO_3X2 }, /* HVGA */ 21 | { 640, 480, ASPECT_RATIO_4X3 }, /* VGA */ 22 | { 800, 600, ASPECT_RATIO_4X3 }, /* SVGA */ 23 | { 1024, 768, ASPECT_RATIO_4X3 }, /* XGA */ 24 | { 1280, 720, ASPECT_RATIO_16X9 }, /* HD */ 25 | { 1280, 1024, ASPECT_RATIO_5X4 }, /* SXGA */ 26 | { 1600, 1200, ASPECT_RATIO_4X3 }, /* UXGA */ 27 | // 3MP Sensors 28 | { 1920, 1080, ASPECT_RATIO_16X9 }, /* FHD */ 29 | { 720, 1280, ASPECT_RATIO_9X16 }, /* Portrait HD */ 30 | { 864, 1536, ASPECT_RATIO_9X16 }, /* Portrait 3MP */ 31 | { 2048, 1536, ASPECT_RATIO_4X3 }, /* QXGA */ 32 | // 5MP Sensors 33 | { 2560, 1440, ASPECT_RATIO_16X9 }, /* QHD */ 34 | { 2560, 1600, ASPECT_RATIO_16X10 }, /* WQXGA */ 35 | { 1088, 1920, ASPECT_RATIO_9X16 }, /* Portrait FHD */ 36 | { 2560, 1920, ASPECT_RATIO_4X3 }, /* QSXGA */ 37 | }; 38 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/to_jpg.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | #include 16 | #include "esp_attr.h" 17 | #include "soc/efuse_reg.h" 18 | #include "esp_heap_caps.h" 19 | #include "esp_camera.h" 20 | #include "img_converters.h" 21 | #include "jpge.h" 22 | #include "yuv.h" 23 | 24 | #include "esp_system.h" 25 | #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ 26 | #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 27 | #include "esp32/spiram.h" 28 | #elif CONFIG_IDF_TARGET_ESP32S2 29 | #include "esp32s2/spiram.h" 30 | #elif CONFIG_IDF_TARGET_ESP32S3 31 | #include "esp32s3/spiram.h" 32 | #else 33 | #error Target CONFIG_IDF_TARGET is not supported 34 | #endif 35 | #else // ESP32 Before IDF 4.0 36 | #include "esp_spiram.h" 37 | #endif 38 | 39 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 40 | #include "esp32-hal-log.h" 41 | #define TAG "" 42 | #else 43 | #include "esp_log.h" 44 | static const char* TAG = "to_jpg"; 45 | #endif 46 | 47 | static void *_malloc(size_t size) 48 | { 49 | void * res = malloc(size); 50 | if(res) { 51 | return res; 52 | } 53 | return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); 54 | } 55 | 56 | static IRAM_ATTR void convert_line_format(uint8_t * src, pixformat_t format, uint8_t * dst, size_t width, size_t in_channels, size_t line) 57 | { 58 | int i=0, o=0, l=0; 59 | if(format == PIXFORMAT_GRAYSCALE) { 60 | memcpy(dst, src + line * width, width); 61 | } else if(format == PIXFORMAT_RGB888) { 62 | l = width * 3; 63 | src += l * line; 64 | for(i=0; i> 3; 75 | dst[o++] = (src[i+1] & 0x1F) << 3; 76 | } 77 | } else if(format == PIXFORMAT_YUV422) { 78 | uint8_t y0, y1, u, v; 79 | uint8_t r, g, b; 80 | l = width * 2; 81 | src += l * line; 82 | for(i=0; i 100) { 114 | quality = 100; 115 | } 116 | 117 | jpge::params comp_params = jpge::params(); 118 | comp_params.m_subsampling = subsampling; 119 | comp_params.m_quality = quality; 120 | 121 | jpge::jpeg_encoder dst_image; 122 | 123 | if (!dst_image.init(dst_stream, width, height, num_channels, comp_params)) { 124 | ESP_LOGE(TAG, "JPG encoder init failed"); 125 | return false; 126 | } 127 | 128 | uint8_t* line = (uint8_t*)_malloc(width * num_channels); 129 | if(!line) { 130 | ESP_LOGE(TAG, "Scan line malloc failed"); 131 | return false; 132 | } 133 | 134 | for (int i = 0; i < height; i++) { 135 | convert_line_format(src, format, line, width, num_channels, i); 136 | if (!dst_image.process_scanline(line)) { 137 | ESP_LOGE(TAG, "JPG process line %u failed", i); 138 | free(line); 139 | return false; 140 | } 141 | } 142 | free(line); 143 | 144 | if (!dst_image.process_scanline(NULL)) { 145 | ESP_LOGE(TAG, "JPG image finish failed"); 146 | return false; 147 | } 148 | dst_image.deinit(); 149 | return true; 150 | } 151 | 152 | class callback_stream : public jpge::output_stream { 153 | protected: 154 | jpg_out_cb ocb; 155 | void * oarg; 156 | size_t index; 157 | 158 | public: 159 | callback_stream(jpg_out_cb cb, void * arg) : ocb(cb), oarg(arg), index(0) { } 160 | virtual ~callback_stream() { } 161 | virtual bool put_buf(const void* data, int len) 162 | { 163 | index += ocb(oarg, index, data, len); 164 | return true; 165 | } 166 | virtual size_t get_size() const 167 | { 168 | return index; 169 | } 170 | }; 171 | 172 | bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg) 173 | { 174 | callback_stream dst_stream(cb, arg); 175 | return convert_image(src, width, height, format, quality, &dst_stream); 176 | } 177 | 178 | bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg) 179 | { 180 | return fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, cb, arg); 181 | } 182 | 183 | 184 | 185 | class memory_stream : public jpge::output_stream { 186 | protected: 187 | uint8_t *out_buf; 188 | size_t max_len, index; 189 | 190 | public: 191 | memory_stream(void *pBuf, uint buf_size) : out_buf(static_cast(pBuf)), max_len(buf_size), index(0) { } 192 | 193 | virtual ~memory_stream() { } 194 | 195 | virtual bool put_buf(const void* pBuf, int len) 196 | { 197 | if (!pBuf) { 198 | //end of image 199 | return true; 200 | } 201 | if ((size_t)len > (max_len - index)) { 202 | //ESP_LOGW(TAG, "JPG output overflow: %d bytes (%d,%d,%d)", len - (max_len - index), len, index, max_len); 203 | len = max_len - index; 204 | } 205 | if (len) { 206 | memcpy(out_buf + index, pBuf, len); 207 | index += len; 208 | } 209 | return true; 210 | } 211 | 212 | virtual size_t get_size() const 213 | { 214 | return index; 215 | } 216 | }; 217 | 218 | bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len) 219 | { 220 | //todo: allocate proper buffer for holding JPEG data 221 | //this should be enough for CIF frame size 222 | int jpg_buf_len = 128*1024; 223 | 224 | 225 | uint8_t * jpg_buf = (uint8_t *)_malloc(jpg_buf_len); 226 | if(jpg_buf == NULL) { 227 | ESP_LOGE(TAG, "JPG buffer malloc failed"); 228 | return false; 229 | } 230 | memory_stream dst_stream(jpg_buf, jpg_buf_len); 231 | 232 | if(!convert_image(src, width, height, format, quality, &dst_stream)) { 233 | free(jpg_buf); 234 | return false; 235 | } 236 | 237 | *out = jpg_buf; 238 | *out_len = dst_stream.get_size(); 239 | return true; 240 | } 241 | 242 | bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len) 243 | { 244 | return fmt2jpg(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, out, out_len); 245 | } 246 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/xclk.c: -------------------------------------------------------------------------------- 1 | #include "driver/gpio.h" 2 | #include "driver/ledc.h" 3 | #include "esp_err.h" 4 | #include "esp_log.h" 5 | #include "esp_system.h" 6 | #include "xclk.h" 7 | 8 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 9 | #include "esp32-hal-log.h" 10 | #else 11 | #include "esp_log.h" 12 | static const char* TAG = "camera_xclk"; 13 | #endif 14 | 15 | esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz) 16 | { 17 | ledc_timer_config_t timer_conf; 18 | timer_conf.duty_resolution = LEDC_TIMER_1_BIT; 19 | timer_conf.freq_hz = xclk_freq_hz; 20 | #if CONFIG_IDF_TARGET_ESP32 21 | timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE; 22 | #else 23 | timer_conf.speed_mode = LEDC_LOW_SPEED_MODE; 24 | #endif 25 | #if ESP_IDF_VERSION_MAJOR >= 4 26 | timer_conf.clk_cfg = LEDC_AUTO_CLK; 27 | #endif 28 | timer_conf.timer_num = (ledc_timer_t)ledc_timer; 29 | esp_err_t err = ledc_timer_config(&timer_conf); 30 | if (err != ESP_OK) { 31 | ESP_LOGE(TAG, "ledc_timer_config failed for freq %d, rc=%x", xclk_freq_hz, err); 32 | } 33 | return err; 34 | } 35 | 36 | esp_err_t camera_enable_out_clock(camera_config_t* config) 37 | { 38 | periph_module_enable(PERIPH_LEDC_MODULE); 39 | 40 | esp_err_t err = xclk_timer_conf(config->ledc_timer, config->xclk_freq_hz); 41 | if (err != ESP_OK) { 42 | ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err); 43 | return err; 44 | } 45 | 46 | ledc_channel_config_t ch_conf; 47 | ch_conf.gpio_num = config->pin_xclk; 48 | #if CONFIG_IDF_TARGET_ESP32 49 | ch_conf.speed_mode = LEDC_HIGH_SPEED_MODE; 50 | #else 51 | ch_conf.speed_mode = LEDC_LOW_SPEED_MODE; 52 | #endif 53 | ch_conf.channel = config->ledc_channel; 54 | ch_conf.intr_type = LEDC_INTR_DISABLE; 55 | ch_conf.timer_sel = config->ledc_timer; 56 | ch_conf.duty = 1; 57 | ch_conf.hpoint = 0; 58 | err = ledc_channel_config(&ch_conf); 59 | if (err != ESP_OK) { 60 | ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err); 61 | return err; 62 | } 63 | return ESP_OK; 64 | } 65 | 66 | void camera_disable_out_clock() 67 | { 68 | periph_module_disable(PERIPH_LEDC_MODULE); 69 | } 70 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/xclk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "camera_common.h" 4 | 5 | esp_err_t camera_enable_out_clock(); 6 | 7 | void camera_disable_out_clock(); 8 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam-rtos/yuv.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _CONVERSIONS_YUV_H_ 15 | #define _CONVERSIONS_YUV_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | 23 | void yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* _CONVERSIONS_YUV_H_ */ 30 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") 2 | set(COMPONENT_SRCS 3 | driver/esp_camera.c 4 | driver/cam_hal.c 5 | driver/sccb.c 6 | driver/sensor.c 7 | sensors/ov2640.c 8 | sensors/ov3660.c 9 | sensors/ov5640.c 10 | sensors/ov7725.c 11 | sensors/ov7670.c 12 | sensors/nt99141.c 13 | conversions/yuv.c 14 | conversions/to_jpg.cpp 15 | conversions/to_bmp.c 16 | conversions/jpge.cpp 17 | conversions/esp_jpg_decode.c 18 | ) 19 | 20 | set(COMPONENT_ADD_INCLUDEDIRS 21 | driver/include 22 | conversions/include 23 | ) 24 | 25 | set(COMPONENT_PRIV_INCLUDEDIRS 26 | driver/private_include 27 | sensors/private_include 28 | conversions/private_include 29 | target/private_include 30 | ) 31 | 32 | if(IDF_TARGET STREQUAL "esp32") 33 | list(APPEND COMPONENT_SRCS 34 | target/xclk.c 35 | target/esp32/ll_cam.c 36 | ) 37 | endif() 38 | 39 | if(IDF_TARGET STREQUAL "esp32s2") 40 | list(APPEND COMPONENT_SRCS 41 | target/xclk.c 42 | target/esp32s2/ll_cam.c 43 | target/esp32s2/tjpgd.c 44 | ) 45 | 46 | list(APPEND COMPONENT_PRIV_INCLUDEDIRS 47 | target/esp32s2/private_include 48 | ) 49 | endif() 50 | 51 | if(IDF_TARGET STREQUAL "esp32s3") 52 | list(APPEND COMPONENT_SRCS 53 | target/esp32s3/ll_cam.c 54 | ) 55 | endif() 56 | 57 | set(COMPONENT_REQUIRES driver) 58 | set(COMPONENT_PRIV_REQUIRES freertos nvs_flash) 59 | 60 | register_component() 61 | endif() 62 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/Kconfig: -------------------------------------------------------------------------------- 1 | menu "Camera configuration" 2 | 3 | config OV7670_SUPPORT 4 | bool "Support OV7670 VGA" 5 | default y 6 | help 7 | Enable this option if you want to use the OV7670. 8 | Disable this option to save memory. 9 | 10 | config OV7725_SUPPORT 11 | bool "Support OV7725 SVGA" 12 | default n 13 | help 14 | Enable this option if you want to use the OV7725. 15 | Disable this option to save memory. 16 | 17 | config NT99141_SUPPORT 18 | bool "Support NT99141 HD" 19 | default y 20 | help 21 | Enable this option if you want to use the NT99141. 22 | Disable this option to save memory. 23 | 24 | config OV2640_SUPPORT 25 | bool "Support OV2640 2MP" 26 | default y 27 | help 28 | Enable this option if you want to use the OV2640. 29 | Disable this option to save memory. 30 | 31 | config OV3660_SUPPORT 32 | bool "Support OV3660 3MP" 33 | default y 34 | help 35 | Enable this option if you want to use the OV3360. 36 | Disable this option to save memory. 37 | 38 | config OV5640_SUPPORT 39 | bool "Support OV5640 5MP" 40 | default y 41 | help 42 | Enable this option if you want to use the OV5640. 43 | Disable this option to save memory. 44 | 45 | choice SCCB_HARDWARE_I2C_PORT 46 | bool "I2C peripheral to use for SCCB" 47 | default SCCB_HARDWARE_I2C_PORT1 48 | 49 | config SCCB_HARDWARE_I2C_PORT0 50 | bool "I2C0" 51 | config SCCB_HARDWARE_I2C_PORT1 52 | bool "I2C1" 53 | 54 | endchoice 55 | 56 | choice CAMERA_TASK_PINNED_TO_CORE 57 | bool "Camera task pinned to core" 58 | default CAMERA_CORE0 59 | help 60 | Pin the camera handle task to a certain core(0/1). It can also be done automatically choosing NO_AFFINITY. 61 | 62 | config CAMERA_CORE0 63 | bool "CORE0" 64 | config CAMERA_CORE1 65 | bool "CORE1" 66 | config CAMERA_NO_AFFINITY 67 | bool "NO_AFFINITY" 68 | 69 | endchoice 70 | 71 | endmenu 72 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/cam_hal.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include "esp_camera.h" 18 | 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /** 25 | * @brief Uninitialize the lcd_cam module 26 | * 27 | * @param handle Provide handle pointer to release resources 28 | * 29 | * @return 30 | * - ESP_OK Success 31 | * - ESP_FAIL Uninitialize fail 32 | */ 33 | esp_err_t cam_deinit(void); 34 | 35 | /** 36 | * @brief Initialize the lcd_cam module 37 | * 38 | * @param config Configurations - see lcd_cam_config_t struct 39 | * 40 | * @return 41 | * - ESP_OK Success 42 | * - ESP_ERR_INVALID_ARG Parameter error 43 | * - ESP_ERR_NO_MEM No memory to initialize lcd_cam 44 | * - ESP_FAIL Initialize fail 45 | */ 46 | esp_err_t cam_init(const camera_config_t *config); 47 | 48 | esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint8_t sensor_pid); 49 | 50 | void cam_stop(void); 51 | 52 | void cam_start(void); 53 | 54 | camera_fb_t *cam_take(TickType_t timeout); 55 | 56 | void cam_give(camera_fb_t *dma_buffer); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/camera_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "esp_err.h" 7 | #include "esp_intr_alloc.h" 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/semphr.h" 10 | #include "freertos/task.h" 11 | #include "esp_camera.h" 12 | #include "sensor.h" 13 | 14 | #include "esp_system.h" 15 | #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ 16 | #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 17 | #include "esp32/rom/lldesc.h" 18 | #elif CONFIG_IDF_TARGET_ESP32S2 // ESP32-S2 19 | #include "esp32s2/rom/lldesc.h" 20 | #elif CONFIG_IDF_TARGET_ESP32S3 // ESP32-S3 21 | #include "esp32s3/rom/lldesc.h" 22 | #else 23 | #error Target CONFIG_IDF_TARGET is not supported 24 | #endif 25 | #else // ESP32 Before IDF 4.0 26 | #include "rom/lldesc.h" 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/camera_pins.h: -------------------------------------------------------------------------------- 1 | 2 | #if defined(CAMERA_MODEL_WROVER_KIT) 3 | #define PWDN_GPIO_NUM -1 4 | #define RESET_GPIO_NUM -1 5 | #define XCLK_GPIO_NUM 21 6 | #define SIOD_GPIO_NUM 26 7 | #define SIOC_GPIO_NUM 27 8 | 9 | #define Y9_GPIO_NUM 35 10 | #define Y8_GPIO_NUM 34 11 | #define Y7_GPIO_NUM 39 12 | #define Y6_GPIO_NUM 36 13 | #define Y5_GPIO_NUM 19 14 | #define Y4_GPIO_NUM 18 15 | #define Y3_GPIO_NUM 5 16 | #define Y2_GPIO_NUM 4 17 | #define VSYNC_GPIO_NUM 25 18 | #define HREF_GPIO_NUM 23 19 | #define PCLK_GPIO_NUM 22 20 | 21 | #elif defined(CAMERA_MODEL_ESP_EYE) 22 | #define PWDN_GPIO_NUM -1 23 | #define RESET_GPIO_NUM -1 24 | #define XCLK_GPIO_NUM 4 25 | #define SIOD_GPIO_NUM 18 26 | #define SIOC_GPIO_NUM 23 27 | 28 | #define Y9_GPIO_NUM 36 29 | #define Y8_GPIO_NUM 37 30 | #define Y7_GPIO_NUM 38 31 | #define Y6_GPIO_NUM 39 32 | #define Y5_GPIO_NUM 35 33 | #define Y4_GPIO_NUM 14 34 | #define Y3_GPIO_NUM 13 35 | #define Y2_GPIO_NUM 34 36 | #define VSYNC_GPIO_NUM 5 37 | #define HREF_GPIO_NUM 27 38 | #define PCLK_GPIO_NUM 25 39 | 40 | #elif defined(CAMERA_MODEL_M5STACK_PSRAM) 41 | #define PWDN_GPIO_NUM -1 42 | #define RESET_GPIO_NUM 15 43 | #define XCLK_GPIO_NUM 27 44 | #define SIOD_GPIO_NUM 25 45 | #define SIOC_GPIO_NUM 23 46 | 47 | #define Y9_GPIO_NUM 19 48 | #define Y8_GPIO_NUM 36 49 | #define Y7_GPIO_NUM 18 50 | #define Y6_GPIO_NUM 39 51 | #define Y5_GPIO_NUM 5 52 | #define Y4_GPIO_NUM 34 53 | #define Y3_GPIO_NUM 35 54 | #define Y2_GPIO_NUM 32 55 | #define VSYNC_GPIO_NUM 22 56 | #define HREF_GPIO_NUM 26 57 | #define PCLK_GPIO_NUM 21 58 | 59 | #elif defined(CAMERA_MODEL_M5STACK_WIDE) 60 | #define PWDN_GPIO_NUM -1 61 | #define RESET_GPIO_NUM 15 62 | #define XCLK_GPIO_NUM 27 63 | #define SIOD_GPIO_NUM 22 64 | #define SIOC_GPIO_NUM 23 65 | 66 | #define Y9_GPIO_NUM 19 67 | #define Y8_GPIO_NUM 36 68 | #define Y7_GPIO_NUM 18 69 | #define Y6_GPIO_NUM 39 70 | #define Y5_GPIO_NUM 5 71 | #define Y4_GPIO_NUM 34 72 | #define Y3_GPIO_NUM 35 73 | #define Y2_GPIO_NUM 32 74 | #define VSYNC_GPIO_NUM 25 75 | #define HREF_GPIO_NUM 26 76 | #define PCLK_GPIO_NUM 21 77 | 78 | #elif defined(CAMERA_MODEL_AI_THINKER) 79 | #define PWDN_GPIO_NUM 32 80 | #define RESET_GPIO_NUM -1 81 | #define XCLK_GPIO_NUM 0 82 | #define SIOD_GPIO_NUM 26 83 | #define SIOC_GPIO_NUM 27 84 | 85 | #define Y9_GPIO_NUM 35 86 | #define Y8_GPIO_NUM 34 87 | #define Y7_GPIO_NUM 39 88 | #define Y6_GPIO_NUM 36 89 | #define Y5_GPIO_NUM 21 90 | #define Y4_GPIO_NUM 19 91 | #define Y3_GPIO_NUM 18 92 | #define Y2_GPIO_NUM 5 93 | #define VSYNC_GPIO_NUM 25 94 | #define HREF_GPIO_NUM 23 95 | #define PCLK_GPIO_NUM 22 96 | 97 | #else 98 | #error "Camera model not selected" 99 | #endif 100 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_ADD_INCLUDEDIRS := driver/include conversions/include 2 | COMPONENT_PRIV_INCLUDEDIRS := driver/private_include conversions/private_include sensors/private_include target/private_include 3 | COMPONENT_SRCDIRS := driver conversions sensors target target/esp32 4 | CXXFLAGS += -fno-rtti 5 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/esp32-camera-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arkhipenko/esp32-mjpeg-multiclient-espcam-drivers/b9451ebb6dff814bc0bebbd1850a411915e78eff/Arduino-IDE/esp32-cam/esp32-camera-master.zip -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/esp_jpg_decode.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "esp_jpg_decode.h" 15 | 16 | #include "esp_system.h" 17 | #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ 18 | #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 19 | #include "esp32/rom/tjpgd.h" 20 | #elif CONFIG_IDF_TARGET_ESP32S2 21 | #include "tjpgd.h" 22 | #elif CONFIG_IDF_TARGET_ESP32S3 23 | #include "esp32s3/rom/tjpgd.h" 24 | #else 25 | #error Target CONFIG_IDF_TARGET is not supported 26 | #endif 27 | #else // ESP32 Before IDF 4.0 28 | #include "rom/tjpgd.h" 29 | #endif 30 | 31 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 32 | #include "esp32-hal-log.h" 33 | #define TAG "" 34 | #else 35 | #include "esp_log.h" 36 | static const char* TAG = "esp_jpg_decode"; 37 | #endif 38 | 39 | typedef struct { 40 | jpg_scale_t scale; 41 | jpg_reader_cb reader; 42 | jpg_writer_cb writer; 43 | void * arg; 44 | size_t len; 45 | size_t index; 46 | } esp_jpg_decoder_t; 47 | 48 | static const char * jd_errors[] = { 49 | "Succeeded", 50 | "Interrupted by output function", 51 | "Device error or wrong termination of input stream", 52 | "Insufficient memory pool for the image", 53 | "Insufficient stream input buffer", 54 | "Parameter error", 55 | "Data format error", 56 | "Right format but not supported", 57 | "Not supported JPEG standard" 58 | }; 59 | 60 | static uint32_t _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect) 61 | { 62 | uint16_t x = rect->left; 63 | uint16_t y = rect->top; 64 | uint16_t w = rect->right + 1 - x; 65 | uint16_t h = rect->bottom + 1 - y; 66 | uint8_t *data = (uint8_t *)bitmap; 67 | 68 | esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; 69 | 70 | if (jpeg->writer) { 71 | return jpeg->writer(jpeg->arg, x, y, w, h, data); 72 | } 73 | return 0; 74 | } 75 | 76 | static uint32_t _jpg_read(JDEC *decoder, uint8_t *buf, uint32_t len) 77 | { 78 | esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; 79 | if (jpeg->len && len > (jpeg->len - jpeg->index)) { 80 | len = jpeg->len - jpeg->index; 81 | } 82 | if (len) { 83 | len = jpeg->reader(jpeg->arg, jpeg->index, buf, len); 84 | if (!len) { 85 | ESP_LOGE(TAG, "Read Fail at %u/%u", jpeg->index, jpeg->len); 86 | } 87 | jpeg->index += len; 88 | } 89 | return len; 90 | } 91 | 92 | esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg) 93 | { 94 | static uint8_t work[3100]; 95 | JDEC decoder; 96 | esp_jpg_decoder_t jpeg; 97 | 98 | jpeg.len = len; 99 | jpeg.reader = reader; 100 | jpeg.writer = writer; 101 | jpeg.arg = arg; 102 | jpeg.scale = scale; 103 | jpeg.index = 0; 104 | 105 | JRESULT jres = jd_prepare(&decoder, _jpg_read, work, 3100, &jpeg); 106 | if(jres != JDR_OK){ 107 | ESP_LOGE(TAG, "JPG Header Parse Failed! %s", jd_errors[jres]); 108 | return ESP_FAIL; 109 | } 110 | 111 | uint16_t output_width = decoder.width / (1 << (uint8_t)(jpeg.scale)); 112 | uint16_t output_height = decoder.height / (1 << (uint8_t)(jpeg.scale)); 113 | 114 | //output start 115 | writer(arg, 0, 0, output_width, output_height, NULL); 116 | //output write 117 | jres = jd_decomp(&decoder, _jpg_write, (uint8_t)jpeg.scale); 118 | //output end 119 | writer(arg, output_width, output_height, output_width, output_height, NULL); 120 | 121 | if (jres != JDR_OK) { 122 | ESP_LOGE(TAG, "JPG Decompression Failed! %s", jd_errors[jres]); 123 | return ESP_FAIL; 124 | } 125 | //check if all data has been consumed. 126 | if (len && jpeg.index < len) { 127 | _jpg_read(&decoder, NULL, len - jpeg.index); 128 | } 129 | 130 | return ESP_OK; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/esp_jpg_decode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _ESP_JPG_DECODE_H_ 15 | #define _ESP_JPG_DECODE_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include "esp_err.h" 25 | 26 | typedef enum { 27 | JPG_SCALE_NONE, 28 | JPG_SCALE_2X, 29 | JPG_SCALE_4X, 30 | JPG_SCALE_8X, 31 | JPG_SCALE_MAX = JPG_SCALE_8X 32 | } jpg_scale_t; 33 | 34 | typedef size_t (* jpg_reader_cb)(void * arg, size_t index, uint8_t *buf, size_t len); 35 | typedef bool (* jpg_writer_cb)(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data); 36 | 37 | esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif /* _ESP_JPG_DECODE_H_ */ 44 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/img_converters.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _IMG_CONVERTERS_H_ 15 | #define _IMG_CONVERTERS_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include "esp_camera.h" 25 | #include "esp_jpg_decode.h" 26 | 27 | typedef size_t (* jpg_out_cb)(void * arg, size_t index, const void* data, size_t len); 28 | 29 | /** 30 | * @brief Convert image buffer to JPEG 31 | * 32 | * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format 33 | * @param src_len Length in bytes of the source buffer 34 | * @param width Width in pixels of the source image 35 | * @param height Height in pixels of the source image 36 | * @param format Format of the source image 37 | * @param quality JPEG quality of the resulting image 38 | * @param cp Callback to be called to write the bytes of the output JPEG 39 | * @param arg Pointer to be passed to the callback 40 | * 41 | * @return true on success 42 | */ 43 | bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg); 44 | 45 | /** 46 | * @brief Convert camera frame buffer to JPEG 47 | * 48 | * @param fb Source camera frame buffer 49 | * @param quality JPEG quality of the resulting image 50 | * @param cp Callback to be called to write the bytes of the output JPEG 51 | * @param arg Pointer to be passed to the callback 52 | * 53 | * @return true on success 54 | */ 55 | bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg); 56 | 57 | /** 58 | * @brief Convert image buffer to JPEG buffer 59 | * 60 | * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format 61 | * @param src_len Length in bytes of the source buffer 62 | * @param width Width in pixels of the source image 63 | * @param height Height in pixels of the source image 64 | * @param format Format of the source image 65 | * @param quality JPEG quality of the resulting image 66 | * @param out Pointer to be populated with the address of the resulting buffer. 67 | * You MUST free the pointer once you are done with it. 68 | * @param out_len Pointer to be populated with the length of the output buffer 69 | * 70 | * @return true on success 71 | */ 72 | bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len); 73 | 74 | /** 75 | * @brief Convert camera frame buffer to JPEG buffer 76 | * 77 | * @param fb Source camera frame buffer 78 | * @param quality JPEG quality of the resulting image 79 | * @param out Pointer to be populated with the address of the resulting buffer 80 | * @param out_len Pointer to be populated with the length of the output buffer 81 | * 82 | * @return true on success 83 | */ 84 | bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len); 85 | 86 | /** 87 | * @brief Convert image buffer to BMP buffer 88 | * 89 | * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format 90 | * @param src_len Length in bytes of the source buffer 91 | * @param width Width in pixels of the source image 92 | * @param height Height in pixels of the source image 93 | * @param format Format of the source image 94 | * @param out Pointer to be populated with the address of the resulting buffer 95 | * @param out_len Pointer to be populated with the length of the output buffer 96 | * 97 | * @return true on success 98 | */ 99 | bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len); 100 | 101 | /** 102 | * @brief Convert camera frame buffer to BMP buffer 103 | * 104 | * @param fb Source camera frame buffer 105 | * @param out Pointer to be populated with the address of the resulting buffer 106 | * @param out_len Pointer to be populated with the length of the output buffer 107 | * 108 | * @return true on success 109 | */ 110 | bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len); 111 | 112 | /** 113 | * @brief Convert image buffer to RGB888 buffer (used for face detection) 114 | * 115 | * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format 116 | * @param src_len Length in bytes of the source buffer 117 | * @param format Format of the source image 118 | * @param rgb_buf Pointer to the output buffer (width * height * 3) 119 | * 120 | * @return true on success 121 | */ 122 | bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf); 123 | 124 | bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale); 125 | 126 | #ifdef __cplusplus 127 | } 128 | #endif 129 | 130 | #endif /* _IMG_CONVERTERS_H_ */ 131 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/jpge.h: -------------------------------------------------------------------------------- 1 | // jpge.h - C++ class for JPEG compression. 2 | // Public domain, Rich Geldreich 3 | // Alex Evans: Added RGBA support, linear memory allocator. 4 | #ifndef JPEG_ENCODER_H 5 | #define JPEG_ENCODER_H 6 | 7 | namespace jpge 8 | { 9 | typedef unsigned char uint8; 10 | typedef signed short int16; 11 | typedef signed int int32; 12 | typedef unsigned short uint16; 13 | typedef unsigned int uint32; 14 | typedef unsigned int uint; 15 | 16 | // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common. 17 | enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 }; 18 | 19 | // JPEG compression parameters structure. 20 | struct params { 21 | inline params() : m_quality(85), m_subsampling(H2V2) { } 22 | 23 | inline bool check() const { 24 | if ((m_quality < 1) || (m_quality > 100)) { 25 | return false; 26 | } 27 | if ((uint)m_subsampling > (uint)H2V2) { 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | // Quality: 1-100, higher is better. Typical values are around 50-95. 34 | int m_quality; 35 | 36 | // m_subsampling: 37 | // 0 = Y (grayscale) only 38 | // 1 = H1V1 subsampling (YCbCr 1x1x1, 3 blocks per MCU) 39 | // 2 = H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU) 40 | // 3 = H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common) 41 | subsampling_t m_subsampling; 42 | }; 43 | 44 | // Output stream abstract class - used by the jpeg_encoder class to write to the output stream. 45 | // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts. 46 | class output_stream { 47 | public: 48 | virtual ~output_stream() { }; 49 | virtual bool put_buf(const void* Pbuf, int len) = 0; 50 | virtual uint get_size() const = 0; 51 | }; 52 | 53 | // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions. 54 | class jpeg_encoder { 55 | public: 56 | jpeg_encoder(); 57 | ~jpeg_encoder(); 58 | 59 | // Initializes the compressor. 60 | // pStream: The stream object to use for writing compressed data. 61 | // params - Compression parameters structure, defined above. 62 | // width, height - Image dimensions. 63 | // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data. 64 | // Returns false on out of memory or if a stream write fails. 65 | bool init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params = params()); 66 | 67 | // Call this method with each source scanline. 68 | // width * src_channels bytes per scanline is expected (RGB or Y format). 69 | // You must call with NULL after all scanlines are processed to finish compression. 70 | // Returns false on out of memory or if a stream write fails. 71 | bool process_scanline(const void* pScanline); 72 | 73 | // Deinitializes the compressor, freeing any allocated memory. May be called at any time. 74 | void deinit(); 75 | 76 | private: 77 | jpeg_encoder(const jpeg_encoder &); 78 | jpeg_encoder &operator =(const jpeg_encoder &); 79 | 80 | typedef int32 sample_array_t; 81 | enum { JPGE_OUT_BUF_SIZE = 512 }; 82 | 83 | output_stream *m_pStream; 84 | params m_params; 85 | uint8 m_num_components; 86 | uint8 m_comp_h_samp[3], m_comp_v_samp[3]; 87 | int m_image_x, m_image_y, m_image_bpp, m_image_bpl; 88 | int m_image_x_mcu, m_image_y_mcu; 89 | int m_image_bpl_xlt, m_image_bpl_mcu; 90 | int m_mcus_per_row; 91 | int m_mcu_x, m_mcu_y; 92 | uint8 *m_mcu_lines[16]; 93 | uint8 m_mcu_y_ofs; 94 | sample_array_t m_sample_array[64]; 95 | int16 m_coefficient_array[64]; 96 | 97 | int m_last_dc_val[3]; 98 | uint8 m_out_buf[JPGE_OUT_BUF_SIZE]; 99 | uint8 *m_pOut_buf; 100 | uint m_out_buf_left; 101 | uint32 m_bit_buffer; 102 | uint m_bits_in; 103 | uint8 m_pass_num; 104 | bool m_all_stream_writes_succeeded; 105 | 106 | bool jpg_open(int p_x_res, int p_y_res, int src_channels); 107 | 108 | void flush_output_buffer(); 109 | void put_bits(uint bits, uint len); 110 | 111 | void emit_byte(uint8 i); 112 | void emit_word(uint i); 113 | void emit_marker(int marker); 114 | 115 | void emit_jfif_app0(); 116 | void emit_dqt(); 117 | void emit_sof(); 118 | void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag); 119 | void emit_dhts(); 120 | void emit_sos(); 121 | 122 | void compute_quant_table(int32 *dst, const int16 *src); 123 | void load_quantized_coefficients(int component_num); 124 | 125 | void load_block_8_8_grey(int x); 126 | void load_block_8_8(int x, int y, int c); 127 | void load_block_16_8(int x, int c); 128 | void load_block_16_8_8(int x, int c); 129 | 130 | void code_coefficients_pass_two(int component_num); 131 | void code_block(int component_num); 132 | 133 | void process_mcu_row(); 134 | bool process_end_of_image(); 135 | void load_mcu(const void* src); 136 | void clear(); 137 | void init(); 138 | }; 139 | 140 | } // namespace jpge 141 | 142 | #endif // JPEG_ENCODER 143 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esp32-camera", 3 | "version": "1.0.0", 4 | "keywords": "esp32, camera, espressif, esp32-cam", 5 | "description": "ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/espressif/esp32-camera" 9 | }, 10 | "frameworks": "espidf", 11 | "platforms": "*", 12 | "build": { 13 | "flags": [ 14 | "-Idriver/include", 15 | "-Iconversions/include", 16 | "-Idriver/private_include", 17 | "-Iconversions/private_include", 18 | "-Isensors/private_include", 19 | "-Itarget/private_include", 20 | "-fno-rtti" 21 | ], 22 | "includeDir": ".", 23 | "srcDir": ".", 24 | "srcFilter": ["-<*>", "+", "+", "+"] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/ll_cam.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "sdkconfig.h" 19 | #if CONFIG_IDF_TARGET_ESP32 20 | #if ESP_IDF_VERSION_MAJOR >= 4 21 | #include "esp32/rom/lldesc.h" 22 | #else 23 | #include "rom/lldesc.h" 24 | #endif 25 | #elif CONFIG_IDF_TARGET_ESP32S2 26 | #include "esp32s2/rom/lldesc.h" 27 | #elif CONFIG_IDF_TARGET_ESP32S3 28 | #include "esp32s3/rom/lldesc.h" 29 | #endif 30 | #include "esp_log.h" 31 | #include "esp_camera.h" 32 | #include "camera_common.h" 33 | #include "freertos/FreeRTOS.h" 34 | #include "freertos/queue.h" 35 | #include "freertos/task.h" 36 | #include "freertos/semphr.h" 37 | 38 | #define CAMERA_DBG_PIN_ENABLE 0 39 | #if CAMERA_DBG_PIN_ENABLE 40 | #if CONFIG_IDF_TARGET_ESP32 41 | #define DBG_PIN_NUM 26 42 | #else 43 | #define DBG_PIN_NUM 7 44 | #endif 45 | #include "hal/gpio_ll.h" 46 | #define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v) 47 | #else 48 | #define DBG_PIN_SET(v) 49 | #endif 50 | 51 | #define CAM_CHECK(a, str, ret) if (!(a)) { \ 52 | ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ 53 | return (ret); \ 54 | } 55 | 56 | #define CAM_CHECK_GOTO(a, str, lab) if (!(a)) { \ 57 | ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ 58 | goto lab; \ 59 | } 60 | 61 | #define LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE (4092) 62 | 63 | typedef enum { 64 | CAM_IN_SUC_EOF_EVENT = 0, 65 | CAM_VSYNC_EVENT 66 | } cam_event_t; 67 | 68 | typedef enum { 69 | CAM_STATE_IDLE = 0, 70 | CAM_STATE_READ_BUF = 1, 71 | } cam_state_t; 72 | 73 | typedef struct { 74 | camera_fb_t fb; 75 | uint8_t en; 76 | //for RGB/YUV modes 77 | lldesc_t *dma; 78 | size_t fb_offset; 79 | } cam_frame_t; 80 | 81 | typedef struct { 82 | uint32_t dma_bytes_per_item; 83 | uint32_t dma_buffer_size; 84 | uint32_t dma_half_buffer_size; 85 | uint32_t dma_half_buffer_cnt; 86 | uint32_t dma_node_buffer_size; 87 | uint32_t dma_node_cnt; 88 | uint32_t frame_copy_cnt; 89 | 90 | //for JPEG mode 91 | lldesc_t *dma; 92 | uint8_t *dma_buffer; 93 | 94 | cam_frame_t *frames; 95 | 96 | QueueHandle_t event_queue; 97 | QueueHandle_t frame_buffer_queue; 98 | TaskHandle_t task_handle; 99 | intr_handle_t cam_intr_handle; 100 | 101 | uint8_t dma_num;//ESP32-S3 102 | intr_handle_t dma_intr_handle;//ESP32-S3 103 | 104 | uint8_t jpeg_mode; 105 | uint8_t vsync_pin; 106 | uint8_t vsync_invert; 107 | uint32_t frame_cnt; 108 | uint32_t recv_size; 109 | bool swap_data; 110 | bool psram_mode; 111 | 112 | //for RGB/YUV modes 113 | uint16_t width; 114 | uint16_t height; 115 | uint8_t in_bytes_per_pixel; 116 | uint8_t fb_bytes_per_pixel; 117 | uint32_t fb_size; 118 | 119 | cam_state_t state; 120 | } cam_obj_t; 121 | 122 | 123 | bool ll_cam_stop(cam_obj_t *cam); 124 | bool ll_cam_start(cam_obj_t *cam, int frame_pos); 125 | esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config); 126 | void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en); 127 | esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config); 128 | esp_err_t ll_cam_init_isr(cam_obj_t *cam); 129 | void ll_cam_do_vsync(cam_obj_t *cam); 130 | uint8_t ll_cam_get_dma_align(cam_obj_t *cam); 131 | bool ll_cam_dma_sizes(cam_obj_t *cam); 132 | size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len); 133 | esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint8_t sensor_pid); 134 | 135 | // implemented in cam_hal 136 | void ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType_t * HPTaskAwoken); 137 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/nt99141.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * NT99141 driver. 7 | * 8 | */ 9 | #ifndef __NT99141_H__ 10 | #define __NT99141_H__ 11 | 12 | #include "sensor.h" 13 | 14 | int NT99141_init(sensor_t *sensor); 15 | 16 | #endif // __NT99141_H__ 17 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/ov2640.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV2640 driver. 7 | * 8 | */ 9 | #ifndef __OV2640_H__ 10 | #define __OV2640_H__ 11 | #include "sensor.h" 12 | int ov2640_init(sensor_t *sensor); 13 | #endif // __OV2640_H__ 14 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/ov3660.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV3660 driver. 7 | * 8 | */ 9 | #ifndef __OV3660_H__ 10 | #define __OV3660_H__ 11 | 12 | #include "sensor.h" 13 | 14 | int ov3660_init(sensor_t *sensor); 15 | 16 | #endif // __OV3660_H__ 17 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/ov5640.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __OV5640_H__ 3 | #define __OV5640_H__ 4 | 5 | #include "sensor.h" 6 | 7 | int ov5640_init(sensor_t *sensor); 8 | 9 | #endif // __OV5640_H__ 10 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/ov7670.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * author: Juan Schiavoni 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7670 driver. 7 | * 8 | */ 9 | #ifndef __OV7670_H__ 10 | #define __OV7670_H__ 11 | #include "sensor.h" 12 | 13 | int ov7670_init(sensor_t *sensor); 14 | #endif // __OV7670_H__ 15 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/ov7725.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7725 driver. 7 | * 8 | */ 9 | #ifndef __OV7725_H__ 10 | #define __OV7725_H__ 11 | #include "sensor.h" 12 | 13 | int ov7725_init(sensor_t *sensor); 14 | #endif // __OV7725_H__ 15 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/sccb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver. 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "sccb.h" 14 | #include "sensor.h" 15 | #include 16 | #include "sdkconfig.h" 17 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 18 | #include "esp32-hal-log.h" 19 | #else 20 | #include "esp_log.h" 21 | static const char* TAG = "sccb"; 22 | #endif 23 | 24 | #define LITTLETOBIG(x) ((x<<8)|(x>>8)) 25 | 26 | #include "driver/i2c.h" 27 | 28 | #define SCCB_FREQ 100000 /*!< I2C master frequency*/ 29 | #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ 30 | #define READ_BIT I2C_MASTER_READ /*!< I2C master read */ 31 | #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ 32 | #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ 33 | #define ACK_VAL 0x0 /*!< I2C ack value */ 34 | #define NACK_VAL 0x1 /*!< I2C nack value */ 35 | #if CONFIG_SCCB_HARDWARE_I2C_PORT1 36 | const int SCCB_I2C_PORT = 1; 37 | #else 38 | const int SCCB_I2C_PORT = 0; 39 | #endif 40 | 41 | int SCCB_Init(int pin_sda, int pin_scl) 42 | { 43 | ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl); 44 | i2c_config_t conf; 45 | memset(&conf, 0, sizeof(i2c_config_t)); 46 | conf.mode = I2C_MODE_MASTER; 47 | conf.sda_io_num = pin_sda; 48 | conf.sda_pullup_en = GPIO_PULLUP_ENABLE; 49 | conf.scl_io_num = pin_scl; 50 | conf.scl_pullup_en = GPIO_PULLUP_ENABLE; 51 | conf.master.clk_speed = SCCB_FREQ; 52 | 53 | i2c_param_config(SCCB_I2C_PORT, &conf); 54 | i2c_driver_install(SCCB_I2C_PORT, conf.mode, 0, 0, 0); 55 | return 0; 56 | } 57 | 58 | int SCCB_Deinit(void) 59 | { 60 | return i2c_driver_delete(SCCB_I2C_PORT); 61 | } 62 | 63 | uint8_t SCCB_Probe(void) 64 | { 65 | uint8_t slave_addr = 0x0; 66 | // for (size_t i = 1; i < 0x80; i++) { 67 | // i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 68 | // i2c_master_start(cmd); 69 | // i2c_master_write_byte(cmd, ( i << 1 ) | WRITE_BIT, ACK_CHECK_EN); 70 | // i2c_master_stop(cmd); 71 | // esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 72 | // i2c_cmd_link_delete(cmd); 73 | // if( ret == ESP_OK) { 74 | // ESP_LOGW(TAG, "Found I2C Device at 0x%02X", i); 75 | // } 76 | // } 77 | for (size_t i = 0; i < CAMERA_MODEL_MAX; i++) { 78 | if (slave_addr == camera_sensor[i].sccb_addr) { 79 | continue; 80 | } 81 | slave_addr = camera_sensor[i].sccb_addr; 82 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 83 | i2c_master_start(cmd); 84 | i2c_master_write_byte(cmd, ( slave_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 85 | i2c_master_stop(cmd); 86 | esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 87 | i2c_cmd_link_delete(cmd); 88 | if( ret == ESP_OK) { 89 | return slave_addr; 90 | } 91 | } 92 | return 0; 93 | } 94 | 95 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg) 96 | { 97 | uint8_t data=0; 98 | esp_err_t ret = ESP_FAIL; 99 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 100 | i2c_master_start(cmd); 101 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 102 | i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); 103 | i2c_master_stop(cmd); 104 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 105 | i2c_cmd_link_delete(cmd); 106 | if(ret != ESP_OK) return -1; 107 | cmd = i2c_cmd_link_create(); 108 | i2c_master_start(cmd); 109 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); 110 | i2c_master_read_byte(cmd, &data, NACK_VAL); 111 | i2c_master_stop(cmd); 112 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 113 | i2c_cmd_link_delete(cmd); 114 | if(ret != ESP_OK) { 115 | ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); 116 | } 117 | return data; 118 | } 119 | 120 | uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data) 121 | { 122 | esp_err_t ret = ESP_FAIL; 123 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 124 | i2c_master_start(cmd); 125 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 126 | i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); 127 | i2c_master_write_byte(cmd, data, ACK_CHECK_EN); 128 | i2c_master_stop(cmd); 129 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 130 | i2c_cmd_link_delete(cmd); 131 | if(ret != ESP_OK) { 132 | ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); 133 | } 134 | return ret == ESP_OK ? 0 : -1; 135 | } 136 | 137 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg) 138 | { 139 | uint8_t data=0; 140 | esp_err_t ret = ESP_FAIL; 141 | uint16_t reg_htons = LITTLETOBIG(reg); 142 | uint8_t *reg_u8 = (uint8_t *)®_htons; 143 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 144 | i2c_master_start(cmd); 145 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 146 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 147 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 148 | i2c_master_stop(cmd); 149 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 150 | i2c_cmd_link_delete(cmd); 151 | if(ret != ESP_OK) return -1; 152 | cmd = i2c_cmd_link_create(); 153 | i2c_master_start(cmd); 154 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); 155 | i2c_master_read_byte(cmd, &data, NACK_VAL); 156 | i2c_master_stop(cmd); 157 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 158 | i2c_cmd_link_delete(cmd); 159 | if(ret != ESP_OK) { 160 | ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data); 161 | } 162 | return data; 163 | } 164 | 165 | uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data) 166 | { 167 | static uint16_t i = 0; 168 | esp_err_t ret = ESP_FAIL; 169 | uint16_t reg_htons = LITTLETOBIG(reg); 170 | uint8_t *reg_u8 = (uint8_t *)®_htons; 171 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 172 | i2c_master_start(cmd); 173 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 174 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 175 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 176 | i2c_master_write_byte(cmd, data, ACK_CHECK_EN); 177 | i2c_master_stop(cmd); 178 | ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS); 179 | i2c_cmd_link_delete(cmd); 180 | if(ret != ESP_OK) { 181 | ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++); 182 | } 183 | return ret == ESP_OK ? 0 : -1; 184 | } 185 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/sccb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver. 7 | * 8 | */ 9 | #ifndef __SCCB_H__ 10 | #define __SCCB_H__ 11 | #include 12 | int SCCB_Init(int pin_sda, int pin_scl); 13 | int SCCB_Deinit(void); 14 | uint8_t SCCB_Probe(); 15 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg); 16 | uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data); 17 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg); 18 | uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data); 19 | #endif // __SCCB_H__ 20 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/sensor.c: -------------------------------------------------------------------------------- 1 | #include "sensor.h" 2 | 3 | const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = { 4 | {CAMERA_OV7725, OV7725_SCCB_ADDR, OV7725_PID, FRAMESIZE_VGA}, 5 | {CAMERA_OV2640, OV2640_SCCB_ADDR, OV2640_PID, FRAMESIZE_UXGA}, 6 | {CAMERA_OV3660, OV3660_SCCB_ADDR, OV3660_PID, FRAMESIZE_QXGA}, 7 | {CAMERA_OV5640, OV5640_SCCB_ADDR, OV5640_PID, FRAMESIZE_QSXGA}, 8 | {CAMERA_OV7670, OV7670_SCCB_ADDR, OV7670_PID, FRAMESIZE_VGA}, 9 | {CAMERA_NT99141, NT99141_SCCB_ADDR, NT99141_PID, FRAMESIZE_HD}, 10 | }; 11 | 12 | const resolution_info_t resolution[FRAMESIZE_INVALID] = { 13 | { 96, 96, ASPECT_RATIO_1X1 }, /* 96x96 */ 14 | { 160, 120, ASPECT_RATIO_4X3 }, /* QQVGA */ 15 | { 176, 144, ASPECT_RATIO_5X4 }, /* QCIF */ 16 | { 240, 176, ASPECT_RATIO_4X3 }, /* HQVGA */ 17 | { 240, 240, ASPECT_RATIO_1X1 }, /* 240x240 */ 18 | { 320, 240, ASPECT_RATIO_4X3 }, /* QVGA */ 19 | { 400, 296, ASPECT_RATIO_4X3 }, /* CIF */ 20 | { 480, 320, ASPECT_RATIO_3X2 }, /* HVGA */ 21 | { 640, 480, ASPECT_RATIO_4X3 }, /* VGA */ 22 | { 800, 600, ASPECT_RATIO_4X3 }, /* SVGA */ 23 | { 1024, 768, ASPECT_RATIO_4X3 }, /* XGA */ 24 | { 1280, 720, ASPECT_RATIO_16X9 }, /* HD */ 25 | { 1280, 1024, ASPECT_RATIO_5X4 }, /* SXGA */ 26 | { 1600, 1200, ASPECT_RATIO_4X3 }, /* UXGA */ 27 | // 3MP Sensors 28 | { 1920, 1080, ASPECT_RATIO_16X9 }, /* FHD */ 29 | { 720, 1280, ASPECT_RATIO_9X16 }, /* Portrait HD */ 30 | { 864, 1536, ASPECT_RATIO_9X16 }, /* Portrait 3MP */ 31 | { 2048, 1536, ASPECT_RATIO_4X3 }, /* QXGA */ 32 | // 5MP Sensors 33 | { 2560, 1440, ASPECT_RATIO_16X9 }, /* QHD */ 34 | { 2560, 1600, ASPECT_RATIO_16X10 }, /* WQXGA */ 35 | { 1088, 1920, ASPECT_RATIO_9X16 }, /* Portrait FHD */ 36 | { 2560, 1920, ASPECT_RATIO_4X3 }, /* QSXGA */ 37 | }; 38 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/to_jpg.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | #include 16 | #include "esp_attr.h" 17 | #include "soc/efuse_reg.h" 18 | #include "esp_heap_caps.h" 19 | #include "esp_camera.h" 20 | #include "img_converters.h" 21 | #include "jpge.h" 22 | #include "yuv.h" 23 | 24 | #include "esp_system.h" 25 | #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ 26 | #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 27 | #include "esp32/spiram.h" 28 | #elif CONFIG_IDF_TARGET_ESP32S2 29 | #include "esp32s2/spiram.h" 30 | #elif CONFIG_IDF_TARGET_ESP32S3 31 | #include "esp32s3/spiram.h" 32 | #else 33 | #error Target CONFIG_IDF_TARGET is not supported 34 | #endif 35 | #else // ESP32 Before IDF 4.0 36 | #include "esp_spiram.h" 37 | #endif 38 | 39 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 40 | #include "esp32-hal-log.h" 41 | #define TAG "" 42 | #else 43 | #include "esp_log.h" 44 | static const char* TAG = "to_jpg"; 45 | #endif 46 | 47 | static void *_malloc(size_t size) 48 | { 49 | void * res = malloc(size); 50 | if(res) { 51 | return res; 52 | } 53 | return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); 54 | } 55 | 56 | static IRAM_ATTR void convert_line_format(uint8_t * src, pixformat_t format, uint8_t * dst, size_t width, size_t in_channels, size_t line) 57 | { 58 | int i=0, o=0, l=0; 59 | if(format == PIXFORMAT_GRAYSCALE) { 60 | memcpy(dst, src + line * width, width); 61 | } else if(format == PIXFORMAT_RGB888) { 62 | l = width * 3; 63 | src += l * line; 64 | for(i=0; i> 3; 75 | dst[o++] = (src[i+1] & 0x1F) << 3; 76 | } 77 | } else if(format == PIXFORMAT_YUV422) { 78 | uint8_t y0, y1, u, v; 79 | uint8_t r, g, b; 80 | l = width * 2; 81 | src += l * line; 82 | for(i=0; i 100) { 114 | quality = 100; 115 | } 116 | 117 | jpge::params comp_params = jpge::params(); 118 | comp_params.m_subsampling = subsampling; 119 | comp_params.m_quality = quality; 120 | 121 | jpge::jpeg_encoder dst_image; 122 | 123 | if (!dst_image.init(dst_stream, width, height, num_channels, comp_params)) { 124 | ESP_LOGE(TAG, "JPG encoder init failed"); 125 | return false; 126 | } 127 | 128 | uint8_t* line = (uint8_t*)_malloc(width * num_channels); 129 | if(!line) { 130 | ESP_LOGE(TAG, "Scan line malloc failed"); 131 | return false; 132 | } 133 | 134 | for (int i = 0; i < height; i++) { 135 | convert_line_format(src, format, line, width, num_channels, i); 136 | if (!dst_image.process_scanline(line)) { 137 | ESP_LOGE(TAG, "JPG process line %u failed", i); 138 | free(line); 139 | return false; 140 | } 141 | } 142 | free(line); 143 | 144 | if (!dst_image.process_scanline(NULL)) { 145 | ESP_LOGE(TAG, "JPG image finish failed"); 146 | return false; 147 | } 148 | dst_image.deinit(); 149 | return true; 150 | } 151 | 152 | class callback_stream : public jpge::output_stream { 153 | protected: 154 | jpg_out_cb ocb; 155 | void * oarg; 156 | size_t index; 157 | 158 | public: 159 | callback_stream(jpg_out_cb cb, void * arg) : ocb(cb), oarg(arg), index(0) { } 160 | virtual ~callback_stream() { } 161 | virtual bool put_buf(const void* data, int len) 162 | { 163 | index += ocb(oarg, index, data, len); 164 | return true; 165 | } 166 | virtual size_t get_size() const 167 | { 168 | return index; 169 | } 170 | }; 171 | 172 | bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg) 173 | { 174 | callback_stream dst_stream(cb, arg); 175 | return convert_image(src, width, height, format, quality, &dst_stream); 176 | } 177 | 178 | bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg) 179 | { 180 | return fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, cb, arg); 181 | } 182 | 183 | 184 | 185 | class memory_stream : public jpge::output_stream { 186 | protected: 187 | uint8_t *out_buf; 188 | size_t max_len, index; 189 | 190 | public: 191 | memory_stream(void *pBuf, uint buf_size) : out_buf(static_cast(pBuf)), max_len(buf_size), index(0) { } 192 | 193 | virtual ~memory_stream() { } 194 | 195 | virtual bool put_buf(const void* pBuf, int len) 196 | { 197 | if (!pBuf) { 198 | //end of image 199 | return true; 200 | } 201 | if ((size_t)len > (max_len - index)) { 202 | //ESP_LOGW(TAG, "JPG output overflow: %d bytes (%d,%d,%d)", len - (max_len - index), len, index, max_len); 203 | len = max_len - index; 204 | } 205 | if (len) { 206 | memcpy(out_buf + index, pBuf, len); 207 | index += len; 208 | } 209 | return true; 210 | } 211 | 212 | virtual size_t get_size() const 213 | { 214 | return index; 215 | } 216 | }; 217 | 218 | bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len) 219 | { 220 | //todo: allocate proper buffer for holding JPEG data 221 | //this should be enough for CIF frame size 222 | int jpg_buf_len = 128*1024; 223 | 224 | 225 | uint8_t * jpg_buf = (uint8_t *)_malloc(jpg_buf_len); 226 | if(jpg_buf == NULL) { 227 | ESP_LOGE(TAG, "JPG buffer malloc failed"); 228 | return false; 229 | } 230 | memory_stream dst_stream(jpg_buf, jpg_buf_len); 231 | 232 | if(!convert_image(src, width, height, format, quality, &dst_stream)) { 233 | free(jpg_buf); 234 | return false; 235 | } 236 | 237 | *out = jpg_buf; 238 | *out_len = dst_stream.get_size(); 239 | return true; 240 | } 241 | 242 | bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len) 243 | { 244 | return fmt2jpg(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, out, out_len); 245 | } 246 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/xclk.c: -------------------------------------------------------------------------------- 1 | #include "driver/gpio.h" 2 | #include "driver/ledc.h" 3 | #include "esp_err.h" 4 | #include "esp_log.h" 5 | #include "esp_system.h" 6 | #include "xclk.h" 7 | 8 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 9 | #include "esp32-hal-log.h" 10 | #else 11 | #include "esp_log.h" 12 | static const char* TAG = "camera_xclk"; 13 | #endif 14 | 15 | esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz) 16 | { 17 | ledc_timer_config_t timer_conf; 18 | timer_conf.duty_resolution = LEDC_TIMER_1_BIT; 19 | timer_conf.freq_hz = xclk_freq_hz; 20 | #if CONFIG_IDF_TARGET_ESP32 21 | timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE; 22 | #else 23 | timer_conf.speed_mode = LEDC_LOW_SPEED_MODE; 24 | #endif 25 | #if ESP_IDF_VERSION_MAJOR >= 4 26 | timer_conf.clk_cfg = LEDC_AUTO_CLK; 27 | #endif 28 | timer_conf.timer_num = (ledc_timer_t)ledc_timer; 29 | esp_err_t err = ledc_timer_config(&timer_conf); 30 | if (err != ESP_OK) { 31 | ESP_LOGE(TAG, "ledc_timer_config failed for freq %d, rc=%x", xclk_freq_hz, err); 32 | } 33 | return err; 34 | } 35 | 36 | esp_err_t camera_enable_out_clock(camera_config_t* config) 37 | { 38 | periph_module_enable(PERIPH_LEDC_MODULE); 39 | 40 | esp_err_t err = xclk_timer_conf(config->ledc_timer, config->xclk_freq_hz); 41 | if (err != ESP_OK) { 42 | ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err); 43 | return err; 44 | } 45 | 46 | ledc_channel_config_t ch_conf; 47 | ch_conf.gpio_num = config->pin_xclk; 48 | #if CONFIG_IDF_TARGET_ESP32 49 | ch_conf.speed_mode = LEDC_HIGH_SPEED_MODE; 50 | #else 51 | ch_conf.speed_mode = LEDC_LOW_SPEED_MODE; 52 | #endif 53 | ch_conf.channel = config->ledc_channel; 54 | ch_conf.intr_type = LEDC_INTR_DISABLE; 55 | ch_conf.timer_sel = config->ledc_timer; 56 | ch_conf.duty = 1; 57 | ch_conf.hpoint = 0; 58 | err = ledc_channel_config(&ch_conf); 59 | if (err != ESP_OK) { 60 | ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err); 61 | return err; 62 | } 63 | return ESP_OK; 64 | } 65 | 66 | void camera_disable_out_clock() 67 | { 68 | periph_module_disable(PERIPH_LEDC_MODULE); 69 | } 70 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/xclk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "camera_common.h" 4 | 5 | esp_err_t camera_enable_out_clock(); 6 | 7 | void camera_disable_out_clock(); 8 | -------------------------------------------------------------------------------- /Arduino-IDE/esp32-cam/yuv.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _CONVERSIONS_YUV_H_ 15 | #define _CONVERSIONS_YUV_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | 23 | void yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* _CONVERSIONS_YUV_H_ */ 30 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2020, Anatoli Arkhipenko. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 24 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /PlatformIO/README.md: -------------------------------------------------------------------------------- 1 | # MJPEG Multiclient Streaming Server 2 | 3 | ## THIS DOCUMENT IS WORK IN PROGRESS 4 | 5 | 6 | 7 | ## With latest ESP-CAM drivers 8 | **Full story:** https://www.hackster.io/anatoli-arkhipenko/multi-client-mjpeg-streaming-from-esp32-47768f 9 | 10 | **Video:** https://youtu.be/bsAVJSZeSmc 11 | 12 | 13 | 14 | **Updated on 2024-09-26:** 15 | 16 | - moved to Platform IO 17 | 18 | - code includes all three RTOS frame delivery options: 19 | 20 | - Single RTOS task serving the same frame to all clients (compile CAMERA_MULTICLIENT_QUEUE) 21 | 22 | - Separate dedicated RTOS tasks serving the same frame to clients independently (compile CAMERA_MULTICLIENT_TASK) 23 | 24 | - Serarate dedicated RTOS tasks serving individual frames to clients - no frames are "dropped" (compile CAMERA_ALL_FRAMES) 25 | 26 | 27 | ### Quick start 28 | 29 | Pull the repo recursively in order to include the latest esp32-camera drivers. 30 | 31 | `git clone --recurse-submodules https://github.com/arkhipenko/esp32-mjpeg-multiclient-espcam-drivers.git` 32 | 33 | Open workspace file `esp32-cam-rtos-pio\esp32-cam-rtos-pio.code-workspace` with MS VSCode 34 | 35 | Inspect the platformio.ini file: 36 | 37 | - Select frame service: 38 | - -D CAMERA_MULTICLIENT_QUEUE 39 | - -D CAMERA_MULTICLIENT_TASK 40 | - -D CAMERA_ALL_FRAMES 41 | - Select appropriate frame size: -D FRAME_SIZE=FRAMESIZE_HVGA <== example 42 | - Choose FPS (10 recommended) 43 | - Choose JPEG quality: JPEG_QUALITY ==> 0-63 lower means higher quality (0, 1, and 2 did not work for me) 44 | 45 | Switch to Platform IO menu then build and upload appropriate camera options 46 | 47 | If your camera model is not listed - read on or try contacting me to create appropriate build option, device file and partition scheme. 48 | 49 | When firmware is running, connect to the WIFI AP it creates: 50 | 51 | - SSID: mjpeg-ap 52 | - Password: MJPEG123 53 | 54 | Navigate to: http://192.168.4.1 to the WiFiManager main page. 55 | 56 | Provide WIFI credentials for your network 57 | 58 | Once connected, the MJPEG stream is available on: Stream Link: http://your.local.network.IP.address/mjpeg/1 59 | 60 | e.g.: Stream Link: http://192.168.122.132/mjpeg/1 61 | 62 | 63 | 64 | ### Notes: 65 | 66 | #### What is this? 67 | 68 | MJPEG Multiclient Streaming Server using RTOS tasks and queues to serve video frames to clients from the onboard camera. 69 | 70 | Several video frame delivery options are available: 71 | 72 | - Single RTOS task serving the same frame to all clients (compile CAMERA_MULTICLIENT_QUEUE) 73 | 74 | - Separate dedicated RTOS tasks serving the same frame to clients independently (compile CAMERA_MULTICLIENT_TASK) 75 | 76 | - Serarate dedicated RTOS tasks serving individual frames to clients - no frames are "dropped" (compile CAMERA_ALL_FRAMES) 77 | 78 | 79 | #### Compile options - Camera types 80 | 81 | The following camearas are supported. (configurable in the `platformio.ini` file) 82 | Only ESP32-CAM and ESP-EYE were actually tested. 83 | 84 | Pinouts for some/all cameras are described here: 85 | https://randomnerdtutorials.com/esp32-cam-camera-pin-gpios/ 86 | 87 | - ESP-EYE (CAMERA_MODEL_ESP_EYE) 88 | 89 | - ESP32-CAM AI-Thinker (CAMERA_MODEL_AI_THINKER) 90 | 91 | These cameras could be supported, but require additional work (creating board and partition files, and editing of platformio.ini file) 92 | 93 | - Freenove ESP32-Wrover (CAMERA_MODEL_WROVER_KIT) 94 | 95 | - M5 Cameras (models A and B) (CAMERA_MODEL_M5STACK_PSRAM) 96 | 97 | - M5-stack ESP32 camera without PSRAM (CAMERA_MODEL_M5STACK_WIDE) 98 | 99 | - TTGO T-Journal (CAMERA_TTGO_T_JOURNAL) 100 | 101 | - TTGO T-Camera Plus (CAMERA_TTGO_T_PLUS) 102 | 103 | - TTGO T-Camera Plus (CAMERA_TTGO_PIR) 104 | 105 | 106 | #### Compile options - Frame size 107 | 108 | The following frame sizes are currently supported by the camera: (configurable in the `platformio.ini` file) 109 | 110 | - FRAMESIZE_96X96, // 96x96 111 | 112 | - FRAMESIZE_QQVGA, // 160x120 113 | 114 | - FRAMESIZE_QCIF, // 176x144 115 | 116 | - FRAMESIZE_HQVGA, // 240x176 117 | 118 | - FRAMESIZE_240X240, // 240x240 119 | 120 | - FRAMESIZE_QVGA, // 320x240 121 | 122 | - FRAMESIZE_CIF, // 400x296 123 | 124 | - FRAMESIZE_HVGA, // 480x320 125 | 126 | - FRAMESIZE_VGA, // 640x480 127 | 128 | - FRAMESIZE_SVGA, // 800x600 129 | 130 | - FRAMESIZE_XGA, // 1024x768 131 | 132 | - FRAMESIZE_HD, // 1280x720 133 | 134 | - FRAMESIZE_SXGA, // 1280x1024 135 | 136 | - FRAMESIZE_UXGA, // 1600x1200 137 | 138 | Larger frames are served slower 139 | 140 | 141 | #### Latest camera drivers 142 | 143 | This repo references Espressif's latest camera drivers' git repo directly as a component. 144 | The drivers re located at: https://github.com/espressif/esp32-camera 145 | 146 | To update to the latest - run `git pull origin` command from the `esp32-camera` folder. 147 | 148 | 149 | 150 | ### DISCLAIMER: 151 | 152 | The repository should compile and work **AS-IS** as of the date stated above. Espressif is actively working on the camera drivers, and their **future updates may break the procedure below**. Please report the broken process providing as much information as possible, definitely the make and model of your camera device, version of the Arduino Core and IDE used. 153 | 154 | Remember, this is a hack, a POC and a test. This is **NOT GUARANTEED** to work on all ESP32-based devices. The performance could be different depending on the make, brand and manufacturer of your camera. 155 | 156 | Please do not demand fixes and updates - you are welcome to take this repo as a baseline and improve upon it. 157 | 158 | *Have fun!* 159 | 160 | 161 | 162 | ### Procedure: 163 | 164 | #### WORK IN PROGRESS 165 | 166 | ### Results: 167 | 168 | I was able to run multiple browser windows, multiple VLC windows and connect multiple Blynk video widgets (max: 10) to ESP-EYE chip. The delay on the browser window was almost unnoticeable. In VLC you notice a 1 second delay due to buffering. Blynk performance all depends on the phone, so no comments there. 169 | 170 | This is incredible considering the size of this thing! The camera on ESP-EYE is actually quite good. 171 | 172 | ### Enjoy! 173 | 174 | 175 | 176 | ------ 177 | 178 | ##### Other repositories that may be of interest 179 | 180 | ###### ESP32 MJPEG streaming server servicing a single client: 181 | 182 | https://github.com/arkhipenko/esp32-cam-mjpeg 183 | 184 | 185 | 186 | ###### ESP32 MJPEG streaming server servicing multiple clients (FreeRTOS based): 187 | 188 | https://github.com/arkhipenko/esp32-cam-mjpeg-multiclient 189 | 190 | 191 | 192 | ###### ESP32 MJPEG streaming server servicing multiple clients (FreeRTOS based) with the latest camera drivers from espressif. 193 | 194 | https://github.com/arkhipenko/esp32-mjpeg-multiclient-espcam-drivers 195 | 196 | 197 | 198 | ###### Cooperative multitasking library: 199 | 200 | https://github.com/arkhipenko/TaskScheduler 201 | 202 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode/.browse.c_cpp.db* 3 | .vscode/c_cpp_properties.json 4 | .vscode/launch.json 5 | .vscode/ipch 6 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "platformio.platformio-ide" 6 | ], 7 | "unwantedRecommendations": [ 8 | "ms-vscode.cpptools-extension-pack" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.tcc": "cpp" 4 | } 5 | } -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16.0) 2 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 3 | project(esp32-cam-rtos-allframes-pio) 4 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/ai-thinker-cam.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | nvs, data, nvs, 0x9000, 0x5000, 3 | otadata, data, ota, 0xe000, 0x2000, 4 | app0, app, ota_0, 0x10000, 0x140000, 5 | app1, app, ota_1, 0x150000,0x140000, 6 | spiffs, data, spiffs, 0x290000,0x160000, 7 | coredump, data, coredump,0x3F0000,0x10000, -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/boards/ai-thinker-cam.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino":{ 4 | "ldscript": "esp32_out.ld" 5 | }, 6 | "core": "esp32", 7 | "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", 8 | "f_cpu": "240000000L", 9 | "f_flash": "80000000L", 10 | "flash_mode": "qio", 11 | "mcu": "esp32", 12 | "variant": "esp32" 13 | }, 14 | "connectivity": [ 15 | "wifi", 16 | "bluetooth", 17 | "ethernet", 18 | "can" 19 | ], 20 | "debug": { 21 | "openocd_board": "esp-wroom-32.cfg" 22 | }, 23 | "frameworks": [ 24 | "arduino", 25 | "espidf" 26 | ], 27 | "name": "AI Thinker ESP32-CAM", 28 | "upload": { 29 | "flash_size": "4MB", 30 | "maximum_ram_size": 327680, 31 | "maximum_size": 4194304, 32 | "require_upload_port": true, 33 | "speed": 921600 34 | }, 35 | "url": "https://wiki.ai-thinker.com/esp32-cam", 36 | "vendor": "Espressif" 37 | } 38 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/boards/esp-eye.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino":{ 4 | "ldscript": "esp32_out.ld" 5 | }, 6 | "core": "esp32", 7 | "extra_flags": "-DARDUINO_ESP32_PICO -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_SPIRAM_CACHE_WORKAROUND", 8 | "f_cpu": "240000000L", 9 | "f_flash": "80000000L", 10 | "flash_mode": "qio", 11 | "mcu": "esp32", 12 | "variant": "pico32" 13 | }, 14 | "connectivity": [ 15 | "wifi", 16 | "bluetooth", 17 | "ethernet", 18 | "can" 19 | ], 20 | "frameworks": [ 21 | "arduino", 22 | "espidf" 23 | ], 24 | "name": "Espressif ESP32 ESP-EYE", 25 | "upload": { 26 | "flash_size": "4MB", 27 | "maximum_ram_size": 327680, 28 | "maximum_size": 4194304, 29 | "require_upload_port": true, 30 | "speed": 921600 31 | }, 32 | "url": "https://github.com/espressif/esp-who/blob/master/docs/en/get-started/ESP-EYE_Getting_Started_Guide.md", 33 | "vendor": "Espressif" 34 | } 35 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/boards/freenove-wrover-cam.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "arduino":{ 4 | "ldscript": "esp32_out.ld" 5 | }, 6 | "core": "esp32", 7 | "extra_flags": "-DARDUINO_ESP32_DEV -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue", 8 | "f_cpu": "240000000L", 9 | "f_flash": "40000000L", 10 | "flash_mode": "dio", 11 | "mcu": "esp32", 12 | "variant": "esp32" 13 | }, 14 | "connectivity": [ 15 | "wifi", 16 | "bluetooth", 17 | "ethernet", 18 | "can" 19 | ], 20 | "debug": { 21 | "openocd_board": "esp-wroom-32.cfg" 22 | }, 23 | "frameworks": [ 24 | "arduino", 25 | "espidf" 26 | ], 27 | "name": "Freenove ESP32-Wrover CAM", 28 | "upload": { 29 | "flash_size": "4MB", 30 | "maximum_ram_size": 327680, 31 | "maximum_size": 4194304, 32 | "require_upload_port": true, 33 | "speed": 921600 34 | }, 35 | "url": "https://store.freenove.com/products/fnk0060", 36 | "vendor": "Freenove" 37 | } 38 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/dependencies.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | idf: 3 | component_hash: null 4 | source: 5 | type: idf 6 | version: 4.4.7 7 | manifest_hash: 3e6980bc5fca475de2a39d94c3ea3944c0528040d862609e810d1d8f5ea7f661 8 | target: esp32 9 | version: 1.0.0 10 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/esp-eye.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | nvs, data, nvs, 0x9000, 0x5000, 3 | otadata, data, ota, 0xe000, 0x2000, 4 | app0, app, ota_0, 0x10000, 0x1d0000, 5 | app1, app, ota_1, , 0x1d0000, 6 | spiffs, data, spiffs, , 0x40000, 7 | coredump, data, coredump, , 0x10000 -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/esp32-cam-rtos-pio.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": {} 8 | } -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/files/camera_pins.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arkhipenko/esp32-mjpeg-multiclient-espcam-drivers/b9451ebb6dff814bc0bebbd1850a411915e78eff/PlatformIO/esp32-cam-rtos-pio/files/camera_pins.ods -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/freenove-wrover-cam.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | nvs, data, nvs, 0x9000, 0x5000, 3 | otadata, data, ota, 0xe000, 0x2000, 4 | app0, app, ota_0, 0x10000, 0x140000, 5 | app1, app, ota_1, 0x150000,0x140000, 6 | spiffs, data, spiffs, 0x290000,0x160000, 7 | coredump, data, coredump,0x3F0000,0x10000, -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/include/camera_pins.h: -------------------------------------------------------------------------------- 1 | 2 | #if defined(CAMERA_MODEL_WROVER_KIT) 3 | #define PWDN_GPIO_NUM -1 4 | #define RESET_GPIO_NUM -1 5 | #define XCLK_GPIO_NUM 21 6 | #define SIOD_GPIO_NUM 26 7 | #define SIOC_GPIO_NUM 27 8 | #define Y9_GPIO_NUM 35 9 | #define Y8_GPIO_NUM 34 10 | #define Y7_GPIO_NUM 39 11 | #define Y6_GPIO_NUM 36 12 | #define Y5_GPIO_NUM 19 13 | #define Y4_GPIO_NUM 18 14 | #define Y3_GPIO_NUM 5 15 | #define Y2_GPIO_NUM 4 16 | #define VSYNC_GPIO_NUM 25 17 | #define HREF_GPIO_NUM 23 18 | #define PCLK_GPIO_NUM 22 19 | 20 | #elif defined(CAMERA_MODEL_ESP_EYE) 21 | #define PWDN_GPIO_NUM -1 22 | #define RESET_GPIO_NUM -1 23 | #define XCLK_GPIO_NUM 4 24 | #define SIOD_GPIO_NUM 18 25 | #define SIOC_GPIO_NUM 23 26 | #define Y9_GPIO_NUM 36 27 | #define Y8_GPIO_NUM 37 28 | #define Y7_GPIO_NUM 38 29 | #define Y6_GPIO_NUM 39 30 | #define Y5_GPIO_NUM 35 31 | #define Y4_GPIO_NUM 14 32 | #define Y3_GPIO_NUM 13 33 | #define Y2_GPIO_NUM 34 34 | #define VSYNC_GPIO_NUM 5 35 | #define HREF_GPIO_NUM 27 36 | #define PCLK_GPIO_NUM 25 37 | 38 | #elif defined(CAMERA_MODEL_M5STACK_PSRAM) 39 | #define PWDN_GPIO_NUM -1 40 | #define RESET_GPIO_NUM 15 41 | #define XCLK_GPIO_NUM 27 42 | #define SIOD_GPIO_NUM 25 43 | #define SIOC_GPIO_NUM 23 44 | #define Y9_GPIO_NUM 19 45 | #define Y8_GPIO_NUM 36 46 | #define Y7_GPIO_NUM 18 47 | #define Y6_GPIO_NUM 39 48 | #define Y5_GPIO_NUM 5 49 | #define Y4_GPIO_NUM 34 50 | #define Y3_GPIO_NUM 35 51 | #define Y2_GPIO_NUM 32 52 | #define VSYNC_GPIO_NUM 22 53 | #define HREF_GPIO_NUM 26 54 | #define PCLK_GPIO_NUM 21 55 | 56 | #elif defined(CAMERA_MODEL_M5STACK_WIDE) 57 | #define PWDN_GPIO_NUM -1 58 | #define RESET_GPIO_NUM 15 59 | #define XCLK_GPIO_NUM 27 60 | #define SIOD_GPIO_NUM 22 61 | #define SIOC_GPIO_NUM 23 62 | #define Y9_GPIO_NUM 19 63 | #define Y8_GPIO_NUM 36 64 | #define Y7_GPIO_NUM 18 65 | #define Y6_GPIO_NUM 39 66 | #define Y5_GPIO_NUM 5 67 | #define Y4_GPIO_NUM 34 68 | #define Y3_GPIO_NUM 35 69 | #define Y2_GPIO_NUM 32 70 | #define VSYNC_GPIO_NUM 25 71 | #define HREF_GPIO_NUM 26 72 | #define PCLK_GPIO_NUM 21 73 | 74 | #elif defined(CAMERA_MODEL_AI_THINKER) 75 | #define PWDN_GPIO_NUM 32 76 | #define RESET_GPIO_NUM -1 77 | #define XCLK_GPIO_NUM 0 78 | #define SIOD_GPIO_NUM 26 79 | #define SIOC_GPIO_NUM 27 80 | #define Y9_GPIO_NUM 35 81 | #define Y8_GPIO_NUM 34 82 | #define Y7_GPIO_NUM 39 83 | #define Y6_GPIO_NUM 36 84 | #define Y5_GPIO_NUM 21 85 | #define Y4_GPIO_NUM 19 86 | #define Y3_GPIO_NUM 18 87 | #define Y2_GPIO_NUM 5 88 | #define VSYNC_GPIO_NUM 25 89 | #define HREF_GPIO_NUM 23 90 | #define PCLK_GPIO_NUM 22 91 | 92 | #elif defined(CAMERA_TTGO_T_JOURNAL) 93 | #define PWDN_GPIO_NUM 32 94 | #define RESET_GPIO_NUM -1 95 | #define XCLK_GPIO_NUM 27 96 | #define SIOD_GPIO_NUM 25 97 | #define SIOC_GPIO_NUM 23 98 | #define Y9_GPIO_NUM 19 99 | #define Y8_GPIO_NUM 36 100 | #define Y7_GPIO_NUM 18 101 | #define Y6_GPIO_NUM 39 102 | #define Y5_GPIO_NUM 5 103 | #define Y4_GPIO_NUM 34 104 | #define Y3_GPIO_NUM 35 105 | #define Y2_GPIO_NUM 17 106 | #define VSYNC_GPIO_NUM 22 107 | #define HREF_GPIO_NUM 26 108 | #define PCLK_GPIO_NUM 21 109 | 110 | #elif defined(CAMERA_TTGO_T_PLUS) 111 | #define PWDN_GPIO_NUM -1 112 | #define RESET_GPIO_NUM -1 113 | #define XCLK_GPIO_NUM 4 114 | #define SIOD_GPIO_NUM 18 115 | #define SIOC_GPIO_NUM 23 116 | #define Y9_GPIO_NUM 36 117 | #define Y8_GPIO_NUM 37 118 | #define Y7_GPIO_NUM 38 119 | #define Y6_GPIO_NUM 39 120 | #define Y5_GPIO_NUM 35 121 | #define Y4_GPIO_NUM 26 122 | #define Y3_GPIO_NUM 13 123 | #define Y2_GPIO_NUM 34 124 | #define VSYNC_GPIO_NUM 5 125 | #define HREF_GPIO_NUM 27 126 | #define PCLK_GPIO_NUM 25 127 | 128 | #elif defined(CAMERA_TTGO_T_PIR) 129 | #define PWDN_GPIO_NUM -1 130 | #define RESET_GPIO_NUM -1 131 | #define XCLK_GPIO_NUM 32 132 | #define SIOD_GPIO_NUM 13 133 | #define SIOC_GPIO_NUM 12 134 | #define Y9_GPIO_NUM 39 135 | #define Y8_GPIO_NUM 36 136 | #define Y7_GPIO_NUM 23 137 | #define Y6_GPIO_NUM 18 138 | #define Y5_GPIO_NUM 15 139 | #define Y4_GPIO_NUM 4 140 | #define Y3_GPIO_NUM 14 141 | #define Y2_GPIO_NUM 5 142 | #define VSYNC_GPIO_NUM 27 143 | #define HREF_GPIO_NUM 25 144 | #define PCLK_GPIO_NUM 19 145 | 146 | #else 147 | #error "Camera model not selected" 148 | #endif 149 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/include/credentials.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define AP_SSID "mjpeg-ap" 4 | #define AP_PWD "MJPEG123" -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/include/definitions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // ESP32 has two cores: APPlication core and PROcess core (the one that runs ESP32 SDK stack) 4 | #define APP_CPU 1 5 | #define PRO_CPU 0 6 | 7 | #define KILOBYTE 1024 8 | 9 | #define SERIAL_RATE 115200 10 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/include/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // ==== includes ================================= 3 | #include "references.h" 4 | 5 | #define MILLIS_FUNCTION xTaskGetTickCount() 6 | // #define MILLIS_FUNCTION millis() 7 | 8 | // ==== prototypes =============================== 9 | void setupLogging(); 10 | 11 | #ifndef DISABLE_LOGGING 12 | void printTimestampMillis(Print* logOutput); 13 | void printBuffer(const char* aBuf, size_t aSize); 14 | #endif // #ifndef DISABLE_LOGGING 15 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/include/references.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "logging.h" 6 | 7 | #include "esp_camera.h" 8 | #include "ov2640.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | extern SemaphoreHandle_t frameSync; 19 | extern WebServer server; 20 | extern TaskHandle_t tMjpeg; // handles client connections to the webserver 21 | extern TaskHandle_t tCam; // handles getting picture frames from the camera and storing them locally 22 | extern TaskHandle_t tStream; 23 | extern uint8_t noActiveClients; // number of active clients 24 | 25 | extern const char* STREAMING_URL; 26 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/include/streaming.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "definitions.h" 3 | #include "references.h" 4 | 5 | typedef struct { 6 | uint32_t frame; 7 | WiFiClient *client; 8 | TaskHandle_t task; 9 | char* buffer; 10 | size_t len; 11 | } streamInfo_t; 12 | 13 | typedef struct { 14 | uint8_t cnt; // served to clients counter. when equal to number of active clients, could be deleted 15 | void* nxt; // next chunck 16 | uint32_t fnm; // frame number 17 | uint32_t siz; // frame size 18 | uint8_t* dat; // frame pointer 19 | } frameChunck_t; 20 | 21 | 22 | void camCB(void* pvParameters); 23 | void handleJPGSstream(void); 24 | void handleNotFound(void); 25 | void streamCB(void * pvParameters); 26 | void mjpegCB(void * pvParameters); 27 | 28 | #define FAIL_IF_OOM true 29 | #define OK_IF_OOM false 30 | #define PSRAM_ONLY true 31 | #define ANY_MEMORY false 32 | char* allocateMemory(char* aPtr, size_t aSize, bool fail = FAIL_IF_OOM, bool psramOnly = ANY_MEMORY); 33 | 34 | extern const char* HEADER; 35 | extern const char* BOUNDARY; 36 | extern const char* CTNTTYPE; 37 | extern const int hdrLen; 38 | extern const int bdrLen; 39 | extern const int cntLen; 40 | extern volatile uint32_t frameNumber; 41 | 42 | extern frameChunck_t* fstFrame; 43 | extern frameChunck_t* curFrame; 44 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/lib/ArduinoLog/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ArduinoLog", 3 | "version": "1.0.3", 4 | "dependencies": { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/lib/ArduinoLog/src/ArduinoLog.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "ArduinoLog.h" 3 | 4 | /* 5 | _ ___ ___ _ _ ___ _ _ ___ _ ___ ___ 6 | /_\ | _ \ \| | | |_ _| \| |/ _ \| | / _ \ / __| 7 | / _ \| / |) | |_| || || .` | (_) | |_| (_) | (_ | 8 | /_/ \_\_|_\___/ \___/|___|_|\_|\___/|____\___/ \___| 9 | 10 | Log library for Arduino 11 | version 1.0.3 12 | https://github.com/thijse/Arduino-Log 13 | 14 | Licensed under the MIT License . 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | */ 34 | 35 | // #include "ArduinoLog.h" 36 | 37 | void Logging::begin(int level, Print* logOutput, bool showLevel) 38 | { 39 | #ifndef DISABLE_LOGGING 40 | setLevel(level); 41 | setShowLevel(showLevel); 42 | _logOutput = logOutput; 43 | 44 | #endif 45 | } 46 | 47 | void Logging::setLevel(int level) 48 | { 49 | #ifndef DISABLE_LOGGING 50 | _level = constrain(level, LOG_LEVEL_SILENT, LOG_LEVEL_VERBOSE); 51 | #endif 52 | } 53 | 54 | int Logging::getLevel() const 55 | { 56 | #ifndef DISABLE_LOGGING 57 | return _level; 58 | #else 59 | return 0; 60 | #endif 61 | } 62 | 63 | void Logging::setOutput(Print* output) 64 | { 65 | #ifndef DISABLE_LOGGING 66 | _logOutput = output; 67 | #endif 68 | } 69 | 70 | void Logging::setShowLevel(bool showLevel) 71 | { 72 | #ifndef DISABLE_LOGGING 73 | _showLevel = showLevel; 74 | #endif 75 | } 76 | 77 | bool Logging::getShowLevel() const 78 | { 79 | #ifndef DISABLE_LOGGING 80 | return _showLevel; 81 | #else 82 | return false; 83 | #endif 84 | } 85 | 86 | void Logging::setPrefix(printfunction f) 87 | { 88 | #ifndef DISABLE_LOGGING 89 | _prefix = f; 90 | #endif 91 | } 92 | 93 | void Logging::setSuffix(printfunction f) 94 | { 95 | #ifndef DISABLE_LOGGING 96 | _suffix = f; 97 | #endif 98 | } 99 | 100 | void Logging::print(const __FlashStringHelper *format, va_list args) 101 | { 102 | #ifndef DISABLE_LOGGING 103 | PGM_P p = reinterpret_cast(format); 104 | char c = pgm_read_byte(p++); 105 | for (; c != 0; c = pgm_read_byte(p++)) 106 | { 107 | if (c == '%') 108 | { 109 | c = pgm_read_byte(p++); 110 | printFormat(c, &args); 111 | } 112 | else 113 | { 114 | _logOutput->print(c); 115 | } 116 | } 117 | #endif 118 | } 119 | 120 | void Logging::print(const char *format, va_list args) { 121 | #ifndef DISABLE_LOGGING 122 | for (; *format != 0; ++format) 123 | { 124 | if (*format == '%') 125 | { 126 | ++format; 127 | printFormat(*format, &args); 128 | } 129 | else 130 | { 131 | _logOutput->print(*format); 132 | } 133 | } 134 | #endif 135 | } 136 | 137 | void Logging::printFormat(const char format, va_list *args) { 138 | #ifndef DISABLE_LOGGING 139 | if (format == '%') 140 | { 141 | _logOutput->print(format); 142 | } 143 | else if (format == 's') 144 | { 145 | register char *s = (char *)va_arg(*args, int); 146 | _logOutput->print(s); 147 | } 148 | #if !defined(ESP8266) 149 | else if (format == 'S') 150 | { 151 | String s = (String)va_arg(*args, String); 152 | _logOutput->print(s); 153 | } 154 | else if (format == 'I') 155 | { 156 | char s[16]; 157 | IPAddress ip = (IPAddress)va_arg(*args, IPAddress ); 158 | sprintf(s, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); 159 | _logOutput->print(s); 160 | } 161 | #endif 162 | else if (format == 'P') 163 | { 164 | register __FlashStringHelper *s = (__FlashStringHelper *)va_arg(*args, int); 165 | _logOutput->print(s); 166 | } 167 | else if (format == 'd' || format == 'i') 168 | { 169 | _logOutput->print(va_arg(*args, int), DEC); 170 | } 171 | else if (format == 'D' || format == 'F') 172 | { 173 | _logOutput->print(va_arg(*args, double)); 174 | } 175 | else if (format == 'x') 176 | { 177 | _logOutput->print(va_arg(*args, int), HEX); 178 | } 179 | else if (format == 'X') 180 | { 181 | _logOutput->print("0x"); 182 | _logOutput->print(va_arg(*args, int), HEX); 183 | } 184 | else if (format == 'b') 185 | { 186 | _logOutput->print(va_arg(*args, int), BIN); 187 | } 188 | else if (format == 'B') 189 | { 190 | _logOutput->print("0b"); 191 | _logOutput->print(va_arg(*args, int), BIN); 192 | } 193 | else if (format == 'l') 194 | { 195 | _logOutput->print(va_arg(*args, long), DEC); 196 | } 197 | else if (format == 'u') 198 | { 199 | _logOutput->print(va_arg(*args, unsigned long), DEC); 200 | } 201 | else if (format == 'c') 202 | { 203 | _logOutput->print((char) va_arg(*args, int)); 204 | } 205 | else if (format == 't') 206 | { 207 | if (va_arg(*args, int) == 1) 208 | { 209 | _logOutput->print("T"); 210 | } 211 | else 212 | { 213 | _logOutput->print("F"); 214 | } 215 | } 216 | else if (format == 'T') 217 | { 218 | if (va_arg(*args, int) == 1) 219 | { 220 | _logOutput->print(F("true")); 221 | } 222 | else 223 | { 224 | _logOutput->print(F("false")); 225 | } 226 | } 227 | #endif 228 | } 229 | 230 | Logging Log = Logging(); 231 | StaticSemaphore_t semMutexBuffer; 232 | SemaphoreHandle_t semLog = xSemaphoreCreateMutexStatic( &semMutexBuffer ); -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/lib/AverageFilter/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2020, Anatoli Arkhipenko. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 24 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/lib/AverageFilter/README.md: -------------------------------------------------------------------------------- 1 | # Average Filter 2 | 3 | ### Digital implementation of an average filter 4 | [![arduino-library-badge](https://www.ardu-badge.com/badge/AverageFilter.svg?)](https://www.ardu-badge.com/AverageFilter) 5 | 6 | ##### With variable number of tracked values and externally provided storage 7 | 8 | ##### Version 1.0.0 9 | 10 | 11 | 12 | ###### Changelog: 13 | 14 | v1.0.0: 15 | 16 | - 2015-11-18 - initial release 17 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/lib/AverageFilter/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For TaskManager 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | averageFilter KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | initialize KEYWORD2 16 | value KEYWORD2 17 | currentValue KEYWORD2 18 | samples KEYWORD2 19 | 20 | ####################################### 21 | # Constants (LITERAL1) 22 | ####################################### 23 | 24 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/lib/AverageFilter/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AverageFilter", 3 | "keywords": "integer, filter, average, signal, processing", 4 | "description": "Integer implementation of the Average Filter", 5 | "repository": 6 | { 7 | "type": "git", 8 | "url": "https://github.com/arkhipenko/AverageFilter" 9 | }, 10 | "authors": 11 | [ 12 | { 13 | "name": "Anatoli Arkhipenko", 14 | "email": "arkhipenko@hotmail.com", 15 | "url": "https://github.com/arkhipenko", 16 | "maintainer": true 17 | } 18 | ], 19 | "version": "1.0.1", 20 | "frameworks": "arduino", 21 | "platforms": "*" 22 | } 23 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/lib/AverageFilter/src/AverageFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Digital implementation of an average filter 3 | // with variable number of samples 4 | // 5 | 6 | #include 7 | 8 | #ifndef _AVERAGEFILTER_H 9 | #define _AVERAGEFILTER_H 10 | 11 | template 12 | class averageFilter { 13 | public: 14 | averageFilter(int aSamples); 15 | averageFilter(int aSamples, T* aStorage); 16 | ~averageFilter(); 17 | 18 | void initialize(); 19 | T value(T aSample); 20 | void setSamples( int aSamples ); 21 | 22 | inline T currentValue() { return iCV; } 23 | inline int32_t samples() { return iCount; } 24 | inline bool memoryError() { return iReadings == NULL; } 25 | 26 | private: 27 | T *iReadings; 28 | T iTotal; 29 | T iCV; 30 | int32_t iIndex; 31 | int32_t iCount; 32 | int32_t iSamples; 33 | }; 34 | 35 | 36 | 37 | template 38 | averageFilter::averageFilter(int aSamples) { 39 | iSamples = constrain(aSamples, 1, aSamples); 40 | iReadings = (T *) malloc (sizeof (T) * aSamples); 41 | // if there is a memory allocation error. 42 | if (iReadings == NULL) { 43 | iReadings = &iCV; 44 | iSamples = 1; 45 | } 46 | initialize(); 47 | } 48 | 49 | template 50 | averageFilter::averageFilter(int aSamples, T* aStorage) { 51 | iSamples = constrain(aSamples, 1, aSamples); 52 | iReadings = aStorage; 53 | // if storage provided is NULL 54 | if (iReadings == NULL) { 55 | iReadings = &iCV; 56 | iSamples = 1; 57 | } 58 | initialize(); 59 | } 60 | 61 | template 62 | void averageFilter::setSamples(int aSamples) { 63 | iSamples = constrain(aSamples, 1, aSamples); 64 | if ( iCount ) initialize(); 65 | } 66 | 67 | template 68 | averageFilter::~averageFilter() { 69 | if ( iReadings && iReadings != &iCV ) free (iReadings); 70 | iReadings = NULL; 71 | iIndex = 0; 72 | iTotal = 0; 73 | iCount = 0; 74 | } 75 | 76 | template 77 | void averageFilter::initialize() { 78 | iIndex = 0; 79 | iTotal = 0; 80 | iCount = 0; 81 | iCV = 0; 82 | for (int i=0; i 86 | T averageFilter::value(T aSample) { 87 | // if ( !iReadings ) return 0; 88 | iTotal -= iReadings[iIndex]; 89 | iReadings[iIndex] = aSample; 90 | iTotal += aSample; 91 | if (++iIndex >= iSamples) iIndex = 0; 92 | if (++iCount > iSamples) iCount = iSamples; 93 | iCV = (T) iTotal/iCount; 94 | return iCV; 95 | } 96 | 97 | #endif // _AVERAGEFILTER_H -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file was automatically generated for projects 2 | # without default 'CMakeLists.txt' file. 3 | 4 | FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*) 5 | 6 | idf_component_register(SRCS ${app_sources}) 7 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/src/logging.cpp: -------------------------------------------------------------------------------- 1 | // === Arduino-Log implementation ================================================================= 2 | #include "logging.h" 3 | 4 | // Setup default logging system 5 | void setupLogging() { 6 | #ifndef DISABLE_LOGGING 7 | Log.begin(LOG_LEVEL, &Serial); 8 | Log.setPrefix(printTimestampMillis); 9 | Log.trace("setupLogging()" CR); 10 | #endif // #ifndef DISABLE_LOGGING 11 | } 12 | 13 | 14 | // === millis() - based timestamp == 15 | void printTimestamp(Print* logOutput) { 16 | char c[24]; 17 | sprintf(c, "%10lu ", (long unsigned int) MILLIS_FUNCTION); 18 | logOutput->print(c); 19 | } 20 | 21 | 22 | // start-time-based timestamp ======== 23 | void printTimestampMillis(Print* logOutput) { 24 | char c[64]; 25 | unsigned long mm = MILLIS_FUNCTION; 26 | int ms = mm % 1000; 27 | int s = mm / 1000; 28 | int m = s / 60; 29 | int h = m / 60; 30 | int d = h / 24; 31 | sprintf(c, "%02d:%02d:%02d:%02d.%03d ", d, h % 24, m % 60, s % 60, ms); 32 | logOutput->print(c); 33 | } 34 | 35 | 36 | #ifndef DISABLE_LOGGING 37 | void printBuffer(const char* aBuf, size_t aSize) { 38 | Serial.println("Buffer contents:"); 39 | 40 | char c; 41 | String s; 42 | size_t cnt = 0; 43 | 44 | for (int j = 0; j < aSize / 16 + 1; j++) { 45 | Serial.printf("%04x : ", j * 16); 46 | for (int i = 0; i < 16 && cnt < aSize; i++) { 47 | c = aBuf[cnt++]; 48 | Serial.printf("%02x ", c); 49 | if (c < 32) { 50 | s += '.'; 51 | } 52 | else { 53 | s += c; 54 | } 55 | } 56 | Serial.print(" : "); 57 | Serial.println(s); 58 | s = ""; 59 | } 60 | Serial.println(); 61 | } 62 | #else 63 | void printBuffer(const char* aBuf, size_t aSize) {} 64 | #endif 65 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is a MJPEG streaming webserver implemented for AI-Thinker ESP32-CAM 4 | and ESP-EYE modules. 5 | This is tested to work with VLC and Blynk video widget and can support up to 10 6 | simultaneously connected streaming clients. 7 | Simultaneous streaming is implemented with FreeRTOS tools: queue and tasks. 8 | 9 | Inspired by and based on this Instructable: $9 RTSP Video Streamer Using the ESP32-CAM Board 10 | (https://www.instructables.com/id/9-RTSP-Video-Streamer-Using-the-ESP32-CAM-Board/) 11 | 12 | */ 13 | 14 | #include "definitions.h" 15 | #include "references.h" 16 | 17 | 18 | #include "credentials.h" 19 | #include "streaming.h" 20 | 21 | const char *c_ssid = AP_SSID; 22 | const char *c_pwd = AP_PWD; 23 | 24 | // Camera models overview: 25 | // https://randomnerdtutorials.com/esp32-cam-camera-pin-gpios/ 26 | 27 | 28 | #include "camera_pins.h" 29 | 30 | WebServer server(80); 31 | 32 | // ===== rtos task handles ========================= 33 | // Streaming is implemented with tasks: 34 | TaskHandle_t tMjpeg; // handles client connections to the webserver 35 | TaskHandle_t tCam; // handles getting picture frames from the camera and storing them locally 36 | TaskHandle_t tStream; 37 | 38 | uint8_t noActiveClients; // number of active clients 39 | 40 | // frameSync semaphore is used to prevent streaming buffer as it is replaced with the next frame 41 | SemaphoreHandle_t frameSync = NULL; 42 | 43 | 44 | // ==== SETUP method ================================================================== 45 | void setup() { 46 | 47 | // Setup Serial connection: 48 | Serial.begin(SERIAL_RATE); 49 | delay(500); // wait for a bit to let Serial connect 50 | 51 | setupLogging(); 52 | 53 | Log.trace("\n\nMulti-client MJPEG Server\n"); 54 | Log.trace("setup: total heap : %d\n", ESP.getHeapSize()); 55 | Log.trace("setup: free heap : %d\n", ESP.getFreeHeap()); 56 | Log.trace("setup: total psram : %d\n", ESP.getPsramSize()); 57 | Log.trace("setup: free psram : %d\n", ESP.getFreePsram()); 58 | 59 | static camera_config_t camera_config = { 60 | .pin_pwdn = PWDN_GPIO_NUM, 61 | .pin_reset = RESET_GPIO_NUM, 62 | .pin_xclk = XCLK_GPIO_NUM, 63 | .pin_sscb_sda = SIOD_GPIO_NUM, 64 | .pin_sscb_scl = SIOC_GPIO_NUM, 65 | .pin_d7 = Y9_GPIO_NUM, 66 | .pin_d6 = Y8_GPIO_NUM, 67 | .pin_d5 = Y7_GPIO_NUM, 68 | .pin_d4 = Y6_GPIO_NUM, 69 | .pin_d3 = Y5_GPIO_NUM, 70 | .pin_d2 = Y4_GPIO_NUM, 71 | .pin_d1 = Y3_GPIO_NUM, 72 | .pin_d0 = Y2_GPIO_NUM, 73 | .pin_vsync = VSYNC_GPIO_NUM, 74 | .pin_href = HREF_GPIO_NUM, 75 | .pin_pclk = PCLK_GPIO_NUM, 76 | 77 | .xclk_freq_hz = XCLK_FREQ, 78 | .ledc_timer = LEDC_TIMER_0, 79 | .ledc_channel = LEDC_CHANNEL_0, 80 | .pixel_format = PIXFORMAT_JPEG, 81 | .frame_size = FRAME_SIZE, 82 | .jpeg_quality = JPEG_QUALITY, 83 | .fb_count = 2, 84 | .fb_location = CAMERA_FB_IN_DRAM, 85 | .grab_mode = CAMERA_GRAB_LATEST, 86 | // .sccb_i2c_port = -1 87 | }; 88 | 89 | #if defined(CAMERA_MODEL_ESP_EYE) 90 | pinMode(13, INPUT_PULLUP); 91 | pinMode(14, INPUT_PULLUP); 92 | #endif 93 | 94 | if (esp_camera_init(&camera_config) != ESP_OK) { 95 | Log.fatal("setup: Error initializing the camera\n"); 96 | delay(10000); 97 | ESP.restart(); 98 | } 99 | 100 | #if defined (FLIP_VERTICALLY) 101 | sensor_t* s = esp_camera_sensor_get(); 102 | s->set_vflip(s, true); 103 | #endif 104 | 105 | // Configure and connect to WiFi 106 | char apname[65]; 107 | char passwd[65]; 108 | IPAddress ip; 109 | WiFiManager wm; 110 | 111 | 112 | WiFi.setAutoConnect(true); 113 | 114 | std::vector menu = {"wifi","restart","exit"}; 115 | wm.setMenu(menu); 116 | 117 | wm.setConfigPortalTimeout(180); // seconds 118 | wm.setConnectTimeout(45); 119 | wm.setConnectRetries(3); 120 | 121 | strcpy(apname, c_ssid); 122 | strcpy(passwd, c_pwd); 123 | if ( !wm.autoConnect((const char*) apname, (const char*) passwd) ) { // password protected ap 124 | Log.fatal("setup: Unble to connect to WiFI - restarting\n"); 125 | delay(5000); 126 | ESP.restart(); 127 | } 128 | 129 | ip = WiFi.localIP(); 130 | Log.verbose(F("setup: WiFi connected\n")); 131 | // Log.verbose("Stream Link: http://%S/mjpeg/1\n\n", ip.toString()); 132 | Serial.printf("Stream Link: http://%s%s\n\n", ip.toString().c_str(), STREAMING_URL); 133 | 134 | // Start main streaming RTOS task 135 | xTaskCreatePinnedToCore( 136 | mjpegCB, 137 | "mjpeg", 138 | 3 * KILOBYTE, 139 | NULL, 140 | tskIDLE_PRIORITY + 2, 141 | &tMjpeg, 142 | PRO_CPU); 143 | 144 | Log.trace("setup complete: free heap : %d\n", ESP.getFreeHeap()); 145 | } 146 | 147 | void loop() { 148 | vTaskDelete(NULL); 149 | } 150 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/src/streaming.cpp: -------------------------------------------------------------------------------- 1 | #include "streaming.h" 2 | 3 | const char* HEADER = "HTTP/1.1 200 OK\r\n" \ 4 | "Access-Control-Allow-Origin: *\r\n" \ 5 | "Content-Type: multipart/x-mixed-replace; boundary=+++===123454321===+++\r\n"; 6 | const char* BOUNDARY = "\r\n--+++===123454321===+++\r\n"; 7 | const char* CTNTTYPE = "Content-Type: image/jpeg\r\nContent-Length: "; 8 | const int hdrLen = strlen(HEADER); 9 | const int bdrLen = strlen(BOUNDARY); 10 | const int cntLen = strlen(CTNTTYPE); 11 | volatile uint32_t frameNumber; 12 | 13 | frameChunck_t* fstFrame = NULL; // first frame 14 | frameChunck_t* curFrame = NULL; // current frame being captured by the camera 15 | 16 | const char* STREAMING_URL = "/mjpeg/1"; 17 | 18 | void mjpegCB(void* pvParameters) { 19 | TickType_t xLastWakeTime; 20 | const TickType_t xFrequency = pdMS_TO_TICKS(WSINTERVAL); 21 | 22 | // Creating frame synchronization semaphore and initializing it 23 | frameSync = xSemaphoreCreateBinary(); 24 | xSemaphoreGive( frameSync ); 25 | 26 | 27 | // Creating RTOS task for grabbing frames from the camera 28 | xTaskCreatePinnedToCore( 29 | camCB, // callback 30 | "cam", // name 31 | 4 * KILOBYTE, // stack size 32 | NULL, // parameters 33 | tskIDLE_PRIORITY + 2, // priority 34 | &tCam, // RTOS task handle 35 | APP_CPU); // core 36 | 37 | // Registering webserver handling routines 38 | server.on(STREAMING_URL, HTTP_GET, handleJPGSstream); 39 | server.onNotFound(handleNotFound); 40 | 41 | // Starting webserver 42 | server.begin(); 43 | 44 | Log.trace("mjpegCB: Starting streaming service\n"); 45 | Log.verbose ("mjpegCB: free heap (start) : %d\n", ESP.getFreeHeap()); 46 | 47 | //=== loop() section =================== 48 | xLastWakeTime = xTaskGetTickCount(); 49 | for (;;) { 50 | server.handleClient(); 51 | 52 | // After every server client handling request, we let other tasks run and then pause 53 | if ( xTaskDelayUntil(&xLastWakeTime, xFrequency) != pdTRUE ) taskYIELD(); 54 | } 55 | } 56 | 57 | 58 | // ==== Memory allocator that takes advantage of PSRAM if present ======================= 59 | char* allocatePSRAM(size_t aSize) { 60 | if ( psramFound() && ESP.getFreePsram() > aSize ) { 61 | return (char*) ps_malloc(aSize); 62 | } 63 | return NULL; 64 | } 65 | 66 | char* allocateMemory(char* aPtr, size_t aSize, bool fail, bool psramOnly) { 67 | 68 | // Since current buffer is too smal, free it 69 | if (aPtr != NULL) { 70 | free(aPtr); 71 | aPtr = NULL; 72 | } 73 | 74 | char* ptr = NULL; 75 | 76 | if ( psramOnly ) { 77 | ptr = allocatePSRAM(aSize); 78 | } 79 | else { 80 | // If memory requested is more than 2/3 of the currently free heap, try PSRAM immediately 81 | if ( aSize > ESP.getFreeHeap() * 2 / 3 ) { 82 | ptr = allocatePSRAM(aSize); 83 | } 84 | else { 85 | // Enough free heap - let's try allocating fast RAM as a buffer 86 | ptr = (char*) malloc(aSize); 87 | 88 | // If allocation on the heap failed, let's give PSRAM one more chance: 89 | if ( ptr == NULL ) ptr = allocatePSRAM(aSize); 90 | } 91 | } 92 | // Finally, if the memory pointer is NULL, we were not able to allocate any memory, and that is a terminal condition. 93 | if (fail && ptr == NULL) { 94 | Log.fatal("allocateMemory: Out of memory!"); 95 | delay(5000); 96 | ESP.restart(); 97 | } 98 | return ptr; 99 | } 100 | 101 | 102 | // ==== Handle invalid URL requests ============================================ 103 | void handleNotFound() { 104 | String message = "Server is running!\n\n"; 105 | message += "URI: "; 106 | message += server.uri(); 107 | message += "\nMethod: "; 108 | message += (server.method() == HTTP_GET) ? "GET" : "POST"; 109 | message += "\nArguments: "; 110 | message += server.args(); 111 | message += "\n"; 112 | server.send(200, "text / plain", message); 113 | } 114 | 115 | -------------------------------------------------------------------------------- /PlatformIO/esp32-cam-rtos-pio/test/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for PlatformIO Test Runner and project tests. 3 | 4 | Unit Testing is a software testing method by which individual units of 5 | source code, sets of one or more MCU program modules together with associated 6 | control data, usage procedures, and operating procedures, are tested to 7 | determine whether they are fit for use. Unit testing finds problems early 8 | in the development cycle. 9 | 10 | More information about PlatformIO Unit Testing: 11 | - https://docs.platformio.org/en/latest/advanced/unit-testing/index.html 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MJPEG Multiclient Streaming Server 2 | 3 | ## With latest ESP-CAM drivers 4 | **Full story:** https://www.hackster.io/anatoli-arkhipenko/multi-client-mjpeg-streaming-from-esp32-47768f 5 | 6 | **Video:** https://youtu.be/bsAVJSZeSmc 7 | 8 | 9 | 10 | **Updated on 2021-07-01:** 11 | 12 | - OP updated to account for recent repo changes by Espressif 13 | 14 | - Recompiled with ESP32 Arduino Core 1.0.6 15 | 16 | - Updated with latest ESP CAM drivers 17 | 18 | 19 | 20 | ### Contents: 21 | 22 | #### Arduino IDE folder: 23 | 24 | MJPEG Multiclient Streaming Server using RTOS - supports up to 10 clients. 25 | 26 | This folder is for sketches created in Arduino IDE 27 | 28 | #### Platform IO folder: 29 | 30 | MJPEG Multiclient Streaming Server using RTOS - supports up to 10 clients. 31 | 32 | This folder is for Platform IO package 33 | 34 | 35 | ### Enjoy! 36 | 37 | 38 | 39 | ------ 40 | 41 | ##### Other repositories that may be of interest 42 | 43 | ###### ESP32 MJPEG streaming server servicing a single client: 44 | 45 | https://github.com/arkhipenko/esp32-cam-mjpeg 46 | 47 | 48 | 49 | ###### ESP32 MJPEG streaming server servicing multiple clients (FreeRTOS based): 50 | 51 | https://github.com/arkhipenko/esp32-cam-mjpeg-multiclient 52 | 53 | 54 | 55 | ###### Cooperative multitasking library: 56 | 57 | https://github.com/arkhipenko/TaskScheduler 58 | 59 | --------------------------------------------------------------------------------