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

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