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

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