source: trunk/MagicSoft/Cosy/videodev/Camera.cc@ 920

Last change on this file since 920 was 910, checked in by tbretz, 24 years ago
*** empty log message ***
File size: 6.2 KB
Line 
1#include "Camera.h"
2
3#include <iostream.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <errno.h>
7#include <fcntl.h>
8#include <string.h>
9#include <signal.h>
10#include <endian.h>
11#include <sys/ioctl.h>
12#include <sys/mman.h>
13#include <sys/ipc.h>
14#include <sys/shm.h>
15
16#include "MStopwatch.h"
17
18#include "videodev.h"
19
20#include <sys/time.h>
21#include <sys/resource.h>
22
23inline int Camera::Ioctl(int req, void *opt, const char *str)
24{
25 int rc = ioctl(fd, req, opt);
26
27 if (rc==-1)
28 {
29 cout << "Error! Ioctl " << req << ": ";
30 cout << (str?str:strerror(errno)) << " (rc=" << rc << ")" << endl;
31 }
32
33 return rc;
34}
35
36void Camera::Error(const char *str, int fatal)
37{
38 cout << endl
39 << (fatal?"Fatal ":"") << "Error! " << str << ": " << strerror(errno)
40 << endl;
41
42 if (fatal)
43 exit(1);
44}
45void Camera::SigInit()
46{
47 struct sigaction act, old;
48
49 memset(&act, 0, sizeof(act));
50
51 act.sa_handler = SigAlarm;
52
53 sigemptyset(&act. sa_mask);
54 sigaction(SIGALRM, &act, &old);
55
56 // signal(SIGINT, ctrlc);
57}
58
59void Camera::SigAlarm(int signal)
60{
61 cout << "Camera: oops: got sigalarm" << endl;
62 exit(1);
63}
64
65char *Camera::GetImg(unsigned int frame)
66{
67 // wait until grabbing is finished??
68 //
69 // give signal SIGALARM
70 const int SYNC_TIMEOUT = 1;
71
72 alarm(SYNC_TIMEOUT);
73 Ioctl(VIDIOCSYNC, &frame); // sync with mmap grabbing
74 alarm(0);
75
76 return pMapBuffer+iOffsets[frame];
77}
78
79int Camera::StartGrab(unsigned int frame)
80{
81 static struct video_mmap gb =
82 {
83 0, // frame
84 rows, cols, // height, width
85 VIDEO_PALETTE_RGB24 // palette
86 };
87
88 gb.frame = frame&1;
89
90 //
91 // capture frame
92 //
93 if (Ioctl(VIDIOCMCAPTURE, &gb) != -1)
94 return true;
95
96 if (errno == EAGAIN)
97 cout << "Grabber chip can't sync" << endl;
98
99 return false;
100}
101
102Camera::Camera() : fd(-1), iBufferSize(0)
103{
104 cout << "Starting thread..." << flush;
105 pthread_cond_init(&fCond, NULL);
106 pthread_mutex_init(&fMux, NULL);
107 pthread_mutex_lock(&fMux);
108 pthread_create(&fThread, NULL, MapThread, this);
109 cout << "done." << endl;
110
111 cout << "/dev/video: opening..." << flush;
112
113 //
114 // ------ Open device /dev/video ------
115 //
116 do
117 {
118 fd = open("/dev/video", O_RDWR);
119 usleep(1);
120 }
121 while (errno==19 && fd==-1);
122
123 if (fd == -1)
124 Error("open /dev/video");
125
126 fcntl(fd, F_SETFD, FD_CLOEXEC); // Close device on exit
127 SigInit();
128
129 //
130 // get input channel 0 information
131 //
132 struct video_channel ch;
133 ch.channel = 0;
134 Ioctl(VIDIOCGCHAN, &ch);
135
136 //
137 // ioctl probe, switch to input 0
138 //
139 Ioctl(VIDIOCSCHAN, &ch, "You need a bttv version > 0.5.13");
140
141 //
142 // map grab buffer, get size and offset
143 //
144 struct video_mbuf buffers;
145 Ioctl(VIDIOCGMBUF, &buffers);
146
147 iBufferSize = buffers.size;
148 iOffsets[0] = buffers.offsets[0];
149 iOffsets[1] = buffers.offsets[1];
150
151 //
152 // map file (device) into memory
153 //
154 pMapBuffer = mmap(0, iBufferSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
155
156 if ((int)pMapBuffer == -1)
157 Error("mmap");
158
159 cout << "OK." << endl;
160
161 cout << "Buffer Offset " << buffers.offsets[1] << endl;
162 cout << "grab: use: 768x576 24 bit TrueColor (LE: bgr)" << endl;
163}
164
165Camera::~Camera()
166{
167 cout << "Stopping thread..." << flush;
168 pthread_cancel(fThread);
169 pthread_mutex_destroy(&fMux);
170 pthread_cond_destroy(&fCond);
171 cout << "done." << endl;
172
173 cout << "/dev/video: closing... " << flush;
174
175 // unmap device memory
176 if ((int)pMapBuffer != -1)
177 munmap(pMapBuffer, iBufferSize);
178
179 if (fd != -1)
180 {
181 close(fd);
182 fd = -1;
183 }
184
185 cout << " Done." << endl;
186}
187
188
189void Camera::ProcessFrame(const unsigned long n, byte *img,
190 struct timeval *tm)
191{
192 cout << "Img: " << n << " " << (void*)img << endl;
193}
194
195void *Camera::MapThread(void *arg)
196{
197 Camera *cam = (Camera*)arg;
198
199 // setpriority(PRIO_PROCESS, 0, 10);
200 pthread_detach(pthread_self());
201
202 cam->Thread();
203
204 return 0;
205}
206
207
208void Camera::LoopStep(const unsigned long n)
209{
210 char *img = GetImg(n&1);
211
212 gettimeofday(&fTime, NULL);
213
214 const char *end = img + cols*rows*depth;
215 char *beg = fImg;
216
217 while (img < end)
218 {
219 *beg = *img;
220
221 img += depth;
222 beg++;
223 }
224}
225
226void Camera::Thread()
227{
228#define IsOdd(i) (2*(i/2)!=i)
229 while (1)
230 {
231 pthread_cond_wait(&fCond, &fMux);
232 MStopwatch t;
233 t.Start();
234
235 unsigned long i=0;
236
237 if (!StartGrab(0))
238 continue;
239
240 if (!StartGrab(1))
241 continue;
242
243 while (!(fStop || fNum && i==fNum-2))
244 {
245 LoopStep(i);
246 if (!StartGrab(i&1))
247 break;
248 ProcessFrame(i, (byte*)fImg, &fTime);
249 i++;
250 }
251
252 if (!IsOdd(i))
253 {
254 LoopStep(i);
255 ProcessFrame(i, (byte*)fImg, &fTime);
256 i++;
257 }
258
259 LoopStep(i);
260 ProcessFrame(i, (byte*)fImg, &fTime);
261 i++;
262
263 //
264 // Wait until processing of frame 1 finished.
265 //
266 t.Stop();
267 t.Print(i);
268
269 fRunning = 0;
270 }
271}
272
273void Camera::Loop(unsigned long nof)
274{
275 if (2*(nof/2) != nof)
276 {
277 cout << "Sorry, only even values are allowed!" << endl;
278 return;
279 }
280
281 //
282 // Stop running loop
283 //
284 fStop = 1;
285
286 //
287 // Wait until loop is stopped (pthread_cond_wait is executing)
288 // set new number of frames to process
289 //
290 pthread_mutex_lock(&fMux);
291 fNum = nof;
292 fStop = 0;
293 fRunning = 1;
294 pthread_mutex_unlock(&fMux);
295
296 //
297 // Start execution
298 //
299 pthread_cond_signal(&fCond);
300}
301
302void Camera::SetPicPar(int bright, int hue, int contrast)
303{
304 struct video_picture pict;
305
306 Ioctl(VIDIOCGPICT, &pict); // get
307
308 if (contrast != -1)
309 pict.contrast = contrast;
310
311 if (bright != -1)
312 pict.brightness = bright;
313
314 if (hue != -1)
315 pict.hue = hue;
316
317 Ioctl(VIDIOCSPICT, &pict); //set
318}
319
320void Camera::GetPicPar(int *bright, int *hue, int *contrast)
321{
322 struct video_picture pict;
323
324 Ioctl(VIDIOCGPICT, &pict); // get
325
326 *contrast = pict.contrast;
327 *bright = pict.brightness;
328 *hue = pict.hue;
329}
330
Note: See TracBrowser for help on using the repository browser.