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