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

Last change on this file since 1531 was 1531, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 6.5 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 = (char*)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 Address: " << (void*)pMapBuffer << endl;
164 cout << "Buffer Offset 1: " << (void*)iOffsets[0] << endl;
165 cout << "Buffer Offset 2: " << (void*)iOffsets[1] << endl;
166 cout << "Buffer Size: " << (void*)iBufferSize << endl;
167 cout << "grab: use: 768x576 24 bit TrueColor (LE: bgr) = " << (void*)(768*576*3) << "b" << endl;
168}
169
170Camera::~Camera()
171{
172 cout << "Stopping thread..." << flush;
173 pthread_cancel(fThread);
174 pthread_mutex_destroy(&fMux);
175 pthread_cond_destroy(&fCond);
176 cout << "done." << endl;
177
178 cout << "/dev/video: closing... " << flush;
179
180 // unmap device memory
181 if ((int)pMapBuffer != -1)
182 munmap(pMapBuffer, iBufferSize);
183
184 if (fd != -1)
185 {
186 close(fd);
187 fd = -1;
188 }
189
190 cout << " Done." << endl;
191}
192
193
194void Camera::ProcessFrame(const unsigned long n, byte *img,
195 struct timeval *tm)
196{
197 cout << "Img: " << n << " " << (void*)img << endl;
198}
199
200void *Camera::MapThread(void *arg)
201{
202 Camera *cam = (Camera*)arg;
203
204 // setpriority(PRIO_PROCESS, 0, 10);
205 pthread_detach(pthread_self());
206
207 cam->Thread();
208
209 return 0;
210}
211
212void Camera::LoopStep(const unsigned long n)
213{
214 char *img = GetImg(n&1);
215
216 gettimeofday(&fTime, NULL);
217
218 const char *end = img + cols*rows*depth;
219 char *beg = fImg;
220
221 while (img < end)
222 {
223 *beg = *img;
224
225 img += depth;
226 beg++;
227 }
228}
229
230void Camera::Thread()
231{
232#define IsOdd(i) (2*(i/2)!=i)
233 while (1)
234 {
235 pthread_cond_wait(&fCond, &fMux);
236 MStopwatch t;
237 t.Start();
238
239 unsigned long i=0;
240
241 if (!StartGrab(0))
242 continue;
243
244 if (!StartGrab(1))
245 continue;
246
247 while (!(fStop || fNum && i==fNum-2))
248 {
249 LoopStep(i);
250 if (!StartGrab(i&1))
251 break;
252
253 ProcessFrame(i, (byte*)fImg, &fTime);
254 i++;
255 }
256
257 if (!IsOdd(i))
258 {
259 LoopStep(i);
260 ProcessFrame(i, (byte*)fImg, &fTime);
261 i++;
262 }
263
264 LoopStep(i);
265 ProcessFrame(i, (byte*)fImg, &fTime);
266 i++;
267
268 //
269 // Wait until processing of frame 1 finished.
270 //
271 t.Stop();
272 t.Print(i);
273
274 fRunning = 0;
275 }
276}
277
278void Camera::Loop(unsigned long nof)
279{
280 if (2*(nof/2) != nof)
281 {
282 cout << "Sorry, only even values are allowed!" << endl;
283 return;
284 }
285
286 //
287 // Stop running loop
288 //
289 fStop = 1;
290
291 //
292 // Wait until loop is stopped (pthread_cond_wait is executing)
293 // set new number of frames to process
294 //
295 pthread_mutex_lock(&fMux);
296 fNum = nof;
297 fStop = 0;
298 fRunning = 1;
299 pthread_mutex_unlock(&fMux);
300
301 //
302 // Start execution
303 //
304 pthread_cond_signal(&fCond);
305}
306
307void Camera::SetPicPar(int bright, int hue, int contrast)
308{
309 struct video_picture pict;
310
311 Ioctl(VIDIOCGPICT, &pict); // get
312
313 if (contrast != -1)
314 pict.contrast = contrast;
315
316 if (bright != -1)
317 pict.brightness = bright;
318
319 if (hue != -1)
320 pict.hue = hue;
321
322 Ioctl(VIDIOCSPICT, &pict); //set
323}
324
325void Camera::GetPicPar(int *bright, int *hue, int *contrast)
326{
327 struct video_picture pict;
328
329 Ioctl(VIDIOCGPICT, &pict); // get
330
331 *contrast = pict.contrast;
332 *bright = pict.brightness;
333 *hue = pict.hue;
334}
335
Note: See TracBrowser for help on using the repository browser.