Skip to content

Commit

Permalink
Changed the cpp file into a class
Browse files Browse the repository at this point in the history
  • Loading branch information
Dyspersja committed Apr 21, 2024
1 parent f1a2dcf commit 98f1d5a
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 102 deletions.
32 changes: 32 additions & 0 deletions AsyncJpegStreamResponse.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef ASYNC_JPEG_STREAM_RESPONSE_H
#define ASYNC_JPEG_STREAM_RESPONSE_H

#include "Arduino.h"
#include "ESPAsyncWebServer.h"
#include "camera_pins.h"
#include "esp_camera.h"

typedef struct {
camera_fb_t * fb;
size_t index;
} camera_frame_t;

class AsyncJpegStreamResponse : public AsyncAbstractResponse {
private:
camera_frame_t _frame;
size_t _index;
size_t _jpg_buf_len;
uint8_t *_jpg_buf;

public:
AsyncJpegStreamResponse();
~AsyncJpegStreamResponse();

bool _sourceValid() const;

virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;

size_t _content(uint8_t *buffer, size_t maxLen, size_t index);
};

#endif // ASYNC_JPEG_STREAM_RESPONSE_H
187 changes: 85 additions & 102 deletions AsyncWebCamera.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
#include "Arduino.h"
#include "AsyncJpegStreamResponse.h"
#include "esp_camera.h"
#include "ESPAsyncWebServer.h"

typedef struct {
camera_fb_t * fb;
size_t index;
} camera_frame_t;
#include "camera_pins.h"

#define PART_BOUNDARY "123456789000000000000987654321"
static const char* STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
Expand All @@ -14,117 +9,105 @@ static const char* STREAM_PART = "Content-Type: %s\r\nContent-Length: %u\r\n\r\n

static const char * JPG_CONTENT_TYPE = "image/jpeg";

class AsyncJpegStreamResponse: public AsyncAbstractResponse {
private:
camera_frame_t _frame;
size_t _index;
size_t _jpg_buf_len;
uint8_t * _jpg_buf;
uint64_t lastAsyncRequest;
public:
AsyncJpegStreamResponse(){
_callback = nullptr;
_code = 200;
_contentLength = 0;
_contentType = STREAM_CONTENT_TYPE;
_sendContentLength = false;
_chunked = true;
_index = 0;
_jpg_buf_len = 0;
_jpg_buf = NULL;
lastAsyncRequest = 0;
memset(&_frame, 0, sizeof(camera_frame_t));
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() {
if (_frame.fb) {
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) {
size_t ret = _content(buf, maxLen, _index);
if (ret != RESPONSE_TRY_AGAIN) {
_index += ret;
}
~AsyncJpegStreamResponse(){
if(_frame.fb){
if(_frame.fb->format != PIXFORMAT_JPEG){
return ret;
}

size_t AsyncJpegStreamResponse::_content(uint8_t *buffer, size_t maxLen, size_t index) {
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);
_frame.fb = NULL;
_jpg_buf_len = 0;
_jpg_buf = NULL;
}
}
bool _sourceValid() const {
return true;
}
virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override {
size_t ret = _content(buf, maxLen, _index);
if(ret != RESPONSE_TRY_AGAIN){
_index += ret;
if (maxLen < (strlen(STREAM_BOUNDARY) + strlen(STREAM_PART) + strlen(JPG_CONTENT_TYPE) + 8)) {
return RESPONSE_TRY_AGAIN;
}
return ret;
}
size_t _content(uint8_t *buffer, size_t maxLen, size_t index){
if(!_frame.fb || _frame.index == _jpg_buf_len){
if(index && _frame.fb){
uint64_t end = (uint64_t)micros();
int fp = (end - lastAsyncRequest) / 1000;
log_printf("Size: %uKB, Time: %ums (%.1ffps)\n", _jpg_buf_len/1024, fp);
lastAsyncRequest = end;
if(_frame.fb->format != PIXFORMAT_JPEG){
free(_jpg_buf);
}

_frame.index = 0;
_frame.fb = esp_camera_fb_get();

if (_frame.fb == NULL) {
return 0;
}

if (_frame.fb->format != PIXFORMAT_JPEG) {
unsigned long st = millis();
bool jpeg_converted = frame2jpg(_frame.fb, 80, &_jpg_buf, &_jpg_buf_len);
if (!jpeg_converted) {
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(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;
}
} else {
_jpg_buf_len = _frame.fb->len;
_jpg_buf = _frame.fb->buf;
}

if(_frame.fb->format != PIXFORMAT_JPEG){
unsigned long st = millis();
bool jpeg_converted = frame2jpg(_frame.fb, 80, &_jpg_buf, &_jpg_buf_len);
if(!jpeg_converted){
log_e("JPEG compression failed");
esp_camera_fb_return(_frame.fb);
_frame.fb = NULL;
_jpg_buf_len = 0;
_jpg_buf = NULL;
return 0;
}
log_i("JPEG: %lums, %uB", millis() - st, _jpg_buf_len);
} else {
_jpg_buf_len = _frame.fb->len;
_jpg_buf = _frame.fb->buf;
}


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 blen = 0;
if (index) {
blen = strlen(STREAM_BOUNDARY);
memcpy(buffer, STREAM_BOUNDARY, blen);
buffer += blen;
}

size_t available = _jpg_buf_len - _frame.index;
if(maxLen > available){
maxLen = available;
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+_frame.index, maxLen);
_frame.index += maxLen;

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;
}

0 comments on commit 98f1d5a

Please sign in to comment.