mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-29 13:46:37 +00:00
Refactor webcam
This commit is contained in:
parent
cd081c5521
commit
7078466e7c
@ -630,10 +630,10 @@ void send_message_txt(char *txt) {
|
|||||||
uint32_t cnt;
|
uint32_t cnt;
|
||||||
uint8_t *buff;
|
uint8_t *buff;
|
||||||
uint32_t len,picmax;
|
uint32_t len,picmax;
|
||||||
picmax=get_picstore(-1,0);
|
picmax=WcGetPicstore(-1,0);
|
||||||
cnt=*txt&7;
|
cnt=*txt&7;
|
||||||
if (cnt<1 || cnt>picmax) cnt=1;
|
if (cnt<1 || cnt>picmax) cnt=1;
|
||||||
len=get_picstore(cnt-1,&buff);
|
len=WcGetPicstore(cnt-1,&buff);
|
||||||
if (len) {
|
if (len) {
|
||||||
char str[12];
|
char str[12];
|
||||||
sprintf(str,"img_%1d.jpg",cnt+1);
|
sprintf(str,"img_%1d.jpg",cnt+1);
|
||||||
|
@ -1407,9 +1407,9 @@ chknext:
|
|||||||
if (ind>=SFS_MAX) ind=SFS_MAX-1;
|
if (ind>=SFS_MAX) ind=SFS_MAX-1;
|
||||||
if (glob_script_mem.file_flags[ind].is_open) {
|
if (glob_script_mem.file_flags[ind].is_open) {
|
||||||
uint8_t *buff;
|
uint8_t *buff;
|
||||||
float maxps=get_picstore(-1,0);
|
float maxps=WcGetPicstore(-1,0);
|
||||||
if (fvar<1 || fvar>maxps) fvar=1;
|
if (fvar<1 || fvar>maxps) fvar=1;
|
||||||
uint32_t len=get_picstore(fvar-1, &buff);
|
uint32_t len=WcGetPicstore(fvar-1, &buff);
|
||||||
if (len) {
|
if (len) {
|
||||||
//glob_script_mem.files[ind].seek(0,SeekEnd);
|
//glob_script_mem.files[ind].seek(0,SeekEnd);
|
||||||
fvar=glob_script_mem.files[ind].write(buff,len);
|
fvar=glob_script_mem.files[ind].write(buff,len);
|
||||||
@ -2056,13 +2056,13 @@ chknext:
|
|||||||
case 0:
|
case 0:
|
||||||
{ float fvar2;
|
{ float fvar2;
|
||||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||||
fvar=wc_setup(fvar2);
|
fvar=WcSetup(fvar2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
{ float fvar2;
|
{ float fvar2;
|
||||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||||
fvar=wc_get_frame(fvar2);
|
fvar=WcGetFrame(fvar2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
@ -2070,32 +2070,32 @@ chknext:
|
|||||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||||
SCRIPT_SKIP_SPACES
|
SCRIPT_SKIP_SPACES
|
||||||
lp=GetNumericResult(lp,OPER_EQU,&fvar3,0);
|
lp=GetNumericResult(lp,OPER_EQU,&fvar3,0);
|
||||||
fvar=wc_set_options(fvar2,fvar3);
|
fvar=WcSetOptions(fvar2,fvar3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
fvar=wc_get_width();
|
fvar=WcGetWidth();
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
fvar=wc_get_height();
|
fvar=WcGetHeight();
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
{ float fvar2;
|
{ float fvar2;
|
||||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||||
fvar=wc_set_streamserver(fvar2);
|
fvar=WcSetStreamserver(fvar2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
{ float fvar2;
|
{ float fvar2;
|
||||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||||
fvar=wc_set_motion_detect(fvar2);
|
fvar=WcSetMotionDetect(fvar2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef USE_FACE_DETECT
|
#ifdef USE_FACE_DETECT
|
||||||
case 7:
|
case 7:
|
||||||
{ float fvar2;
|
{ float fvar2;
|
||||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||||
fvar=wc_set_face_detect(fvar2);
|
fvar=WcSetFaceDetect(fvar2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,25 +25,25 @@
|
|||||||
* Template as used on ESP32-CAM WiFi + bluetooth Camera Module Development Board ESP32 With Camera Module OV2640 Geekcreit for Arduino
|
* Template as used on ESP32-CAM WiFi + bluetooth Camera Module Development Board ESP32 With Camera Module OV2640 Geekcreit for Arduino
|
||||||
* {"NAME":"AITHINKER CAM No SPI","GPIO":[4992,65504,65504,65504,65504,5088,65504,65504,65504,65504,65504,65504,65504,65504,5089,5090,0,5091,5184,5152,0,5120,5024,5056,0,0,0,0,4928,65504,5094,5095,5092,0,0,5093],"FLAG":0,"BASE":1}
|
* {"NAME":"AITHINKER CAM No SPI","GPIO":[4992,65504,65504,65504,65504,5088,65504,65504,65504,65504,65504,65504,65504,65504,5089,5090,0,5091,5184,5152,0,5120,5024,5056,0,0,0,0,4928,65504,5094,5095,5092,0,0,5093],"FLAG":0,"BASE":1}
|
||||||
*
|
*
|
||||||
* Command: prefix = WC
|
* Supported commands:
|
||||||
* Stream = 1,0 => start, stop streaming
|
* WcStream = Control streaming, 0 = stop, 1 = start
|
||||||
* Resolution = 0 .. 10 => set resolution
|
* WcResolution = Set resolution
|
||||||
* 0 = FRAMESIZE_96x96, (96x96)
|
* 0 = FRAMESIZE_96x96, (96x96)
|
||||||
* 1 = FRAMESIZE_QQVGA2 (128x160)
|
* 1 = FRAMESIZE_QQVGA2 (128x160)
|
||||||
* 2 = FRAMESIZE_QCIF (176x144)
|
* 2 = FRAMESIZE_QCIF (176x144)
|
||||||
* 3 = FRAMESIZE_HQVGA (240x176)
|
* 3 = FRAMESIZE_HQVGA (240x176)
|
||||||
* 4 = FRAMESIZE_QVGA (320x240)
|
* 4 = FRAMESIZE_QVGA (320x240)
|
||||||
* 5 = FRAMESIZE_CIF (400x296)
|
* 5 = FRAMESIZE_CIF (400x296)
|
||||||
* 6 = FRAMESIZE_VGA (640x480)
|
* 6 = FRAMESIZE_VGA (640x480)
|
||||||
* 7 = FRAMESIZE_SVGA (800x600)
|
* 7 = FRAMESIZE_SVGA (800x600)
|
||||||
* 8 = FRAMESIZE_XGA (1024x768)
|
* 8 = FRAMESIZE_XGA (1024x768)
|
||||||
* 9 = FRAMESIZE_SXGA (1280x1024)
|
* 9 = FRAMESIZE_SXGA (1280x1024)
|
||||||
* 10 = FRAMESIZE_UXGA (1600x1200)
|
* 10 = FRAMESIZE_UXGA (1600x1200)
|
||||||
* Mirror = 1,0 => mirror picture on,off
|
* WcMirror = Mirror picture, 0 = no, 1 = yes
|
||||||
* Flip = 1,0 => Flip picture on,off
|
* WcFlip = Flip picture, 0 = no, 1 = yes
|
||||||
* Saturation = -2 ... +2 => set picture Saturation
|
* WcSaturation = Set picture Saturation -2 ... +2
|
||||||
* Brightness = -2 ... +2 => set picture Brightness
|
* WcBrightness = Set picture Brightness -2 ... +2
|
||||||
* Contrast = -2 ... +2 => set picture Contrast
|
* WcContrast = Set picture Contrast -2 ... +2
|
||||||
*
|
*
|
||||||
* Only boards with PSRAM should be used. To enable PSRAM board should be se set to esp32cam in common32 of platform_override.ini
|
* Only boards with PSRAM should be used. To enable PSRAM board should be se set to esp32cam in common32 of platform_override.ini
|
||||||
* board = esp32cam
|
* board = esp32cam
|
||||||
@ -60,13 +60,20 @@
|
|||||||
|
|
||||||
#define XDRV_81 81
|
#define XDRV_81 81
|
||||||
|
|
||||||
|
#include "esp_camera.h"
|
||||||
#define WC_LOGLEVEL LOG_LEVEL_INFO
|
#include "sensor.h"
|
||||||
|
|
||||||
#include "fb_gfx.h"
|
#include "fb_gfx.h"
|
||||||
#include "fd_forward.h"
|
#include "fd_forward.h"
|
||||||
#include "fr_forward.h"
|
#include "fr_forward.h"
|
||||||
|
|
||||||
|
bool HttpCheckPriviledgedAccess(bool);
|
||||||
|
extern ESP8266WebServer *Webserver;
|
||||||
|
|
||||||
|
ESP8266WebServer *CamServer;
|
||||||
|
#define BOUNDARY "e8b8c539-047d-4777-a985-fbba6edff11e"
|
||||||
|
|
||||||
|
WiFiClient client;
|
||||||
|
|
||||||
|
|
||||||
// CAMERA_MODEL_AI_THINKER default template pins
|
// CAMERA_MODEL_AI_THINKER default template pins
|
||||||
#define PWDN_GPIO_NUM 32
|
#define PWDN_GPIO_NUM 32
|
||||||
@ -87,10 +94,6 @@
|
|||||||
#define HREF_GPIO_NUM 23
|
#define HREF_GPIO_NUM 23
|
||||||
#define PCLK_GPIO_NUM 22
|
#define PCLK_GPIO_NUM 22
|
||||||
|
|
||||||
|
|
||||||
#include "esp_camera.h"
|
|
||||||
#include "sensor.h"
|
|
||||||
|
|
||||||
uint8_t wc_up;
|
uint8_t wc_up;
|
||||||
uint16_t wc_width;
|
uint16_t wc_width;
|
||||||
uint16_t wc_height;
|
uint16_t wc_height;
|
||||||
@ -100,6 +103,8 @@ uint8_t faces;
|
|||||||
uint16_t face_detect_time;
|
uint16_t face_detect_time;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
bool WcPinUsed(void) {
|
bool WcPinUsed(void) {
|
||||||
bool pin_used = true;
|
bool pin_used = true;
|
||||||
for (uint32_t i = 0; i < MAX_WEBCAM_DATA; i++) {
|
for (uint32_t i = 0; i < MAX_WEBCAM_DATA; i++) {
|
||||||
@ -120,7 +125,7 @@ bool WcPinUsed(void) {
|
|||||||
return pin_used;
|
return pin_used;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t wc_setup(int32_t fsiz) {
|
uint32_t WcSetup(int32_t fsiz) {
|
||||||
if (fsiz > 10) { fsiz = 10; }
|
if (fsiz > 10) { fsiz = 10; }
|
||||||
|
|
||||||
wc_stream_active = 0;
|
wc_stream_active = 0;
|
||||||
@ -133,7 +138,7 @@ uint32_t wc_setup(int32_t fsiz) {
|
|||||||
|
|
||||||
if (wc_up) {
|
if (wc_up) {
|
||||||
esp_camera_deinit();
|
esp_camera_deinit();
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: deinit"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Deinit"));
|
||||||
//return wc_up;
|
//return wc_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +170,7 @@ uint32_t wc_setup(int32_t fsiz) {
|
|||||||
config.pin_pwdn = (PinUsed(GPIO_WEBCAM_PWDN)) ? Pin(GPIO_WEBCAM_PWDN) : -1; // PWDN_GPIO_NUM;
|
config.pin_pwdn = (PinUsed(GPIO_WEBCAM_PWDN)) ? Pin(GPIO_WEBCAM_PWDN) : -1; // PWDN_GPIO_NUM;
|
||||||
config.pin_reset = (PinUsed(GPIO_WEBCAM_RESET)) ? Pin(GPIO_WEBCAM_RESET) : -1; // RESET_GPIO_NUM;
|
config.pin_reset = (PinUsed(GPIO_WEBCAM_RESET)) ? Pin(GPIO_WEBCAM_RESET) : -1; // RESET_GPIO_NUM;
|
||||||
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: User template"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: User template"));
|
||||||
} else {
|
} else {
|
||||||
// defaults to AI THINKER
|
// defaults to AI THINKER
|
||||||
config.pin_d0 = Y2_GPIO_NUM;
|
config.pin_d0 = Y2_GPIO_NUM;
|
||||||
@ -184,7 +189,7 @@ uint32_t wc_setup(int32_t fsiz) {
|
|||||||
config.pin_sscb_scl = SIOC_GPIO_NUM;
|
config.pin_sscb_scl = SIOC_GPIO_NUM;
|
||||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||||
config.pin_reset = RESET_GPIO_NUM;
|
config.pin_reset = RESET_GPIO_NUM;
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Default template"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Default template"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//ESP.getPsramSize()
|
//ESP.getPsramSize()
|
||||||
@ -200,12 +205,12 @@ uint32_t wc_setup(int32_t fsiz) {
|
|||||||
config.frame_size = FRAMESIZE_UXGA;
|
config.frame_size = FRAMESIZE_UXGA;
|
||||||
config.jpeg_quality = 10;
|
config.jpeg_quality = 10;
|
||||||
config.fb_count = 2;
|
config.fb_count = 2;
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: PSRAM found"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: PSRAM found"));
|
||||||
} else {
|
} else {
|
||||||
config.frame_size = FRAMESIZE_VGA;
|
config.frame_size = FRAMESIZE_VGA;
|
||||||
config.jpeg_quality = 12;
|
config.jpeg_quality = 12;
|
||||||
config.fb_count = 1;
|
config.fb_count = 1;
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: PSRAM not found"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: PSRAM not found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// stupid workaround camera diver eats up static ram should prefer PSRAM
|
// stupid workaround camera diver eats up static ram should prefer PSRAM
|
||||||
@ -218,7 +223,7 @@ uint32_t wc_setup(int32_t fsiz) {
|
|||||||
if (x) { free(x); }
|
if (x) { free(x); }
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Init failed with error 0x%x"), err);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Init failed with error 0x%x"), err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +247,7 @@ uint32_t wc_setup(int32_t fsiz) {
|
|||||||
fd_init();
|
fd_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Initialized"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Initialized"));
|
||||||
|
|
||||||
wc_up = 1;
|
wc_up = 1;
|
||||||
if (psram) { wc_up=2; }
|
if (psram) { wc_up=2; }
|
||||||
@ -250,7 +255,9 @@ uint32_t wc_setup(int32_t fsiz) {
|
|||||||
return wc_up;
|
return wc_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t wc_set_options(uint32_t sel, int32_t value) {
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
int32_t WcSetOptions(uint32_t sel, int32_t value) {
|
||||||
int32_t res = 0;
|
int32_t res = 0;
|
||||||
sensor_t *s = esp_camera_sensor_get();
|
sensor_t *s = esp_camera_sensor_get();
|
||||||
if (!s) { return -99; }
|
if (!s) { return -99; }
|
||||||
@ -289,7 +296,7 @@ int32_t wc_set_options(uint32_t sel, int32_t value) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t wc_get_width(void) {
|
uint32_t WcGetWidth(void) {
|
||||||
camera_fb_t *wc_fb = esp_camera_fb_get();
|
camera_fb_t *wc_fb = esp_camera_fb_get();
|
||||||
if (!wc_fb) { return 0; }
|
if (!wc_fb) { return 0; }
|
||||||
wc_width = wc_fb->width;
|
wc_width = wc_fb->width;
|
||||||
@ -297,7 +304,7 @@ uint32_t wc_get_width(void) {
|
|||||||
return wc_width;
|
return wc_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t wc_get_height(void) {
|
uint32_t WcGetHeight(void) {
|
||||||
camera_fb_t *wc_fb = esp_camera_fb_get();
|
camera_fb_t *wc_fb = esp_camera_fb_get();
|
||||||
if (!wc_fb) { return 0; }
|
if (!wc_fb) { return 0; }
|
||||||
wc_height = wc_fb->height;
|
wc_height = wc_fb->height;
|
||||||
@ -305,199 +312,69 @@ uint32_t wc_get_height(void) {
|
|||||||
return wc_height;
|
return wc_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MAX_PICSTORE
|
/*********************************************************************************************/
|
||||||
#define MAX_PICSTORE 4
|
|
||||||
#endif
|
|
||||||
struct PICSTORE {
|
|
||||||
uint8_t *buff;
|
|
||||||
uint32_t len;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PICSTORE picstore[MAX_PICSTORE];
|
uint16_t motion_detect;
|
||||||
|
uint32_t motion_ltime;
|
||||||
|
uint32_t motion_trigger;
|
||||||
|
uint32_t motion_brightness;
|
||||||
|
uint8_t *last_motion_buffer;
|
||||||
|
|
||||||
#ifdef COPYFRAME
|
uint32_t WcSetMotionDetect(int32_t value) {
|
||||||
struct PICSTORE tmp_picstore;
|
if (value >= 0) { motion_detect = value; }
|
||||||
#endif
|
if (-1 == value) {
|
||||||
|
return motion_trigger;
|
||||||
uint32_t get_picstore(int32_t num, uint8_t **buff) {
|
} else {
|
||||||
if (num<0) { return MAX_PICSTORE; }
|
return motion_brightness;
|
||||||
*buff = picstore[num].buff;
|
}
|
||||||
return picstore[num].len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t wc_get_frame(int32_t bnum) {
|
// optional motion detector
|
||||||
size_t _jpg_buf_len = 0;
|
void WcDetectMotion(void) {
|
||||||
uint8_t * _jpg_buf = NULL;
|
camera_fb_t *wc_fb;
|
||||||
camera_fb_t *wc_fb = 0;
|
uint8_t *out_buf = 0;
|
||||||
bool jpeg_converted = false;
|
|
||||||
|
|
||||||
if (bnum < 0) {
|
if ((millis()-motion_ltime) > motion_detect) {
|
||||||
if (bnum < -MAX_PICSTORE) { bnum=-1; }
|
motion_ltime = millis();
|
||||||
bnum = -bnum;
|
|
||||||
bnum--;
|
|
||||||
if (picstore[bnum].buff) { free(picstore[bnum].buff); }
|
|
||||||
picstore[bnum].len = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef COPYFRAME
|
|
||||||
if (bnum & 0x10) {
|
|
||||||
bnum &= 0xf;
|
|
||||||
_jpg_buf = tmp_picstore.buff;
|
|
||||||
_jpg_buf_len = tmp_picstore.len;
|
|
||||||
if (!_jpg_buf_len) { return 0; }
|
|
||||||
goto pcopy;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
wc_fb = esp_camera_fb_get();
|
|
||||||
if (!wc_fb) {
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Can't get frame"));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!bnum) {
|
|
||||||
wc_width = wc_fb->width;
|
|
||||||
wc_height = wc_fb->height;
|
|
||||||
esp_camera_fb_return(wc_fb);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wc_fb->format != PIXFORMAT_JPEG) {
|
|
||||||
jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
|
||||||
if (!jpeg_converted){
|
|
||||||
//Serial.println("JPEG compression failed");
|
|
||||||
_jpg_buf_len = wc_fb->len;
|
|
||||||
_jpg_buf = wc_fb->buf;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_jpg_buf_len = wc_fb->len;
|
|
||||||
_jpg_buf = wc_fb->buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
pcopy:
|
|
||||||
if ((bnum < 1) || (bnum > MAX_PICSTORE)) { bnum = 1; }
|
|
||||||
bnum--;
|
|
||||||
if (picstore[bnum].buff) { free(picstore[bnum].buff); }
|
|
||||||
picstore[bnum].buff = (uint8_t *)heap_caps_malloc(_jpg_buf_len+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
|
||||||
if (picstore[bnum].buff) {
|
|
||||||
memcpy(picstore[bnum].buff, _jpg_buf, _jpg_buf_len);
|
|
||||||
picstore[bnum].len = _jpg_buf_len;
|
|
||||||
} else {
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Can't allocate picstore"));
|
|
||||||
picstore[bnum].len = 0;
|
|
||||||
}
|
|
||||||
if (wc_fb) { esp_camera_fb_return(wc_fb); }
|
|
||||||
if (jpeg_converted) { free(_jpg_buf); }
|
|
||||||
if (!picstore[bnum].buff) { return 0; }
|
|
||||||
|
|
||||||
return _jpg_buf_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HttpCheckPriviledgedAccess(bool);
|
|
||||||
extern ESP8266WebServer *Webserver;
|
|
||||||
|
|
||||||
void HandleImage(void) {
|
|
||||||
if (!HttpCheckPriviledgedAccess(true)) { return; }
|
|
||||||
|
|
||||||
uint32_t bnum = Webserver->arg(F("p")).toInt();
|
|
||||||
if ((bnum < 0) || (bnum > MAX_PICSTORE)) { bnum= 1; }
|
|
||||||
WiFiClient client = Webserver->client();
|
|
||||||
String response = "HTTP/1.1 200 OK\r\n";
|
|
||||||
response += "Content-disposition: inline; filename=cap.jpg\r\n";
|
|
||||||
response += "Content-type: image/jpeg\r\n\r\n";
|
|
||||||
Webserver->sendContent(response);
|
|
||||||
|
|
||||||
if (!bnum) {
|
|
||||||
size_t _jpg_buf_len = 0;
|
|
||||||
uint8_t * _jpg_buf = NULL;
|
|
||||||
camera_fb_t *wc_fb = 0;
|
|
||||||
wc_fb = esp_camera_fb_get();
|
wc_fb = esp_camera_fb_get();
|
||||||
if (!wc_fb) { return; }
|
if (!wc_fb) { return; }
|
||||||
if (wc_fb->format != PIXFORMAT_JPEG) {
|
|
||||||
bool jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
if (!last_motion_buffer) {
|
||||||
if (!jpeg_converted) {
|
last_motion_buffer=(uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
_jpg_buf_len = wc_fb->len;
|
}
|
||||||
_jpg_buf = wc_fb->buf;
|
if (last_motion_buffer) {
|
||||||
|
if (PIXFORMAT_JPEG == wc_fb->format) {
|
||||||
|
out_buf = (uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height*3)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
|
if (out_buf) {
|
||||||
|
fmt2rgb888(wc_fb->buf, wc_fb->len, wc_fb->format, out_buf);
|
||||||
|
uint32_t x, y;
|
||||||
|
uint8_t *pxi = out_buf;
|
||||||
|
uint8_t *pxr = last_motion_buffer;
|
||||||
|
// convert to bw
|
||||||
|
uint64_t accu = 0;
|
||||||
|
uint64_t bright = 0;
|
||||||
|
for (y = 0; y < wc_fb->height; y++) {
|
||||||
|
for (x = 0; x < wc_fb->width; x++) {
|
||||||
|
int32_t gray = (pxi[0] + pxi[1] + pxi[2]) / 3;
|
||||||
|
int32_t lgray = pxr[0];
|
||||||
|
pxr[0] = gray;
|
||||||
|
pxi += 3;
|
||||||
|
pxr++;
|
||||||
|
accu += abs(gray - lgray);
|
||||||
|
bright += gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
motion_trigger = accu / ((wc_fb->height * wc_fb->width) / 100);
|
||||||
|
motion_brightness = bright / ((wc_fb->height * wc_fb->width) / 100);
|
||||||
|
free(out_buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
_jpg_buf_len = wc_fb->len;
|
|
||||||
_jpg_buf = wc_fb->buf;
|
|
||||||
}
|
}
|
||||||
if (_jpg_buf_len) {
|
esp_camera_fb_return(wc_fb);
|
||||||
client.write((char *)_jpg_buf, _jpg_buf_len);
|
|
||||||
}
|
|
||||||
if (wc_fb) { esp_camera_fb_return(wc_fb); }
|
|
||||||
} else {
|
|
||||||
bnum--;
|
|
||||||
if (!picstore[bnum].len) {
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: No image #: %d"), bnum);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
client.write((char *)picstore[bnum].buff, picstore[bnum].len);
|
|
||||||
}
|
}
|
||||||
client.stop();
|
|
||||||
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Sending image #: %d"), bnum+1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP8266WebServer *CamServer;
|
/*********************************************************************************************/
|
||||||
#define BOUNDARY "e8b8c539-047d-4777-a985-fbba6edff11e"
|
|
||||||
|
|
||||||
WiFiClient client;
|
|
||||||
|
|
||||||
void handleMjpeg(void) {
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Handle camserver"));
|
|
||||||
// if (!wc_stream_active) {
|
|
||||||
// always restart stream
|
|
||||||
wc_stream_active = 1;
|
|
||||||
client = CamServer->client();
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Create client"));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleImageTheo(void) {
|
|
||||||
if (!HttpCheckPriviledgedAccess(true)) { return; }
|
|
||||||
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Capture image"));
|
|
||||||
|
|
||||||
if (Settings.webcam_config.stream) {
|
|
||||||
if (!CamServer) {
|
|
||||||
WcStreamControl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
camera_fb_t *wc_fb;
|
|
||||||
wc_fb = esp_camera_fb_get(); // Acquire frame
|
|
||||||
if (!wc_fb) {
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Frame buffer could not be acquired"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t _jpg_buf_len = 0;
|
|
||||||
uint8_t * _jpg_buf = NULL;
|
|
||||||
if (wc_fb->format != PIXFORMAT_JPEG) {
|
|
||||||
bool jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
|
||||||
if (!jpeg_converted) {
|
|
||||||
_jpg_buf_len = wc_fb->len;
|
|
||||||
_jpg_buf = wc_fb->buf;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_jpg_buf_len = wc_fb->len;
|
|
||||||
_jpg_buf = wc_fb->buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_jpg_buf_len) {
|
|
||||||
Webserver->client().flush();
|
|
||||||
WSHeaderSend();
|
|
||||||
Webserver->sendHeader(F("Content-disposition"), F("inline; filename=cap.jpg"));
|
|
||||||
Webserver->send_P(200, "image/jpeg", (char *)_jpg_buf, _jpg_buf_len);
|
|
||||||
Webserver->client().stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_camera_fb_return(wc_fb); // Free frame buffer
|
|
||||||
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Image sent"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_FACE_DETECT
|
#ifdef USE_FACE_DETECT
|
||||||
|
|
||||||
@ -569,23 +446,23 @@ void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_
|
|||||||
|
|
||||||
#define DL_SPIRAM_SUPPORT
|
#define DL_SPIRAM_SUPPORT
|
||||||
|
|
||||||
uint32_t wc_set_face_detect(int32_t value) {
|
uint32_t WcSetFaceDetect(int32_t value) {
|
||||||
if (value >= 0) { face_detect_time = value; }
|
if (value >= 0) { face_detect_time = value; }
|
||||||
return faces;
|
return faces;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t face_ltime;
|
uint32_t face_ltime;
|
||||||
|
|
||||||
uint32_t detect_face(void);
|
uint32_t WcDetectFace(void);
|
||||||
|
|
||||||
uint32_t detect_face(void) {
|
uint32_t WcDetectFace(void) {
|
||||||
dl_matrix3du_t *image_matrix;
|
dl_matrix3du_t *image_matrix;
|
||||||
size_t out_len, out_width, out_height;
|
size_t out_len, out_width, out_height;
|
||||||
uint8_t * out_buf;
|
uint8_t * out_buf;
|
||||||
bool s;
|
bool s;
|
||||||
bool detected = false;
|
bool detected = false;
|
||||||
int face_id = 0;
|
int face_id = 0;
|
||||||
camera_fb_t *fb;
|
camera_fb_t *fb;
|
||||||
|
|
||||||
if ((millis() - face_ltime) > face_detect_time) {
|
if ((millis() - face_ltime) > face_detect_time) {
|
||||||
face_ltime = millis();
|
face_ltime = millis();
|
||||||
@ -594,7 +471,7 @@ camera_fb_t *fb;
|
|||||||
|
|
||||||
image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
|
image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
|
||||||
if (!image_matrix) {
|
if (!image_matrix) {
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: dl_matrix3du_alloc failed"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: dl_matrix3du_alloc failed"));
|
||||||
esp_camera_fb_return(fb);
|
esp_camera_fb_return(fb);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
@ -608,7 +485,7 @@ camera_fb_t *fb;
|
|||||||
esp_camera_fb_return(fb);
|
esp_camera_fb_return(fb);
|
||||||
if (!s){
|
if (!s){
|
||||||
dl_matrix3du_free(image_matrix);
|
dl_matrix3du_free(image_matrix);
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: to rgb888 failed"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: to rgb888 failed"));
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -634,7 +511,195 @@ camera_fb_t *fb;
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void handleMjpeg_task(void) {
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAX_PICSTORE
|
||||||
|
#define MAX_PICSTORE 4
|
||||||
|
#endif
|
||||||
|
struct PICSTORE {
|
||||||
|
uint8_t *buff;
|
||||||
|
uint32_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PICSTORE picstore[MAX_PICSTORE];
|
||||||
|
|
||||||
|
#ifdef COPYFRAME
|
||||||
|
struct PICSTORE tmp_picstore;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t WcGetPicstore(int32_t num, uint8_t **buff) {
|
||||||
|
if (num<0) { return MAX_PICSTORE; }
|
||||||
|
*buff = picstore[num].buff;
|
||||||
|
return picstore[num].len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t WcGetFrame(int32_t bnum) {
|
||||||
|
size_t _jpg_buf_len = 0;
|
||||||
|
uint8_t * _jpg_buf = NULL;
|
||||||
|
camera_fb_t *wc_fb = 0;
|
||||||
|
bool jpeg_converted = false;
|
||||||
|
|
||||||
|
if (bnum < 0) {
|
||||||
|
if (bnum < -MAX_PICSTORE) { bnum=-1; }
|
||||||
|
bnum = -bnum;
|
||||||
|
bnum--;
|
||||||
|
if (picstore[bnum].buff) { free(picstore[bnum].buff); }
|
||||||
|
picstore[bnum].len = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef COPYFRAME
|
||||||
|
if (bnum & 0x10) {
|
||||||
|
bnum &= 0xf;
|
||||||
|
_jpg_buf = tmp_picstore.buff;
|
||||||
|
_jpg_buf_len = tmp_picstore.len;
|
||||||
|
if (!_jpg_buf_len) { return 0; }
|
||||||
|
goto pcopy;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wc_fb = esp_camera_fb_get();
|
||||||
|
if (!wc_fb) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Can't get frame"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!bnum) {
|
||||||
|
wc_width = wc_fb->width;
|
||||||
|
wc_height = wc_fb->height;
|
||||||
|
esp_camera_fb_return(wc_fb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wc_fb->format != PIXFORMAT_JPEG) {
|
||||||
|
jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||||
|
if (!jpeg_converted){
|
||||||
|
//Serial.println("JPEG compression failed");
|
||||||
|
_jpg_buf_len = wc_fb->len;
|
||||||
|
_jpg_buf = wc_fb->buf;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_jpg_buf_len = wc_fb->len;
|
||||||
|
_jpg_buf = wc_fb->buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcopy:
|
||||||
|
if ((bnum < 1) || (bnum > MAX_PICSTORE)) { bnum = 1; }
|
||||||
|
bnum--;
|
||||||
|
if (picstore[bnum].buff) { free(picstore[bnum].buff); }
|
||||||
|
picstore[bnum].buff = (uint8_t *)heap_caps_malloc(_jpg_buf_len+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
|
if (picstore[bnum].buff) {
|
||||||
|
memcpy(picstore[bnum].buff, _jpg_buf, _jpg_buf_len);
|
||||||
|
picstore[bnum].len = _jpg_buf_len;
|
||||||
|
} else {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Can't allocate picstore"));
|
||||||
|
picstore[bnum].len = 0;
|
||||||
|
}
|
||||||
|
if (wc_fb) { esp_camera_fb_return(wc_fb); }
|
||||||
|
if (jpeg_converted) { free(_jpg_buf); }
|
||||||
|
if (!picstore[bnum].buff) { return 0; }
|
||||||
|
|
||||||
|
return _jpg_buf_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleImage(void) {
|
||||||
|
if (!HttpCheckPriviledgedAccess()) { return; }
|
||||||
|
|
||||||
|
uint32_t bnum = Webserver->arg(F("p")).toInt();
|
||||||
|
if ((bnum < 0) || (bnum > MAX_PICSTORE)) { bnum= 1; }
|
||||||
|
WiFiClient client = Webserver->client();
|
||||||
|
String response = "HTTP/1.1 200 OK\r\n";
|
||||||
|
response += "Content-disposition: inline; filename=cap.jpg\r\n";
|
||||||
|
response += "Content-type: image/jpeg\r\n\r\n";
|
||||||
|
Webserver->sendContent(response);
|
||||||
|
|
||||||
|
if (!bnum) {
|
||||||
|
size_t _jpg_buf_len = 0;
|
||||||
|
uint8_t * _jpg_buf = NULL;
|
||||||
|
camera_fb_t *wc_fb = 0;
|
||||||
|
wc_fb = esp_camera_fb_get();
|
||||||
|
if (!wc_fb) { return; }
|
||||||
|
if (wc_fb->format != PIXFORMAT_JPEG) {
|
||||||
|
bool jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||||
|
if (!jpeg_converted) {
|
||||||
|
_jpg_buf_len = wc_fb->len;
|
||||||
|
_jpg_buf = wc_fb->buf;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_jpg_buf_len = wc_fb->len;
|
||||||
|
_jpg_buf = wc_fb->buf;
|
||||||
|
}
|
||||||
|
if (_jpg_buf_len) {
|
||||||
|
client.write((char *)_jpg_buf, _jpg_buf_len);
|
||||||
|
}
|
||||||
|
if (wc_fb) { esp_camera_fb_return(wc_fb); }
|
||||||
|
} else {
|
||||||
|
bnum--;
|
||||||
|
if (!picstore[bnum].len) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: No image #: %d"), bnum);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
client.write((char *)picstore[bnum].buff, picstore[bnum].len);
|
||||||
|
}
|
||||||
|
client.stop();
|
||||||
|
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Sending image #: %d"), bnum+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleImageBasic(void) {
|
||||||
|
if (!HttpCheckPriviledgedAccess()) { return; }
|
||||||
|
|
||||||
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Capture image"));
|
||||||
|
|
||||||
|
if (Settings.webcam_config.stream) {
|
||||||
|
if (!CamServer) {
|
||||||
|
WcStreamControl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
camera_fb_t *wc_fb;
|
||||||
|
wc_fb = esp_camera_fb_get(); // Acquire frame
|
||||||
|
if (!wc_fb) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Frame buffer could not be acquired"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t _jpg_buf_len = 0;
|
||||||
|
uint8_t * _jpg_buf = NULL;
|
||||||
|
if (wc_fb->format != PIXFORMAT_JPEG) {
|
||||||
|
bool jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||||
|
if (!jpeg_converted) {
|
||||||
|
_jpg_buf_len = wc_fb->len;
|
||||||
|
_jpg_buf = wc_fb->buf;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_jpg_buf_len = wc_fb->len;
|
||||||
|
_jpg_buf = wc_fb->buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_jpg_buf_len) {
|
||||||
|
Webserver->client().flush();
|
||||||
|
WSHeaderSend();
|
||||||
|
Webserver->sendHeader(F("Content-disposition"), F("inline; filename=snapshot.jpg"));
|
||||||
|
Webserver->send_P(200, "image/jpeg", (char *)_jpg_buf, _jpg_buf_len);
|
||||||
|
Webserver->client().stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_camera_fb_return(wc_fb); // Free frame buffer
|
||||||
|
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Image sent"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleWebcamMjpeg(void) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Handle camserver"));
|
||||||
|
// if (!wc_stream_active) {
|
||||||
|
// always restart stream
|
||||||
|
wc_stream_active = 1;
|
||||||
|
client = CamServer->client();
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Create client"));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleWebcamMjpegTask(void) {
|
||||||
camera_fb_t *wc_fb;
|
camera_fb_t *wc_fb;
|
||||||
size_t _jpg_buf_len = 0;
|
size_t _jpg_buf_len = 0;
|
||||||
uint8_t * _jpg_buf = NULL;
|
uint8_t * _jpg_buf = NULL;
|
||||||
@ -644,13 +709,13 @@ void handleMjpeg_task(void) {
|
|||||||
bool jpeg_converted = false;
|
bool jpeg_converted = false;
|
||||||
|
|
||||||
if (!client.connected()) {
|
if (!client.connected()) {
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Client fail"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Client fail"));
|
||||||
wc_stream_active = 0;
|
wc_stream_active = 0;
|
||||||
}
|
}
|
||||||
if (1 == wc_stream_active) {
|
if (1 == wc_stream_active) {
|
||||||
client.flush();
|
client.flush();
|
||||||
client.setTimeout(3);
|
client.setTimeout(3);
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Start stream"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Start stream"));
|
||||||
client.print("HTTP/1.1 200 OK\r\n"
|
client.print("HTTP/1.1 200 OK\r\n"
|
||||||
"Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n"
|
"Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n"
|
||||||
"\r\n");
|
"\r\n");
|
||||||
@ -659,7 +724,7 @@ void handleMjpeg_task(void) {
|
|||||||
if (2 == wc_stream_active) {
|
if (2 == wc_stream_active) {
|
||||||
wc_fb = esp_camera_fb_get();
|
wc_fb = esp_camera_fb_get();
|
||||||
if (!wc_fb) {
|
if (!wc_fb) {
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Frame fail"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Frame fail"));
|
||||||
wc_stream_active = 0;
|
wc_stream_active = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -667,7 +732,7 @@ void handleMjpeg_task(void) {
|
|||||||
if (wc_fb->format != PIXFORMAT_JPEG) {
|
if (wc_fb->format != PIXFORMAT_JPEG) {
|
||||||
jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||||
if (!jpeg_converted){
|
if (!jpeg_converted){
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: JPEG compression failed"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: JPEG compression failed"));
|
||||||
_jpg_buf_len = wc_fb->len;
|
_jpg_buf_len = wc_fb->len;
|
||||||
_jpg_buf = wc_fb->buf;
|
_jpg_buf = wc_fb->buf;
|
||||||
}
|
}
|
||||||
@ -684,7 +749,7 @@ void handleMjpeg_task(void) {
|
|||||||
if (tlen!=_jpg_buf_len) {
|
if (tlen!=_jpg_buf_len) {
|
||||||
esp_camera_fb_return(wc_fb);
|
esp_camera_fb_return(wc_fb);
|
||||||
wc_stream_active=0;
|
wc_stream_active=0;
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Send fail"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Send fail"));
|
||||||
}*/
|
}*/
|
||||||
client.print("\r\n--" BOUNDARY "\r\n");
|
client.print("\r\n--" BOUNDARY "\r\n");
|
||||||
|
|
||||||
@ -701,83 +766,25 @@ void handleMjpeg_task(void) {
|
|||||||
|
|
||||||
if (jpeg_converted) { free(_jpg_buf); }
|
if (jpeg_converted) { free(_jpg_buf); }
|
||||||
esp_camera_fb_return(wc_fb);
|
esp_camera_fb_return(wc_fb);
|
||||||
//AddLog_P2(WC_LOGLEVEL, PSTR("CAM: send frame"));
|
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: send frame"));
|
||||||
}
|
}
|
||||||
if (0 == wc_stream_active) {
|
if (0 == wc_stream_active) {
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Stream exit"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream exit"));
|
||||||
client.flush();
|
client.flush();
|
||||||
client.stop();
|
client.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CamHandleRoot(void) {
|
void HandleWebcamRoot(void) {
|
||||||
//CamServer->redirect("http://" + String(ip) + ":81/cam.mjpeg");
|
//CamServer->redirect("http://" + String(ip) + ":81/cam.mjpeg");
|
||||||
CamServer->sendHeader("Location", WiFi.localIP().toString() + ":81/cam.mjpeg");
|
CamServer->sendHeader("Location", WiFi.localIP().toString() + ":81/cam.mjpeg");
|
||||||
CamServer->send(302, "", "");
|
CamServer->send(302, "", "");
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: root called"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Root called"));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t motion_detect;
|
/*********************************************************************************************/
|
||||||
uint32_t motion_ltime;
|
|
||||||
uint32_t motion_trigger;
|
|
||||||
uint32_t motion_brightness;
|
|
||||||
uint8_t *last_motion_buffer;
|
|
||||||
|
|
||||||
uint32_t wc_set_motion_detect(int32_t value) {
|
uint32_t WcSetStreamserver(uint32_t flag) {
|
||||||
if (value >= 0) { motion_detect = value; }
|
|
||||||
if (-1 == value) {
|
|
||||||
return motion_trigger;
|
|
||||||
} else {
|
|
||||||
return motion_brightness;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// optional motion detector
|
|
||||||
void detect_motion(void) {
|
|
||||||
camera_fb_t *wc_fb;
|
|
||||||
uint8_t *out_buf = 0;
|
|
||||||
|
|
||||||
if ((millis()-motion_ltime) > motion_detect) {
|
|
||||||
motion_ltime = millis();
|
|
||||||
wc_fb = esp_camera_fb_get();
|
|
||||||
if (!wc_fb) { return; }
|
|
||||||
|
|
||||||
if (!last_motion_buffer) {
|
|
||||||
last_motion_buffer=(uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
|
||||||
}
|
|
||||||
if (last_motion_buffer) {
|
|
||||||
if (PIXFORMAT_JPEG == wc_fb->format) {
|
|
||||||
out_buf = (uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height*3)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
|
||||||
if (out_buf) {
|
|
||||||
fmt2rgb888(wc_fb->buf, wc_fb->len, wc_fb->format, out_buf);
|
|
||||||
uint32_t x, y;
|
|
||||||
uint8_t *pxi = out_buf;
|
|
||||||
uint8_t *pxr = last_motion_buffer;
|
|
||||||
// convert to bw
|
|
||||||
uint64_t accu = 0;
|
|
||||||
uint64_t bright = 0;
|
|
||||||
for (y = 0; y < wc_fb->height; y++) {
|
|
||||||
for (x = 0; x < wc_fb->width; x++) {
|
|
||||||
int32_t gray = (pxi[0] + pxi[1] + pxi[2]) / 3;
|
|
||||||
int32_t lgray = pxr[0];
|
|
||||||
pxr[0] = gray;
|
|
||||||
pxi += 3;
|
|
||||||
pxr++;
|
|
||||||
accu += abs(gray - lgray);
|
|
||||||
bright += gray;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
motion_trigger = accu / ((wc_fb->height * wc_fb->width) / 100);
|
|
||||||
motion_brightness = bright / ((wc_fb->height * wc_fb->width) / 100);
|
|
||||||
free(out_buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
esp_camera_fb_return(wc_fb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t wc_set_streamserver(uint32_t flag) {
|
|
||||||
if (global_state.wifi_down) { return 0; }
|
if (global_state.wifi_down) { return 0; }
|
||||||
|
|
||||||
wc_stream_active = 0;
|
wc_stream_active = 0;
|
||||||
@ -785,11 +792,11 @@ uint32_t wc_set_streamserver(uint32_t flag) {
|
|||||||
if (flag) {
|
if (flag) {
|
||||||
if (!CamServer) {
|
if (!CamServer) {
|
||||||
CamServer = new ESP8266WebServer(81);
|
CamServer = new ESP8266WebServer(81);
|
||||||
CamServer->on("/", CamHandleRoot);
|
CamServer->on("/", HandleWebcamRoot);
|
||||||
CamServer->on("/cam.mjpeg", handleMjpeg);
|
CamServer->on("/cam.mjpeg", HandleWebcamMjpeg);
|
||||||
CamServer->on("/cam.jpg", handleMjpeg);
|
CamServer->on("/cam.jpg", HandleWebcamMjpeg);
|
||||||
CamServer->on("/stream", handleMjpeg);
|
CamServer->on("/stream", HandleWebcamMjpeg);
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Stream init"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream init"));
|
||||||
CamServer->begin();
|
CamServer->begin();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -797,16 +804,35 @@ uint32_t wc_set_streamserver(uint32_t flag) {
|
|||||||
CamServer->stop();
|
CamServer->stop();
|
||||||
delete CamServer;
|
delete CamServer;
|
||||||
CamServer = NULL;
|
CamServer = NULL;
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Stream exit"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CAM: Stream exit"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WcStreamControl() {
|
void WcStreamControl() {
|
||||||
wc_set_streamserver(Settings.webcam_config.stream);
|
WcSetStreamserver(Settings.webcam_config.stream);
|
||||||
int resolution = (!Settings.webcam_config.stream) ? -1 : Settings.webcam_config.resolution;
|
int resolution = (!Settings.webcam_config.stream) ? -1 : Settings.webcam_config.resolution;
|
||||||
wc_setup(resolution);
|
WcSetup(resolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void WcLoop(void) {
|
||||||
|
if (CamServer) {
|
||||||
|
CamServer->handleClient();
|
||||||
|
if (wc_stream_active) { HandleWebcamMjpegTask(); }
|
||||||
|
}
|
||||||
|
if (motion_detect) { WcDetectMotion(); }
|
||||||
|
#ifdef USE_FACE_DETECT
|
||||||
|
if (face_detect_time) { WcDetectFace(); }
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void WcPicSetup(void) {
|
||||||
|
Webserver->on("/wc.jpg", HandleImage);
|
||||||
|
Webserver->on("/wc.mjpeg", HandleImage);
|
||||||
|
Webserver->on("/snapshot.jpg", HandleImageBasic);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WcShowStream(void) {
|
void WcShowStream(void) {
|
||||||
@ -822,26 +848,6 @@ void WcShowStream(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wc_loop(void) {
|
|
||||||
if (CamServer) {
|
|
||||||
CamServer->handleClient();
|
|
||||||
if (wc_stream_active) { handleMjpeg_task(); }
|
|
||||||
}
|
|
||||||
if (motion_detect) { detect_motion(); }
|
|
||||||
#ifdef USE_FACE_DETECT
|
|
||||||
if (face_detect_time) { detect_face(); }
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void wc_pic_setup(void) {
|
|
||||||
Webserver->on("/wc.jpg", HandleImage);
|
|
||||||
Webserver->on("/wc.mjpeg", HandleImage);
|
|
||||||
|
|
||||||
Webserver->on("/snapshot.jpg", HandleImageTheo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void WcInit(void) {
|
void WcInit(void) {
|
||||||
if (!Settings.webcam_config.data) {
|
if (!Settings.webcam_config.data) {
|
||||||
Settings.webcam_config.stream = 1;
|
Settings.webcam_config.stream = 1;
|
||||||
@ -897,7 +903,7 @@ void CmndWebcamStream(void) {
|
|||||||
void CmndWebcamResolution(void) {
|
void CmndWebcamResolution(void) {
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) {
|
||||||
Settings.webcam_config.resolution = XdrvMailbox.payload;
|
Settings.webcam_config.resolution = XdrvMailbox.payload;
|
||||||
wc_set_options(0, Settings.webcam_config.resolution);
|
WcSetOptions(0, Settings.webcam_config.resolution);
|
||||||
}
|
}
|
||||||
ResponseCmndNumber(Settings.webcam_config.resolution);
|
ResponseCmndNumber(Settings.webcam_config.resolution);
|
||||||
}
|
}
|
||||||
@ -905,7 +911,7 @@ void CmndWebcamResolution(void) {
|
|||||||
void CmndWebcamMirror(void) {
|
void CmndWebcamMirror(void) {
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||||
Settings.webcam_config.mirror = XdrvMailbox.payload;
|
Settings.webcam_config.mirror = XdrvMailbox.payload;
|
||||||
wc_set_options(3, Settings.webcam_config.mirror);
|
WcSetOptions(3, Settings.webcam_config.mirror);
|
||||||
}
|
}
|
||||||
ResponseCmndStateText(Settings.webcam_config.mirror);
|
ResponseCmndStateText(Settings.webcam_config.mirror);
|
||||||
}
|
}
|
||||||
@ -913,7 +919,7 @@ void CmndWebcamMirror(void) {
|
|||||||
void CmndWebcamFlip(void) {
|
void CmndWebcamFlip(void) {
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||||
Settings.webcam_config.flip = XdrvMailbox.payload;
|
Settings.webcam_config.flip = XdrvMailbox.payload;
|
||||||
wc_set_options(2, Settings.webcam_config.flip);
|
WcSetOptions(2, Settings.webcam_config.flip);
|
||||||
}
|
}
|
||||||
ResponseCmndStateText(Settings.webcam_config.flip);
|
ResponseCmndStateText(Settings.webcam_config.flip);
|
||||||
}
|
}
|
||||||
@ -921,7 +927,7 @@ void CmndWebcamFlip(void) {
|
|||||||
void CmndWebcamSaturation(void) {
|
void CmndWebcamSaturation(void) {
|
||||||
if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) {
|
if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) {
|
||||||
Settings.webcam_config.saturation = XdrvMailbox.payload +2;
|
Settings.webcam_config.saturation = XdrvMailbox.payload +2;
|
||||||
wc_set_options(6, Settings.webcam_config.saturation -2);
|
WcSetOptions(6, Settings.webcam_config.saturation -2);
|
||||||
}
|
}
|
||||||
ResponseCmndNumber(Settings.webcam_config.saturation -2);
|
ResponseCmndNumber(Settings.webcam_config.saturation -2);
|
||||||
}
|
}
|
||||||
@ -929,7 +935,7 @@ void CmndWebcamSaturation(void) {
|
|||||||
void CmndWebcamBrightness(void) {
|
void CmndWebcamBrightness(void) {
|
||||||
if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) {
|
if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) {
|
||||||
Settings.webcam_config.brightness = XdrvMailbox.payload +2;
|
Settings.webcam_config.brightness = XdrvMailbox.payload +2;
|
||||||
wc_set_options(5, Settings.webcam_config.brightness -2);
|
WcSetOptions(5, Settings.webcam_config.brightness -2);
|
||||||
}
|
}
|
||||||
ResponseCmndNumber(Settings.webcam_config.brightness -2);
|
ResponseCmndNumber(Settings.webcam_config.brightness -2);
|
||||||
}
|
}
|
||||||
@ -937,7 +943,7 @@ void CmndWebcamBrightness(void) {
|
|||||||
void CmndWebcamContrast(void) {
|
void CmndWebcamContrast(void) {
|
||||||
if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) {
|
if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) {
|
||||||
Settings.webcam_config.contrast = XdrvMailbox.payload +2;
|
Settings.webcam_config.contrast = XdrvMailbox.payload +2;
|
||||||
wc_set_options(4, Settings.webcam_config.contrast -2);
|
WcSetOptions(4, Settings.webcam_config.contrast -2);
|
||||||
}
|
}
|
||||||
ResponseCmndNumber(Settings.webcam_config.contrast -2);
|
ResponseCmndNumber(Settings.webcam_config.contrast -2);
|
||||||
}
|
}
|
||||||
@ -951,10 +957,10 @@ bool Xdrv81(uint8_t function) {
|
|||||||
|
|
||||||
switch (function) {
|
switch (function) {
|
||||||
case FUNC_LOOP:
|
case FUNC_LOOP:
|
||||||
wc_loop();
|
WcLoop();
|
||||||
break;
|
break;
|
||||||
case FUNC_WEB_ADD_HANDLER:
|
case FUNC_WEB_ADD_HANDLER:
|
||||||
wc_pic_setup();
|
WcPicSetup();
|
||||||
break;
|
break;
|
||||||
case FUNC_WEB_ADD_MAIN_BUTTON:
|
case FUNC_WEB_ADD_MAIN_BUTTON:
|
||||||
WcShowStream();
|
WcShowStream();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user