Give better name to Inverse_Table_6_9
[mplayer/glamo.git] / stream / tvi_bsdbt848.c
blob1926a5d45b0883087b648b0c32197b9013454ed9
1 /*
2 (C)2002 Charles R. Henrich (henrich@msu.edu)
3 *BSD (hopefully, requires working driver!) BrookTree capture support.
5 Still in (active) development!
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.
13 #include "config.h"
15 #define RINGSIZE 8
16 #define FRAGSIZE 4096 /* (2^12 see SETFRAGSIZE below) */
18 #define TRUE (1==1)
19 #define FALSE (1==0)
21 #define PAL_WIDTH 768
22 #define PAL_HEIGHT 576
23 #define PAL_FPS 25
25 #define NTSC_WIDTH 640
26 #define NTSC_HEIGHT 480
27 #define NTSC_FPS 29.97
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 #include <errno.h>
41 #include <sys/param.h>
42 #ifdef CONFIG_SUN_AUDIO
43 #include <sys/audioio.h>
44 #endif
46 #ifdef IOCTL_METEOR_H_NAME
47 #include IOCTL_METEOR_H_NAME
48 #endif
50 #ifdef IOCTL_BT848_H_NAME
51 #include IOCTL_BT848_H_NAME
52 #endif
54 #ifdef HAVE_SYS_SOUNDCARD_H
55 #include <sys/soundcard.h>
56 #else
57 #ifdef HAVE_SOUNDCARD_H
58 #include <soundcard.h>
59 #else
60 #include <machine/soundcard.h>
61 #endif
62 #endif
64 #include "libaf/af_format.h"
65 #include "libmpcodecs/img_format.h"
66 #include "tv.h"
67 #include "help_mp.h"
68 #include "mp_msg.h"
70 static tvi_handle_t *tvi_init_bsdbt848(tv_param_t* tv_param);
71 /* information about this file */
72 const tvi_info_t tvi_info_bsdbt848 = {
73 tvi_init_bsdbt848,
74 "Brooktree848 Support",
75 "bsdbt848",
76 "Charles Henrich",
77 "in development"
80 typedef struct {
81 int dirty;
82 double timestamp;
83 char *buf;
84 } RBFRAME;
86 /* private data's */
87 typedef struct {
89 /* Audio */
90 char *dspdev;
91 int dspready;
92 int dspfd;
93 int dspsamplesize;
94 int dspstereo;
95 int dspspeed;
96 int dspfmt;
97 int dspframesize;
98 int dsprate;
99 long long dspbytesread;
101 /* Video */
102 char *btdev;
103 int videoready;
104 int btfd;
105 int source;
106 float maxfps;
107 float fps;
108 int iformat;
109 int maxheight;
110 int maxwidth;
111 struct meteor_geomet geom;
112 struct meteor_capframe capframe;
114 /* Frame Buffer */
116 int framebufsize;
117 float timestamp;
118 int curpaintframe;
119 int curbufframe;
120 unsigned char *livebuf;
121 RBFRAME framebuf[RINGSIZE];
123 /* Inputs */
125 int input;
127 /* Tuner */
129 char *tunerdev;
130 int tunerfd;
131 int tunerready;
132 u_long tunerfreq;
133 struct bktr_chnlset cset;
135 /* Other */
137 int immediatemode;
138 double starttime;
140 tv_param_t *tv_param;
141 } priv_t;
143 #include "tvi_def.h"
145 static priv_t *G_private=NULL;
147 static int getinput(int innumber);
149 static void processframe(int signal)
151 struct timeval curtime;
153 if(G_private->immediatemode == TRUE) return;
155 gettimeofday(&curtime, NULL);
157 if(G_private->framebuf[G_private->curpaintframe].dirty == TRUE)
159 memcpy(G_private->framebuf[G_private->curpaintframe].buf,
160 G_private->livebuf, G_private->framebufsize);
162 G_private->framebuf[G_private->curpaintframe].dirty = FALSE;
164 G_private->framebuf[G_private->curpaintframe].timestamp =
165 curtime.tv_sec + curtime.tv_usec*.000001;
167 G_private->curpaintframe++;
169 if(G_private->curpaintframe >= RINGSIZE) G_private->curpaintframe = 0;
172 return;
175 /* handler creator - entry point ! */
176 static tvi_handle_t *tvi_init_bsdbt848(tv_param_t* tv_param)
178 char* sep ;
179 tvi_handle_t* tvh;
180 priv_t* priv;
182 tvh=new_handle();
183 if(!tvh)
184 return NULL;
185 priv=(priv_t*)tvh->priv;
187 if user needs to specify both /dev/bktr<n> and /dev/tuner<n>
188 it can do this with "-tv device=/dev/bktr1,/dev/tuner1"
191 /* set video device name */
192 if (!tv_param->device){
193 priv->btdev = strdup("/dev/bktr0");
194 priv->tunerdev = strdup("/dev/tuner0");
195 }else{
196 sep = strchr(tv_param->device,',');
197 priv->btdev = strdup(tv_param->device);
198 if(sep){
199 // tuner device is also passed
200 priv->tunerdev = strdup(sep+1);
201 priv->btdev[sep - tv_param->device] = 0;
202 }else{
203 priv->tunerdev = strdup("/dev/tuner0");
207 /* set audio device name */
208 if (!tv_param->adevice)
209 #ifdef CONFIG_SUN_AUDIO
210 priv->dspdev = strdup("/dev/sound");
211 #else
212 priv->dspdev = strdup("/dev/dsp");
213 #endif
214 else
215 priv->dspdev = strdup(tv_param->adevice);
217 priv->tv_param=tv_param;
218 return tvh;
221 static int control(priv_t *priv, int cmd, void *arg)
223 switch(cmd)
226 /* Tuner Controls */
228 case TVI_CONTROL_IS_TUNER:
229 if(priv->tunerready == FALSE) return TVI_CONTROL_FALSE;
230 return TVI_CONTROL_TRUE;
232 case TVI_CONTROL_TUN_GET_FREQ:
234 if(ioctl(priv->tunerfd, TVTUNER_GETFREQ, &priv->tunerfreq) < 0)
236 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "TVTUNER_GETFREQ", strerror(errno));
237 return TVI_CONTROL_FALSE;
240 *(int *)arg = priv->tunerfreq;
241 return TVI_CONTROL_TRUE;
244 case TVI_CONTROL_TUN_SET_FREQ:
246 priv->tunerfreq = *(int *)arg;
248 if(ioctl(priv->tunerfd, TVTUNER_SETFREQ, &priv->tunerfreq) < 0)
250 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "TVTUNER_SETFREQ", strerror(errno));
251 return 0;
254 return TVI_CONTROL_TRUE;
256 case TVI_CONTROL_TUN_GET_SIGNAL:
258 int status;
259 if(ioctl(priv->tunerfd, TVTUNER_GETSTATUS, &status) < 0)
261 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "GETSTATUS", strerror(errno));
262 return 0;
264 *(int*)arg=(status & 0x02)? 100 : 0;
265 return TVI_CONTROL_TRUE;
268 case TVI_CONTROL_TUN_GET_TUNER:
269 case TVI_CONTROL_TUN_SET_TUNER:
271 /* Inputs */
273 case TVI_CONTROL_SPC_GET_INPUT:
275 if(ioctl(priv->btfd, METEORGINPUT, &priv->input) < 0)
277 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORGINPUT", strerror(errno));
278 return TVI_CONTROL_FALSE;
281 *(int *)arg = priv->input;
282 return TVI_CONTROL_TRUE;
285 case TVI_CONTROL_SPC_SET_INPUT:
287 priv->input = getinput(*(int *)arg);
289 if(ioctl(priv->btfd, METEORSINPUT, &priv->input) < 0)
291 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSINPUT", strerror(errno));
292 return 0;
295 return TVI_CONTROL_TRUE;
298 /* Audio Controls */
300 case TVI_CONTROL_IS_AUDIO:
301 if(priv->dspready == FALSE) return TVI_CONTROL_FALSE;
302 return TVI_CONTROL_TRUE;
304 case TVI_CONTROL_AUD_GET_FORMAT:
306 *(int *)arg = AF_FORMAT_S16_LE;
307 return TVI_CONTROL_TRUE;
309 case TVI_CONTROL_AUD_GET_CHANNELS:
311 *(int *)arg = 2;
312 return TVI_CONTROL_TRUE;
314 case TVI_CONTROL_AUD_SET_SAMPLERATE:
316 int dspspeed = *(int *)arg;
318 if(ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &dspspeed) == -1)
320 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848InvalidAudioRate, strerror(errno));
321 return TVI_CONTROL_FALSE;
324 priv->dspspeed = dspspeed;
326 priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/
327 priv->fps * (priv->dspstereo+1);
328 priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*
329 (priv->dspstereo+1);
331 return TVI_CONTROL_TRUE;
333 case TVI_CONTROL_AUD_GET_SAMPLERATE:
335 *(int *)arg = priv->dspspeed;
336 return TVI_CONTROL_TRUE;
338 case TVI_CONTROL_AUD_GET_SAMPLESIZE:
340 *(int *)arg = priv->dspsamplesize/8;
341 return TVI_CONTROL_TRUE;
344 /* Video Controls */
346 case TVI_CONTROL_IS_VIDEO:
347 if(priv->videoready == FALSE) return TVI_CONTROL_FALSE;
348 return TVI_CONTROL_TRUE;
350 case TVI_CONTROL_TUN_SET_NORM:
352 int req_mode = *(int *)arg;
353 u_short tmp_fps;
355 priv->iformat = METEOR_FMT_AUTOMODE;
357 if(req_mode == TV_NORM_PAL)
359 priv->iformat = METEOR_FMT_PAL;
360 priv->maxheight = PAL_HEIGHT;
361 priv->maxwidth = PAL_WIDTH;
362 priv->maxfps = PAL_FPS;
363 priv->fps = PAL_FPS;
365 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
367 if(priv->geom.rows > priv->maxheight)
369 priv->geom.rows = priv->maxheight;
372 if(priv->geom.columns > priv->maxwidth)
374 priv->geom.columns = priv->maxwidth;
378 if(req_mode == TV_NORM_NTSC)
380 priv->iformat = METEOR_FMT_NTSC;
381 priv->maxheight = NTSC_HEIGHT;
382 priv->maxwidth = NTSC_WIDTH;
383 priv->maxfps = NTSC_FPS;
384 priv->fps = NTSC_FPS;
386 priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/
387 priv->fps * (priv->dspstereo+1);
388 priv->dsprate = priv->dspspeed * priv->dspsamplesize/8 *
389 (priv->dspstereo+1);
391 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
393 if(priv->geom.rows > priv->maxheight)
395 priv->geom.rows = priv->maxheight;
398 if(priv->geom.columns > priv->maxwidth)
400 priv->geom.columns = priv->maxwidth;
404 if(req_mode == TV_NORM_SECAM) priv->iformat = METEOR_FMT_SECAM;
406 if(ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0)
408 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSFMT", strerror(errno));
409 return TVI_CONTROL_FALSE;
412 if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0)
414 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSETGEO", strerror(errno));
415 return 0;
418 tmp_fps = priv->fps;
419 if(ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0)
421 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSFPS", strerror(errno));
422 return 0;
425 #ifdef BT848_SAUDIO
426 if(priv->tunerready == TRUE &&
427 ioctl(priv->tunerfd, BT848_SAUDIO, &priv->tv_param->audio_id) < 0)
429 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "BT848_SAUDIO", strerror(errno));
431 #endif
433 return TVI_CONTROL_TRUE;
436 case TVI_CONTROL_VID_GET_FORMAT:
437 *(int *)arg = IMGFMT_UYVY;
438 return TVI_CONTROL_TRUE;
440 case TVI_CONTROL_VID_SET_FORMAT:
442 int req_fmt = *(int *)arg;
444 if(req_fmt != IMGFMT_UYVY) return TVI_CONTROL_FALSE;
446 return TVI_CONTROL_TRUE;
448 case TVI_CONTROL_VID_SET_WIDTH:
449 priv->geom.columns = *(int *)arg;
451 if(priv->geom.columns > priv->maxwidth)
453 priv->geom.columns = priv->maxwidth;
456 if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0)
458 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848ErrorSettingWidth, strerror(errno));
459 return 0;
462 return TVI_CONTROL_TRUE;
464 case TVI_CONTROL_VID_GET_WIDTH:
465 *(int *)arg = priv->geom.columns;
466 return TVI_CONTROL_TRUE;
468 case TVI_CONTROL_VID_SET_HEIGHT:
469 priv->geom.rows = *(int *)arg;
471 if(priv->geom.rows > priv->maxheight)
473 priv->geom.rows = priv->maxheight;
476 if(priv->geom.rows <= priv->maxheight / 2)
478 priv->geom.oformat |= METEOR_GEO_EVEN_ONLY;
481 if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0)
483 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848ErrorSettingWidth, strerror(errno));
484 return 0;
487 return TVI_CONTROL_TRUE;
489 case TVI_CONTROL_VID_GET_HEIGHT:
490 *(int *)arg = priv->geom.rows;
491 return TVI_CONTROL_TRUE;
493 case TVI_CONTROL_VID_GET_FPS:
494 *(float *)arg = priv->fps;
495 return TVI_CONTROL_TRUE;
498 case TVI_CONTROL_VID_SET_FPS:
499 priv->fps = *(int *)arg;
501 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
503 if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0)
505 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSFPS", strerror(errno));
506 return 0;
509 return TVI_CONTROL_TRUE;
512 case TVI_CONTROL_VID_CHK_WIDTH:
513 case TVI_CONTROL_VID_CHK_HEIGHT:
514 return TVI_CONTROL_TRUE;
516 case TVI_CONTROL_IMMEDIATE:
517 priv->immediatemode = TRUE;
518 return TVI_CONTROL_TRUE;
521 return TVI_CONTROL_UNKNOWN;
524 static int init(priv_t *priv)
526 int marg;
527 int count;
528 u_short tmp_fps;
530 G_private = priv; /* Oooh, sick */
532 /* Video Configuration */
534 priv->videoready = TRUE;
535 priv->immediatemode = FALSE;
536 priv->iformat = METEOR_FMT_PAL;
537 priv->maxheight = PAL_HEIGHT;
538 priv->maxwidth = PAL_WIDTH;
539 priv->maxfps = PAL_FPS;
540 priv->source = METEOR_INPUT_DEV0;
541 priv->fps = priv->maxfps;
543 priv->starttime=0;
544 priv->curpaintframe=0;
545 priv->curbufframe=0;
547 priv->geom.columns = priv->maxwidth;
548 priv->geom.rows = priv->maxheight;
549 priv->geom.frames = 1;
550 priv->geom.oformat = METEOR_GEO_YUV_PACKED;
552 priv->btfd = open(priv->btdev, O_RDONLY);
554 if(priv->btfd < 0)
556 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848ErrorOpeningBktrDev, strerror(errno));
557 priv->videoready = FALSE;
560 if(priv->videoready == TRUE &&
561 ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0)
563 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "SETEORSFMT", strerror(errno));
566 if(priv->videoready == TRUE &&
567 ioctl(priv->btfd, METEORSINPUT, &priv->source) < 0)
569 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSINPUT", strerror(errno));
572 tmp_fps = priv->fps;
573 if(priv->videoready == TRUE &&
574 ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0)
576 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSFPS", strerror(errno));
579 if(priv->videoready == TRUE &&
580 ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0)
582 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSGEQ", strerror(errno));
585 if(priv->videoready == TRUE)
587 priv->framebufsize = (priv->geom.columns * priv->geom.rows * 2);
589 priv->livebuf = (u_char *)mmap((caddr_t)0, priv->framebufsize, PROT_READ,
590 MAP_SHARED, priv->btfd, (off_t)0);
592 if(priv->livebuf == (u_char *) MAP_FAILED)
594 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848MmapFailed, strerror(errno));
595 priv->videoready = FALSE;
598 for(count=0;count<RINGSIZE;count++)
600 priv->framebuf[count].buf = malloc(priv->framebufsize);
602 if(priv->framebuf[count].buf == NULL)
604 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848FrameBufAllocFailed, strerror(errno));
605 priv->videoready = FALSE;
606 break;
609 priv->framebuf[count].dirty = TRUE;
610 priv->framebuf[count].timestamp = 0;
614 /* Tuner Configuration */
616 priv->tunerready = TRUE;
618 priv->tunerfd = open(priv->tunerdev, O_RDONLY);
620 if(priv->tunerfd < 0)
622 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848ErrorOpeningTunerDev, strerror(errno));
623 priv->tunerready = FALSE;
626 /* Audio Configuration */
628 priv->dspready = TRUE;
629 priv->dspsamplesize = 16;
630 priv->dspstereo = 1;
631 priv->dspspeed = 44100;
632 priv->dspfmt = AFMT_S16_LE;
633 priv->dspbytesread = 0;
634 priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*(priv->dspstereo+1);
635 priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/priv->fps *
636 (priv->dspstereo+1);
638 if((priv->dspfd = open (priv->dspdev, O_RDONLY, 0)) < 0)
640 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848ErrorOpeningDspDev, strerror(errno));
641 priv->dspready = FALSE;
644 marg = (256 << 16) | 12;
646 if (ioctl(priv->dspfd, SNDCTL_DSP_SETFRAGMENT, &marg ) < 0 )
648 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "SNDCTL_DSP_SETFRAGMENT", strerror(errno));
649 priv->dspready = FALSE;
652 if((priv->dspready == TRUE) &&
653 ((ioctl(priv->dspfd, SNDCTL_DSP_SAMPLESIZE, &priv->dspsamplesize) == -1) ||
654 (ioctl(priv->dspfd, SNDCTL_DSP_STEREO, &priv->dspstereo) == -1) ||
655 (ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &priv->dspspeed) == -1) ||
656 (ioctl(priv->dspfd, SNDCTL_DSP_SETFMT, &priv->dspfmt) == -1)))
658 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848ErrorConfiguringDsp, strerror(errno));
659 close(priv->dspfd);
660 priv->dspready = FALSE;
663 return 1;
666 /* that's the real start, we'got the format parameters (checked with control) */
667 static int start(priv_t *priv)
669 int tmp;
670 struct timeval curtime;
671 int marg;
673 fprintf(stderr,"START\n");
674 if(priv->videoready == FALSE) return 0;
676 signal(SIGUSR1, processframe);
677 signal(SIGALRM, processframe);
679 marg = SIGUSR1;
681 if(ioctl(priv->btfd, METEORSSIGNAL, &marg) < 0)
683 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSSIGNAL", strerror(errno));
684 return 0;
687 read(priv->dspfd, &tmp, 2);
689 gettimeofday(&curtime, NULL);
691 priv->starttime = curtime.tv_sec + (curtime.tv_usec *.000001);
693 marg = METEOR_CAP_CONTINOUS;
695 if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0)
697 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORCAPTUR", strerror(errno));
698 return 0;
701 return 1;
704 static int uninit(priv_t *priv)
706 int marg;
708 if(priv->videoready == FALSE) return 0;
710 marg = METEOR_SIG_MODE_MASK;
712 if(ioctl( priv->btfd, METEORSSIGNAL, &marg) < 0 )
714 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "METEORSSIGNAL", strerror(errno));
715 return 0;
718 marg = METEOR_CAP_STOP_CONT;
720 if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0 )
722 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848UnableToStopCapture, strerror(errno));
723 return 0;
726 close(priv->btfd);
727 close(priv->dspfd);
729 priv->dspfd = -1;
730 priv->btfd = -1;
732 priv->dspready = priv->videoready = FALSE;
734 return 1;
738 static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
740 sigset_t sa_mask;
742 if(priv->videoready == FALSE) return 0;
744 alarm(1);
745 sigfillset(&sa_mask);
746 sigdelset(&sa_mask,SIGINT);
747 sigdelset(&sa_mask,SIGUSR1);
748 sigdelset(&sa_mask,SIGALRM);
749 sigsuspend(&sa_mask);
750 alarm(0);
752 memcpy(buffer, priv->livebuf, len);
754 /* PTS = 0, show the frame NOW, this routine is only used in playback mode
755 without audio capture .. */
757 return 0;
760 static double grab_video_frame(priv_t *priv, char *buffer, int len)
762 double timestamp=0;
763 sigset_t sa_mask;
765 if(priv->videoready == FALSE) return 0;
767 if(priv->immediatemode == TRUE)
769 return grabimmediate_video_frame(priv, buffer, len);
772 while(priv->framebuf[priv->curbufframe].dirty == TRUE)
774 alarm(1);
775 sigemptyset(&sa_mask);
776 sigsuspend(&sa_mask);
777 alarm(0);
780 memcpy(buffer, priv->framebuf[priv->curbufframe].buf, len);
781 timestamp = priv->framebuf[priv->curbufframe].timestamp;
782 priv->framebuf[priv->curbufframe].dirty = TRUE;
784 priv->curbufframe++;
785 if(priv->curbufframe >= RINGSIZE) priv->curbufframe = 0;
787 return timestamp-priv->starttime;
790 static int get_video_framesize(priv_t *priv)
792 return priv->geom.columns * priv->geom.rows * 16 / 8;
795 static double grab_audio_frame(priv_t *priv, char *buffer, int len)
797 struct timeval curtime;
798 double curpts;
799 double timeskew;
800 int bytesread;
801 int ret;
803 if(priv->dspready == FALSE) return 0;
805 gettimeofday(&curtime, NULL);
807 /* Get exactly one frame of audio, which forces video sync to audio.. */
809 bytesread=read(priv->dspfd, buffer, len);
811 while(bytesread < len)
813 ret=read(priv->dspfd, &buffer[bytesread], len-bytesread);
815 if(ret == -1)
817 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848ErrorReadingAudio, strerror(errno));
818 return 0;
821 bytesread+=ret;
824 priv->dspbytesread += bytesread;
826 curpts = curtime.tv_sec + curtime.tv_usec * .000001;
828 timeskew = priv->dspbytesread * 1.0 / priv->dsprate - (curpts-priv->starttime);
830 if(timeskew > .125/priv->fps)
832 priv->starttime -= timeskew;
834 else
836 if(timeskew < -.125/priv->fps)
838 priv->starttime -= timeskew;
842 return priv->dspbytesread * 1.0 / priv->dsprate;
845 static int get_audio_framesize(priv_t *priv)
847 int bytesavail;
848 #ifdef CONFIG_SUN_AUDIO
849 struct audio_info auinf;
850 #endif
852 if(priv->dspready == FALSE) return 0;
854 #ifdef CONFIG_SUN_AUDIO
855 if(ioctl(priv->dspfd, AUDIO_GETINFO, &auinf) < 0)
857 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "AUDIO_GETINFO", strerror(errno));
858 return TVI_CONTROL_FALSE;
860 else
861 bytesavail = auinf.record.seek; /* *priv->dspsamplesize; */
862 #else
863 if(ioctl(priv->dspfd, FIONREAD, &bytesavail) < 0)
865 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_Bt848IoctlFailed, "FIONREAD", strerror(errno));
866 return TVI_CONTROL_FALSE;
868 #endif
870 /* When mencoder wants audio data, it wants data..
871 it won't go do anything else until it gets it :( */
873 if(bytesavail == 0) return FRAGSIZE;
875 return bytesavail;
878 static int getinput(int innumber)
880 switch(innumber)
882 case 0: return METEOR_INPUT_DEV0; /* RCA */
883 case 1: return METEOR_INPUT_DEV1; /* Tuner */
884 case 2: return METEOR_INPUT_DEV2; /* In 1 */
885 case 3: return METEOR_INPUT_DEV3; /* In 2 */
886 case 4: return METEOR_INPUT_DEV_RGB; /* RGB */
887 case 5: return METEOR_INPUT_DEV_SVIDEO; /* SVid */
890 return 0;