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

Last change on this file since 1802 was 1802, 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 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(PixClient &client) : fd(-1), iBufferSize(0), fClient(client)
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::MapThread(void *arg)
195{
196 Camera *cam = (Camera*)arg;
197
198 // setpriority(PRIO_PROCESS, 0, 10);
199 pthread_detach(pthread_self());
200
201 cam->Thread();
202
203 return 0;
204}
205
206void Camera::LoopStep(const unsigned long n)
207{
208 char *img = GetImg(n&1);
209
210 gettimeofday(&fTime, NULL);
211
212 const char *end = img + cols*rows*depth;
213 char *beg = fImg;
214
215 while (img < end)
216 {
217 *beg = *img;
218
219 img += depth;
220 beg++;
221 }
222}
223
224void Camera::Thread()
225{
226#define IsOdd(i) (2*(i/2)!=i)
227 while (1)
228 {
229 pthread_cond_wait(&fCond, &fMux);
230 MStopwatch t;
231 t.Start();
232
233 unsigned long i=0;
234
235 if (!StartGrab(0))
236 continue;
237
238 if (!StartGrab(1))
239 continue;
240
241 while (!(fStop || fNum && i==fNum-2))
242 {
243 LoopStep(i);
244 if (!StartGrab(i&1))
245 break;
246
247 fClient.ProcessFrame(i, (byte*)fImg, &fTime);
248 i++;
249 }
250
251 if (!IsOdd(i))
252 {
253 LoopStep(i);
254 fClient.ProcessFrame(i, (byte*)fImg, &fTime);
255 i++;
256 }
257
258 LoopStep(i);
259 fClient.ProcessFrame(i, (byte*)fImg, &fTime);
260 i++;
261
262 //
263 // Wait until processing of frame 1 finished.
264 //
265 t.Stop();
266 t.Print(i);
267
268 fRunning = 0;
269 }
270}
271
272void Camera::Loop(unsigned long nof)
273{
274 if (2*(nof/2) != nof)
275 {
276 cout << "Sorry, only even values are allowed!" << endl;
277 return;
278 }
279
280 //
281 // Stop running loop
282 //
283 fStop = 1;
284
285 //
286 // Wait until loop is stopped (pthread_cond_wait is executing)
287 // set new number of frames to process
288 //
289 pthread_mutex_lock(&fMux);
290 fNum = nof;
291 fStop = 0;
292 fRunning = 1;
293 pthread_mutex_unlock(&fMux);
294
295 //
296 // Start execution
297 //
298 pthread_cond_signal(&fCond);
299}
300
301void Camera::SetPicPar(int bright, int hue, int contrast)
302{
303 struct video_picture pict;
304
305 Ioctl(VIDIOCGPICT, &pict); // get
306
307 if (contrast != -1)
308 pict.contrast = contrast;
309
310 if (bright != -1)
311 pict.brightness = bright;
312
313 if (hue != -1)
314 pict.hue = hue;
315
316 Ioctl(VIDIOCSPICT, &pict); //set
317}
318
319void Camera::GetPicPar(int *bright, int *hue, int *contrast)
320{
321 struct video_picture pict;
322
323 Ioctl(VIDIOCGPICT, &pict); // get
324
325 *contrast = pict.contrast;
326 *bright = pict.brightness;
327 *hue = pict.hue;
328}
329
Note: See TracBrowser for help on using the repository browser.