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

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