77#include < freertos/FreeRTOS.h>
88#include < freertos/queue.h>
99#include < freertos/task.h>
10+ #include < sys/socket.h>
1011
1112#include " cam_streamer.h"
1213
14+ #if __has_include("myconfig.h")
15+ struct station {
16+ const char ssid[65 ];
17+ const char password[65 ];
18+ const bool dhcp;
19+ };
20+ #include " myconfig.h"
21+ #endif
22+
23+ #ifndef CAM_STREAMER_MAX_CLIENTS
24+ #warning "CAM_STREAMER_MAX_CLIENTS undefined, using default value of 10"
25+ #define CAM_STREAMER_MAX_CLIENTS 10
26+ #endif
27+
1328#define PART_BOUNDARY " 123456789000000000000987654321"
1429
1530#define _STREAM_HEADERS " HTTP/1.1 200 OK\r\n " \
1833 " Keep-Alive: timeout=15\r\n " \
1934 " Content-Type: multipart/x-mixed-replace;boundary=" PART_BOUNDARY " \r\n "
2035
36+ #define _TEXT_HEADERS " HTTP/1.1 200 OK\r\n " \
37+ " Access-Control-Allow-Origin: *\r\n " \
38+ " Connection: Close\r\n " \
39+ " Content-Type: text/plain\r\n\r\n "
40+
41+ extern bool debugData;
42+ extern int lampVal;
43+ extern bool autoLamp;
44+ extern void setLamp (int );
45+
2146static const char * _STREAM_BOUNDARY = " \r\n --" PART_BOUNDARY " \r\n " ;
2247static const char * _STREAM_PART = " Content-Type: image/jpeg\r\n Content-Length: %u\r\n\r\n " ;
2348
49+ static inline void print_debug (const char *fmt, ...) {
50+ if (debugData) {
51+ va_list l;
52+ va_start (l, fmt);
53+ vprintf (fmt, l);
54+ va_end (l);
55+ }
56+ }
57+
2458static uint8_t is_send_error (int r) {
2559 switch (r) {
2660 case HTTPD_SOCK_ERR_INVALID:
27- #ifdef DEBUG_DEFAULT_ON
28- printf ("[cam_streamer] invalid argument occured!\n" );
29- #endif
61+ print_debug (" [cam_streamer] invalid argument occured!\n " );
3062 return 1 ;
3163 case HTTPD_SOCK_ERR_TIMEOUT:
32- #ifdef DEBUG_DEFAULT_ON
33- printf ("[cam_streamer] timeout/interrupt occured!\n" );
34- #endif
64+ print_debug (" [cam_streamer] timeout/interrupt occured!\n " );
3565 return 1 ;
3666 case HTTPD_SOCK_ERR_FAIL:
37- #ifdef DEBUG_DEFAULT_ON
38- printf ("[cam_streamer] unrecoverable error while send()!\n" );
39- #endif
67+ print_debug (" [cam_streamer] unrecoverable error while send()!\n " );
4068 return 1 ;
4169 case ESP_ERR_INVALID_ARG:
42- #ifdef DEBUG_DEFAULT_ON
43- printf ("[text-streamer] session closed!\n" );
44- #endif
70+ print_debug (" [text-streamer] session closed!\n " );
4571 return 1 ;
4672 default :
47- #ifdef DEBUG_DEFAULT_ON
48- printf ("[cam_streamer] sent %d bytes!\n" , r );
49- #endif
73+ print_debug (" [cam_streamer] sent %d bytes!\n " , r);
5074 return 0 ;
5175 }
5276}
5377
54- void cam_streamer_init (cam_streamer_t * s , httpd_handle_t server , uint16_t fps ) {
78+ void cam_streamer_init (cam_streamer_t *s, httpd_handle_t server, uint16_t frame_delay ) {
5579 memset (s, 0 , sizeof (cam_streamer_t ));
56- s -> frame_delay = 1000000 / fps ;
80+ s->frame_delay =1000 *frame_delay ;
5781 s->clients =xQueueCreate (CAM_STREAMER_MAX_CLIENTS*2 , sizeof (int ));
5882 s->server =server;
5983}
6084
85+ // frame_delay must be in ms (not us)
86+ void cam_streamer_set_frame_delay (cam_streamer_t *s, uint16_t frame_delay) {
87+ s->frame_delay =1000 *frame_delay;
88+ }
89+
6190static void cam_streamer_update_frame (cam_streamer_t *s) {
6291 uint8_t l=0 ;
6392 while (!__atomic_compare_exchange_n (&s->buf_lock , &l, 1 , 0 , __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
@@ -73,17 +102,13 @@ static void cam_streamer_update_frame(cam_streamer_t *s) {
73102 s->last_updated =esp_timer_get_time ();
74103 s->part_len =snprintf (s->part_buf , 64 , _STREAM_PART, s->buf ->len );
75104 __atomic_store_n (&s->buf_lock , 0 , __ATOMIC_RELAXED);
76- #ifdef DEBUG_DEFAULT_ON
77- printf ("[cam_streamer] fetched new frame\n" );
78- #endif
105+ print_debug (" [cam_streamer] fetched new frame\n " );
79106}
80107
81108static void cam_streamer_decrement_num_clients (cam_streamer_t *s) {
82109 size_t num_clients=s->num_clients ;
83110 while (num_clients>0 && !__atomic_compare_exchange_n (&s->num_clients , &num_clients, num_clients-1 , 0 , __ATOMIC_RELAXED, __ATOMIC_RELAXED));
84- #ifdef DEBUG_DEFAULT_ON
85- printf ("[cam_streamer] num_clients decremented\n" );
86- #endif
111+ print_debug (" [cam_streamer] num_clients decremented\n " );
87112}
88113
89114void cam_streamer_task (void *p) {
@@ -93,35 +118,35 @@ void cam_streamer_task(void *p) {
93118 int fd;
94119 unsigned int n_entries;
95120 for (;;) {
96- while (!(n_entries = uxQueueMessagesWaiting (s -> clients )))
121+ while (!(n_entries=uxQueueMessagesWaiting (s->clients ))) {
122+ if (autoLamp && lampVal!=-1 ) setLamp (0 );
97123 vTaskSuspend (NULL );
124+ if (autoLamp && lampVal!=-1 ) setLamp (lampVal);
125+ }
98126
99127 current_time=esp_timer_get_time ();
100128 if ((current_time-last_time)<s->frame_delay )
101129 vTaskDelay ((s->frame_delay -(current_time-last_time))/(1000 *portTICK_PERIOD_MS));
102- last_time = current_time ;
103130
104131 cam_streamer_update_frame (s);
105132
133+ print_debug (" [cam_streamer] frame_size: %luB %lums\n " , s->buf ->len , (current_time-last_time)/1000 );
134+ last_time=current_time;
135+
106136 for (unsigned int i=0 ; i<n_entries; ++i) {
107137 if (xQueueReceive (s->clients , &fd, 10 /portTICK_PERIOD_MS)==pdFALSE) {
108- #ifdef DEBUG_DEFAULT_ON
109- printf ("[cam_streamer] failed to dequeue fd!\n" );
110- #endif
138+ print_debug (" [cam_streamer] failed to dequeue fd!\n " );
111139 continue ;
112140 }
113141
114- #ifdef DEBUG_DEFAULT_ON
115- printf ("[cam_streamer] dequeued fd %d\n" , fd );
116- printf ("[cam_streamer] sending part: \"%.*s\"\n" , (int ) s -> part_len , s -> part_buf );
117- #endif
142+ print_debug (" [cam_streamer] fd %d dequeued\n " , fd);
118143
119144 if (is_send_error (httpd_socket_send (s->server , fd, s->part_buf , s->part_len , 0 ))) {
120145 cam_streamer_decrement_num_clients (s);
121146 continue ;
122147 }
123148
124- if (is_send_error (httpd_socket_send (s -> server , fd , s -> buf -> buf , s -> buf -> len , 0 ))) {
149+ if (is_send_error (httpd_socket_send (s->server , fd, ( const char *) s->buf ->buf , s->buf ->len , 0 ))) {
125150 cam_streamer_decrement_num_clients (s);
126151 continue ;
127152 }
@@ -132,20 +157,16 @@ void cam_streamer_task(void *p) {
132157 }
133158
134159 xQueueSend (s->clients , (void *) &fd, 10 /portTICK_PERIOD_MS);
135- #ifdef DEBUG_DEFAULT_ON
136- printf ("[cam_streamer] fd %d requeued\n" , fd );
137- #endif
160+ print_debug (" [cam_streamer] fd %d requeued\n " , fd);
138161 }
139162 }
140163}
141164
142165void cam_streamer_start (cam_streamer_t *s) {
143166 BaseType_t r=xTaskCreate (cam_streamer_task, " cam_streamer" , 10 *1024 , (void *) s, tskIDLE_PRIORITY+3 , &s->task );
144167
145- #ifdef DEBUG_DEFAULT_ON
146168 if (r!=pdPASS)
147- printf ("[cam_streamer] failed to create task!\n" );
148- #endif
169+ print_debug (" [cam_streamer] failed to create task!\n " );
149170}
150171
151172void cam_streamer_stop (cam_streamer_t *s) {
@@ -162,35 +183,41 @@ void cam_streamer_dequeue_all_clients(cam_streamer_t *s) {
162183}
163184
164185bool cam_streamer_enqueue_client (cam_streamer_t *s, int fd) {
165- #ifdef DEBUG_DEFAULT_ON
166- printf ("sending stream headers:\n%s\nLength: %d\n" , _STREAM_HEADERS , strlen (_STREAM_HEADERS ));
167- #endif
186+ if (s->num_clients >=CAM_STREAMER_MAX_CLIENTS) {
187+ if (httpd_socket_send (s->server , fd, _TEXT_HEADERS, strlen (_TEXT_HEADERS), 0 )) {
188+ print_debug (" failed sending text headers!\n " );
189+ return false ;
190+ }
191+
192+ #define EMSG " too many clients"
193+ if (httpd_socket_send (s->server , fd, EMSG, strlen (EMSG), 0 )) {
194+ print_debug (" failed sending message\n " );
195+ return false ;
196+ }
197+ #undef EMSG
198+ close (fd);
199+ return false ;
200+ }
201+
202+ print_debug (" sending stream headers:\n %s\n Length: %d\n " , _STREAM_HEADERS, strlen (_STREAM_HEADERS));
168203 if (is_send_error (httpd_socket_send (s->server , fd, _STREAM_HEADERS, strlen (_STREAM_HEADERS), 0 ))) {
169- #ifdef DEBUG_DEFAULT_ON
170- printf ("failed sending headers!\n" );
171- #endif
204+ print_debug (" failed sending headers!\n " );
172205 return false ;
173206 }
174207
175208 if (is_send_error (httpd_socket_send (s->server , fd, _STREAM_BOUNDARY, strlen (_STREAM_BOUNDARY), 0 ))) {
176- #ifdef DEBUG_DEFAULT_ON
177- printf ("failed sending boundary!\n" );
178- #endif
209+ print_debug (" failed sending boundary!\n " );
179210 return false ;
180211 }
181212
182213 const BaseType_t r=xQueueSend (s->clients , (void *) &fd, 10 *portTICK_PERIOD_MS);
183214 if (r!=pdTRUE) {
184- #ifdef DEBUG_DEFAULT_ON
185- printf ("[cam_streamer] failed to enqueue fd %d\n" , fd );
186- #endif
215+ print_debug (" [cam_streamer] failed to enqueue fd %d\n " , fd);
187216#define EMSG " failed to enqueue"
188217 httpd_socket_send (s->server , fd, EMSG, strlen (EMSG), 0 );
189218#undef EMSG
190219 } else {
191- #ifdef DEBUG_DEFAULT_ON
192- printf ("[cam_streamer] socket %d enqueued\n" , fd );
193- #endif
220+ print_debug (" [cam_streamer] socket %d enqueued\n " , fd);
194221 __atomic_fetch_add (&s->num_clients , 1 , __ATOMIC_RELAXED);
195222 vTaskResume (s->task );
196223 }
0 commit comments