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
9 v1.0 Feb 19 2002 First Release, need to add support for changing
16 #define FRAGSIZE 4096 /* (2^12 see SETFRAGSIZE below) */
22 #define PAL_HEIGHT 576
25 #define NTSC_WIDTH 640
26 #define NTSC_HEIGHT 480
27 #define NTSC_FPS 29.97
33 #include <sys/types.h>
35 #include <sys/filio.h>
41 #include <sys/param.h>
42 #ifdef CONFIG_SUN_AUDIO
43 #include <sys/audioio.h>
46 #ifdef IOCTL_METEOR_H_NAME
47 #include IOCTL_METEOR_H_NAME
50 #ifdef IOCTL_BT848_H_NAME
51 #include IOCTL_BT848_H_NAME
54 #ifdef HAVE_SYS_SOUNDCARD_H
55 #include <sys/soundcard.h>
57 #ifdef HAVE_SOUNDCARD_H
58 #include <soundcard.h>
60 #include <machine/soundcard.h>
64 #include "libaf/af_format.h"
65 #include "libmpcodecs/img_format.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
= {
74 "Brooktree848 Support",
99 long long dspbytesread
;
111 struct meteor_geomet geom
;
112 struct meteor_capframe capframe
;
120 unsigned char *livebuf
;
121 RBFRAME framebuf
[RINGSIZE
];
133 struct bktr_chnlset cset
;
140 tv_param_t
*tv_param
;
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;
175 /* handler creator - entry point ! */
176 static tvi_handle_t
*tvi_init_bsdbt848(tv_param_t
* tv_param
)
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");
196 sep
= strchr(tv_param
->device
,',');
197 priv
->btdev
= strdup(tv_param
->device
);
199 // tuner device is also passed
200 priv
->tunerdev
= strdup(sep
+1);
201 priv
->btdev
[sep
- tv_param
->device
] = 0;
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");
212 priv
->dspdev
= strdup("/dev/dsp");
215 priv
->dspdev
= strdup(tv_param
->adevice
);
217 priv
->tv_param
=tv_param
;
221 static int control(priv_t
*priv
, int cmd
, void *arg
)
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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "TVTUNER_SETFREQ", strerror(errno
));
254 return TVI_CONTROL_TRUE
;
256 case TVI_CONTROL_TUN_GET_SIGNAL
:
259 if(ioctl(priv
->tunerfd
, TVTUNER_GETSTATUS
, &status
) < 0)
261 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "GETSTATUS", strerror(errno
));
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
:
273 case TVI_CONTROL_SPC_GET_INPUT
:
275 if(ioctl(priv
->btfd
, METEORGINPUT
, &priv
->input
) < 0)
277 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSINPUT", strerror(errno
));
295 return TVI_CONTROL_TRUE
;
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
:
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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Invalid audio rate. Error: %s\n", 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*
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
;
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
;
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
;
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 *
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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSFMT", strerror(errno
));
409 return TVI_CONTROL_FALSE
;
412 if(ioctl(priv
->btfd
, METEORSETGEO
, &priv
->geom
) < 0)
414 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSETGEO", strerror(errno
));
419 if(ioctl(priv
->btfd
, METEORSFPS
, &tmp_fps
) < 0)
421 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSFPS", strerror(errno
));
426 if(priv
->tunerready
== TRUE
&&
427 ioctl(priv
->tunerfd
, BT848_SAUDIO
, &priv
->tv_param
->audio_id
) < 0)
429 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "BT848_SAUDIO", strerror(errno
));
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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Error setting picture width. Error: %s\n", strerror(errno
));
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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Error setting picture width. Error: %s\n", strerror(errno
));
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_tmsg(MSGT_TV, MSGL_ERR, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSFPS", strerror(errno));
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
)
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
;
544 priv
->curpaintframe
=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
);
556 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Unable to open bktr device. Error: %s\n", strerror(errno
));
557 priv
->videoready
= FALSE
;
560 if(priv
->videoready
== TRUE
&&
561 ioctl(priv
->btfd
, METEORSFMT
, &priv
->iformat
) < 0)
563 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "SETEORSFMT", strerror(errno
));
566 if(priv
->videoready
== TRUE
&&
567 ioctl(priv
->btfd
, METEORSINPUT
, &priv
->source
) < 0)
569 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSINPUT", strerror(errno
));
573 if(priv
->videoready
== TRUE
&&
574 ioctl(priv
->btfd
, METEORSFPS
, &tmp_fps
) < 0)
576 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSFPS", strerror(errno
));
579 if(priv
->videoready
== TRUE
&&
580 ioctl(priv
->btfd
, METEORSETGEO
, &priv
->geom
) < 0)
582 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: mmap failed. Error: %s\n", 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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Frame buffer allocation failed. Error: %s\n", strerror(errno
));
605 priv
->videoready
= FALSE
;
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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Unable to open tuner device. Error: %s\n", strerror(errno
));
623 priv
->tunerready
= FALSE
;
626 /* Audio Configuration */
628 priv
->dspready
= TRUE
;
629 priv
->dspsamplesize
= 16;
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
*
638 if((priv
->dspfd
= open (priv
->dspdev
, O_RDONLY
, 0)) < 0)
640 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Unable to open dsp device. Error: %s\n", strerror(errno
));
641 priv
->dspready
= FALSE
;
644 marg
= (256 << 16) | 12;
646 if (ioctl(priv
->dspfd
, SNDCTL_DSP_SETFRAGMENT
, &marg
) < 0 )
648 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Configuration of dsp failed. Error: %s\n", strerror(errno
));
660 priv
->dspready
= FALSE
;
666 /* that's the real start, we'got the format parameters (checked with control) */
667 static int start(priv_t
*priv
)
670 struct timeval curtime
;
673 fprintf(stderr
,"START\n");
674 if(priv
->videoready
== FALSE
) return 0;
676 signal(SIGUSR1
, processframe
);
677 signal(SIGALRM
, processframe
);
681 if(ioctl(priv
->btfd
, METEORSSIGNAL
, &marg
) < 0)
683 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSSIGNAL", strerror(errno
));
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_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORCAPTUR", strerror(errno
));
704 static int uninit(priv_t
*priv
)
708 if(priv
->videoready
== FALSE
) return 0;
710 marg
= METEOR_SIG_MODE_MASK
;
712 if(ioctl( priv
->btfd
, METEORSSIGNAL
, &marg
) < 0 )
714 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSSIGNAL", strerror(errno
));
718 marg
= METEOR_CAP_STOP_CONT
;
720 if(ioctl(priv
->btfd
, METEORCAPTUR
, &marg
) < 0 )
722 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Unable to stop capture. Error: %s\n", strerror(errno
));
732 priv
->dspready
= priv
->videoready
= FALSE
;
738 static double grabimmediate_video_frame(priv_t
*priv
, char *buffer
, int len
)
742 if(priv
->videoready
== FALSE
) return 0;
745 sigfillset(&sa_mask
);
746 sigdelset(&sa_mask
,SIGINT
);
747 sigdelset(&sa_mask
,SIGUSR1
);
748 sigdelset(&sa_mask
,SIGALRM
);
749 sigsuspend(&sa_mask
);
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 .. */
760 static double grab_video_frame(priv_t
*priv
, char *buffer
, int len
)
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
)
775 sigemptyset(&sa_mask
);
776 sigsuspend(&sa_mask
);
780 memcpy(buffer
, priv
->framebuf
[priv
->curbufframe
].buf
, len
);
781 timestamp
= priv
->framebuf
[priv
->curbufframe
].timestamp
;
782 priv
->framebuf
[priv
->curbufframe
].dirty
= TRUE
;
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
;
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
);
817 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Error reading audio data. Error: %s\n", strerror(errno
));
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
;
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
)
848 #ifdef CONFIG_SUN_AUDIO
849 struct audio_info auinf
;
852 if(priv
->dspready
== FALSE
) return 0;
854 #ifdef CONFIG_SUN_AUDIO
855 if(ioctl(priv
->dspfd
, AUDIO_GETINFO
, &auinf
) < 0)
857 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "AUDIO_GETINFO", strerror(errno
));
858 return TVI_CONTROL_FALSE
;
861 bytesavail
= auinf
.record
.seek
; /* *priv->dspsamplesize; */
863 if(ioctl(priv
->dspfd
, FIONREAD
, &bytesavail
) < 0)
865 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "FIONREAD", strerror(errno
));
866 return TVI_CONTROL_FALSE
;
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
;
878 static int getinput(int 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 */