Comments (6)
This happens when a task is taking up too many cpu cycles. The doc that describes the operation of the esp32 watch dog timer is here. You will have to assign
the offending task to be monitored by the wdt then use "esp_task_wdt_reset()" somewhere in that task to reset the wdt.
from espasyncwebserver.
Hi @noweare1, thanks for answering. I've already tried adding the esp_task_wdt_reset() inside the callback, but it didn't help. Since the connection will be closed on request->send(), right now I have no idea on how to implement something that can help me achieving the live streaming. With the WebServer.h library(The one not async) I've been able to achieve that, but it takes too much time to send frames through server.send() or server.sendContent()
from espasyncwebserver.
I am just learning to use the espAsynchWebServer library. I am also trying to stream frames using this library. It took me a while to figure out how streaming works with the espressif Camera example.
Some of the magic is actually in the header files. The header "multipart/x-mixed-replace;boundary=" PART_BOUNDARY" is part of the response to the browser. That header tells the browser that it will pushing images to the browser without having the browser ask for the next image (which saves time). So you might want to take a look at that.
from espasyncwebserver.
Hi @noweare1 , thanks again for answering. I took a look at some examples I found and came up to this.
#define PART_BOUNDARY "123456789000000000000987654321"
static const char* STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
static const char* STREAM_PART = "Content-Type: %s\r\nContent-Length: %u\r\n\r\n";
static const char * JPG_CONTENT_TYPE = "image/jpeg";
void handleStreaming(AsyncWebServerRequest *request){
AsyncWebServerResponse* response = request->beginChunkedResponse(JPG_CONTENT_TYPE, _sendContent);
response->addHeader("Access-Control-Allow-Origin", "*");
request->send(response);
}
size_t _sendContent(uint8_t* buffer, size_t maxLen, size_t index){
Serial.println("MAX LEN: " + String(maxLen));
Serial.println("INDEX: " + String(index));
Serial.println("STRLEN BOUNDARY: " + String(strlen(STREAM_BOUNDARY)));
Serial.println("STRLEN PART: " + String(strlen(STREAM_PART)));
Serial.println("STRLEN CONTENT TYPE: " + String(strlen(JPG_CONTENT_TYPE)));
esp_err_t err = ESP_OK;
vTaskDelay(10);
if(!_frame.fb || _frame.index == _jpg_buf_len){
Serial.println("Need a new frame");
//Ho bisogno di un nuovo frame
if(index && _frame.fb){
//Ho gia' inizializzato il frame almeno una volta
if(_frame.fb->format != PIXFORMAT_JPEG){
Serial.println("Previous frame was not in JPEG format");
free(_jpg_buf);
}
esp_camera_fb_return(_frame.fb);
_frame.fb = NULL;
_jpg_buf_len = 0;
_jpg_buf = NULL;
}
if(maxLen < (strlen(STREAM_BOUNDARY) + strlen(STREAM_PART) + strlen("image/jpeg") + 8)){
Serial.println("Cannot send the frame. Retry!");
return RESPONSE_TRY_AGAIN;
}
//Getting new frame
_frame.index = 0;
Serial.println("Getting a new frame");
_frame.fb = esp_camera_fb_get();
if(_frame.fb == NULL){
Serial.println("Camera failed");
if(esp_camera_deinit() == ESP_OK){
camera_init();
};
return 0;
}
if(_frame.fb->format != PIXFORMAT_JPEG){
Serial.println("new frame not in JPEG format");
bool jpeg_converted = frame2jpg(_frame.fb, 80, &_jpg_buf, &_jpg_buf_len);
if(!jpeg_converted){
Serial.println("Conversion failed");
_frame.fb = NULL;
_jpg_buf_len = 0;
_jpg_buf = NULL;
return 0;
}
esp_task_wdt_reset();
}
Serial.println("New frame's already in JPEG format");
Serial.println("Sending boundary");
size_t boundaryLen = 0;
if(index){
boundaryLen = strlen(STREAM_BOUNDARY);
memcpy(buffer, STREAM_BOUNDARY, boundaryLen);
buffer += boundaryLen;
}
//send header
Serial.println("Sending header");
size_t headerLen = sprintf((char*)buffer, STREAM_PART, "image/jpeg", _jpg_buf_len);
buffer += headerLen;
//send frame
headerLen = maxLen - headerLen - boundaryLen;
Serial.println("Sending frame");
if(headerLen > _jpg_buf_len){
maxLen -= headerLen - _jpg_buf_len;
headerLen = _jpg_buf_len;
}
memcpy(buffer, _jpg_buf, headerLen);
_frame.index += headerLen;
return maxLen;
}
Serial.println("Sending frame 2");
size_t available = _jpg_buf_len - _frame.index;
if(maxLen > available){
maxLen = available;
}
memcpy(buffer, _jpg_buf+ _frame.index , maxLen);
_frame.index += maxLen;
esp_task_wdt_reset();
return maxLen;
}
I can see in the console that it is indeed working, but:
- I'm not able to see the image on the browser page
- Still getting Task watchdog got triggered after a while
EDIT:
I forgot to assign _frame.fb->buf to _jpg_buf and _frame.fb->len to _jpg_buf_len. But still, I'm not able to see the images on a web page
from espasyncwebserver.
@noweare1 I managed to solve the problem. I had to create a class that extends the AsyncAbstractResponse class. Then I had to override the _fillBuffer method and it happened to be working.
#include "AsyncJpegStreamResponse.h"
#include <cstring>
AsyncJpegStreamResponse::AsyncJpegStreamResponse() {
_callback = nullptr;
_code = 200;
_contentLength = 0;
_contentType = STREAM_CONTENT_TYPE;
_sendContentLength = false;
_chunked = true;
_index = 0;
_jpg_buf_len = 0;
_jpg_buf = NULL;
memset(&_frame, 0, sizeof(camera_frame_t));
}
AsyncJpegStreamResponse::~AsyncJpegStreamResponse() {
Serial.println("In the constructor");
if (_frame.fb) {
Serial.println("Frame fb not null");
if (_frame.fb->format != PIXFORMAT_JPEG) {
free(_jpg_buf);
}
esp_camera_fb_return(_frame.fb);
}
}
bool AsyncJpegStreamResponse::_sourceValid() const {
return true;
}
size_t AsyncJpegStreamResponse::_fillBuffer(uint8_t* buf, size_t maxLen) {
Serial.println("In the _fillBuffer function");
size_t ret = _sendContent(buf, maxLen, _index);
if (ret != RESPONSE_TRY_AGAIN) {
_index += ret;
}
return ret;
}
size_t AsyncJpegStreamResponse::_sendContent(uint8_t* buffer, size_t maxLen, size_t index) {
Serial.println("In the _sendContent function");
if (!_frame.fb || _frame.index == _jpg_buf_len) {
if (index && _frame.fb) {
if (_frame.fb->format != PIXFORMAT_JPEG) {
free(_jpg_buf);
}
esp_camera_fb_return(_frame.fb);
_jpg_buf = NULL;
_jpg_buf_len = 0;
_frame.fb = NULL;
}
if (maxLen < (strlen(STREAM_BOUNDARY) + strlen(STREAM_PART) + strlen(JPG_CONTENT_TYPE) + 8)) {
return RESPONSE_TRY_AGAIN;
}
_frame.index = 0;
_frame.fb = esp_camera_fb_get();
if (_frame.fb == NULL) {
log_e("Camera frame failed");
return 0;
}
if (_frame.fb->format != PIXFORMAT_JPEG) {
bool _jpg_converted = frame2jpg(_frame.fb, 80, &_jpg_buf, &_jpg_buf_len);
if (!_jpg_converted) {
log_e("JPEG compression failed");
esp_camera_fb_return(_frame.fb);
_frame.fb = NULL;
_jpg_buf_len = 0;
_jpg_buf = NULL;
return 0;
}
} else {
_jpg_buf = _frame.fb->buf;
_jpg_buf_len = _frame.fb->len;
}
size_t blen = 0;
if (index) {
blen = strlen(STREAM_BOUNDARY);
memcpy(buffer, STREAM_BOUNDARY, blen);
buffer += blen;
}
size_t hlen = sprintf((char*) buffer, STREAM_PART, JPG_CONTENT_TYPE, _jpg_buf_len);
buffer += hlen;
hlen = maxLen - hlen - blen;
if (hlen > _jpg_buf_len) {
maxLen -= hlen - _jpg_buf_len;
hlen = _jpg_buf_len;
}
memcpy(buffer, _jpg_buf, hlen);
_frame.index += hlen;
return maxLen;
}
size_t available = _jpg_buf_len - _frame.index;
if (maxLen > available) {
maxLen = available;
}
memcpy(buffer, _jpg_buf + _frame.index, maxLen);
_frame.index += maxLen;
return maxLen;
}
Then, in your main.cpp, simply call
AsyncWebServerResponse* response = new AsyncJpegStreamResponse();
request->send(response);
from espasyncwebserver.
Congratulations ! I will have to follow the code to see what you did. I mostly program using C. I am not a C++ programmer so this could be a little challenging for me. The espressif IDF has a webserver module that also supports websockets. I have been looking at that library also.
from espasyncwebserver.
Related Issues (20)
- Send content with beginChunkedResponse
- Question: is it possible to replicate AsyncWebSocket with WebServer in arduino-esp32 v3.0.0 ? HOT 4
- Images won't load randomly
- Compiling issues HOT 8
- I Can't make the web explorer to offer to save credentials
- Change bool AsyncStaticWebHandler::canHandle to use exact match instead of String::startsWith(_uri)
- small ddos (press F5) crash: async_tcp ....watchdog got triggered HOT 2
- Compilation Error for Newer ESP32 HOT 3
- possible memory leak at send_p?
- Forwarding Webserver with websockets HOT 2
- Get new client ID at every refresh :( HOT 1
- Refusing connection when making httpGet request with mDNS
- Problem resolved ? "Arduino\libraries\ESPAsyncWebSrv\src\WebAuthentication.cpp:74:3: error: 'mbedtls_md5_starts_ret' was not declared in this scope; did you mean 'mbedtls_md5_starts'?" HOT 10
- does not compile with ESP32C3
- ESP8266: Compilation error: invalid conversion from 'const AsyncWebParameter*' to 'AsyncWebParameter*' [-fpermissive] HOT 1
- IDF 5 Coexistence support HOT 3
- It is possible Increase buffer size for rx data by websocket?
- Cant set Table or Cell width % because of template processing HOT 2
- Web server hangs up HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from espasyncwebserver.