@@ -216,9 +216,33 @@ static esp_err_t capture_handler(httpd_req_t *req){
216
216
return res;
217
217
}
218
218
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
+
219
244
static esp_err_t stream_handler (httpd_req_t *req){
220
245
camera_fb_t * fb = NULL ;
221
- esp_err_t res = ESP_OK;
222
246
size_t _jpg_buf_len = 0 ;
223
247
uint8_t * _jpg_buf = NULL ;
224
248
char * part_buf[64 ];
@@ -235,39 +259,65 @@ static esp_err_t stream_handler(httpd_req_t *req){
235
259
last_frame = esp_timer_get_time ();
236
260
}
237
261
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...
240
279
streamCount = 0 ;
241
280
if (autoLamp && (lampVal != -1 )) setLamp (0 );
242
281
Serial.println (" STREAM: failed to set HTTP response type" );
243
282
return res;
244
283
}
245
-
246
- httpd_resp_set_hdr (req, " Access-Control-Allow-Origin" , " *" );
247
284
248
285
while (true ){
249
286
fb = esp_camera_fb_get ();
250
287
if (!fb) {
251
288
Serial.println (" STREAM: failed to acquire frame" );
252
- res = ESP_FAIL ;
289
+ res = - 1 ;
253
290
} else {
254
291
if (fb->format != PIXFORMAT_JPEG){
255
292
Serial.println (" STREAM: Non-JPEG frame returned by camera module" );
256
- res = ESP_FAIL ;
293
+ res = - 2 ;
257
294
} else {
258
295
_jpg_buf_len = fb->len ;
259
296
_jpg_buf = fb->buf ;
260
297
}
261
298
}
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
+ }
264
304
}
265
- if (res == ESP_OK ){
305
+ if (res > 0 ){
266
306
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
+ }
268
311
}
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
+ }
271
321
}
272
322
if (fb){
273
323
esp_camera_fb_return (fb);
@@ -277,7 +327,7 @@ static esp_err_t stream_handler(httpd_req_t *req){
277
327
free (_jpg_buf);
278
328
_jpg_buf = NULL ;
279
329
}
280
- if (res != ESP_OK ){
330
+ if (res < 0 ){
281
331
// This is the only exit point from the stream loop.
282
332
// We end the stream here only if a Hard failure has been encountered or the connection has been interrupted.
283
333
break ;
@@ -297,7 +347,7 @@ static esp_err_t stream_handler(httpd_req_t *req){
297
347
if (autoLamp && (lampVal != -1 )) setLamp (0 );
298
348
Serial.println (" Stream ended" );
299
349
last_frame = 0 ;
300
- return res;
350
+ return res < 0 ? ESP_FAIL : ESP_OK ;
301
351
}
302
352
303
353
static esp_err_t cmd_handler (httpd_req_t *req){
0 commit comments