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

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