7
7
#include < freertos/FreeRTOS.h>
8
8
#include < freertos/queue.h>
9
9
#include < freertos/task.h>
10
+ #include < sys/socket.h>
10
11
11
12
#include " cam_streamer.h"
12
13
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
+
13
28
#define PART_BOUNDARY " 123456789000000000000987654321"
14
29
15
30
#define _STREAM_HEADERS " HTTP/1.1 200 OK\r\n " \
18
33
" Keep-Alive: timeout=15\r\n " \
19
34
" Content-Type: multipart/x-mixed-replace;boundary=" PART_BOUNDARY " \r\n "
20
35
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
+
21
46
static const char * _STREAM_BOUNDARY = " \r\n --" PART_BOUNDARY " \r\n " ;
22
47
static const char * _STREAM_PART = " Content-Type: image/jpeg\r\n Content-Length: %u\r\n\r\n " ;
23
48
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
+
24
58
static uint8_t is_send_error (int r) {
25
59
switch (r) {
26
60
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 " );
30
62
return 1 ;
31
63
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 " );
35
65
return 1 ;
36
66
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 " );
40
68
return 1 ;
41
69
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 " );
45
71
return 1 ;
46
72
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);
50
74
return 0 ;
51
75
}
52
76
}
53
77
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 ) {
55
79
memset (s, 0 , sizeof (cam_streamer_t ));
56
- s -> frame_delay = 1000000 / fps ;
80
+ s->frame_delay =1000 *frame_delay ;
57
81
s->clients =xQueueCreate (CAM_STREAMER_MAX_CLIENTS*2 , sizeof (int ));
58
82
s->server =server;
59
83
}
60
84
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
+
61
90
static void cam_streamer_update_frame (cam_streamer_t *s) {
62
91
uint8_t l=0 ;
63
92
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) {
73
102
s->last_updated =esp_timer_get_time ();
74
103
s->part_len =snprintf (s->part_buf , 64 , _STREAM_PART, s->buf ->len );
75
104
__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 " );
79
106
}
80
107
81
108
static void cam_streamer_decrement_num_clients (cam_streamer_t *s) {
82
109
size_t num_clients=s->num_clients ;
83
110
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 " );
87
112
}
88
113
89
114
void cam_streamer_task (void *p) {
@@ -93,35 +118,35 @@ void cam_streamer_task(void *p) {
93
118
int fd;
94
119
unsigned int n_entries;
95
120
for (;;) {
96
- while (!(n_entries = uxQueueMessagesWaiting (s -> clients )))
121
+ while (!(n_entries=uxQueueMessagesWaiting (s->clients ))) {
122
+ if (autoLamp && lampVal!=-1 ) setLamp (0 );
97
123
vTaskSuspend (NULL );
124
+ if (autoLamp && lampVal!=-1 ) setLamp (lampVal);
125
+ }
98
126
99
127
current_time=esp_timer_get_time ();
100
128
if ((current_time-last_time)<s->frame_delay )
101
129
vTaskDelay ((s->frame_delay -(current_time-last_time))/(1000 *portTICK_PERIOD_MS));
102
- last_time = current_time ;
103
130
104
131
cam_streamer_update_frame (s);
105
132
133
+ print_debug (" [cam_streamer] frame_size: %luB %lums\n " , s->buf ->len , (current_time-last_time)/1000 );
134
+ last_time=current_time;
135
+
106
136
for (unsigned int i=0 ; i<n_entries; ++i) {
107
137
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 " );
111
139
continue ;
112
140
}
113
141
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);
118
143
119
144
if (is_send_error (httpd_socket_send (s->server , fd, s->part_buf , s->part_len , 0 ))) {
120
145
cam_streamer_decrement_num_clients (s);
121
146
continue ;
122
147
}
123
148
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 ))) {
125
150
cam_streamer_decrement_num_clients (s);
126
151
continue ;
127
152
}
@@ -132,20 +157,16 @@ void cam_streamer_task(void *p) {
132
157
}
133
158
134
159
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);
138
161
}
139
162
}
140
163
}
141
164
142
165
void cam_streamer_start (cam_streamer_t *s) {
143
166
BaseType_t r=xTaskCreate (cam_streamer_task, " cam_streamer" , 10 *1024 , (void *) s, tskIDLE_PRIORITY+3 , &s->task );
144
167
145
- #ifdef DEBUG_DEFAULT_ON
146
168
if (r!=pdPASS)
147
- printf ("[cam_streamer] failed to create task!\n" );
148
- #endif
169
+ print_debug (" [cam_streamer] failed to create task!\n " );
149
170
}
150
171
151
172
void cam_streamer_stop (cam_streamer_t *s) {
@@ -162,35 +183,41 @@ void cam_streamer_dequeue_all_clients(cam_streamer_t *s) {
162
183
}
163
184
164
185
bool 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));
168
203
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 " );
172
205
return false ;
173
206
}
174
207
175
208
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 " );
179
210
return false ;
180
211
}
181
212
182
213
const BaseType_t r=xQueueSend (s->clients , (void *) &fd, 10 *portTICK_PERIOD_MS);
183
214
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);
187
216
#define EMSG " failed to enqueue"
188
217
httpd_socket_send (s->server , fd, EMSG, strlen (EMSG), 0 );
189
218
#undef EMSG
190
219
} 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);
194
221
__atomic_fetch_add (&s->num_clients , 1 , __ATOMIC_RELAXED);
195
222
vTaskResume (s->task );
196
223
}
0 commit comments