commit
71b9bb55c7
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2015-2020, Anatoli Arkhipenko.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,39 @@
|
|||||||
|
# ESP32 MJPEG Streaming Server
|
||||||
|
|
||||||
|
This is a simple MJPEG streaming webserver implemented for AI-Thinker ESP32-CAM and ESP-EYE modules.
|
||||||
|
|
||||||
|
This is tested to work with **VLC** and **Blynk** video widget.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Inspired by and based on this Instructable: [$9 RTSP Video Streamer Using the ESP32-CAM Board](https://www.instructables.com/id/9-RTSP-Video-Streamer-Using-the-ESP32-CAM-Board/)
|
||||||
|
|
||||||
|
Full story: https://www.hackster.io/anatoli-arkhipenko/multi-client-mjpeg-streaming-from-esp32-47768f
|
||||||
|
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
##### Other repositories that may be of interest
|
||||||
|
|
||||||
|
###### ESP32 MJPEG streaming server servicing a single client:
|
||||||
|
|
||||||
|
https://github.com/arkhipenko/esp32-cam-mjpeg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###### ESP32 MJPEG streaming server servicing multiple clients (FreeRTOS based):
|
||||||
|
|
||||||
|
https://github.com/arkhipenko/esp32-cam-mjpeg-multiclient
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###### ESP32 MJPEG streaming server servicing multiple clients (FreeRTOS based) with the latest camera drivers from espressif.
|
||||||
|
|
||||||
|
https://github.com/arkhipenko/esp32-mjpeg-multiclient-espcam-drivers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###### Cooperative multitasking library:
|
||||||
|
|
||||||
|
https://github.com/arkhipenko/TaskScheduler
|
||||||
|
|
@ -0,0 +1,99 @@
|
|||||||
|
|
||||||
|
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||||
|
#define PWDN_GPIO_NUM -1
|
||||||
|
#define RESET_GPIO_NUM -1
|
||||||
|
#define XCLK_GPIO_NUM 21
|
||||||
|
#define SIOD_GPIO_NUM 26
|
||||||
|
#define SIOC_GPIO_NUM 27
|
||||||
|
|
||||||
|
#define Y9_GPIO_NUM 35
|
||||||
|
#define Y8_GPIO_NUM 34
|
||||||
|
#define Y7_GPIO_NUM 39
|
||||||
|
#define Y6_GPIO_NUM 36
|
||||||
|
#define Y5_GPIO_NUM 19
|
||||||
|
#define Y4_GPIO_NUM 18
|
||||||
|
#define Y3_GPIO_NUM 5
|
||||||
|
#define Y2_GPIO_NUM 4
|
||||||
|
#define VSYNC_GPIO_NUM 25
|
||||||
|
#define HREF_GPIO_NUM 23
|
||||||
|
#define PCLK_GPIO_NUM 22
|
||||||
|
|
||||||
|
#elif defined(CAMERA_MODEL_ESP_EYE)
|
||||||
|
#define PWDN_GPIO_NUM -1
|
||||||
|
#define RESET_GPIO_NUM -1
|
||||||
|
#define XCLK_GPIO_NUM 4
|
||||||
|
#define SIOD_GPIO_NUM 18
|
||||||
|
#define SIOC_GPIO_NUM 23
|
||||||
|
|
||||||
|
#define Y9_GPIO_NUM 36
|
||||||
|
#define Y8_GPIO_NUM 37
|
||||||
|
#define Y7_GPIO_NUM 38
|
||||||
|
#define Y6_GPIO_NUM 39
|
||||||
|
#define Y5_GPIO_NUM 35
|
||||||
|
#define Y4_GPIO_NUM 14
|
||||||
|
#define Y3_GPIO_NUM 13
|
||||||
|
#define Y2_GPIO_NUM 34
|
||||||
|
#define VSYNC_GPIO_NUM 5
|
||||||
|
#define HREF_GPIO_NUM 27
|
||||||
|
#define PCLK_GPIO_NUM 25
|
||||||
|
|
||||||
|
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||||
|
#define PWDN_GPIO_NUM -1
|
||||||
|
#define RESET_GPIO_NUM 15
|
||||||
|
#define XCLK_GPIO_NUM 27
|
||||||
|
#define SIOD_GPIO_NUM 25
|
||||||
|
#define SIOC_GPIO_NUM 23
|
||||||
|
|
||||||
|
#define Y9_GPIO_NUM 19
|
||||||
|
#define Y8_GPIO_NUM 36
|
||||||
|
#define Y7_GPIO_NUM 18
|
||||||
|
#define Y6_GPIO_NUM 39
|
||||||
|
#define Y5_GPIO_NUM 5
|
||||||
|
#define Y4_GPIO_NUM 34
|
||||||
|
#define Y3_GPIO_NUM 35
|
||||||
|
#define Y2_GPIO_NUM 32
|
||||||
|
#define VSYNC_GPIO_NUM 22
|
||||||
|
#define HREF_GPIO_NUM 26
|
||||||
|
#define PCLK_GPIO_NUM 21
|
||||||
|
|
||||||
|
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
|
||||||
|
#define PWDN_GPIO_NUM -1
|
||||||
|
#define RESET_GPIO_NUM 15
|
||||||
|
#define XCLK_GPIO_NUM 27
|
||||||
|
#define SIOD_GPIO_NUM 22
|
||||||
|
#define SIOC_GPIO_NUM 23
|
||||||
|
|
||||||
|
#define Y9_GPIO_NUM 19
|
||||||
|
#define Y8_GPIO_NUM 36
|
||||||
|
#define Y7_GPIO_NUM 18
|
||||||
|
#define Y6_GPIO_NUM 39
|
||||||
|
#define Y5_GPIO_NUM 5
|
||||||
|
#define Y4_GPIO_NUM 34
|
||||||
|
#define Y3_GPIO_NUM 35
|
||||||
|
#define Y2_GPIO_NUM 32
|
||||||
|
#define VSYNC_GPIO_NUM 25
|
||||||
|
#define HREF_GPIO_NUM 26
|
||||||
|
#define PCLK_GPIO_NUM 21
|
||||||
|
|
||||||
|
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||||
|
#define PWDN_GPIO_NUM 32
|
||||||
|
#define RESET_GPIO_NUM -1
|
||||||
|
#define XCLK_GPIO_NUM 0
|
||||||
|
#define SIOD_GPIO_NUM 26
|
||||||
|
#define SIOC_GPIO_NUM 27
|
||||||
|
|
||||||
|
#define Y9_GPIO_NUM 35
|
||||||
|
#define Y8_GPIO_NUM 34
|
||||||
|
#define Y7_GPIO_NUM 39
|
||||||
|
#define Y6_GPIO_NUM 36
|
||||||
|
#define Y5_GPIO_NUM 21
|
||||||
|
#define Y4_GPIO_NUM 19
|
||||||
|
#define Y3_GPIO_NUM 18
|
||||||
|
#define Y2_GPIO_NUM 5
|
||||||
|
#define VSYNC_GPIO_NUM 25
|
||||||
|
#define HREF_GPIO_NUM 23
|
||||||
|
#define PCLK_GPIO_NUM 22
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Camera model not selected"
|
||||||
|
#endif
|
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This is a simple MJPEG streaming webserver implemented for AI-Thinker ESP32-CAM and
|
||||||
|
ESP32-EYE modules.
|
||||||
|
This is tested to work with VLC and Blynk video widget.
|
||||||
|
|
||||||
|
Inspired by and based on this Instructable: $9 RTSP Video Streamer Using the ESP32-CAM Board
|
||||||
|
(https://www.instructables.com/id/9-RTSP-Video-Streamer-Using-the-ESP32-CAM-Board/)
|
||||||
|
|
||||||
|
Board: AI-Thinker ESP32-CAM
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "src/OV2640.h"
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <WebServer.h>
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
|
||||||
|
// Select camera model
|
||||||
|
//#define CAMERA_MODEL_WROVER_KIT
|
||||||
|
#define CAMERA_MODEL_ESP_EYE
|
||||||
|
//#define CAMERA_MODEL_M5STACK_PSRAM
|
||||||
|
//#define CAMERA_MODEL_M5STACK_WIDE
|
||||||
|
//#define CAMERA_MODEL_AI_THINKER
|
||||||
|
|
||||||
|
#include "camera_pins.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define SSID1 "ssid"
|
||||||
|
#define PWD1 "password"
|
||||||
|
|
||||||
|
|
||||||
|
OV2640 cam;
|
||||||
|
|
||||||
|
WebServer server(80);
|
||||||
|
|
||||||
|
const char HEADER[] = "HTTP/1.1 200 OK\r\n" \
|
||||||
|
"Access-Control-Allow-Origin: *\r\n" \
|
||||||
|
"Content-Type: multipart/x-mixed-replace; boundary=123456789000000000000987654321\r\n";
|
||||||
|
const char BOUNDARY[] = "\r\n--123456789000000000000987654321\r\n";
|
||||||
|
const char CTNTTYPE[] = "Content-Type: image/jpeg\r\nContent-Length: ";
|
||||||
|
const int hdrLen = strlen(HEADER);
|
||||||
|
const int bdrLen = strlen(BOUNDARY);
|
||||||
|
const int cntLen = strlen(CTNTTYPE);
|
||||||
|
|
||||||
|
void handle_jpg_stream(void)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
int s;
|
||||||
|
|
||||||
|
WiFiClient client = server.client();
|
||||||
|
|
||||||
|
client.write(HEADER, hdrLen);
|
||||||
|
client.write(BOUNDARY, bdrLen);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (!client.connected()) break;
|
||||||
|
cam.run();
|
||||||
|
s = cam.getSize();
|
||||||
|
client.write(CTNTTYPE, cntLen);
|
||||||
|
sprintf( buf, "%d\r\n\r\n", s );
|
||||||
|
client.write(buf, strlen(buf));
|
||||||
|
client.write((char *)cam.getfb(), s);
|
||||||
|
client.write(BOUNDARY, bdrLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char JHEADER[] = "HTTP/1.1 200 OK\r\n" \
|
||||||
|
"Content-disposition: inline; filename=capture.jpg\r\n" \
|
||||||
|
"Content-type: image/jpeg\r\n\r\n";
|
||||||
|
const int jhdLen = strlen(JHEADER);
|
||||||
|
|
||||||
|
void handle_jpg(void)
|
||||||
|
{
|
||||||
|
WiFiClient client = server.client();
|
||||||
|
|
||||||
|
cam.run();
|
||||||
|
if (!client.connected()) return;
|
||||||
|
|
||||||
|
client.write(JHEADER, jhdLen);
|
||||||
|
client.write((char *)cam.getfb(), cam.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleNotFound()
|
||||||
|
{
|
||||||
|
String message = "Server is running!\n\n";
|
||||||
|
message += "URI: ";
|
||||||
|
message += server.uri();
|
||||||
|
message += "\nMethod: ";
|
||||||
|
message += (server.method() == HTTP_GET) ? "GET" : "POST";
|
||||||
|
message += "\nArguments: ";
|
||||||
|
message += server.args();
|
||||||
|
message += "\n";
|
||||||
|
server.send(200, "text / plain", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
//while (!Serial); //wait for serial connection.
|
||||||
|
|
||||||
|
camera_config_t config;
|
||||||
|
config.ledc_channel = LEDC_CHANNEL_0;
|
||||||
|
config.ledc_timer = LEDC_TIMER_0;
|
||||||
|
config.pin_d0 = Y2_GPIO_NUM;
|
||||||
|
config.pin_d1 = Y3_GPIO_NUM;
|
||||||
|
config.pin_d2 = Y4_GPIO_NUM;
|
||||||
|
config.pin_d3 = Y5_GPIO_NUM;
|
||||||
|
config.pin_d4 = Y6_GPIO_NUM;
|
||||||
|
config.pin_d5 = Y7_GPIO_NUM;
|
||||||
|
config.pin_d6 = Y8_GPIO_NUM;
|
||||||
|
config.pin_d7 = Y9_GPIO_NUM;
|
||||||
|
config.pin_xclk = XCLK_GPIO_NUM;
|
||||||
|
config.pin_pclk = PCLK_GPIO_NUM;
|
||||||
|
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||||
|
config.pin_href = HREF_GPIO_NUM;
|
||||||
|
config.pin_sscb_sda = SIOD_GPIO_NUM;
|
||||||
|
config.pin_sscb_scl = SIOC_GPIO_NUM;
|
||||||
|
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||||
|
config.pin_reset = RESET_GPIO_NUM;
|
||||||
|
config.xclk_freq_hz = 20000000;
|
||||||
|
config.pixel_format = PIXFORMAT_JPEG;
|
||||||
|
|
||||||
|
// Frame parameters
|
||||||
|
// config.frame_size = FRAMESIZE_UXGA;
|
||||||
|
config.frame_size = FRAMESIZE_QVGA;
|
||||||
|
config.jpeg_quality = 12;
|
||||||
|
config.fb_count = 2;
|
||||||
|
|
||||||
|
#if defined(CAMERA_MODEL_ESP_EYE)
|
||||||
|
pinMode(13, INPUT_PULLUP);
|
||||||
|
pinMode(14, INPUT_PULLUP);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cam.init(config);
|
||||||
|
|
||||||
|
IPAddress ip;
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(SSID1, PWD1);
|
||||||
|
while (WiFi.status() != WL_CONNECTED)
|
||||||
|
{
|
||||||
|
delay(500);
|
||||||
|
Serial.print(F("."));
|
||||||
|
}
|
||||||
|
ip = WiFi.localIP();
|
||||||
|
Serial.println(F("WiFi connected"));
|
||||||
|
Serial.println("");
|
||||||
|
Serial.println(ip);
|
||||||
|
Serial.print("Stream Link: http://");
|
||||||
|
Serial.print(ip);
|
||||||
|
Serial.println("/mjpeg/1");
|
||||||
|
server.on("/mjpeg/1", HTTP_GET, handle_jpg_stream);
|
||||||
|
server.on("/jpg", HTTP_GET, handle_jpg);
|
||||||
|
server.onNotFound(handleNotFound);
|
||||||
|
server.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
server.handleClient();
|
||||||
|
}
|
@ -0,0 +1,193 @@
|
|||||||
|
#include "OV2640.h"
|
||||||
|
|
||||||
|
#define TAG "OV2640"
|
||||||
|
|
||||||
|
// definitions appropriate for the ESP32-CAM devboard (and most clones)
|
||||||
|
camera_config_t esp32cam_config{
|
||||||
|
|
||||||
|
.pin_pwdn = -1, // FIXME: on the TTGO T-Journal I think this is GPIO 0
|
||||||
|
.pin_reset = 15,
|
||||||
|
|
||||||
|
.pin_xclk = 27,
|
||||||
|
|
||||||
|
.pin_sscb_sda = 25,
|
||||||
|
.pin_sscb_scl = 23,
|
||||||
|
|
||||||
|
.pin_d7 = 19,
|
||||||
|
.pin_d6 = 36,
|
||||||
|
.pin_d5 = 18,
|
||||||
|
.pin_d4 = 39,
|
||||||
|
.pin_d3 = 5,
|
||||||
|
.pin_d2 = 34,
|
||||||
|
.pin_d1 = 35,
|
||||||
|
.pin_d0 = 17,
|
||||||
|
.pin_vsync = 22,
|
||||||
|
.pin_href = 26,
|
||||||
|
.pin_pclk = 21,
|
||||||
|
.xclk_freq_hz = 20000000,
|
||||||
|
.ledc_timer = LEDC_TIMER_0,
|
||||||
|
.ledc_channel = LEDC_CHANNEL_0,
|
||||||
|
.pixel_format = PIXFORMAT_JPEG,
|
||||||
|
// .frame_size = FRAMESIZE_UXGA, // needs 234K of framebuffer space
|
||||||
|
// .frame_size = FRAMESIZE_SXGA, // needs 160K for framebuffer
|
||||||
|
// .frame_size = FRAMESIZE_XGA, // needs 96K or even smaller FRAMESIZE_SVGA - can work if using only 1 fb
|
||||||
|
.frame_size = FRAMESIZE_SVGA,
|
||||||
|
.jpeg_quality = 12, //0-63 lower numbers are higher quality
|
||||||
|
.fb_count = 2 // if more than one i2s runs in continous mode. Use only with jpeg
|
||||||
|
};
|
||||||
|
|
||||||
|
camera_config_t esp32cam_aithinker_config{
|
||||||
|
|
||||||
|
.pin_pwdn = 32,
|
||||||
|
.pin_reset = -1,
|
||||||
|
|
||||||
|
.pin_xclk = 0,
|
||||||
|
|
||||||
|
.pin_sscb_sda = 26,
|
||||||
|
.pin_sscb_scl = 27,
|
||||||
|
|
||||||
|
// Note: LED GPIO is apparently 4 not sure where that goes
|
||||||
|
// per https://github.com/donny681/ESP32_CAMERA_QR/blob/e4ef44549876457cd841f33a0892c82a71f35358/main/led.c
|
||||||
|
.pin_d7 = 35,
|
||||||
|
.pin_d6 = 34,
|
||||||
|
.pin_d5 = 39,
|
||||||
|
.pin_d4 = 36,
|
||||||
|
.pin_d3 = 21,
|
||||||
|
.pin_d2 = 19,
|
||||||
|
.pin_d1 = 18,
|
||||||
|
.pin_d0 = 5,
|
||||||
|
.pin_vsync = 25,
|
||||||
|
.pin_href = 23,
|
||||||
|
.pin_pclk = 22,
|
||||||
|
.xclk_freq_hz = 20000000,
|
||||||
|
.ledc_timer = LEDC_TIMER_1,
|
||||||
|
.ledc_channel = LEDC_CHANNEL_1,
|
||||||
|
.pixel_format = PIXFORMAT_JPEG,
|
||||||
|
// .frame_size = FRAMESIZE_UXGA, // needs 234K of framebuffer space
|
||||||
|
// .frame_size = FRAMESIZE_SXGA, // needs 160K for framebuffer
|
||||||
|
// .frame_size = FRAMESIZE_XGA, // needs 96K or even smaller FRAMESIZE_SVGA - can work if using only 1 fb
|
||||||
|
.frame_size = FRAMESIZE_SVGA,
|
||||||
|
.jpeg_quality = 12, //0-63 lower numbers are higher quality
|
||||||
|
.fb_count = 2 // if more than one i2s runs in continous mode. Use only with jpeg
|
||||||
|
};
|
||||||
|
|
||||||
|
camera_config_t esp32cam_ttgo_t_config{
|
||||||
|
|
||||||
|
.pin_pwdn = 26,
|
||||||
|
.pin_reset = -1,
|
||||||
|
|
||||||
|
.pin_xclk = 32,
|
||||||
|
|
||||||
|
.pin_sscb_sda = 13,
|
||||||
|
.pin_sscb_scl = 12,
|
||||||
|
|
||||||
|
.pin_d7 = 39,
|
||||||
|
.pin_d6 = 36,
|
||||||
|
.pin_d5 = 23,
|
||||||
|
.pin_d4 = 18,
|
||||||
|
.pin_d3 = 15,
|
||||||
|
.pin_d2 = 4,
|
||||||
|
.pin_d1 = 14,
|
||||||
|
.pin_d0 = 5,
|
||||||
|
.pin_vsync = 27,
|
||||||
|
.pin_href = 25,
|
||||||
|
.pin_pclk = 19,
|
||||||
|
.xclk_freq_hz = 20000000,
|
||||||
|
.ledc_timer = LEDC_TIMER_0,
|
||||||
|
.ledc_channel = LEDC_CHANNEL_0,
|
||||||
|
.pixel_format = PIXFORMAT_JPEG,
|
||||||
|
.frame_size = FRAMESIZE_SVGA,
|
||||||
|
.jpeg_quality = 12, //0-63 lower numbers are higher quality
|
||||||
|
.fb_count = 2 // if more than one i2s runs in continous mode. Use only with jpeg
|
||||||
|
};
|
||||||
|
|
||||||
|
void OV2640::run(void)
|
||||||
|
{
|
||||||
|
if (fb)
|
||||||
|
//return the frame buffer back to the driver for reuse
|
||||||
|
esp_camera_fb_return(fb);
|
||||||
|
|
||||||
|
fb = esp_camera_fb_get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OV2640::runIfNeeded(void)
|
||||||
|
{
|
||||||
|
if (!fb)
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
|
||||||
|
int OV2640::getWidth(void)
|
||||||
|
{
|
||||||
|
runIfNeeded();
|
||||||
|
return fb->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OV2640::getHeight(void)
|
||||||
|
{
|
||||||
|
runIfNeeded();
|
||||||
|
return fb->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t OV2640::getSize(void)
|
||||||
|
{
|
||||||
|
runIfNeeded();
|
||||||
|
if (!fb)
|
||||||
|
return 0; // FIXME - this shouldn't be possible but apparently the new cam board returns null sometimes?
|
||||||
|
return fb->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *OV2640::getfb(void)
|
||||||
|
{
|
||||||
|
runIfNeeded();
|
||||||
|
if (!fb)
|
||||||
|
return NULL; // FIXME - this shouldn't be possible but apparently the new cam board returns null sometimes?
|
||||||
|
|
||||||
|
return fb->buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
framesize_t OV2640::getFrameSize(void)
|
||||||
|
{
|
||||||
|
return _cam_config.frame_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OV2640::setFrameSize(framesize_t size)
|
||||||
|
{
|
||||||
|
_cam_config.frame_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixformat_t OV2640::getPixelFormat(void)
|
||||||
|
{
|
||||||
|
return _cam_config.pixel_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OV2640::setPixelFormat(pixformat_t format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case PIXFORMAT_RGB565:
|
||||||
|
case PIXFORMAT_YUV422:
|
||||||
|
case PIXFORMAT_GRAYSCALE:
|
||||||
|
case PIXFORMAT_JPEG:
|
||||||
|
_cam_config.pixel_format = format;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_cam_config.pixel_format = PIXFORMAT_GRAYSCALE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t OV2640::init(camera_config_t config)
|
||||||
|
{
|
||||||
|
memset(&_cam_config, 0, sizeof(_cam_config));
|
||||||
|
memcpy(&_cam_config, &config, sizeof(config));
|
||||||
|
|
||||||
|
esp_err_t err = esp_camera_init(&_cam_config);
|
||||||
|
if (err != ESP_OK)
|
||||||
|
{
|
||||||
|
printf("Camera probe failed with error 0x%x", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
// ESP_ERROR_CHECK(gpio_install_isr_service(0));
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef OV2640_H_
|
||||||
|
#define OV2640_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <pgmspace.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "esp_camera.h"
|
||||||
|
|
||||||
|
extern camera_config_t esp32cam_config, esp32cam_aithinker_config, esp32cam_ttgo_t_config;
|
||||||
|
|
||||||
|
class OV2640
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OV2640(){
|
||||||
|
fb = NULL;
|
||||||
|
};
|
||||||
|
~OV2640(){
|
||||||
|
};
|
||||||
|
esp_err_t init(camera_config_t config);
|
||||||
|
void run(void);
|
||||||
|
size_t getSize(void);
|
||||||
|
uint8_t *getfb(void);
|
||||||
|
int getWidth(void);
|
||||||
|
int getHeight(void);
|
||||||
|
framesize_t getFrameSize(void);
|
||||||
|
pixformat_t getPixelFormat(void);
|
||||||
|
|
||||||
|
void setFrameSize(framesize_t size);
|
||||||
|
void setPixelFormat(pixformat_t format);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void runIfNeeded(); // grab a frame if we don't already have one
|
||||||
|
|
||||||
|
// camera_framesize_t _frame_size;
|
||||||
|
// camera_pixelformat_t _pixel_format;
|
||||||
|
camera_config_t _cam_config;
|
||||||
|
|
||||||
|
camera_fb_t *fb;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //OV2640_H_
|
Loading…
Reference in new issue