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

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