comparison stream/tvi_bsdbt848.c @ 19271:64d82a45a05d

introduce new 'stream' directory for all stream layer related components and split them from libmpdemux
author ben
date Mon, 31 Jul 2006 17:39:17 +0000
parents libmpdemux/tvi_bsdbt848.c@d2d9d011203f
children ac69ba536915
comparison
equal deleted inserted replaced
19270:7d39b911f0bd 19271:64d82a45a05d
1 /*
2 (C)2002 Charles R. Henrich (henrich@msu.edu)
3 *BSD (hopefully, requires working driver!) BrookTree capture support.
4
5 Still in (active) development!
6
7 v1.1 Mar 13 2002 Fully functional, need to move ring buffer to
8 the kernel driver.
9 v1.0 Feb 19 2002 First Release, need to add support for changing
10 audio parameters.
11 */
12
13 #include "config.h"
14
15 #define RINGSIZE 8
16 #define FRAGSIZE 4096 /* (2^12 see SETFRAGSIZE below) */
17
18 #define TRUE (1==1)
19 #define FALSE (1==0)
20
21 #define PAL_WIDTH 768
22 #define PAL_HEIGHT 576
23 #define PAL_FPS 25
24
25 #define NTSC_WIDTH 640
26 #define NTSC_HEIGHT 480
27 #define NTSC_FPS 29.97
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/mman.h>
35 #include <sys/filio.h>
36 #include <sys/time.h>
37 #include <signal.h>
38 #include <string.h>
39
40 #include <sys/param.h>
41 #ifdef __NetBSD__
42 #include <dev/ic/bt8xx.h>
43 #include <sys/audioio.h>
44 #elif defined(__DragonFly__)
45 #include <dev/video/meteor/ioctl_meteor.h>
46 #include <dev/video/bktr/ioctl_bt848.h>
47 #elif __FreeBSD_version >= 502100
48 #include <dev/bktr/ioctl_meteor.h>
49 #include <dev/bktr/ioctl_bt848.h>
50 #else
51 #include <machine/ioctl_meteor.h>
52 #include <machine/ioctl_bt848.h>
53 #endif
54
55 #ifdef HAVE_SYS_SOUNDCARD_H
56 #include <sys/soundcard.h>
57 #else
58 #ifdef HAVE_SOUNDCARD_H
59 #include <soundcard.h>
60 #else
61 #include <machine/soundcard.h>
62 #endif
63 #endif
64
65 #include "libaf/af_format.h"
66 #include "libvo/img_format.h"
67 #include "tv.h"
68
69 /* information about this file */
70 static tvi_info_t info = {
71 "Brooktree848 Support",
72 "bsdbt848",
73 "Charles Henrich",
74 "in development"
75 };
76
77 typedef struct {
78 int dirty;
79 double timestamp;
80 char *buf;
81 } RBFRAME;
82
83 /* private data's */
84 typedef struct {
85
86 /* Audio */
87 char *dspdev;
88 int dspready;
89 int dspfd;
90 int dspsamplesize;
91 int dspstereo;
92 int dspspeed;
93 int dspfmt;
94 int dspframesize;
95 int dsprate;
96 long long dspbytesread;
97
98 /* Video */
99 char *btdev;
100 int videoready;
101 int btfd;
102 int source;
103 float maxfps;
104 float fps;
105 int iformat;
106 int maxheight;
107 int maxwidth;
108 struct meteor_geomet geom;
109 struct meteor_capframe capframe;
110
111 /* Frame Buffer */
112
113 int framebufsize;
114 float timestamp;
115 int curpaintframe;
116 int curbufframe;
117 unsigned char *livebuf;
118 RBFRAME framebuf[RINGSIZE];
119
120 /* Inputs */
121
122 int input;
123
124 /* Tuner */
125
126 char *tunerdev;
127 int tunerfd;
128 int tunerready;
129 u_long tunerfreq;
130 struct bktr_chnlset cset;
131
132 /* Other */
133
134 int immediatemode;
135 double starttime;
136
137 } priv_t;
138
139 #include "tvi_def.h"
140
141 static priv_t *G_private=NULL;
142
143 static int getinput(int innumber);
144
145 static void processframe(int signal)
146 {
147 struct timeval curtime;
148
149 if(G_private->immediatemode == TRUE) return;
150
151 gettimeofday(&curtime, NULL);
152
153 if(G_private->framebuf[G_private->curpaintframe].dirty == TRUE)
154 {
155 memcpy(G_private->framebuf[G_private->curpaintframe].buf,
156 G_private->livebuf, G_private->framebufsize);
157
158 G_private->framebuf[G_private->curpaintframe].dirty = FALSE;
159
160 G_private->framebuf[G_private->curpaintframe].timestamp =
161 curtime.tv_sec + curtime.tv_usec*.000001;
162
163 G_private->curpaintframe++;
164
165 if(G_private->curpaintframe >= RINGSIZE) G_private->curpaintframe = 0;
166 }
167
168 return;
169 }
170
171 /* handler creator - entry point ! */
172 tvi_handle_t *tvi_init_bsdbt848(char *device)
173 {
174 return(new_handle());
175 }
176
177 static int control(priv_t *priv, int cmd, void *arg)
178 {
179 switch(cmd)
180 {
181
182 /* Tuner Controls */
183
184 case TVI_CONTROL_IS_TUNER:
185 if(priv->tunerready == FALSE) return TVI_CONTROL_FALSE;
186 return(TVI_CONTROL_TRUE);
187
188 case TVI_CONTROL_TUN_GET_FREQ:
189 {
190 if(ioctl(priv->tunerfd, TVTUNER_GETFREQ, &priv->tunerfreq) < 0)
191 {
192 perror("GETFREQ:ioctl");
193 return(TVI_CONTROL_FALSE);
194 }
195
196 (int)*(void **)arg = priv->tunerfreq;
197 return(TVI_CONTROL_TRUE);
198 }
199
200 case TVI_CONTROL_TUN_SET_FREQ:
201 {
202 priv->tunerfreq = (int)*(void **)arg;
203
204 if(ioctl(priv->tunerfd, TVTUNER_SETFREQ, &priv->tunerfreq) < 0)
205 {
206 perror("SETFREQ:ioctl");
207 return(0);
208 }
209
210 return(TVI_CONTROL_TRUE);
211 }
212
213 case TVI_CONTROL_TUN_GET_TUNER:
214 case TVI_CONTROL_TUN_SET_TUNER:
215
216 /* Inputs */
217
218 case TVI_CONTROL_SPC_GET_INPUT:
219 {
220 if(ioctl(priv->btfd, METEORGINPUT, &priv->input) < 0)
221 {
222 perror("GINPUT:ioctl");
223 return(TVI_CONTROL_FALSE);
224 }
225
226 (int)*(void **)arg = priv->input;
227 return(TVI_CONTROL_TRUE);
228 }
229
230 case TVI_CONTROL_SPC_SET_INPUT:
231 {
232 priv->input = getinput((int)*(void **)arg);
233
234 if(ioctl(priv->btfd, METEORSINPUT, &priv->input) < 0)
235 {
236 perror("tunerfreq:ioctl");
237 return(0);
238 }
239
240 return(TVI_CONTROL_TRUE);
241 }
242
243 /* Audio Controls */
244
245 case TVI_CONTROL_IS_AUDIO:
246 if(priv->dspready == FALSE) return TVI_CONTROL_FALSE;
247 return(TVI_CONTROL_TRUE);
248
249 case TVI_CONTROL_AUD_GET_FORMAT:
250 {
251 (int)*(void **)arg = AF_FORMAT_S16_LE;
252 return(TVI_CONTROL_TRUE);
253 }
254 case TVI_CONTROL_AUD_GET_CHANNELS:
255 {
256 (int)*(void **)arg = 2;
257 return(TVI_CONTROL_TRUE);
258 }
259 case TVI_CONTROL_AUD_SET_SAMPLERATE:
260 {
261 int dspspeed = (int)*(void **)arg;
262
263 if(ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &dspspeed) == -1)
264 {
265 perror("invalidaudiorate");
266 return(TVI_CONTROL_FALSE);
267 }
268
269 priv->dspspeed = dspspeed;
270
271 priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/
272 priv->fps * (priv->dspstereo+1);
273 priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*
274 (priv->dspstereo+1);
275
276 return(TVI_CONTROL_TRUE);
277 }
278 case TVI_CONTROL_AUD_GET_SAMPLERATE:
279 {
280 (int)*(void **)arg = priv->dspspeed;
281 return(TVI_CONTROL_TRUE);
282 }
283 case TVI_CONTROL_AUD_GET_SAMPLESIZE:
284 {
285 (int)*(void **)arg = priv->dspsamplesize/8;
286 return(TVI_CONTROL_TRUE);
287 }
288
289 /* Video Controls */
290
291 case TVI_CONTROL_IS_VIDEO:
292 if(priv->videoready == FALSE) return TVI_CONTROL_FALSE;
293 return(TVI_CONTROL_TRUE);
294
295 case TVI_CONTROL_TUN_SET_NORM:
296 {
297 int req_mode = (int)*(void **)arg;
298 u_short tmp_fps;
299
300 priv->iformat = METEOR_FMT_AUTOMODE;
301
302 if(req_mode == TV_NORM_PAL)
303 {
304 priv->iformat = METEOR_FMT_PAL;
305 priv->maxheight = PAL_HEIGHT;
306 priv->maxwidth = PAL_WIDTH;
307 priv->maxfps = PAL_FPS;
308 priv->fps = PAL_FPS;
309
310 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
311
312 if(priv->geom.rows > priv->maxheight)
313 {
314 priv->geom.rows = priv->maxheight;
315 }
316
317 if(priv->geom.columns > priv->maxwidth)
318 {
319 priv->geom.columns = priv->maxwidth;
320 }
321 }
322
323 if(req_mode == TV_NORM_NTSC)
324 {
325 priv->iformat = METEOR_FMT_NTSC;
326 priv->maxheight = NTSC_HEIGHT;
327 priv->maxwidth = NTSC_WIDTH;
328 priv->maxfps = NTSC_FPS;
329 priv->fps = NTSC_FPS;
330
331 priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/
332 priv->fps * (priv->dspstereo+1);
333 priv->dsprate = priv->dspspeed * priv->dspsamplesize/8 *
334 (priv->dspstereo+1);
335
336 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
337
338 if(priv->geom.rows > priv->maxheight)
339 {
340 priv->geom.rows = priv->maxheight;
341 }
342
343 if(priv->geom.columns > priv->maxwidth)
344 {
345 priv->geom.columns = priv->maxwidth;
346 }
347 }
348
349 if(req_mode == TV_NORM_SECAM) priv->iformat = METEOR_FMT_SECAM;
350
351 if(ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0)
352 {
353 perror("format:ioctl");
354 return(TVI_CONTROL_FALSE);
355 }
356
357 if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0)
358 {
359 perror("geo:ioctl");
360 return(0);
361 }
362
363 tmp_fps = priv->fps;
364 if(ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0)
365 {
366 perror("fps:ioctl");
367 return(0);
368 }
369
370 #ifdef BT848_SAUDIO
371 if(priv->tunerready == TRUE &&
372 ioctl(priv->tunerfd, BT848_SAUDIO, &tv_param_audio_id) < 0)
373 {
374 perror("audioid:ioctl");
375 }
376 #endif
377
378 return(TVI_CONTROL_TRUE);
379 }
380
381 case TVI_CONTROL_VID_GET_FORMAT:
382 (int)*(void **)arg = IMGFMT_UYVY;
383 return(TVI_CONTROL_TRUE);
384
385 case TVI_CONTROL_VID_SET_FORMAT:
386 {
387 int req_fmt = (int)*(void **)arg;
388
389 if(req_fmt != IMGFMT_UYVY) return(TVI_CONTROL_FALSE);
390
391 return(TVI_CONTROL_TRUE);
392 }
393 case TVI_CONTROL_VID_SET_WIDTH:
394 priv->geom.columns = (int)*(void **)arg;
395
396 if(priv->geom.columns > priv->maxwidth)
397 {
398 priv->geom.columns = priv->maxwidth;
399 }
400
401 if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0)
402 {
403 perror("width:ioctl");
404 return(0);
405 }
406
407 return(TVI_CONTROL_TRUE);
408
409 case TVI_CONTROL_VID_GET_WIDTH:
410 (int)*(void **)arg = priv->geom.columns;
411 return(TVI_CONTROL_TRUE);
412
413 case TVI_CONTROL_VID_SET_HEIGHT:
414 priv->geom.rows = (int)*(void **)arg;
415
416 if(priv->geom.rows > priv->maxheight)
417 {
418 priv->geom.rows = priv->maxheight;
419 }
420
421 if(priv->geom.rows <= priv->maxheight / 2)
422 {
423 priv->geom.oformat |= METEOR_GEO_EVEN_ONLY;
424 }
425
426 if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0)
427 {
428 perror("height:ioctl");
429 return(0);
430 }
431
432 return(TVI_CONTROL_TRUE);
433
434 case TVI_CONTROL_VID_GET_HEIGHT:
435 (int)*(void **)arg = priv->geom.rows;
436 return(TVI_CONTROL_TRUE);
437
438 case TVI_CONTROL_VID_GET_FPS:
439 *(float *)arg = priv->fps;
440 return(TVI_CONTROL_TRUE);
441
442 /*
443 case TVI_CONTROL_VID_SET_FPS:
444 priv->fps = (int)*(void **)arg;
445
446 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
447
448 if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0)
449 {
450 perror("fps:ioctl");
451 return(0);
452 }
453
454 return(TVI_CONTROL_TRUE);
455 */
456
457 case TVI_CONTROL_VID_CHK_WIDTH:
458 case TVI_CONTROL_VID_CHK_HEIGHT:
459 return(TVI_CONTROL_TRUE);
460
461 case TVI_CONTROL_IMMEDIATE:
462 priv->immediatemode = TRUE;
463 return(TVI_CONTROL_TRUE);
464 }
465
466 return(TVI_CONTROL_UNKNOWN);
467 }
468
469 static int init(priv_t *priv)
470 {
471 int marg;
472 int count;
473 u_short tmp_fps;
474
475 G_private = priv; /* Oooh, sick */
476
477 /* Video Configuration */
478
479 priv->videoready = TRUE;
480 priv->btdev = strdup("/dev/bktr0");
481 priv->immediatemode = FALSE;
482 priv->iformat = METEOR_FMT_PAL;
483 priv->maxheight = PAL_HEIGHT;
484 priv->maxwidth = PAL_WIDTH;
485 priv->maxfps = PAL_FPS;
486 priv->source = METEOR_INPUT_DEV0;
487 priv->fps = priv->maxfps;
488
489 priv->starttime=0;
490 priv->curpaintframe=0;
491 priv->curbufframe=0;
492
493 priv->geom.columns = priv->maxwidth;
494 priv->geom.rows = priv->maxheight;
495 priv->geom.frames = 1;
496 priv->geom.oformat = METEOR_GEO_YUV_PACKED;
497
498 priv->btfd = open(priv->btdev, O_RDONLY);
499
500 if(priv->btfd < 0)
501 {
502 perror("bktr open");
503 priv->videoready = FALSE;
504 }
505
506 if(priv->videoready == TRUE &&
507 ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0)
508 {
509 perror("FMT:ioctl");
510 }
511
512 if(priv->videoready == TRUE &&
513 ioctl(priv->btfd, METEORSINPUT, &priv->source) < 0)
514 {
515 perror("SINPUT:ioctl");
516 }
517
518 tmp_fps = priv->fps;
519 if(priv->videoready == TRUE &&
520 ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0)
521 {
522 perror("SFPS:ioctl");
523 }
524
525 if(priv->videoready == TRUE &&
526 ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0)
527 {
528 perror("SGEO:ioctl");
529 }
530
531 if(priv->videoready == TRUE)
532 {
533 priv->framebufsize = (priv->geom.columns * priv->geom.rows * 2);
534
535 priv->livebuf = (u_char *)mmap((caddr_t)0, priv->framebufsize, PROT_READ,
536 MAP_SHARED, priv->btfd, (off_t)0);
537
538 if(priv->livebuf == (u_char *) MAP_FAILED)
539 {
540 perror("mmap");
541 priv->videoready = FALSE;
542 }
543
544 for(count=0;count<RINGSIZE;count++)
545 {
546 priv->framebuf[count].buf = malloc(priv->framebufsize);
547
548 if(priv->framebuf[count].buf == NULL)
549 {
550 perror("framebufmalloc");
551 priv->videoready = FALSE;
552 break;
553 }
554
555 priv->framebuf[count].dirty = TRUE;
556 priv->framebuf[count].timestamp = 0;
557 }
558 }
559
560 /* Tuner Configuration */
561
562 priv->tunerdev = strdup("/dev/tuner0");
563 priv->tunerready = TRUE;
564
565 priv->tunerfd = open(priv->tunerdev, O_RDONLY);
566
567 if(priv->tunerfd < 0)
568 {
569 perror("tune open");
570 priv->tunerready = FALSE;
571 }
572
573 /* Audio Configuration */
574
575 priv->dspready = TRUE;
576 #ifdef __NetBSD__
577 priv->dspdev = strdup("/dev/sound");
578 #else
579 priv->dspdev = strdup("/dev/dsp");
580 #endif
581 priv->dspsamplesize = 16;
582 priv->dspstereo = 1;
583 priv->dspspeed = 44100;
584 priv->dspfmt = AFMT_S16_LE;
585 priv->dspbytesread = 0;
586 priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*(priv->dspstereo+1);
587 priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/priv->fps *
588 (priv->dspstereo+1);
589
590 if((priv->dspfd = open (priv->dspdev, O_RDONLY, 0)) < 0)
591 {
592 perror("dsp open");
593 priv->dspready = FALSE;
594 }
595
596 marg = (256 << 16) | 12;
597
598 if (ioctl(priv->dspfd, SNDCTL_DSP_SETFRAGMENT, &marg ) < 0 )
599 {
600 perror("setfrag");
601 priv->dspready = FALSE;
602 }
603
604 if((priv->dspready == TRUE) &&
605 ((ioctl(priv->dspfd, SNDCTL_DSP_SAMPLESIZE, &priv->dspsamplesize) == -1) ||
606 (ioctl(priv->dspfd, SNDCTL_DSP_STEREO, &priv->dspstereo) == -1) ||
607 (ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &priv->dspspeed) == -1) ||
608 (ioctl(priv->dspfd, SNDCTL_DSP_SETFMT, &priv->dspfmt) == -1)))
609 {
610 perror ("configuration of dsp failed");
611 close(priv->dspfd);
612 priv->dspready = FALSE;
613 }
614
615 return(1);
616 }
617
618 /* that's the real start, we'got the format parameters (checked with control) */
619 static int start(priv_t *priv)
620 {
621 int tmp;
622 struct timeval curtime;
623 int marg;
624
625 fprintf(stderr,"START\n");
626 if(priv->videoready == FALSE) return(0);
627
628 signal(SIGUSR1, processframe);
629 signal(SIGALRM, processframe);
630
631 marg = SIGUSR1;
632
633 if(ioctl(priv->btfd, METEORSSIGNAL, &marg) < 0)
634 {
635 perror("METEORSSIGNAL failed");
636 return(0);
637 }
638
639 read(priv->dspfd, &tmp, 2);
640
641 gettimeofday(&curtime, NULL);
642
643 priv->starttime = curtime.tv_sec + (curtime.tv_usec *.000001);
644
645 marg = METEOR_CAP_CONTINOUS;
646
647 if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0)
648 {
649 perror("METEORCAPTUR failed");
650 return(0);
651 }
652
653 return(1);
654 }
655
656 static int uninit(priv_t *priv)
657 {
658 int marg;
659
660 if(priv->videoready == FALSE) return(0);
661
662 marg = METEOR_SIG_MODE_MASK;
663
664 if(ioctl( priv->btfd, METEORSSIGNAL, &marg) < 0 )
665 {
666 perror("METEORSSIGNAL");
667 return(0);
668 }
669
670 marg = METEOR_CAP_STOP_CONT;
671
672 if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0 )
673 {
674 perror("METEORCAPTUR STOP");
675 return(0);
676 }
677
678 close(priv->btfd);
679 close(priv->dspfd);
680
681 priv->dspfd = -1;
682 priv->btfd = -1;
683
684 priv->dspready = priv->videoready = FALSE;
685
686 return(1);
687 }
688
689
690 static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
691 {
692 struct timeval curtime;
693 sigset_t sa_mask;
694
695 if(priv->videoready == FALSE) return(0);
696
697 alarm(1);
698 sigfillset(&sa_mask);
699 sigdelset(&sa_mask,SIGINT);
700 sigdelset(&sa_mask,SIGUSR1);
701 sigdelset(&sa_mask,SIGALRM);
702 sigsuspend(&sa_mask);
703 alarm(0);
704
705 memcpy(buffer, priv->livebuf, len);
706
707 /* PTS = 0, show the frame NOW, this routine is only used in playback mode
708 without audio capture .. */
709
710 return(0);
711 }
712
713 static double grab_video_frame(priv_t *priv, char *buffer, int len)
714 {
715 struct timeval curtime;
716 double timestamp=0;
717 sigset_t sa_mask;
718
719 if(priv->videoready == FALSE) return(0);
720
721 if(priv->immediatemode == TRUE)
722 {
723 return grabimmediate_video_frame(priv, buffer, len);
724 }
725
726 while(priv->framebuf[priv->curbufframe].dirty == TRUE)
727 {
728 alarm(1);
729 sigemptyset(&sa_mask);
730 sigsuspend(&sa_mask);
731 alarm(0);
732 }
733
734 memcpy(buffer, priv->framebuf[priv->curbufframe].buf, len);
735 timestamp = priv->framebuf[priv->curbufframe].timestamp;
736 priv->framebuf[priv->curbufframe].dirty = TRUE;
737
738 priv->curbufframe++;
739 if(priv->curbufframe >= RINGSIZE) priv->curbufframe = 0;
740
741 return(timestamp-priv->starttime);
742 }
743
744 static int get_video_framesize(priv_t *priv)
745 {
746 return(priv->geom.columns*priv->geom.rows*16/8);
747 }
748
749 static double grab_audio_frame(priv_t *priv, char *buffer, int len)
750 {
751 struct timeval curtime;
752 double curpts;
753 double timeskew;
754 int bytesavail;
755 int bytesread;
756 int ret;
757
758 if(priv->dspready == FALSE) return 0;
759
760 gettimeofday(&curtime, NULL);
761
762 /* Get exactly one frame of audio, which forces video sync to audio.. */
763
764 bytesread=read(priv->dspfd, buffer, len);
765
766 while(bytesread < len)
767 {
768 ret=read(priv->dspfd, &buffer[bytesread], len-bytesread);
769
770 if(ret == -1)
771 {
772 perror("Audio read failed!");
773 return 0;
774 }
775
776 bytesread+=ret;
777 }
778
779 priv->dspbytesread += bytesread;
780
781 curpts = curtime.tv_sec + curtime.tv_usec * .000001;
782
783 timeskew = priv->dspbytesread * 1.0 / priv->dsprate - (curpts-priv->starttime);
784
785 if(timeskew > .125/priv->fps)
786 {
787 priv->starttime -= timeskew;
788 }
789 else
790 {
791 if(timeskew < -.125/priv->fps)
792 {
793 priv->starttime -= timeskew;
794 }
795 }
796
797 return(priv->dspbytesread * 1.0 / priv->dsprate);
798 }
799
800 static int get_audio_framesize(priv_t *priv)
801 {
802 int bytesavail;
803 #ifdef __NetBSD__
804 struct audio_info auinf;
805 #endif
806
807 if(priv->dspready == FALSE) return 0;
808
809 #ifdef __NetBSD__
810 if(ioctl(priv->dspfd, AUDIO_GETINFO, &auinf) < 0)
811 {
812 perror("AUDIO_GETINFO");
813 return(TVI_CONTROL_FALSE);
814 }
815 else
816 bytesavail = auinf.record.seek; /* *priv->dspsamplesize; */
817 #else
818 if(ioctl(priv->dspfd, FIONREAD, &bytesavail) < 0)
819 {
820 perror("FIONREAD");
821 return(TVI_CONTROL_FALSE);
822 }
823 #endif
824
825 /* When mencoder wants audio data, it wants data..
826 it won't go do anything else until it gets it :( */
827
828 if(bytesavail == 0) return FRAGSIZE;
829
830 return(bytesavail);
831 }
832
833 static int getinput(int innumber)
834 {
835 switch(innumber)
836 {
837 case 0: return METEOR_INPUT_DEV0; /* RCA */
838 case 1: return METEOR_INPUT_DEV1; /* Tuner */
839 case 2: return METEOR_INPUT_DEV2; /* In 1 */
840 case 3: return METEOR_INPUT_DEV3; /* In 2 */
841 case 4: return METEOR_INPUT_DEV_RGB; /* RGB */
842 case 5: return METEOR_INPUT_DEV_SVIDEO; /* SVid */
843 }
844
845 return 0;
846 }