1 /*
2 * interface to the bsd bktr driver
3 *
4 * (c) 2000,01 Gerd Knorr <kraxel@bytesex.org>
5 *
6 */
7 #include "config.h"
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <math.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <string.h>
16 #include <signal.h>
17 #include <pthread.h>
18 #include <sys/types.h>
19 #include <sys/time.h>
20 #include <sys/ioctl.h>
21 #include <sys/stat.h>
22 #include <sys/mman.h>
23
24 #ifdef HAVE_DEV_IC_BT8XX_H
25 # include <dev/ic/bt8xx.h>
26 #endif
27 #ifdef HAVE_MACHINE_IOCTL_BT848_H
28 # include <machine/ioctl_bt848.h>
29 # include <machine/ioctl_meteor.h>
30 #endif
31
32 #include "grab-ng.h"
33
34 /* ---------------------------------------------------------------------- */
35 /* global variables */
36
37 struct bsd_handle {
38 int fd;
39 int tfd;
40
41 /* formats */
42 int pf_count;
43 struct meteor_pixfmt pf[64];
44 int xawtv2pf[VIDEO_FMT_COUNT];
45 unsigned char *map;
46
47 /* attributes */
48 int muted;
49 struct ng_attribute *attr;
50
51 /* overlay */
52 struct meteor_video fb,pos;
53 struct meteor_geomet ovgeo;
54 struct meteor_pixfmt *ovfmt;
55 struct bktr_clip clip[BT848_MAX_CLIP_NODE];
56 int ov_enabled,ov_on;
57
58 /* capture */
59 int fps;
60 long long start;
61 struct ng_video_fmt fmt;
62 struct meteor_video nofb;
63 struct meteor_geomet capgeo;
64 struct meteor_pixfmt *capfmt;
65 struct bktr_clip noclip[BT848_MAX_CLIP_NODE];
66 };
67
68 /* ---------------------------------------------------------------------- */
69 /* prototypes */
70
71 /* open/close */
72 static void* bsd_open(char *device);
73 static int bsd_close(void *handle);
74
75 /* attributes */
76 static int bsd_flags(void *handle);
77 static struct ng_attribute* bsd_attrs(void *handle);
78 static int bsd_read_attr(struct ng_attribute*);
79 static void bsd_write_attr(struct ng_attribute*, int val);
80
81 static int bsd_setupfb(void *handle, struct ng_video_fmt *fmt, void *base);
82 static int bsd_overlay(void *handle, struct ng_video_fmt *fmt, int x, int y,
83 struct OVERLAY_CLIP *oc, int count, int aspect);
84
85 /* capture */
86 static void catchsignal(int signal);
87 static void siginit(void);
88 static int bsd_setformat(void *handle, struct ng_video_fmt *fmt);
89 static int bsd_startvideo(void *handle, int fps, unsigned int buffers);
90 static void bsd_stopvideo(void *handle);
91 static struct ng_video_buf* bsd_nextframe(void *handle);
92 static struct ng_video_buf* bsd_getimage(void *handle);
93
94 /* tuner */
95 static unsigned long bsd_getfreq(void *handle);
96 static void bsd_setfreq(void *handle, unsigned long freq);
97 static int bsd_tuned(void *handle);
98
99 struct ng_vid_driver bsd_driver = {
100 name: "bktr",
101 open: bsd_open,
102 close: bsd_close,
103
104 capabilities: bsd_flags,
105 list_attrs: bsd_attrs,
106
107 setupfb: bsd_setupfb,
108 overlay: bsd_overlay,
109
110 setformat: bsd_setformat,
111 startvideo: bsd_startvideo,
112 stopvideo: bsd_stopvideo,
113 nextframe: bsd_nextframe,
114 getimage: bsd_getimage,
115
116 getfreq: bsd_getfreq,
117 setfreq: bsd_setfreq,
118 is_tuned: bsd_tuned,
119 };
120
121 /* ---------------------------------------------------------------------- */
122
123 static struct STRTAB inputs[] = {
124 { 0, "Television" },
125 { 1, "Composite1" },
126 { 2, "S-Video" },
127 { 3, "CSVIDEO" },
128 { -1, NULL }
129 };
130 static int inputs_map[] = {
131 METEOR_INPUT_DEV1,
132 METEOR_INPUT_DEV0,
133 METEOR_INPUT_DEV_SVIDEO,
134 METEOR_INPUT_DEV2,
135 };
136
137 static struct STRTAB norms[] = {
138 { 0, "NTSC" },
139 { 1, "NTSC-JP" },
140 { 2, "PAL" },
141 { 3, "PAL-M" },
142 { 4, "PAL-N" },
143 { 5, "SECAM" },
144 { 6, "RSVD" },
145 { -1, NULL }
146 };
147 static int norms_map[] = {
148 BT848_IFORM_F_NTSCM,
149 BT848_IFORM_F_NTSCJ,
150 BT848_IFORM_F_PALBDGHI,
151 BT848_IFORM_F_PALM,
152 BT848_IFORM_F_PALN,
153 BT848_IFORM_F_SECAM,
154 BT848_IFORM_F_RSVD,
155 };
156
157 static struct STRTAB audio[] = {
158 { 0, "Tuner" },
159 { 1, "Extern" },
160 { 2, "Intern" },
161 { -1, NULL }
162 };
163 static int audio_map[] = {
164 AUDIO_TUNER,
165 AUDIO_EXTERN,
166 AUDIO_INTERN,
167 };
168
169 static struct ng_attribute bsd_attr[] = {
170 {
171 id: ATTR_ID_COUNT+1,
172 name: "audio",
173 type: ATTR_TYPE_CHOICE,
174 choices: audio,
175 read: bsd_read_attr,
176 write: bsd_write_attr,
177 },{
178 id: ATTR_ID_NORM,
179 name: "norm",
180 type: ATTR_TYPE_CHOICE,
181 choices: norms,
182 read: bsd_read_attr,
183 write: bsd_write_attr,
184 },{
185 id: ATTR_ID_INPUT,
186 name: "input",
187 type: ATTR_TYPE_CHOICE,
188 choices: inputs,
189 read: bsd_read_attr,
190 write: bsd_write_attr,
191 },{
192 id: ATTR_ID_MUTE,
193 name: "mute",
194 type: ATTR_TYPE_BOOL,
195 read: bsd_read_attr,
196 write: bsd_write_attr,
197 },{
198 id: ATTR_ID_HUE,
199 name: "hue",
200 type: ATTR_TYPE_INTEGER,
201 min: BT848_HUEREGMIN,
202 max: BT848_HUEREGMAX,
203 read: bsd_read_attr,
204 write: bsd_write_attr,
205 },{
206 id: ATTR_ID_BRIGHT,
207 name: "bright",
208 type: ATTR_TYPE_INTEGER,
209 min: BT848_BRIGHTREGMIN,
210 max: BT848_BRIGHTREGMAX,
211 read: bsd_read_attr,
212 write: bsd_write_attr,
213 },{
214 id: ATTR_ID_CONTRAST,
215 name: "contrast",
216 type: ATTR_TYPE_INTEGER,
217 min: BT848_CONTRASTREGMIN,
218 max: BT848_CONTRASTREGMAX,
219 read: bsd_read_attr,
220 write: bsd_write_attr,
221 },{
222 id: ATTR_ID_COLOR,
223 name: "color",
224 type: ATTR_TYPE_INTEGER,
225 min: BT848_CHROMAREGMIN,
226 max: BT848_CHROMAREGMAX,
227 read: bsd_read_attr,
228 write: bsd_write_attr,
229 },{
230 /* end of list */
231 }
232 };
233
234 static int single = METEOR_CAP_SINGLE;
235 static int start = METEOR_CAP_CONTINOUS;
236 static int stop = METEOR_CAP_STOP_CONT;
237 static int signal_on = SIGUSR1;
238 static int signal_off = METEOR_SIG_MODE_MASK;
239
240 /* ---------------------------------------------------------------------- */
241
242 #define PREFIX "bktr: ioctl: "
243
244 static int
245 xioctl(int fd, int cmd, void *arg)
246 {
247 int rc;
248
249 rc = ioctl(fd,cmd,arg);
250 if (0 == rc && ng_debug < 2)
251 return 0;
252 switch (cmd) {
253 case METEORSVIDEO:
254 {
255 struct meteor_video *a = arg;
256
257 fprintf(stderr,PREFIX "METEORSVIDEO(addr=0x%08lx,width=%ld,bank=%ld,ram=%ld)",
258 a->addr,a->width,a->banksize,a->ramsize);
259 break;
260 }
261 case METEORSETGEO:
262 {
263 struct meteor_geomet *a = arg;
264
265 fprintf(stderr,PREFIX "METEORSETGEO(%dx%d,frames=%d,oformat=0x%lx)",
266 a->columns,a->rows,a->frames,a->oformat);
267 break;
268 }
269 case METEORSACTPIXFMT:
270 {
271 struct meteor_pixfmt *a = arg;
272
273 fprintf(stderr,PREFIX "METEORSACTPIXFMT(%d,type=%d,bpp=%d,"
274 "masks=0x%lx/0x%lx/0x%lx,sb=%d,ss=%d)",
275 a->index,a->type,a->Bpp,a->masks[0],a->masks[1],a->masks[2],
276 a->swap_bytes,a->swap_shorts);
277 break;
278 }
279 case METEORCAPTUR:
280 {
281 int *a = arg;
282
283 fprintf(stderr,PREFIX "METEORCAPTUR(%d)",*a);
284 break;
285 }
286 case METEORSSIGNAL:
287 {
288 int *a = arg;
289
290 fprintf(stderr,PREFIX "METEORSSIGNAL(0x%x)",*a);
291 break;
292 }
293 case BT848SCLIP:
294 {
295 fprintf(stderr,PREFIX "BT848SCLIP");
296 break;
297 }
298 default:
299 fprintf(stderr,PREFIX "UNKNOWN(cmd=0x%x)",cmd);
300 break;
301 }
302 fprintf(stderr,": %s\n",(rc == 0) ? "ok" : strerror(errno));
303 return rc;
304 }
305
306 /* ---------------------------------------------------------------------- */
307
308 static void
309 bsd_print_format(struct meteor_pixfmt *pf, int format)
310 {
311 switch (pf->type) {
312 case METEOR_PIXTYPE_RGB:
313 fprintf(stderr,
314 "bktr: pf: rgb bpp=%d mask=%ld,%ld,%ld",
315 pf->Bpp,pf->masks[0],pf->masks[1],pf->masks[2]);
316 break;
317 case METEOR_PIXTYPE_YUV:
318 fprintf(stderr,"bktr: pf: yuv h422 v111 (planar)");
319 break;
320 case METEOR_PIXTYPE_YUV_PACKED:
321 fprintf(stderr,"bktr: pf: yuyv h422 v111 (packed)");
322 break;
323 case METEOR_PIXTYPE_YUV_12:
324 fprintf(stderr,"bktr: pf: yuv h422 v422 (planar)");
325 break;
326 default:
327 fprintf(stderr,"bktr: pf: unknown");
328 }
329 fprintf(stderr," sbytes=%d sshorts=%d (fmt=%d)\n",
330 pf->swap_bytes,pf->swap_shorts,format);
331 }
332
333 /* ---------------------------------------------------------------------- */
334
335 static void*
336 bsd_open(char *filename)
337 {
338 struct bsd_handle *h;
339 int format,i;
340
341 h = malloc(sizeof(*h));
342 if (NULL == h)
343 return NULL;
344 memset(h,0,sizeof(*h));
345
346 if (-1 == (h->fd = open(filename,O_RDONLY))) {
347 fprintf(stderr,"bktr: open %s: %s\n", filename,strerror(errno));
348 goto err;
349 }
350
351 /* video formats */
352 for (format = 0; format < VIDEO_FMT_COUNT; format++)
353 h->xawtv2pf[format] = -1;
354
355 for (h->pf_count = 0; h->pf_count < 64; h->pf_count++) {
356 h->pf[h->pf_count].index = h->pf_count;
357 if (-1 == ioctl(h->fd, METEORGSUPPIXFMT,h->pf+h->pf_count)) {
358 if (ng_debug)
359 perror("bktr: ioctl METEORGSUPPIXFMT");
360 if (0 == h->pf_count)
361 goto err;
362 break;
363 }
364 format = -1;
365 switch (h->pf[h->pf_count].type) {
366 case METEOR_PIXTYPE_RGB:
367 switch(h->pf[h->pf_count].masks[0]) {
368 case 31744: /* 15 bpp */
369 format = h->pf[h->pf_count].swap_bytes
370 ? VIDEO_RGB15_LE : VIDEO_RGB15_BE;
371 break;
372 case 63488: /* 16 bpp */
373 format = h->pf[h->pf_count].swap_bytes
374 ? VIDEO_RGB16_LE : VIDEO_RGB16_BE;
375 break;
376 case 16711680: /* 24/32 bpp */
377 if (h->pf[h->pf_count].Bpp == 3 &&
378 h->pf[h->pf_count].swap_bytes == 1) {
379 format = VIDEO_BGR24;
380 } else if (h->pf[h->pf_count].Bpp == 4 &&
381 h->pf[h->pf_count].swap_bytes == 1 &&
382 h->pf[h->pf_count].swap_shorts == 1) {
383 format = VIDEO_BGR32;
384 } else if (h->pf[h->pf_count].Bpp == 4 &&
385 h->pf[h->pf_count].swap_bytes == 0 &&
386 h->pf[h->pf_count].swap_shorts == 0) {
387 format = VIDEO_RGB32;
388 }
389 }
390 break;
391 case METEOR_PIXTYPE_YUV:
392 format = VIDEO_YUV422P;
393 break;
394 #if 0
395 case METEOR_PIXTYPE_YUV_PACKED:
396 format = VIDEO_YUV422;
397 h->pf[h->pf_count].swap_shorts = 0; /* seems not to work */
398 break;
399 #endif
400 case METEOR_PIXTYPE_YUV_12:
401 case METEOR_PIXTYPE_YUV_PACKED:
402 /* nothing */
403 break;
404 }
405 if (-1 != format)
406 h->xawtv2pf[format] = h->pf_count;
407
408 if (ng_debug)
409 bsd_print_format(h->pf+h->pf_count,format);
410 }
411
412 h->map = mmap(0,768*576*4, PROT_READ, MAP_SHARED, h->fd, 0);
413 if ((unsigned char*)-1 == h->map) {
414 perror("bktr: mmap");
415 h->map = NULL;
416 }
417
418 if (-1 == (h->tfd = open("/dev/tuner0",O_RDONLY))) {
419 fprintf(stderr,"bktr: open %s: %s\n", "/dev/tuner0",strerror(errno));
420 }
421 siginit();
422
423 h->attr = malloc(sizeof(bsd_attr));
424 memcpy(h->attr,bsd_attr,sizeof(bsd_attr));
425 for (i = 0; h->attr[i].name != NULL; i++)
426 h->attr[i].handle = h;
427
428 return h;
429
430 err:
431 if (-1 != h->fd)
432 close(h->fd);
433 if (-1 != h->tfd)
434 close(h->tfd);
435 if (h)
436 free(h);
437 return NULL;
438 }
439
440 static int
441 bsd_close(void *handle)
442 {
443 struct bsd_handle *h = handle;
444
445 if (ng_debug)
446 fprintf(stderr, "bktr: close\n");
447
448 close(h->fd);
449 if (-1 != h->tfd)
450 close(h->tfd);
451 if (NULL != h->map)
452 munmap(h->map,768*576*4);
453 free(h);
454 return 0;
455 }
456
457 static int bsd_flags(void *handle)
458 {
459 int ret = 0;
460
461 ret |= CAN_OVERLAY;
462 ret |= CAN_CAPTURE;
463 ret |= CAN_TUNE;
464 return ret;
465 }
466
467 static struct ng_attribute* bsd_attrs(void *handle)
468 {
469 struct bsd_handle *h = handle;
470
471 return h->attr;
472 }
473
474 /* ---------------------------------------------------------------------- */
475
476 static int
477 bsd_get_range(int id, int *get, int *set)
478 {
479 switch (id) {
480 case ATTR_ID_HUE:
481 *get = BT848_GHUE;
482 *set = BT848_SHUE;
483 break;
484 case ATTR_ID_BRIGHT:
485 *get = BT848_GBRIG;
486 *set = BT848_SBRIG;
487 break;
488 case ATTR_ID_CONTRAST:
489 *get = BT848_GCONT;
490 *set = BT848_SCONT;
491 break;
492 case ATTR_ID_COLOR:
493 *get = BT848_GCSAT;
494 *set = BT848_SCSAT;
495 break;
496 default:
497 return -1;
498 }
499 return 0;
500 }
501
502 static int bsd_read_attr(struct ng_attribute *attr)
503 {
504 struct bsd_handle *h = attr->handle;
505 int arg, get, set, i;
506 int value = -1;
507
508 switch (attr->id) {
509 case ATTR_ID_NORM:
510 if (-1 != xioctl(h->fd,BT848GFMT,&arg))
511 for (i = 0; i < sizeof(norms_map)/sizeof(int); i++)
512 if (arg == norms_map[i])
513 value = i;
514 break;
515 case ATTR_ID_INPUT:
516 if (-1 != xioctl(h->fd,METEORGINPUT,&arg))
517 for (i = 0; i < sizeof(inputs_map)/sizeof(int); i++)
518 if (arg == inputs_map[i])
519 value = i;
520 break;
521 case ATTR_ID_MUTE:
522 if (-1 != xioctl(h->tfd, BT848_GAUDIO, &arg))
523 value = (arg == AUDIO_MUTE) ? 1 : 0;
524 break;
525 case ATTR_ID_HUE:
526 case ATTR_ID_BRIGHT:
527 case ATTR_ID_CONTRAST:
528 case ATTR_ID_COLOR:
529 bsd_get_range(attr->id,&get,&set);
530 if (-1 != xioctl(h->tfd,get,&arg))
531 value = arg;
532 break;
533 case ATTR_ID_COUNT+1: /* AUDIO */
534 if (-1 != xioctl(h->tfd, BT848_GAUDIO, &arg))
535 for (i = 0; i < sizeof(audio_map)/sizeof(int); i++)
536 if (arg == audio_map[i])
537 value = i;
538 break;
539 default:
540 break;
541 }
542 return value;
543 }
544
545 static void bsd_write_attr(struct ng_attribute *attr, int value)
546 {
547 struct bsd_handle *h = attr->handle;
548 int arg, get, set;
549
550 switch (attr->id) {
551 case ATTR_ID_NORM:
552 xioctl(h->fd,BT848SFMT,&norms_map[value]);
553 break;
554 case ATTR_ID_INPUT:
555 xioctl(h->fd,METEORSINPUT,&inputs_map[value]);
556 break;
557 case ATTR_ID_MUTE:
558 h->muted = value;
559 arg = h->muted ? AUDIO_MUTE : AUDIO_UNMUTE;
560 xioctl(h->tfd, BT848_SAUDIO, &arg);
561 break;
562 case ATTR_ID_HUE:
563 case ATTR_ID_BRIGHT:
564 case ATTR_ID_CONTRAST:
565 case ATTR_ID_COLOR:
566 bsd_get_range(attr->id,&get,&set);
567 arg = value;
568 xioctl(h->tfd,set,&arg);
569 break;
570 case ATTR_ID_COUNT+1: /* audio */
571 xioctl(h->tfd, BT848_SAUDIO,&audio_map[value]);
572 break;
573 default:
574 break;
575 }
576 }
577
578 static unsigned long bsd_getfreq(void *handle)
579 {
580 struct bsd_handle *h = handle;
581 unsigned long freq = 0;
582
583 if (-1 == ioctl(h->tfd, TVTUNER_GETFREQ, &freq))
584 perror("bktr: ioctl TVTUNER_GETFREQ");
585 if (ng_debug)
586 fprintf(stderr,"bktr: get freq: %.3f\n",(float)freq/16);
587 return freq;
588 }
589
590 static void bsd_setfreq(void *handle, unsigned long freq)
591 {
592 struct bsd_handle *h = handle;
593
594 if (ng_debug)
595 fprintf(stderr,"bktr: set freq: %.3f\n",(float)freq/16);
596 if (-1 == ioctl(h->tfd, TVTUNER_SETFREQ, &freq))
597 perror("bktr: ioctl TVTUNER_SETFREQ");
598 }
599
600 static int bsd_tuned(void *handle)
601 {
602 return 0;
603 }
604
605 /* ---------------------------------------------------------------------- */
606 /* overlay */
607
608 static void
609 set_overlay(struct bsd_handle *h, int state)
610 {
611 if (h->ov_on == state)
612 return;
613 h->ov_on = state;
614
615 if (state) {
616 /* enable */
617 xioctl(h->fd, METEORSVIDEO, &h->pos);
618 xioctl(h->fd, METEORSETGEO, &h->ovgeo);
619 xioctl(h->fd, METEORSACTPIXFMT, h->ovfmt);
620 xioctl(h->fd, BT848SCLIP, &h->clip);
621 xioctl(h->fd, METEORCAPTUR, &start);
622 } else {
623 /* disable */
624 xioctl(h->fd, METEORCAPTUR, &stop);
625 }
626 }
627
628 static int bsd_setupfb(void *handle, struct ng_video_fmt *fmt, void *base)
629 {
630 struct bsd_handle *h = handle;
631
632 h->fb.addr = (long)base;
633 h->fb.width = fmt->bytesperline;
634 h->fb.banksize = fmt->bytesperline * fmt->height;
635 h->fb.ramsize = fmt->bytesperline * fmt->height / 1024;
636 return 0;
637 }
638
639 static int bsd_overlay(void *handle, struct ng_video_fmt *fmt, int x, int y,
640 struct OVERLAY_CLIP *oc, int count, int aspect)
641 {
642 struct bsd_handle *h = handle;
643 int i,win_width,win_height,win_x,win_y;
644
645 h->ov_enabled = 0;
646 set_overlay(h,h->ov_enabled);
647 if (NULL == fmt)
648 return 0;
649
650 if (-1 == h->xawtv2pf[fmt->fmtid])
651 return -1;
652
653 /* fixups - fixme: no fixed max size */
654 win_x = x;
655 win_y = y;
656 win_width = fmt->width;
657 win_height = fmt->height;
658 if (win_width > 768) {
659 win_width = 768;
660 win_x += (fmt->width - win_width)/2;
661 }
662 if (win_height > 576) {
663 win_height = 576;
664 win_y += (fmt->height - win_height)/2;
665 }
666 if (aspect)
667 ng_ratio_fixup(&win_width,&win_height,&win_x,&win_y);
668 ng_check_clipping(win_width, win_height,
669 x - win_x, y - win_y,
670 oc, &count);
671
672 /* fill data */
673 h->pos = h->fb;
674 h->pos.addr += win_y*h->pos.width;
675 h->pos.addr += win_x*ng_vfmt_to_depth[fmt->fmtid]>>3;
676 h->ovgeo.rows = win_height;
677 h->ovgeo.columns = win_width;
678 h->ovgeo.frames = 1;
679 h->ovgeo.oformat = 0x10000;
680
681 if (ng_debug)
682 fprintf(stderr,"bktr: overlay win=%dx%d+%d+%d, %d clips\n",
683 win_width,win_height,win_x,win_y,count);
684
685 /* clipping */
686 memset(h->clip,0,sizeof(h->clip));
687 for (i = 0; i < count; i++) {
688 #if 0
689 /* This way it *should* work IMHO ... */
690 h->clip[i].x_min = oc[i].x1;
691 h->clip[i].x_max = oc[i].x2;
692 h->clip[i].y_min = oc[i].y1;
693 h->clip[i].y_max = oc[i].y2;
694 #else
695 /* This way it does work. Sort of ... */
696 h->clip[i].x_min = (oc[i].y1) >> 1;
697 h->clip[i].x_max = (oc[i].y2) >> 1;
698 h->clip[i].y_min = oc[i].x1;
699 h->clip[i].y_max = oc[i].x2;
700 #endif
701 }
702 h->ovfmt = h->pf+h->xawtv2pf[fmt->fmtid];
703
704 h->ov_enabled = 1;
705 set_overlay(h,h->ov_enabled);
706 return 0;
707 }
708
709 /* ---------------------------------------------------------------------- */
710 /* capture */
711
712 static void
713 catchsignal(int signal)
714 {
715 if (signal == SIGUSR1 && ng_debug > 1)
716 fprintf(stderr,"bktr: sigusr1\n");
717 if (signal == SIGALRM)
718 fprintf(stderr,"bktr: sigalrm\n");
719 }
720
721 static void
722 siginit(void)
723 {
724 struct sigaction act,old;
725
726 memset(&act,0,sizeof(act));
727 sigemptyset(&act.sa_mask);
728 act.sa_handler = catchsignal;
729 sigaction(SIGUSR1,&act,&old);
730 sigaction(SIGALRM,&act,&old);
731 }
732
733 static int bsd_setformat(void *handle, struct ng_video_fmt *fmt)
734 {
735 struct bsd_handle *h = handle;
736
737 if (-1 == h->xawtv2pf[fmt->fmtid])
738 return -1;
739
740 if (fmt->width > 768)
741 fmt->width = 768;
742 if (fmt->height > 576)
743 fmt->height = 576;
744 fmt->bytesperline = fmt->width * ng_vfmt_to_depth[fmt->fmtid] / 8;
745
746 h->capfmt = h->pf+h->xawtv2pf[fmt->fmtid];
747 h->capgeo.rows = fmt->height;
748 h->capgeo.columns = fmt->width;
749 h->capgeo.frames = 1;
750 h->capgeo.oformat = 0 /* FIXME */;
751 if (fmt->height <= 320)
752 h->capgeo.oformat |= METEOR_GEO_ODD_ONLY;
753 h->fmt = *fmt;
754 return 0;
755 }
756
757 static void
758 set_capture(struct bsd_handle *h, int state)
759 {
760 if (state) {
761 /* enable */
762 xioctl(h->fd, METEORSVIDEO, &h->nofb);
763 xioctl(h->fd, METEORSETGEO, &h->capgeo);
764 xioctl(h->fd, METEORSACTPIXFMT, h->capfmt);
765 xioctl(h->fd, BT848SCLIP, &h->noclip);
766 } else {
767 /* disable */
768 xioctl(h->fd, METEORCAPTUR, &stop);
769 }
770 }
771
772 static int bsd_startvideo(void *handle, int fps, unsigned int buffers)
773 {
774 struct bsd_handle *h = handle;
775
776 set_overlay(h,0);
777 h->fps = fps;
778 h->start = ng_get_timestamp();
779 set_capture(h,1);
780 xioctl(h->fd, METEORSSIGNAL, &signal_on);
781 xioctl(h->fd, METEORCAPTUR, &start);
782 return 0;
783 }
784
785 static void bsd_stopvideo(void *handle)
786 {
787 struct bsd_handle *h = handle;
788
789 h->fps = 0;
790 set_capture(h,0);
791 xioctl(h->fd, METEORCAPTUR, &stop);
792 xioctl(h->fd, METEORSSIGNAL, &signal_off);
793 set_overlay(h,h->ov_enabled);
794 }
795
796 static struct ng_video_buf* bsd_nextframe(void *handle)
797 {
798 struct bsd_handle *h = handle;
799 struct ng_video_buf *buf;
800 int size;
801 sigset_t sa_mask;
802
803 size = h->fmt.bytesperline * h->fmt.height;
804 buf = ng_malloc_video_buf(&h->fmt,size);
805
806 alarm(1);
807 sigfillset(&sa_mask);
808 sigdelset(&sa_mask,SIGUSR1);
809 sigdelset(&sa_mask,SIGALRM);
810 sigsuspend(&sa_mask);
811 alarm(0);
812
813 memcpy(buf->data,h->map,size);
814 buf->info.ts = ng_get_timestamp() - h->start;
815 return buf;
816 }
817
818 static struct ng_video_buf* bsd_getimage(void *handle)
819 {
820 struct bsd_handle *h = handle;
821 struct ng_video_buf *buf;
822 int size;
823
824 set_overlay(h,0);
825 set_capture(h,1);
826
827 size = h->fmt.bytesperline * h->fmt.height;
828 buf = ng_malloc_video_buf(&h->fmt,size);
829 xioctl(h->fd, METEORCAPTUR, &single);
830 memcpy(buf->data,h->map,size);
831
832 set_capture(h,0);
833 set_overlay(h,h->ov_enabled);
834
835 return buf;
836 }
837
838 /* ---------------------------------------------------------------------- */
839
840 extern void ng_plugin_init(void);
841 void ng_plugin_init(void)
842 {
843 ng_vid_driver_register(NG_PLUGIN_MAGIC,__FILE__,&bsd_driver);
844 }
845
|
This page was automatically generated by the
LXR engine.
|