~ubuntu-branches/ubuntu/karmic/motion/karmic-proposed

« back to all changes in this revision

Viewing changes to video.c

  • Committer: Bazaar Package Importer
  • Author(s): Juan Angulo Moreno
  • Date: 2008-06-10 09:15:47 UTC
  • mfrom: (4.1.4 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080610091547-2dcuzqpznlivgvxl
Tags: 3.2.9-4
* Fixed errors in the file debian/rules that affected the non-apply of 
  two patches (01_ffmpeg_creation_update_API.dpatch and 
  02_webhttpd_security_video2_backport.dpatch) (Closes: #484566).
* Bumped Standards-Version to 3.8.0. No changes to package necessary.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 *      See also the file 'COPYING'.
7
7
 *
8
8
 */
 
9
#ifndef WITHOUT_V4L
9
10
 
10
11
/* Common stuff: */
11
12
#include "motion.h"
12
13
#include "video.h"
13
 
#include "conf.h"
14
14
/* for rotation */
15
15
#include "rotate.h"
16
16
 
17
 
#ifndef WITHOUT_V4L
18
17
 
19
18
/* for the v4l stuff: */
20
19
#include "pwc-ioctl.h"
21
 
#include "sys/mman.h"
22
 
#include "sys/ioctl.h"
23
 
#include "math.h"
 
20
#include <sys/mman.h>
 
21
//#include "sys/ioctl.h"
 
22
#include <math.h>
24
23
#include <sys/utsname.h>
25
24
#include <dirent.h>
26
25
 
27
 
#define MAX2(x, y) ((x) > (y) ? (x) : (y))
28
 
#define MIN2(x, y) ((x) < (y) ? (x) : (y))
29
26
 
30
27
static void v4l_picture_controls(struct context *cnt, struct video_dev *viddev)
31
28
{
32
 
        int dev=viddev->fd;
33
 
        unsigned char *image = cnt->imgs.image_ring_buffer;
 
29
        int dev = viddev->fd;
34
30
        struct video_picture vid_pic;
35
31
        int make_change = 0;
36
32
 
37
33
        if (cnt->conf.contrast && cnt->conf.contrast != viddev->contrast) {
38
34
 
39
35
                if (ioctl(dev, VIDIOCGPICT, &vid_pic)==-1)
40
 
                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
 
36
                        motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
41
37
 
42
38
                make_change = 1;
43
39
                vid_pic.contrast = cnt->conf.contrast * 256;
48
44
 
49
45
                if (!make_change) {
50
46
                        if (ioctl(dev, VIDIOCGPICT, &vid_pic)==-1)
51
 
                                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
 
47
                                motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
52
48
                }
53
49
 
54
50
                make_change = 1;
60
56
 
61
57
                if (!make_change) {
62
58
                        if (ioctl(dev, VIDIOCGPICT, &vid_pic)==-1)
63
 
                                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
 
59
                                motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
64
60
                }
65
61
 
66
62
                make_change = 1;
70
66
        
71
67
        if (cnt->conf.autobright) {
72
68
                
73
 
                int brightness_window_high;
74
 
                int brightness_window_low;
75
 
                int brightness_target;
76
 
                int i, j = 0, avg = 0, step = 0;
77
 
                
78
 
                if (cnt->conf.brightness)
79
 
                        brightness_target = cnt->conf.brightness;
80
 
                else
81
 
                        brightness_target = 128;
82
 
                
83
 
                brightness_window_high = MIN2(brightness_target + 10, 255);
84
 
                brightness_window_low = MAX2(brightness_target - 10, 1);
85
 
                
86
 
                for (i = 0; i < cnt->imgs.motionsize; i += 101) {
87
 
                        avg += image[i];
88
 
                        j++;
89
 
                }
90
 
                avg = avg / j;
91
 
                
92
 
                if (avg > brightness_window_high || avg < brightness_window_low) {
 
69
                if (vid_do_autobright(cnt, viddev)) {
93
70
                        /* If we already read the VIDIOGPICT - we should not do it again */
94
71
                        if (!make_change) {
95
72
                                if (ioctl(dev, VIDIOCGPICT, &vid_pic)==-1)
96
 
                                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
97
 
                        }
98
 
                        /* average is above window - turn down brigtness - go for the target */
99
 
                        if (avg > brightness_window_high) {
100
 
                                step = MIN2((avg - brightness_target)/5+1, viddev->brightness);
101
 
                                if (viddev->brightness > step+1) {
102
 
                                        viddev->brightness -= step;
103
 
                                        vid_pic.brightness = viddev->brightness * 256;
104
 
                                        make_change = 1;
105
 
                                }
106
 
                        }
107
 
                        /* average is below window - turn up brigtness - go for the target */
108
 
                        if (avg < brightness_window_low) {
109
 
                                step = MIN2((brightness_target - avg)/5+1, 255 - viddev->brightness);
110
 
                                if (viddev->brightness < 255-step ) {
111
 
                                        viddev->brightness += step;
112
 
                                        vid_pic.brightness = viddev->brightness * 256;
113
 
                                        make_change = 1;
114
 
                                }
115
 
                        }
 
73
                                        motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
 
74
                        }
 
75
                                        
 
76
                        vid_pic.brightness = viddev->brightness * 256;
 
77
                        make_change = 1;
116
78
                }
 
79
        
117
80
        } else {
118
81
                if (cnt->conf.brightness && cnt->conf.brightness != viddev->brightness) {
119
82
                        if (!make_change) {
120
83
                                if (ioctl(dev, VIDIOCGPICT, &vid_pic)==-1)
121
 
                                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
 
84
                                        motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
122
85
                        }
123
86
        
124
87
                        make_change = 1;
129
92
 
130
93
        if (make_change) {
131
94
                if (ioctl(dev, VIDIOCSPICT, &vid_pic)==-1)
132
 
                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCSPICT)");
133
 
        }
134
 
}
135
 
                
136
 
 
137
 
void yuv422to420p(unsigned char *map, unsigned char *cap_map, int width, int height)
138
 
{
139
 
        unsigned char *src, *dest, *src2, *dest2;
140
 
        int i, j;
141
 
 
142
 
        /* Create the Y plane */
143
 
        src=cap_map;
144
 
        dest=map;
145
 
        for (i=width*height; i; i--) {
146
 
                *dest++=*src;
147
 
                src+=2;
148
 
        }
149
 
        /* Create U and V planes */
150
 
        src=cap_map+1;
151
 
        src2=cap_map+width*2+1;
152
 
        dest=map+width*height;
153
 
        dest2=dest+(width*height)/4;
154
 
        for (i=height/2; i; i--) {
155
 
                for (j=width/2; j; j--) {
156
 
                        *dest=((int)*src+(int)*src2)/2;
157
 
                        src+=2;
158
 
                        src2+=2;
159
 
                        dest++;
160
 
                        *dest2=((int)*src+(int)*src2)/2;
161
 
                        src+=2;
162
 
                        src2+=2;
163
 
                        dest2++;
164
 
                }
165
 
                src+=width*2;
166
 
                src2+=width*2;
167
 
        }
168
 
}
169
 
 
170
 
void rgb24toyuv420p(unsigned char *map, unsigned char *cap_map, int width, int height)
171
 
{
172
 
        unsigned char *y, *u, *v;
173
 
        unsigned char *r, *g, *b;
174
 
        int i, loop;
175
 
 
176
 
        b=cap_map;
177
 
        g=b+1;
178
 
        r=g+1;
179
 
        y=map;
180
 
        u=y+width*height;
181
 
        v=u+(width*height)/4;
182
 
        memset(u, 0, width*height/4);
183
 
        memset(v, 0, width*height/4);
184
 
 
185
 
        for(loop=0; loop<height; loop++) {
186
 
                for(i=0; i<width; i+=2) {
187
 
                        *y++=(9796**r+19235**g+3736**b)>>15;
188
 
                        *u+=((-4784**r-9437**g+14221**b)>>17)+32;
189
 
                        *v+=((20218**r-16941**g-3277**b)>>17)+32;
190
 
                        r+=3;
191
 
                        g+=3;
192
 
                        b+=3;
193
 
                        *y++=(9796**r+19235**g+3736**b)>>15;
194
 
                        *u+=((-4784**r-9437**g+14221**b)>>17)+32;
195
 
                        *v+=((20218**r-16941**g-3277**b)>>17)+32;
196
 
                        r+=3;
197
 
                        g+=3;
198
 
                        b+=3;
199
 
                        u++;
200
 
                        v++;
201
 
                }
202
 
 
203
 
                if ((loop & 1) == 0)
204
 
                {
205
 
                        u-=width/2;
206
 
                        v-=width/2;
207
 
                }
208
 
        }
209
 
}
 
95
                        motion_log(LOG_ERR, 1, "ioctl (VIDIOCSPICT)");
 
96
        }
 
97
}
 
98
 
 
99
 
210
100
 
211
101
/*******************************************************************************************
212
102
        Video4linux capture routines
213
103
*/
214
104
 
215
105
 
216
 
static unsigned char *v4l_start(struct context *cnt, struct video_dev *viddev, int width, int height, int input, int norm,
217
 
                        unsigned long freq, int tuner_number)
 
106
unsigned char *v4l_start(struct context *cnt, struct video_dev *viddev, int width, int height,
 
107
                                int input, int norm, unsigned long freq, int tuner_number)
218
108
{
219
 
        int dev=viddev->fd;
 
109
        int dev = viddev->fd;
220
110
        struct video_capability vid_caps;
221
111
        struct video_channel vid_chnl;
222
112
        struct video_tuner vid_tuner;
223
 
        struct video_window vid_win;
224
113
        struct video_mbuf vid_buf;
225
114
        struct video_mmap vid_mmap;
226
 
        unsigned char *map;
 
115
        void *map;
227
116
 
228
117
        if (ioctl (dev, VIDIOCGCAP, &vid_caps) == -1) {
229
 
                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGCAP)");
 
118
                motion_log(LOG_ERR, 1, "ioctl (VIDIOCGCAP)");
230
119
                return (NULL);
231
120
        }
232
 
        if (vid_caps.type & VID_TYPE_MONOCHROME) viddev->v4l_fmt=VIDEO_PALETTE_GREY;
 
121
 
 
122
        if (vid_caps.type & VID_TYPE_MONOCHROME)
 
123
                viddev->v4l_fmt=VIDEO_PALETTE_GREY;
 
124
 
233
125
        if (input != IN_DEFAULT) {
234
126
                memset(&vid_chnl, 0, sizeof(struct video_channel));
235
127
                vid_chnl.channel = input;
 
128
 
236
129
                if (ioctl (dev, VIDIOCGCHAN, &vid_chnl) == -1) {
237
 
                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGCHAN)");
 
130
                        motion_log(LOG_ERR, 1, "ioctl (VIDIOCGCHAN)");
238
131
                } else {
239
132
                        vid_chnl.channel = input;
240
133
                        vid_chnl.norm    = norm;
241
134
                        if (ioctl (dev, VIDIOCSCHAN, &vid_chnl) == -1) {
242
 
                                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCSCHAN)");
 
135
                                motion_log(LOG_ERR, 1, "ioctl (VIDIOCSCHAN)");
243
136
                                return (NULL);
244
137
                        }
245
138
                }
246
139
        }
 
140
 
247
141
        if (freq) {
248
142
                vid_tuner.tuner = tuner_number;
249
143
                if (ioctl (dev, VIDIOCGTUNER, &vid_tuner)==-1) {
250
 
                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGTUNER)");
 
144
                        motion_log(LOG_ERR, 1, "ioctl (VIDIOCGTUNER)");
251
145
                } else {
252
146
                        if (vid_tuner.flags & VIDEO_TUNER_LOW) {
253
147
                                freq=freq*16; /* steps of 1/16 KHz */
255
149
                                freq=(freq*10)/625;
256
150
                        }
257
151
                        if (ioctl(dev, VIDIOCSFREQ, &freq)==-1) {
258
 
                                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCSFREQ)");
 
152
                                motion_log(LOG_ERR, 1, "ioctl (VIDIOCSFREQ)");
259
153
                                return (NULL);
260
154
                        }
261
155
                        if (cnt->conf.setup_mode)
262
 
                                motion_log(cnt, -1, 0, "Frequency set");
 
156
                                motion_log(-1, 0, "Frequency set");
263
157
                }
264
158
        }
 
159
 
265
160
        if (ioctl (dev, VIDIOCGMBUF, &vid_buf) == -1) {
266
 
                motion_log(cnt, LOG_WARNING, 0, "No mmap falling back on read");
267
 
                if (ioctl (dev, VIDIOCGWIN, &vid_win)== -1) {
268
 
                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGWIN)");
269
 
                        return (NULL);
270
 
                }
271
 
                vid_win.width=width;
272
 
                vid_win.height=height;
273
 
                vid_win.clipcount=0;
274
 
                if (ioctl (dev, VIDIOCSWIN, &vid_win)== -1) {
275
 
                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCSWIN)");
276
 
                        return (NULL);
277
 
                }
278
 
                motion_log(cnt, LOG_WARNING, 0, "V4L capturing using read is deprecated!");
279
 
                motion_log(cnt, LOG_WARNING, 0, "Motion now only supports mmap.");
280
 
                motion_log(cnt, LOG_WARNING, 0, "Motion Exits.");
281
 
                exit(1);  //FIXME - This seems like an old oops that was never cleaned out or fixed
282
 
                viddev->v4l_read_img=1;
283
 
                map=mymalloc(cnt ,width*height*3);
284
 
                viddev->v4l_maxbuffer=1;
285
 
                viddev->v4l_curbuffer=0;
286
 
                viddev->v4l_buffers[0]=map;
287
 
        }else{
 
161
                motion_log(LOG_ERR, 0, "ioctl(VIDIOCGMBUF) - Error device does not support memory map");
 
162
                motion_log(LOG_ERR, 0, "V4L capturing using read is deprecated!");
 
163
                motion_log(LOG_ERR, 0, "Motion only supports mmap.");
 
164
                return NULL;
 
165
        } else {
288
166
                map=mmap(0, vid_buf.size, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0);
289
167
                viddev->size_map=vid_buf.size;
290
168
                if (vid_buf.frames>1) {
291
169
                        viddev->v4l_maxbuffer=2;
292
170
                        viddev->v4l_buffers[0]=map;
293
 
                        viddev->v4l_buffers[1]=map+vid_buf.offsets[1];
 
171
                        viddev->v4l_buffers[1]=(unsigned char *)map + vid_buf.offsets[1];
294
172
                } else {
295
173
                        viddev->v4l_buffers[0]=map;
296
174
                        viddev->v4l_maxbuffer=1;
297
175
                }
298
176
 
299
 
                if ((unsigned char *)-1 == (unsigned char *)map) {
 
177
                if (MAP_FAILED == map) {
300
178
                        return (NULL);
301
179
                }
302
180
                viddev->v4l_curbuffer=0;
305
183
                vid_mmap.width=width;
306
184
                vid_mmap.height=height;
307
185
                if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {
308
 
                        motion_log(cnt, LOG_DEBUG, 1, "Failed with YUV420P, trying YUV422 palette");
 
186
                        motion_log(LOG_DEBUG, 1, "Failed with YUV420P, trying YUV422 palette");
309
187
                        viddev->v4l_fmt=VIDEO_PALETTE_YUV422;
310
188
                        vid_mmap.format=viddev->v4l_fmt;
311
189
                        /* Try again... */
312
190
                        if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {
313
 
                                motion_log(cnt, LOG_DEBUG, 1, "Failed with YUV422, trying RGB24 palette");
314
 
                                viddev->v4l_fmt=VIDEO_PALETTE_RGB24;
 
191
                                motion_log(LOG_DEBUG, 1, "Failed with YUV422, trying YUYV palette");
 
192
                                viddev->v4l_fmt=VIDEO_PALETTE_YUYV;
315
193
                                vid_mmap.format=viddev->v4l_fmt;
316
 
                                /* Try again... */
 
194
                                
317
195
                                if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {
318
 
                                        motion_log(cnt, LOG_DEBUG, 1, "Failed with RGB24, trying GREYSCALE palette");
319
 
                                        viddev->v4l_fmt=VIDEO_PALETTE_GREY;
 
196
                                        motion_log(LOG_DEBUG, 1, "Failed with YUYV, trying RGB24 palette");
 
197
                                        viddev->v4l_fmt=VIDEO_PALETTE_RGB24;
320
198
                                        vid_mmap.format=viddev->v4l_fmt;
321
 
                                        /* Try one last time... */
 
199
                                        /* Try again... */
 
200
                                
322
201
                                        if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {
323
 
                                                motion_log(cnt, LOG_ERR, 1, "Failed with all supported palettes "
 
202
                                                motion_log(LOG_DEBUG, 1, "Failed with RGB24, trying GREYSCALE palette");
 
203
                                                viddev->v4l_fmt=VIDEO_PALETTE_GREY;
 
204
                                                vid_mmap.format=viddev->v4l_fmt;
 
205
                                                /* Try one last time... */
 
206
                                                if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {
 
207
                                                        motion_log(LOG_ERR, 1, "Failed with all supported palettes "
324
208
                                                                            "- giving up");
325
 
                                                return (NULL);
 
209
                                                        return (NULL);
 
210
                                                }
326
211
                                        }
327
212
                                }
328
213
                        }
332
217
        switch (viddev->v4l_fmt) {
333
218
                case VIDEO_PALETTE_YUV420P:
334
219
                        viddev->v4l_bufsize=(width*height*3)/2;
 
220
                        motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_YUV420P palette");
335
221
                        break;
336
222
                case VIDEO_PALETTE_YUV422:
337
223
                        viddev->v4l_bufsize=(width*height*2);
 
224
                        motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_YUV422 palette");
 
225
                        break;
 
226
                case VIDEO_PALETTE_YUYV:
 
227
                        viddev->v4l_bufsize=(width*height*2);
 
228
                        motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_YUYV palette");
338
229
                        break;
339
230
                case VIDEO_PALETTE_RGB24:
340
231
                        viddev->v4l_bufsize=(width*height*3);
 
232
                        motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_RGB24 palette");
341
233
                        break;
342
234
                case VIDEO_PALETTE_GREY:
343
235
                        viddev->v4l_bufsize=width*height;
 
236
                        motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_GREY palette");
344
237
                        break;
345
238
        }
346
239
        return map;
348
241
 
349
242
 
350
243
/**
351
 
 * v4l_next fetches a video frame from a v4l device
 
244
 * v4l_next
 
245
 *                v4l_next fetches a video frame from a v4l device
 
246
 *
352
247
 * Parameters:
353
 
 *     cnt        Pointer to the context for this thread
354
 
 *     viddev     Pointer to struct containing video device handle
 
248
 *     viddev     Pointer to struct containing video device handle amd device parameters
355
249
 *     map        Pointer to the buffer in which the function puts the new image
356
250
 *     width      Width of image in pixels
357
251
 *     height     Height of image in pixels
358
252
 *
359
253
 * Returns
360
 
 *     0          Success
361
 
 *    -1          Fatal error
362
 
 *     1          Non fatal error (not implemented)
 
254
 *     0               Success
 
255
 *    V4L_FATAL_ERROR  Fatal error
 
256
 *    Positive with bit 0 set and bit 1 unset
 
257
 *                     Non fatal error (not implemented)
363
258
 */
364
 
int v4l_next(struct context *cnt, struct video_dev *viddev, unsigned char *map, int width, int height)
 
259
int v4l_next(struct video_dev *viddev, unsigned char *map, int width, int height)
365
260
{
366
 
        int dev=viddev->fd;
367
 
        int frame=viddev->v4l_curbuffer;
 
261
        int dev = viddev->fd;
 
262
        int frame = viddev->v4l_curbuffer;
368
263
        struct video_mmap vid_mmap;
369
 
        unsigned char *cap_map=NULL;
 
264
        unsigned char *cap_map;
370
265
 
371
266
        sigset_t  set, old;
372
267
 
373
 
        if (viddev->v4l_read_img) {
374
 
                if (read(dev, map, viddev->v4l_bufsize) != viddev->v4l_bufsize)
375
 
                        return -1;
376
 
        } else {
377
 
                vid_mmap.format=viddev->v4l_fmt;
378
 
                vid_mmap.width=width;
379
 
                vid_mmap.height=height;
380
 
                /* Block signals during IOCTL */
381
 
                sigemptyset (&set);
382
 
                sigaddset (&set, SIGCHLD);
383
 
                sigaddset (&set, SIGALRM);
384
 
                sigaddset (&set, SIGUSR1);
385
 
                sigaddset (&set, SIGTERM);
386
 
                sigaddset (&set, SIGHUP);
387
 
                pthread_sigmask (SIG_BLOCK, &set, &old);
388
 
 
389
 
                cap_map=viddev->v4l_buffers[viddev->v4l_curbuffer];
390
 
                viddev->v4l_curbuffer++;
391
 
                if (viddev->v4l_curbuffer >= viddev->v4l_maxbuffer)
392
 
                        viddev->v4l_curbuffer=0;
393
 
                vid_mmap.frame=viddev->v4l_curbuffer;
394
 
 
395
 
                if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {
396
 
                        motion_log(cnt, LOG_ERR, 1, "mcapture error in proc %d", getpid());
397
 
                        sigprocmask (SIG_UNBLOCK, &old, NULL);
398
 
                        return (-1);
399
 
                }
400
 
 
401
 
                vid_mmap.frame=frame;
402
 
                if (ioctl(dev, VIDIOCSYNC, &vid_mmap.frame) == -1) {
403
 
                        motion_log(cnt, LOG_ERR, 1, "sync error in proc %d", getpid());
404
 
                        sigprocmask (SIG_UNBLOCK, &old, NULL);
405
 
                }
406
 
                
407
 
                pthread_sigmask (SIG_UNBLOCK, &old, NULL);        /*undo the signal blocking*/
408
 
        }
409
 
        if (!viddev->v4l_read_img) {
410
 
                switch (viddev->v4l_fmt) {
411
 
                        case VIDEO_PALETTE_RGB24:
412
 
                                rgb24toyuv420p(map, cap_map, width, height);
413
 
                                break;
414
 
                        case VIDEO_PALETTE_YUV422:
415
 
                                yuv422to420p(map, cap_map, width, height);
416
 
                                break;
417
 
                        default:
418
 
                                memcpy(map, cap_map, viddev->v4l_bufsize);
419
 
                }
420
 
        }
 
268
        /* MMAP method is used */
 
269
        vid_mmap.format = viddev->v4l_fmt;
 
270
        vid_mmap.width = width;
 
271
        vid_mmap.height = height;
 
272
 
 
273
        /* Block signals during IOCTL */
 
274
        sigemptyset(&set);
 
275
        sigaddset(&set, SIGCHLD);
 
276
        sigaddset(&set, SIGALRM);
 
277
        sigaddset(&set, SIGUSR1);
 
278
        sigaddset(&set, SIGTERM);
 
279
        sigaddset(&set, SIGHUP);
 
280
        pthread_sigmask (SIG_BLOCK, &set, &old);
 
281
 
 
282
        cap_map = viddev->v4l_buffers[viddev->v4l_curbuffer];
 
283
        viddev->v4l_curbuffer++;
 
284
 
 
285
        if (viddev->v4l_curbuffer >= viddev->v4l_maxbuffer)
 
286
                viddev->v4l_curbuffer = 0;
 
287
 
 
288
        vid_mmap.frame = viddev->v4l_curbuffer;
 
289
 
 
290
        if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {
 
291
                motion_log(LOG_ERR, 1, "mcapture error in proc %d", getpid());
 
292
                sigprocmask (SIG_UNBLOCK, &old, NULL);
 
293
                return V4L_FATAL_ERROR;
 
294
        }
 
295
 
 
296
        vid_mmap.frame=frame;
 
297
 
 
298
        if (ioctl(dev, VIDIOCSYNC, &vid_mmap.frame) == -1) {
 
299
                motion_log(LOG_ERR, 1, "sync error in proc %d", getpid());
 
300
                sigprocmask (SIG_UNBLOCK, &old, NULL);
 
301
        }
 
302
 
 
303
        pthread_sigmask (SIG_UNBLOCK, &old, NULL);        /*undo the signal blocking*/
 
304
 
 
305
        switch (viddev->v4l_fmt) {
 
306
                case VIDEO_PALETTE_RGB24:
 
307
                        conv_rgb24toyuv420p(map, cap_map, width, height);
 
308
                        break;
 
309
                case VIDEO_PALETTE_YUYV:
 
310
                case VIDEO_PALETTE_YUV422:
 
311
                        conv_yuv422to420p(map, cap_map, width, height);
 
312
                        break;
 
313
                default:
 
314
                        memcpy(map, cap_map, viddev->v4l_bufsize);
 
315
        }
 
316
 
421
317
 
422
318
        return 0;
423
319
}
436
332
                if (freq) {
437
333
                        vid_tuner.tuner = tuner_number;
438
334
                        if (ioctl (dev, VIDIOCGTUNER, &vid_tuner)==-1) {
439
 
                                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGTUNER)");
 
335
                                motion_log(LOG_ERR, 1, "ioctl (VIDIOCGTUNER)");
440
336
                        } else {
441
337
                                if (vid_tuner.flags & VIDEO_TUNER_LOW) {
442
338
                                        frequnits=freq*16; /* steps of 1/16 KHz */
444
340
                                        frequnits=(freq*10)/625;
445
341
                                }
446
342
                                if (ioctl(dev, VIDIOCSFREQ, &frequnits)==-1) {
447
 
                                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCSFREQ)");
 
343
                                        motion_log(LOG_ERR, 1, "ioctl (VIDIOCSFREQ)");
448
344
                                        return;
449
345
                                }
450
346
                        }
453
349
                vid_chnl.channel = input;
454
350
                
455
351
                if (ioctl (dev, VIDIOCGCHAN, &vid_chnl) == -1) {
456
 
                        motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGCHAN)");
 
352
                        motion_log(LOG_ERR, 1, "ioctl (VIDIOCGCHAN)");
457
353
                } else {
458
354
                        vid_chnl.channel = input;
459
355
                        vid_chnl.norm = norm;
460
356
                        if (ioctl (dev, VIDIOCSCHAN, &vid_chnl) == -1) {
461
 
                                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCSCHAN)");
 
357
                                motion_log(LOG_ERR, 1, "ioctl (VIDIOCSCHAN)");
462
358
                                return;
463
359
                        }
464
360
                }
470
366
                viddev->tuner_number=tuner_number;
471
367
                /* skip a few frames if needed */
472
368
                for (i=0; i<skip; i++)
473
 
                        v4l_next(cnt, viddev, map, width, height);
 
369
                        v4l_next(viddev, map, width, height);
474
370
        } else {
475
371
                /* No round robin - we only adjust picture controls */
476
372
                v4l_picture_controls(cnt, viddev);
477
373
        }
478
374
}
479
375
 
480
 
static int v4l_open_vidpipe(struct context *cnt)
 
376
static int v4l_open_vidpipe(void)
481
377
{
482
 
        int pipe = -1;
 
378
        int pipe_fd = -1;
483
379
        char pipepath[255];
484
380
        char buffer[255];
485
381
        char *major;
487
383
        struct utsname uts;
488
384
 
489
385
        if (uname(&uts) < 0) {
490
 
                motion_log(cnt, LOG_ERR, 1, "Unable to execute uname");
 
386
                motion_log(LOG_ERR, 1, "Unable to execute uname");
491
387
                return -1;
492
388
        }
493
389
        major = strtok(uts.release, ".");
494
390
        minor = strtok(NULL, ".");
495
391
        if ((major == NULL) || (minor == NULL) || (strcmp(major, "2"))) {
496
 
                motion_log(cnt, LOG_ERR, 1, "Unable to decipher OS version");
 
392
                motion_log(LOG_ERR, 1, "Unable to decipher OS version");
497
393
                return -1;
498
394
        }
499
395
        if (strcmp(minor, "5") < 0) {
506
402
 
507
403
                vloopbacks=fopen("/proc/video/vloopback/vloopbacks", "r");
508
404
                if (!vloopbacks) {
509
 
                        motion_log(cnt, LOG_ERR, 1, "Failed to open '/proc/video/vloopback/vloopbacks'");
 
405
                        motion_log(LOG_ERR, 1, "Failed to open '/proc/video/vloopback/vloopbacks'");
510
406
                        return -1;
511
407
                }
512
408
                
513
409
                /* Read vloopback version*/
514
410
                if (!fgets(buffer, 255, vloopbacks)) {
515
 
                        motion_log(cnt, LOG_ERR, 1, "Unable to read vloopback version");
 
411
                        motion_log(LOG_ERR, 1, "Unable to read vloopback version");
516
412
                        return -1;
517
413
                }
518
414
                
519
415
                fprintf(stderr,"\t%s", buffer);
520
416
                
521
 
                /* Read explaination line */
 
417
                /* Read explanation line */
522
418
                
523
419
                if (!fgets(buffer, 255, vloopbacks)) {
524
 
                        motion_log(cnt, LOG_ERR, 1, "Unable to read vloopback explanation line");
 
420
                        motion_log(LOG_ERR, 1, "Unable to read vloopback explanation line");
525
421
                        return -1;
526
422
                }
527
423
                
534
430
                                output=strtok(NULL, "\t");
535
431
                                ostatus=strtok(NULL, "\t");
536
432
                                if (istatus[0]=='-') {
537
 
                                        sprintf(pipepath, "/dev/%s", input);
538
 
                                        pipe=open(pipepath, O_RDWR);
539
 
                                        if (pipe>=0) {
540
 
                                                motion_log(cnt, -1, 0, "\tInput:  /dev/%s", input);
541
 
                                                motion_log(cnt, -1, 0, "\tOutput: /dev/%s", output);
 
433
                                        snprintf(pipepath, 255, "/dev/%s", input);
 
434
                                        pipe_fd=open(pipepath, O_RDWR);
 
435
                                        if (pipe_fd>=0) {
 
436
                                                motion_log(-1, 0, "\tInput:  /dev/%s", input);
 
437
                                                motion_log(-1, 0, "\tOutput: /dev/%s", output);
542
438
                                                break;
543
439
                                        }
544
440
                                }
556
452
                int tnum;
557
453
 
558
454
                if ((dir=opendir(prefix))== NULL) {
559
 
                        motion_log(cnt, LOG_ERR, 1, "Failed to open '%s'", prefix);
 
455
                        motion_log(LOG_ERR, 1, "Failed to open '%s'", prefix);
560
456
                        return -1;
561
457
                }
562
458
                while ((dirp=readdir(dir)) != NULL) {
563
459
                        if (!strncmp(dirp->d_name, "video", 5)) {
564
 
                                strcpy(buffer, prefix);
565
 
                                strcat(buffer, dirp->d_name);
566
 
                                strcat(buffer, "/name");
 
460
                                strncpy(buffer, prefix, 255);
 
461
                                strncat(buffer, dirp->d_name, 255);
 
462
                                strncat(buffer, "/name", 255);
567
463
                                if ((fd=open(buffer, O_RDONLY)) >= 0) {
568
464
                                        if ((read(fd, buffer, sizeof(buffer)-1))<0) {
569
465
                                                close(fd);
591
487
                                                strcat(buffer, dirp->d_name);
592
488
                                                if ((tfd=open(buffer, O_RDWR))>=0) {
593
489
                                                        strcpy(pipepath, buffer);
594
 
                                                        if (pipe>=0) {
595
 
                                                                close(pipe);
 
490
                                                        if (pipe_fd>=0) {
 
491
                                                                close(pipe_fd);
596
492
                                                        }
597
 
                                                        pipe = tfd;
 
493
                                                        pipe_fd = tfd;
598
494
                                                        low = tnum;
599
495
                                                }
600
496
                                        }
603
499
                        }
604
500
                }
605
501
                closedir(dir);
606
 
                if (pipe >= 0)
607
 
                        motion_log(cnt, -1, 0, "Opened input of %s", pipepath);
 
502
                if (pipe_fd >= 0)
 
503
                        motion_log(-1, 0, "Opened input of %s", pipepath);
608
504
        }
609
 
        return pipe;
 
505
        return pipe_fd;
610
506
}
611
507
 
612
 
static int v4l_startpipe(struct context *cnt, char *devname, int width, int height, int type)
 
508
static int v4l_startpipe(char *devname, int width, int height, int type)
613
509
{
614
510
        int dev;
615
511
        struct video_picture vid_pic;
616
512
        struct video_window vid_win;
617
513
 
618
514
        if (!strcmp(devname, "-")) {
619
 
                dev=v4l_open_vidpipe(cnt);
 
515
                dev=v4l_open_vidpipe();
620
516
        } else {
621
517
                dev=open(devname, O_RDWR);
622
518
        }
624
520
                return(-1);
625
521
 
626
522
        if (ioctl(dev, VIDIOCGPICT, &vid_pic)== -1) {
627
 
                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
 
523
                motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");
628
524
                return(-1);
629
525
        }
630
526
        vid_pic.palette=type;
631
527
        if (ioctl(dev, VIDIOCSPICT, &vid_pic)== -1) {
632
 
                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCSPICT)");
 
528
                motion_log(LOG_ERR, 1, "ioctl (VIDIOCSPICT)");
633
529
                return(-1);
634
530
        }
635
531
        if (ioctl(dev, VIDIOCGWIN, &vid_win)== -1) {
636
 
                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCGWIN)");
 
532
                motion_log(LOG_ERR, 1, "ioctl (VIDIOCGWIN)");
637
533
                return(-1);
638
534
        }
639
535
        vid_win.height=height;
640
536
        vid_win.width=width;
641
537
        if (ioctl(dev, VIDIOCSWIN, &vid_win)== -1) {
642
 
                motion_log(cnt, LOG_ERR, 1, "ioctl (VIDIOCSWIN)");
 
538
                motion_log(LOG_ERR, 1, "ioctl (VIDIOCSWIN)");
643
539
                return(-1);
644
540
        }
645
541
        return dev;
650
546
        return write(dev, image, size);
651
547
}
652
548
 
653
 
/*****************************************************************************
654
 
        Wrappers calling the actual capture routines
655
 
 *****************************************************************************/
656
 
 
657
 
#endif /*WITHOUT_V4L*/
658
 
/* big lock for vid_start */
659
 
pthread_mutex_t vid_mutex;
660
 
#ifndef WITHOUT_V4L
661
 
 
662
 
/* structure used for per device locking */
663
 
struct video_dev **viddevs=NULL;
664
 
 
665
 
void vid_init(struct context *cnt)
666
 
{
667
 
        if (!viddevs) {
668
 
                viddevs=mymalloc(cnt, sizeof(struct video_dev *));
669
 
                viddevs[0]=NULL;
670
 
        }
671
 
 
672
 
        pthread_mutex_init(&vid_mutex, NULL);
673
 
}
674
 
 
675
 
/* Called by childs to get rid of open video devices */
676
 
void vid_close(void)
677
 
{
678
 
        int i=-1;
679
 
 
680
 
        if (viddevs) {
681
 
                while(viddevs[++i]) {
682
 
                        close(viddevs[i]->fd);
683
 
                }
684
 
        }
685
 
}
686
 
 
687
 
void vid_cleanup(void)
688
 
{
689
 
        int i=-1;
690
 
        if (viddevs) {
691
 
                while(viddevs[++i]) {
692
 
                        munmap(viddevs[i]->v4l_buffers[0],viddevs[i]->size_map);
693
 
                        free(viddevs[i]);
694
 
                }
695
 
                free(viddevs);
696
 
                viddevs=NULL;
697
 
        }
698
 
}
699
 
#endif /*WITHOUT_V4L*/
700
 
 
701
 
int vid_start (struct context *cnt)
702
 
{
703
 
        struct config *conf=&cnt->conf;
704
 
        int dev=-1;
705
 
 
706
 
        if (conf->netcam_url) {
707
 
                return netcam_start(cnt);
708
 
        }
709
 
 
710
 
#ifndef WITHOUT_V4L
711
 
        {
712
 
                int i=-1;
713
 
                int width, height, input, norm, tuner_number;
714
 
                unsigned long frequency;
715
 
 
716
 
                /* We use width and height from conf in this function. They will be assigned
717
 
                 * to width and height in imgs here, and cap_width and cap_height in 
718
 
                 * rotate_data won't be set until in rotate_init.
719
 
                 */
720
 
                width = conf->width;
721
 
                height = conf->height;
722
 
                input = conf->input;
723
 
                norm = conf->norm;
724
 
                frequency = conf->frequency;
725
 
                tuner_number = conf->tuner_number;
726
 
                
727
 
                pthread_mutex_lock(&vid_mutex);
728
 
 
729
 
                /* Transfer width and height from conf to imgs. The imgs values are the ones
730
 
                 * that is used internally in Motion. That way, setting width and height via
731
 
                 * xmlrpc won't screw things up.
732
 
                 */
733
 
                cnt->imgs.width=width;
734
 
                cnt->imgs.height=height;
735
 
 
736
 
                while (viddevs[++i]) {
737
 
                        if (!strcmp(conf->video_device, viddevs[i]->video_device)) {
738
 
                                int fd;
739
 
                                cnt->imgs.type=viddevs[i]->v4l_fmt;
740
 
                                switch (cnt->imgs.type) {
741
 
                                        case VIDEO_PALETTE_GREY:
742
 
                                                cnt->imgs.motionsize=width*height;
743
 
                                                cnt->imgs.size=width*height;
744
 
                                                break;
745
 
                                        case VIDEO_PALETTE_RGB24:
746
 
                                        case VIDEO_PALETTE_YUV422:
747
 
                                                cnt->imgs.type=VIDEO_PALETTE_YUV420P;
748
 
                                        case VIDEO_PALETTE_YUV420P:
749
 
                                                cnt->imgs.motionsize=width*height;
750
 
                                                cnt->imgs.size=(width*height*3)/2;
751
 
                                                break;
752
 
                                }
753
 
                                fd=viddevs[i]->fd;
754
 
                                pthread_mutex_unlock(&vid_mutex);
755
 
                                return fd;
756
 
                        }
757
 
                }
758
 
 
759
 
                viddevs=myrealloc(cnt, viddevs, sizeof(struct video_dev *)*(i+2), "vid_start");
760
 
                viddevs[i]=mymalloc(cnt, sizeof(struct video_dev));
761
 
                memset(viddevs[i], 0, sizeof(struct video_dev));
762
 
                viddevs[i+1]=NULL;
763
 
 
764
 
                pthread_mutexattr_init(&viddevs[i]->attr);
765
 
                pthread_mutex_init(&viddevs[i]->mutex, NULL);
766
 
 
767
 
                dev=open(conf->video_device, O_RDWR);
768
 
                if (dev <0) {
769
 
                        motion_log(cnt, LOG_ERR, 1, "Failed to open video device %s", conf->video_device);
770
 
                        motion_log(cnt, LOG_ERR, 0, "Motion Exits");
771
 
                        exit(1);
772
 
                }
773
 
 
774
 
                viddevs[i]->video_device=conf->video_device;
775
 
                viddevs[i]->fd=dev;
776
 
                viddevs[i]->input=input;
777
 
                viddevs[i]->height=height;
778
 
                viddevs[i]->width=width;
779
 
                viddevs[i]->freq=frequency;
780
 
                viddevs[i]->tuner_number=tuner_number;
781
 
                
782
 
                /* We set brightness, contrast, saturation and hue = 0 so that they only get
783
 
                 * set if the config is not zero.
784
 
                 */
785
 
                viddevs[i]->brightness=0;
786
 
                viddevs[i]->contrast=0;
787
 
                viddevs[i]->saturation=0;
788
 
                viddevs[i]->hue=0;
789
 
                viddevs[i]->owner=-1;
790
 
 
791
 
                viddevs[i]->v4l_fmt=VIDEO_PALETTE_YUV420P;
792
 
 
793
 
                if (!v4l_start (cnt, viddevs[i], width, height, input, norm, frequency, tuner_number)) {
794
 
                        pthread_mutex_unlock(&vid_mutex);
795
 
                        return -1;
796
 
                }
797
 
                cnt->imgs.type=viddevs[i]->v4l_fmt;
798
 
                switch (cnt->imgs.type) {
799
 
                        case VIDEO_PALETTE_GREY:
800
 
                                cnt->imgs.size=width*height;
801
 
                                cnt->imgs.motionsize=width*height;
802
 
                        break;
803
 
                        case VIDEO_PALETTE_RGB24:
804
 
                        case VIDEO_PALETTE_YUV422:
805
 
                                cnt->imgs.type=VIDEO_PALETTE_YUV420P;
806
 
                        case VIDEO_PALETTE_YUV420P:
807
 
                                cnt->imgs.size=(width*height*3)/2;
808
 
                                cnt->imgs.motionsize=width*height;
809
 
                        break;
810
 
                }
811
 
 
812
 
                pthread_mutex_unlock(&vid_mutex);
813
 
        }
814
 
#endif /*WITHOUT_V4L*/  
815
 
        return dev;
816
 
}
817
 
 
818
 
 
819
 
/**
820
 
 * vid_next fetches a video frame from a either v4l device or netcam
821
 
 * Parameters:
822
 
 *     cnt        Pointer to the context for this thread
823
 
 *     map        Pointer to the buffer in which the function puts the new image
824
 
 *
825
 
 * Returns
826
 
 *     0          Success
827
 
 *    -1          Fatal V4L error
828
 
 *    -2          Fatal Netcam error
829
 
 *     1          Non fatal V4L error (not implemented)
830
 
 *     2          Non fatal Netcam error
831
 
 */
832
 
int vid_next(struct context *cnt, unsigned char *map)
833
 
{
834
 
        struct config *conf=&cnt->conf;
835
 
        int ret = -1;
836
 
 
837
 
        if (conf->netcam_url) {
838
 
                ret = netcam_next(cnt, map);
839
 
                return ret;
840
 
        }
841
 
#ifndef WITHOUT_V4L
842
 
        {
843
 
                int i=-1;
844
 
                int width, height;
845
 
                int dev = cnt->video_dev;
846
 
 
847
 
                /* NOTE: Since this is a capture, we need to use capture dimensions. */
848
 
                width = cnt->rotate_data.cap_width;
849
 
                height = cnt->rotate_data.cap_height;
850
 
                
851
 
                while (viddevs[++i])
852
 
                        if (viddevs[i]->fd==dev)
853
 
                                break;
854
 
 
855
 
                if (!viddevs[i])
856
 
                        return -1;
857
 
 
858
 
                if (viddevs[i]->owner!=cnt->threadnr) {
859
 
                        pthread_mutex_lock(&viddevs[i]->mutex);
860
 
                        viddevs[i]->owner=cnt->threadnr;
861
 
                        viddevs[i]->frames=conf->roundrobin_frames;
862
 
                        cnt->switched=1;
863
 
                }
864
 
 
865
 
                v4l_set_input(cnt, viddevs[i], map, width, height, conf->input, conf->norm,
866
 
                               conf->roundrobin_skip, conf->frequency, conf->tuner_number);
867
 
                ret = v4l_next(cnt, viddevs[i], map, width, height);
868
 
 
869
 
                if (--viddevs[i]->frames <= 0) {
870
 
                        viddevs[i]->owner=-1;
871
 
                        pthread_mutex_unlock(&viddevs[i]->mutex);
872
 
                }
873
 
        
874
 
                if(cnt->rotate_data.degrees > 0) {
875
 
                        /* rotate the image as specified */
876
 
                        rotate_map(cnt, map);
877
 
                }
878
 
        }
879
 
#endif /*WITHOUT_V4L*/
880
 
        return ret;
881
 
}
882
 
 
883
 
#ifndef WITHOUT_V4L
884
 
int vid_startpipe (struct context *cnt, char *devname, int width, int height, int type)
885
 
{
886
 
        return v4l_startpipe(cnt, devname, width, height, type);
 
549
 
 
550
int vid_startpipe(const char *devname, int width, int height, int type)
 
551
{
 
552
        return v4l_startpipe( (char *)devname, width, height, type);
887
553
}
888
554
 
889
555
int vid_putpipe (int dev, unsigned char *image, int size)
890
556
{
891
 
        return v4l_putpipe (dev, image, size);
 
557
        return v4l_putpipe(dev, image, size);
892
558
}
893
559
#endif /*WITHOUT_V4L*/