@@ -216,9 +216,33 @@ static esp_err_t capture_handler(httpd_req_t *req){
216216 return res;
217217}
218218
219+ static int sendData (httpd_req_t *req, const char *buf, const size_t len) {
220+ size_t index = 0 ;
221+ int res = 0 ;
222+ int attempts = 0 ;
223+ const int maxAttempts = 100 ;
224+ do {
225+ res = httpd_send (req, &buf[index], len - index);
226+ if ((res >= 0 && res < (len - index)) || res == HTTPD_SOCK_ERR_TIMEOUT) {
227+ delay (10 );
228+ attempts++;
229+ if (res == HTTPD_SOCK_ERR_TIMEOUT && attempts < maxAttempts) {
230+ res = 0 ;
231+ }
232+ }
233+ if (res >= 0 ) {
234+ index += res;
235+ }
236+ }
237+ while (res >= 0 && index < len && attempts < maxAttempts);
238+ if (index < len && attempts >= maxAttempts) {
239+ res = -1 ;
240+ }
241+ return res;
242+ }
243+
219244static esp_err_t stream_handler (httpd_req_t *req){
220245 camera_fb_t * fb = NULL ;
221- esp_err_t res = ESP_OK;
222246 size_t _jpg_buf_len = 0 ;
223247 uint8_t * _jpg_buf = NULL ;
224248 char * part_buf[64 ];
@@ -235,39 +259,65 @@ static esp_err_t stream_handler(httpd_req_t *req){
235259 last_frame = esp_timer_get_time ();
236260 }
237261
238- res = httpd_resp_set_type (req, _STREAM_CONTENT_TYPE);
239- if (res != ESP_OK){
262+ const char *httpd_chunked_hdr_str = " HTTP/1.1 %s%sContent-Type: %s%s" ;
263+ const char *colon_separator = " : " ;
264+ const char *cr_lf_seperator = " \r\n " ;
265+ static char buffer[256 + 1 ];
266+ const int headerSize = snprintf (buffer, sizeof (buffer) - 1 , httpd_chunked_hdr_str, " 200 OK" , cr_lf_seperator, _STREAM_CONTENT_TYPE, cr_lf_seperator);
267+ int res = sendData (req, buffer, headerSize);
268+ if (res != headerSize) {
269+ // TODO: Make a lambda so as we can re-use...
270+ streamCount = 0 ;
271+ if (autoLamp && (lampVal != -1 )) setLamp (0 );
272+ Serial.println (" STREAM: failed to set HTTP response type" );
273+ return res;
274+ }
275+ const int originSize = snprintf (buffer, sizeof (buffer) - 1 , " Access-Control-Allow-Origin: *%s" , cr_lf_seperator);
276+ res = sendData (req, buffer, originSize);
277+ if (res != originSize) {
278+ // TODO: Make a lambda so as we can re-use...
240279 streamCount = 0 ;
241280 if (autoLamp && (lampVal != -1 )) setLamp (0 );
242281 Serial.println (" STREAM: failed to set HTTP response type" );
243282 return res;
244283 }
245-
246- httpd_resp_set_hdr (req, " Access-Control-Allow-Origin" , " *" );
247284
248285 while (true ){
249286 fb = esp_camera_fb_get ();
250287 if (!fb) {
251288 Serial.println (" STREAM: failed to acquire frame" );
252- res = ESP_FAIL ;
289+ res = - 1 ;
253290 } else {
254291 if (fb->format != PIXFORMAT_JPEG){
255292 Serial.println (" STREAM: Non-JPEG frame returned by camera module" );
256- res = ESP_FAIL ;
293+ res = - 2 ;
257294 } else {
258295 _jpg_buf_len = fb->len ;
259296 _jpg_buf = fb->buf ;
260297 }
261298 }
262- if (res == ESP_OK){
263- res = httpd_resp_send_chunk (req, _STREAM_BOUNDARY, strlen (_STREAM_BOUNDARY));
299+ if (res > 0 ){
300+ res = sendData (req, _STREAM_BOUNDARY, strlen (_STREAM_BOUNDARY));
301+ if (res != strlen (_STREAM_BOUNDARY)) {
302+ res = -3 ;
303+ }
264304 }
265- if (res == ESP_OK ){
305+ if (res > 0 ){
266306 size_t hlen = snprintf ((char *)part_buf, 64 , _STREAM_PART, _jpg_buf_len);
267- res = httpd_resp_send_chunk (req, (const char *)part_buf, hlen);
307+ res = sendData (req, (const char *)part_buf, hlen);
308+ if (res != hlen) {
309+ res = -4 ;
310+ }
268311 }
269- if (res == ESP_OK){
270- res = httpd_resp_send_chunk (req, (const char *)_jpg_buf, _jpg_buf_len);
312+ if (res > 0 ){
313+ yield ();
314+ res = sendData (req, (const char *)_jpg_buf, _jpg_buf_len);
315+ if (res != _jpg_buf_len) {
316+ Serial.printf (" Failed sending chunk of [%d] error: [%d]\n " , _jpg_buf_len, res);
317+ Serial.print (_STREAM_BOUNDARY);
318+ Serial.printf ((char *)part_buf);
319+ res = -5 ;
320+ }
271321 }
272322 if (fb){
273323 esp_camera_fb_return (fb);
@@ -277,7 +327,7 @@ static esp_err_t stream_handler(httpd_req_t *req){
277327 free (_jpg_buf);
278328 _jpg_buf = NULL ;
279329 }
280- if (res != ESP_OK ){
330+ if (res < 0 ){
281331 // This is the only exit point from the stream loop.
282332 // We end the stream here only if a Hard failure has been encountered or the connection has been interrupted.
283333 break ;
@@ -297,7 +347,7 @@ static esp_err_t stream_handler(httpd_req_t *req){
297347 if (autoLamp && (lampVal != -1 )) setLamp (0 );
298348 Serial.println (" Stream ended" );
299349 last_frame = 0 ;
300- return res;
350+ return res < 0 ? ESP_FAIL : ESP_OK ;
301351}
302352
303353static esp_err_t cmd_handler (httpd_req_t *req){
0 commit comments