forked from Motion-Project/motion
-
Notifications
You must be signed in to change notification settings - Fork 0
/
netcam.h
329 lines (271 loc) · 13.1 KB
/
netcam.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
/*
* netcam.h
*
* Include file for handling network cameras.
*
* This code was inspired by the original netcam.c module
* written by Jeroen Vreeken and enhanced by several Motion
* project contributors, particularly Angel Carpintero and
* Christopher Price.
*
* Copyright 2005, William M. Brack
* This software is distributed under the GNU Public license
* Version 2. See also the file 'COPYING'.
*/
#ifndef _INCLUDE_NETCAM_H
#define _INCLUDE_NETCAM_H
#include <jpeglib.h>
#include <setjmp.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <regex.h>
/*
* We are aiming to get the gcc compilation of motion practically "warning
* free", when using all the possible warning switches. The following macro
* is to allow some function prototypes to include parameters which, at the
* moment, are not used, but either still "need to be declared", or else are
* planned to be used in the near future. Eventually this macro will go into
* motion.h, but that will be a little later.
*/
/**
* ATTRIBUTE_UNUSED:
*
* Macro used to signal to GCC unused function parameters
*/
#ifdef __GNUC__
#ifdef HAVE_ANSIDECL_H
#include <ansidecl.h>
#endif
#ifndef ATTRIBUTE_UNUSED
#define ATTRIBUTE_UNUSED __attribute__((unused))
#endif
#else
#define ATTRIBUTE_UNUSED
#endif
/* netcam_wget.h needs to have netcam_context_ptr */
typedef struct netcam_context *netcam_context_ptr;
#include "netcam_wget.h" /* needed for struct rbuf */
#define NETCAM_BUFFSIZE 4096 /* Initial size reserved for a JPEG
image. If expansion is required,
this value is also used for the
amount to increase. */
/*
* Error return codes for netcam routines. The values are "bit
* significant". All error returns will return bit 1 set to indicate
* these are "netcam errors"; additional bits set will give more detail
* as to what kind of error it was.
* Bit 0 is reserved for V4L type errors.
*
*/
#define NETCAM_GENERAL_ERROR 0x02 /* binary 000010 */
#define NETCAM_NOTHING_NEW_ERROR 0x06 /* binary 000110 */
#define NETCAM_JPEG_CONV_ERROR 0x0a /* binary 001010 */
#define NETCAM_RESTART_ERROR 0x12 /* binary 010010 */
#define NETCAM_FATAL_ERROR -2
/*
* struct url_t is used when parsing the user-supplied URL, as well as
* when attempting to connect to the netcam.
*/
struct url_t {
char *service;
char *userpass;
char *host;
int port;
char *path;
};
/*
* We use a special "triple-buffer" technique. There are
* three separate buffers (latest, receiving and jpegbuf)
* which are each described using a struct netcam_image_buff
*/
typedef struct netcam_image_buff {
char *ptr;
int content_length;
size_t size; /* total allocated size */
size_t used; /* bytes already used */
struct timeval image_time; /* time this image was received */
} netcam_buff;
typedef netcam_buff *netcam_buff_ptr;
typedef struct file_context {
char *path; /* the path within the URL */
int control_file_desc; /* file descriptor for the control socket */
time_t last_st_mtime; /* time this image was modified */
} tfile_context;
#define NCS_UNSUPPORTED 0 /* streaming is not supported */
#define NCS_MULTIPART 1 /* streaming is done via multipart */
#define NCS_BLOCK 2 /* streaming is done via MJPG-block */
#define NCS_RTSP 3 /* streaming is done via RTSP */
enum RTSP_STATUS {
RTSP_NOTCONNECTED, /* The camera has never connected */
RTSP_CONNECTED, /* The camera is currently connected */
RTSP_RECONNECTING, /* Motion is trying to reconnect to camera */
RTSP_READINGIMAGE /* Motion is reading a image from camera */
};
/*
* struct netcam_context contains all the structures and other data
* for an individual netcam.
*/
typedef struct netcam_context {
struct context *cnt; /* pointer to parent motion
context structure */
int finish; /* flag to break the camera-
handling thread out of it's
infinite loop in emergency */
int threadnr; /* motion's thread number for
the camera-handling thread
(if required). Used for
error reporting */
pthread_t thread_id; /* thread i.d. for a camera-
handling thread (if required).
Not currently used, but may be
useful in the future */
pthread_mutex_t mutex; /* mutex used with conditional waits */
pthread_cond_t exiting; /* pthread condition structure to let
the camera-handler acknowledge that
it's finished */
pthread_cond_t cap_cond; /* pthread condition structure to
initiate next capture request (used
only with non-streaming cameras */
pthread_cond_t pic_ready; /* pthread condition structure used
for synchronisation between the
camera handler and the motion main
loop, showing new frame is ready */
int start_capture; /* besides our signalling condition,
we also keep a flag to assure the
camera-handler will always start
a new cycle as soon as possible,
even if it's not currently waiting
on the condition. */
char *connect_host; /* the host to connect to (may be
either the camera host, or
possibly a proxy) */
int connect_port; /* usually will be 80, but can be
specified as something else by
the user */
int connect_http_10; /* set to TRUE if HTTP 1.0 connection
(netcam_keepalive off) */
int connect_http_11; /* set to TRUE if HTTP 1.1 connection
(netcam_keepalive on) */
int connect_keepalive; /* set to TRUE if connection maintained after
a request, otherwise FALSE to close down
the socket each time (netcam_keealive force) */
int keepalive_thisconn; /* set to TRUE if cam has sent 'Keep-Alive' in this connection */
int keepalive_timeup; /* set to TRUE if it is time to close netcam's socket,
and then re-open it with Keep-Alive set again.
Even Keep-Alive netcams need a close/open sometimes. */
char *connect_request; /* contains the complete string
required for connection to the
camera */
int sock; /* fd for the camera's socket.
Note that this value is also
present within the struct
rbuf *response. */
struct timeval timeout; /* The current timeout setting for
the socket. */
struct rbuf *response; /* this structure (defined in the
netcam_wget module) contains
the context for an HTTP
connection. Note that this
structure includes a large
buffer for the HTTP data */
struct ftp_context *ftp; /* this structure contains the
context for FTP connection */
struct file_context *file; /* this structure contains the
context for FILE connection */
struct rtsp_context *rtsp; /* this structure contains the
context for RTSP connection */
int (*get_image)(netcam_context_ptr);
/* Function to fetch the image from
the netcam. It is initialised in
netcam_setup depending upon whether
the picture source is from an http
server or from an ftp server */
struct netcam_caps { /* netcam capabilities: */
unsigned char streaming; /* See the NCS_* defines */
unsigned char content_length; /* 0 - unsupported */
} caps;
char *boundary; /* 'boundary' string when used to
separate mjpeg images */
size_t boundary_length; /* string length of the boundary
string */
/* Three separate buffers are used
for handling the data. Their
definitions follow: */
netcam_buff_ptr latest; /* This buffer contains the latest
frame received from the camera */
netcam_buff_ptr receiving; /* This buffer is used for receiving
data from the camera */
netcam_buff_ptr jpegbuf; /* This buffer is used for jpeg
decompression */
int imgcnt; /* count for # of received jpegs */
int imgcnt_last; /* remember last count to check if a new
image arrived */
int warning_count; /* simple count of number of warnings
since last good frame was received */
int error_count; /* simple count of number of errors since
last good frame was received */
unsigned int width; /* info for decompression */
unsigned int height;
int JFIF_marker; /* Debug to know if JFIF was present or not */
unsigned int netcam_tolerant_check; /* For network cameras with buggy firmwares */
struct timeval last_image; /* time the most recent image was
received */
float av_frame_time; /* "running average" of time between
successive frames (microseconds) */
struct jpeg_error_mgr jerr;
jmp_buf setjmp_buffer;
int jpeg_error; /* flag to show error or warning
occurred during decompression*/
} netcam_context;
#define MJPG_MH_MAGIC "MJPG"
#define MJPG_MH_MAGIC_SIZE 4
/*
* MJPG Chunk header for MJPG streaming.
* Little-endian data is read from the network.
*/
typedef struct {
char mh_magic[MJPG_MH_MAGIC_SIZE]; /* must contain the string MJP
not null-terminated. */
unsigned int mh_framesize; /* Total size of the current
frame in bytes (~45kb on WVC200) */
unsigned short mh_framewidth; /* Frame width in pixels */
unsigned short mh_frameheight; /* Frame height in pixels */
unsigned int mh_frameoffset; /* Offset of this chunk relative
to the beginning of frame. */
unsigned short mh_chunksize; /* The size of the chunk data
following this header. */
char mh_reserved[30]; /* Unknown data, seems to be
constant between all headers */
} mjpg_header;
/*
* Declare prototypes for our external entry points
*/
/* Within netcam_jpeg.c */
int netcam_proc_jpeg (struct netcam_context *, unsigned char *);
void netcam_fix_jpeg_header(struct netcam_context *);
void netcam_get_dimensions (struct netcam_context *);
/* Within netcam.c */
int netcam_start (struct context *);
int netcam_next (struct context *, unsigned char *);
void netcam_cleanup (struct netcam_context *, int);
ssize_t netcam_recv(netcam_context_ptr, void *, size_t);
void netcam_url_free(struct url_t *parse_url);
/**
* Publish new image
*
* Moves the image in 'receiving' into 'latest' and updates last frame time
*/
void netcam_image_read_complete(netcam_context_ptr netcam);
/**
* This routine checks whether there is enough room in a buffer to copy
* some additional data. If there is not enough room, it will re-allocate
* the buffer and adjust it's size.
*
* Parameters:
* buff Pointer to a netcam_image_buffer structure.
* numbytes The number of bytes to be copied.
*
* Returns: Nothing
*/
void netcam_check_buffsize(netcam_buff_ptr buff, size_t numbytes);
#endif