2 * *BSD (hopefully, requires working driver!) BrookTree capture support.
4 * Still in (active) development!
6 * v1.1 Mar 13 2002 Fully functional, need to move ring buffer to
8 * v1.0 Feb 19 2002 First Release, need to add support for changing
11 * Copyright (C) 2002 Charles R. Henrich (henrich@msu.edu)
13 * This file is part of MPlayer.
15 * MPlayer is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * MPlayer is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License along
26 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #define FRAGSIZE 4096 /* (2^12 see SETFRAGSIZE below) */
39 #define PAL_HEIGHT 576
42 #define NTSC_WIDTH 640
43 #define NTSC_HEIGHT 480
44 #define NTSC_FPS 29.97
50 #include <sys/types.h>
52 #include <sys/filio.h>
58 #include <sys/param.h>
59 #ifdef CONFIG_SUN_AUDIO
60 #include <sys/audioio.h>
63 #ifdef IOCTL_METEOR_H_NAME
64 #include IOCTL_METEOR_H_NAME
67 #ifdef IOCTL_BT848_H_NAME
68 #include IOCTL_BT848_H_NAME
71 #ifdef HAVE_SYS_SOUNDCARD_H
72 #include <sys/soundcard.h>
74 #ifdef HAVE_SOUNDCARD_H
75 #include <soundcard.h>
77 #include <machine/soundcard.h>
81 #include "libaf/af_format.h"
82 #include "libmpcodecs/img_format.h"
87 static tvi_handle_t
*tvi_init_bsdbt848(tv_param_t
* tv_param
);
88 /* information about this file */
89 const tvi_info_t tvi_info_bsdbt848
= {
91 "Brooktree848 Support",
116 long long dspbytesread
;
128 struct meteor_geomet geom
;
129 struct meteor_capframe capframe
;
137 unsigned char *livebuf
;
138 RBFRAME framebuf
[RINGSIZE
];
150 struct bktr_chnlset cset
;
157 tv_param_t
*tv_param
;
162 static priv_t
*G_private
=NULL
;
164 static int getinput(int innumber
);
166 static void processframe(int signal
)
168 struct timeval curtime
;
170 if(G_private
->immediatemode
== TRUE
) return;
172 gettimeofday(&curtime
, NULL
);
174 if(G_private
->framebuf
[G_private
->curpaintframe
].dirty
== TRUE
)
176 memcpy(G_private
->framebuf
[G_private
->curpaintframe
].buf
,
177 G_private
->livebuf
, G_private
->framebufsize
);
179 G_private
->framebuf
[G_private
->curpaintframe
].dirty
= FALSE
;
181 G_private
->framebuf
[G_private
->curpaintframe
].timestamp
=
182 curtime
.tv_sec
+ curtime
.tv_usec
*.000001;
184 G_private
->curpaintframe
++;
186 if(G_private
->curpaintframe
>= RINGSIZE
) G_private
->curpaintframe
= 0;
192 /* handler creator - entry point ! */
193 static tvi_handle_t
*tvi_init_bsdbt848(tv_param_t
* tv_param
)
202 priv
=(priv_t
*)tvh
->priv
;
204 if user needs to specify both /dev/bktr<n> and /dev/tuner<n>
205 it can do this with "-tv device=/dev/bktr1,/dev/tuner1"
208 /* set video device name */
209 if (!tv_param
->device
){
210 priv
->btdev
= strdup("/dev/bktr0");
211 priv
->tunerdev
= strdup("/dev/tuner0");
213 sep
= strchr(tv_param
->device
,',');
214 priv
->btdev
= strdup(tv_param
->device
);
216 // tuner device is also passed
217 priv
->tunerdev
= strdup(sep
+1);
218 priv
->btdev
[sep
- tv_param
->device
] = 0;
220 priv
->tunerdev
= strdup("/dev/tuner0");
224 /* set audio device name */
225 if (!tv_param
->adevice
)
226 #ifdef CONFIG_SUN_AUDIO
227 priv
->dspdev
= strdup("/dev/sound");
229 priv
->dspdev
= strdup("/dev/dsp");
232 priv
->dspdev
= strdup(tv_param
->adevice
);
234 priv
->tv_param
=tv_param
;
238 static int control(priv_t
*priv
, int cmd
, void *arg
)
245 case TVI_CONTROL_IS_TUNER
:
246 if(priv
->tunerready
== FALSE
) return TVI_CONTROL_FALSE
;
247 return TVI_CONTROL_TRUE
;
249 case TVI_CONTROL_TUN_GET_FREQ
:
251 if(ioctl(priv
->tunerfd
, TVTUNER_GETFREQ
, &priv
->tunerfreq
) < 0)
253 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "TVTUNER_GETFREQ", strerror(errno
));
254 return TVI_CONTROL_FALSE
;
257 *(int *)arg
= priv
->tunerfreq
;
258 return TVI_CONTROL_TRUE
;
261 case TVI_CONTROL_TUN_SET_FREQ
:
263 priv
->tunerfreq
= *(int *)arg
;
265 if(ioctl(priv
->tunerfd
, TVTUNER_SETFREQ
, &priv
->tunerfreq
) < 0)
267 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "TVTUNER_SETFREQ", strerror(errno
));
271 return TVI_CONTROL_TRUE
;
273 case TVI_CONTROL_TUN_GET_SIGNAL
:
276 if(ioctl(priv
->tunerfd
, TVTUNER_GETSTATUS
, &status
) < 0)
278 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "GETSTATUS", strerror(errno
));
281 *(int*)arg
=(status
& 0x02)? 100 : 0;
282 return TVI_CONTROL_TRUE
;
285 case TVI_CONTROL_TUN_GET_TUNER
:
286 case TVI_CONTROL_TUN_SET_TUNER
:
290 case TVI_CONTROL_SPC_GET_INPUT
:
292 if(ioctl(priv
->btfd
, METEORGINPUT
, &priv
->input
) < 0)
294 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORGINPUT", strerror(errno
));
295 return TVI_CONTROL_FALSE
;
298 *(int *)arg
= priv
->input
;
299 return TVI_CONTROL_TRUE
;
302 case TVI_CONTROL_SPC_SET_INPUT
:
304 priv
->input
= getinput(*(int *)arg
);
306 if(ioctl(priv
->btfd
, METEORSINPUT
, &priv
->input
) < 0)
308 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSINPUT", strerror(errno
));
312 return TVI_CONTROL_TRUE
;
317 case TVI_CONTROL_IS_AUDIO
:
318 if(priv
->dspready
== FALSE
) return TVI_CONTROL_FALSE
;
319 return TVI_CONTROL_TRUE
;
321 case TVI_CONTROL_AUD_GET_FORMAT
:
323 *(int *)arg
= AF_FORMAT_S16_LE
;
324 return TVI_CONTROL_TRUE
;
326 case TVI_CONTROL_AUD_GET_CHANNELS
:
329 return TVI_CONTROL_TRUE
;
331 case TVI_CONTROL_AUD_SET_SAMPLERATE
:
333 int dspspeed
= *(int *)arg
;
335 if(ioctl(priv
->dspfd
, SNDCTL_DSP_SPEED
, &dspspeed
) == -1)
337 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Invalid audio rate. Error: %s\n", strerror(errno
));
338 return TVI_CONTROL_FALSE
;
341 priv
->dspspeed
= dspspeed
;
343 priv
->dspframesize
= priv
->dspspeed
*priv
->dspsamplesize
/8/
344 priv
->fps
* (priv
->dspstereo
+1);
345 priv
->dsprate
= priv
->dspspeed
* priv
->dspsamplesize
/8*
348 return TVI_CONTROL_TRUE
;
350 case TVI_CONTROL_AUD_GET_SAMPLERATE
:
352 *(int *)arg
= priv
->dspspeed
;
353 return TVI_CONTROL_TRUE
;
355 case TVI_CONTROL_AUD_GET_SAMPLESIZE
:
357 *(int *)arg
= priv
->dspsamplesize
/8;
358 return TVI_CONTROL_TRUE
;
363 case TVI_CONTROL_IS_VIDEO
:
364 if(priv
->videoready
== FALSE
) return TVI_CONTROL_FALSE
;
365 return TVI_CONTROL_TRUE
;
367 case TVI_CONTROL_TUN_SET_NORM
:
369 int req_mode
= *(int *)arg
;
372 priv
->iformat
= METEOR_FMT_AUTOMODE
;
374 if(req_mode
== TV_NORM_PAL
)
376 priv
->iformat
= METEOR_FMT_PAL
;
377 priv
->maxheight
= PAL_HEIGHT
;
378 priv
->maxwidth
= PAL_WIDTH
;
379 priv
->maxfps
= PAL_FPS
;
382 if(priv
->fps
> priv
->maxfps
) priv
->fps
= priv
->maxfps
;
384 if(priv
->geom
.rows
> priv
->maxheight
)
386 priv
->geom
.rows
= priv
->maxheight
;
389 if(priv
->geom
.columns
> priv
->maxwidth
)
391 priv
->geom
.columns
= priv
->maxwidth
;
395 if(req_mode
== TV_NORM_NTSC
)
397 priv
->iformat
= METEOR_FMT_NTSC
;
398 priv
->maxheight
= NTSC_HEIGHT
;
399 priv
->maxwidth
= NTSC_WIDTH
;
400 priv
->maxfps
= NTSC_FPS
;
401 priv
->fps
= NTSC_FPS
;
403 priv
->dspframesize
= priv
->dspspeed
*priv
->dspsamplesize
/8/
404 priv
->fps
* (priv
->dspstereo
+1);
405 priv
->dsprate
= priv
->dspspeed
* priv
->dspsamplesize
/8 *
408 if(priv
->fps
> priv
->maxfps
) priv
->fps
= priv
->maxfps
;
410 if(priv
->geom
.rows
> priv
->maxheight
)
412 priv
->geom
.rows
= priv
->maxheight
;
415 if(priv
->geom
.columns
> priv
->maxwidth
)
417 priv
->geom
.columns
= priv
->maxwidth
;
421 if(req_mode
== TV_NORM_SECAM
) priv
->iformat
= METEOR_FMT_SECAM
;
423 if(ioctl(priv
->btfd
, METEORSFMT
, &priv
->iformat
) < 0)
425 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSFMT", strerror(errno
));
426 return TVI_CONTROL_FALSE
;
429 if(ioctl(priv
->btfd
, METEORSETGEO
, &priv
->geom
) < 0)
431 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSETGEO", strerror(errno
));
436 if(ioctl(priv
->btfd
, METEORSFPS
, &tmp_fps
) < 0)
438 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSFPS", strerror(errno
));
443 if(priv
->tunerready
== TRUE
&&
444 ioctl(priv
->tunerfd
, BT848_SAUDIO
, &priv
->tv_param
->audio_id
) < 0)
446 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "BT848_SAUDIO", strerror(errno
));
450 return TVI_CONTROL_TRUE
;
453 case TVI_CONTROL_VID_GET_FORMAT
:
454 *(int *)arg
= IMGFMT_UYVY
;
455 return TVI_CONTROL_TRUE
;
457 case TVI_CONTROL_VID_SET_FORMAT
:
459 int req_fmt
= *(int *)arg
;
461 if(req_fmt
!= IMGFMT_UYVY
) return TVI_CONTROL_FALSE
;
463 return TVI_CONTROL_TRUE
;
465 case TVI_CONTROL_VID_SET_WIDTH
:
466 priv
->geom
.columns
= *(int *)arg
;
468 if(priv
->geom
.columns
> priv
->maxwidth
)
470 priv
->geom
.columns
= priv
->maxwidth
;
473 if(ioctl(priv
->btfd
, METEORSETGEO
, &priv
->geom
) < 0)
475 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Error setting picture width. Error: %s\n", strerror(errno
));
479 return TVI_CONTROL_TRUE
;
481 case TVI_CONTROL_VID_GET_WIDTH
:
482 *(int *)arg
= priv
->geom
.columns
;
483 return TVI_CONTROL_TRUE
;
485 case TVI_CONTROL_VID_SET_HEIGHT
:
486 priv
->geom
.rows
= *(int *)arg
;
488 if(priv
->geom
.rows
> priv
->maxheight
)
490 priv
->geom
.rows
= priv
->maxheight
;
493 if(priv
->geom
.rows
<= priv
->maxheight
/ 2)
495 priv
->geom
.oformat
|= METEOR_GEO_EVEN_ONLY
;
498 if(ioctl(priv
->btfd
, METEORSETGEO
, &priv
->geom
) < 0)
500 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Error setting picture width. Error: %s\n", strerror(errno
));
504 return TVI_CONTROL_TRUE
;
506 case TVI_CONTROL_VID_GET_HEIGHT
:
507 *(int *)arg
= priv
->geom
.rows
;
508 return TVI_CONTROL_TRUE
;
510 case TVI_CONTROL_VID_GET_FPS
:
511 *(float *)arg
= priv
->fps
;
512 return TVI_CONTROL_TRUE
;
515 case TVI_CONTROL_VID_SET_FPS:
516 priv->fps = *(int *)arg;
518 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps;
520 if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0)
522 mp_tmsg(MSGT_TV, MSGL_ERR, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSFPS", strerror(errno));
526 return TVI_CONTROL_TRUE;
529 case TVI_CONTROL_VID_CHK_WIDTH
:
530 case TVI_CONTROL_VID_CHK_HEIGHT
:
531 return TVI_CONTROL_TRUE
;
533 case TVI_CONTROL_IMMEDIATE
:
534 priv
->immediatemode
= TRUE
;
535 return TVI_CONTROL_TRUE
;
538 return TVI_CONTROL_UNKNOWN
;
541 static int init(priv_t
*priv
)
547 G_private
= priv
; /* Oooh, sick */
549 /* Video Configuration */
551 priv
->videoready
= TRUE
;
552 priv
->immediatemode
= FALSE
;
553 priv
->iformat
= METEOR_FMT_PAL
;
554 priv
->maxheight
= PAL_HEIGHT
;
555 priv
->maxwidth
= PAL_WIDTH
;
556 priv
->maxfps
= PAL_FPS
;
557 priv
->source
= METEOR_INPUT_DEV0
;
558 priv
->fps
= priv
->maxfps
;
561 priv
->curpaintframe
=0;
564 priv
->geom
.columns
= priv
->maxwidth
;
565 priv
->geom
.rows
= priv
->maxheight
;
566 priv
->geom
.frames
= 1;
567 priv
->geom
.oformat
= METEOR_GEO_YUV_PACKED
;
569 priv
->btfd
= open(priv
->btdev
, O_RDONLY
);
573 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Unable to open bktr device. Error: %s\n", strerror(errno
));
574 priv
->videoready
= FALSE
;
577 if(priv
->videoready
== TRUE
&&
578 ioctl(priv
->btfd
, METEORSFMT
, &priv
->iformat
) < 0)
580 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "SETEORSFMT", strerror(errno
));
583 if(priv
->videoready
== TRUE
&&
584 ioctl(priv
->btfd
, METEORSINPUT
, &priv
->source
) < 0)
586 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSINPUT", strerror(errno
));
590 if(priv
->videoready
== TRUE
&&
591 ioctl(priv
->btfd
, METEORSFPS
, &tmp_fps
) < 0)
593 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSFPS", strerror(errno
));
596 if(priv
->videoready
== TRUE
&&
597 ioctl(priv
->btfd
, METEORSETGEO
, &priv
->geom
) < 0)
599 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSGEQ", strerror(errno
));
602 if(priv
->videoready
== TRUE
)
604 priv
->framebufsize
= (priv
->geom
.columns
* priv
->geom
.rows
* 2);
606 priv
->livebuf
= (u_char
*)mmap((caddr_t
)0, priv
->framebufsize
, PROT_READ
,
607 MAP_SHARED
, priv
->btfd
, (off_t
)0);
609 if(priv
->livebuf
== (u_char
*) MAP_FAILED
)
611 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: mmap failed. Error: %s\n", strerror(errno
));
612 priv
->videoready
= FALSE
;
615 for(count
=0;count
<RINGSIZE
;count
++)
617 priv
->framebuf
[count
].buf
= malloc(priv
->framebufsize
);
619 if(priv
->framebuf
[count
].buf
== NULL
)
621 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Frame buffer allocation failed. Error: %s\n", strerror(errno
));
622 priv
->videoready
= FALSE
;
626 priv
->framebuf
[count
].dirty
= TRUE
;
627 priv
->framebuf
[count
].timestamp
= 0;
631 /* Tuner Configuration */
633 priv
->tunerready
= TRUE
;
635 priv
->tunerfd
= open(priv
->tunerdev
, O_RDONLY
);
637 if(priv
->tunerfd
< 0)
639 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Unable to open tuner device. Error: %s\n", strerror(errno
));
640 priv
->tunerready
= FALSE
;
643 /* Audio Configuration */
645 priv
->dspready
= TRUE
;
646 priv
->dspsamplesize
= 16;
648 priv
->dspspeed
= 44100;
649 priv
->dspfmt
= AFMT_S16_LE
;
650 priv
->dspbytesread
= 0;
651 priv
->dsprate
= priv
->dspspeed
* priv
->dspsamplesize
/8*(priv
->dspstereo
+1);
652 priv
->dspframesize
= priv
->dspspeed
*priv
->dspsamplesize
/8/priv
->fps
*
655 if((priv
->dspfd
= open (priv
->dspdev
, O_RDONLY
, 0)) < 0)
657 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Unable to open dsp device. Error: %s\n", strerror(errno
));
658 priv
->dspready
= FALSE
;
661 marg
= (256 << 16) | 12;
663 if (ioctl(priv
->dspfd
, SNDCTL_DSP_SETFRAGMENT
, &marg
) < 0 )
665 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "SNDCTL_DSP_SETFRAGMENT", strerror(errno
));
666 priv
->dspready
= FALSE
;
669 if((priv
->dspready
== TRUE
) &&
670 ((ioctl(priv
->dspfd
, SNDCTL_DSP_SAMPLESIZE
, &priv
->dspsamplesize
) == -1) ||
671 (ioctl(priv
->dspfd
, SNDCTL_DSP_STEREO
, &priv
->dspstereo
) == -1) ||
672 (ioctl(priv
->dspfd
, SNDCTL_DSP_SPEED
, &priv
->dspspeed
) == -1) ||
673 (ioctl(priv
->dspfd
, SNDCTL_DSP_SETFMT
, &priv
->dspfmt
) == -1)))
675 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Configuration of dsp failed. Error: %s\n", strerror(errno
));
677 priv
->dspready
= FALSE
;
683 /* that's the real start, we'got the format parameters (checked with control) */
684 static int start(priv_t
*priv
)
687 struct timeval curtime
;
690 fprintf(stderr
,"START\n");
691 if(priv
->videoready
== FALSE
) return 0;
693 signal(SIGUSR1
, processframe
);
694 signal(SIGALRM
, processframe
);
698 if(ioctl(priv
->btfd
, METEORSSIGNAL
, &marg
) < 0)
700 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSSIGNAL", strerror(errno
));
704 read(priv
->dspfd
, &tmp
, 2);
706 gettimeofday(&curtime
, NULL
);
708 priv
->starttime
= curtime
.tv_sec
+ (curtime
.tv_usec
*.000001);
710 marg
= METEOR_CAP_CONTINOUS
;
712 if(ioctl(priv
->btfd
, METEORCAPTUR
, &marg
) < 0)
714 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORCAPTUR", strerror(errno
));
721 static int uninit(priv_t
*priv
)
725 if(priv
->videoready
== FALSE
) return 0;
727 marg
= METEOR_SIG_MODE_MASK
;
729 if(ioctl( priv
->btfd
, METEORSSIGNAL
, &marg
) < 0 )
731 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "METEORSSIGNAL", strerror(errno
));
735 marg
= METEOR_CAP_STOP_CONT
;
737 if(ioctl(priv
->btfd
, METEORCAPTUR
, &marg
) < 0 )
739 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Unable to stop capture. Error: %s\n", strerror(errno
));
749 priv
->dspready
= priv
->videoready
= FALSE
;
755 static double grabimmediate_video_frame(priv_t
*priv
, char *buffer
, int len
)
759 if(priv
->videoready
== FALSE
) return 0;
762 sigfillset(&sa_mask
);
763 sigdelset(&sa_mask
,SIGINT
);
764 sigdelset(&sa_mask
,SIGUSR1
);
765 sigdelset(&sa_mask
,SIGALRM
);
766 sigsuspend(&sa_mask
);
769 memcpy(buffer
, priv
->livebuf
, len
);
771 /* PTS = 0, show the frame NOW, this routine is only used in playback mode
772 without audio capture .. */
777 static double grab_video_frame(priv_t
*priv
, char *buffer
, int len
)
782 if(priv
->videoready
== FALSE
) return 0;
784 if(priv
->immediatemode
== TRUE
)
786 return grabimmediate_video_frame(priv
, buffer
, len
);
789 while(priv
->framebuf
[priv
->curbufframe
].dirty
== TRUE
)
792 sigemptyset(&sa_mask
);
793 sigsuspend(&sa_mask
);
797 memcpy(buffer
, priv
->framebuf
[priv
->curbufframe
].buf
, len
);
798 timestamp
= priv
->framebuf
[priv
->curbufframe
].timestamp
;
799 priv
->framebuf
[priv
->curbufframe
].dirty
= TRUE
;
802 if(priv
->curbufframe
>= RINGSIZE
) priv
->curbufframe
= 0;
804 return timestamp
-priv
->starttime
;
807 static int get_video_framesize(priv_t
*priv
)
809 return priv
->geom
.columns
* priv
->geom
.rows
* 16 / 8;
812 static double grab_audio_frame(priv_t
*priv
, char *buffer
, int len
)
814 struct timeval curtime
;
820 if(priv
->dspready
== FALSE
) return 0;
822 gettimeofday(&curtime
, NULL
);
824 /* Get exactly one frame of audio, which forces video sync to audio.. */
826 bytesread
=read(priv
->dspfd
, buffer
, len
);
828 while(bytesread
< len
)
830 ret
=read(priv
->dspfd
, &buffer
[bytesread
], len
-bytesread
);
834 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Error reading audio data. Error: %s\n", strerror(errno
));
841 priv
->dspbytesread
+= bytesread
;
843 curpts
= curtime
.tv_sec
+ curtime
.tv_usec
* .000001;
845 timeskew
= priv
->dspbytesread
* 1.0 / priv
->dsprate
- (curpts
-priv
->starttime
);
847 if(timeskew
> .125/priv
->fps
)
849 priv
->starttime
-= timeskew
;
853 if(timeskew
< -.125/priv
->fps
)
855 priv
->starttime
-= timeskew
;
859 return priv
->dspbytesread
* 1.0 / priv
->dsprate
;
862 static int get_audio_framesize(priv_t
*priv
)
865 #ifdef CONFIG_SUN_AUDIO
866 struct audio_info auinf
;
869 if(priv
->dspready
== FALSE
) return 0;
871 #ifdef CONFIG_SUN_AUDIO
872 if(ioctl(priv
->dspfd
, AUDIO_GETINFO
, &auinf
) < 0)
874 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "AUDIO_GETINFO", strerror(errno
));
875 return TVI_CONTROL_FALSE
;
878 bytesavail
= auinf
.record
.seek
; /* *priv->dspsamplesize; */
880 if(ioctl(priv
->dspfd
, FIONREAD
, &bytesavail
) < 0)
882 mp_tmsg(MSGT_TV
, MSGL_ERR
, "tvi_bsdbt848: Call to %s ioctl failed. Error: %s\n", "FIONREAD", strerror(errno
));
883 return TVI_CONTROL_FALSE
;
887 /* When mencoder wants audio data, it wants data..
888 it won't go do anything else until it gets it :( */
890 if(bytesavail
== 0) return FRAGSIZE
;
895 static int getinput(int innumber
)
899 case 0: return METEOR_INPUT_DEV0
; /* RCA */
900 case 1: return METEOR_INPUT_DEV1
; /* Tuner */
901 case 2: return METEOR_INPUT_DEV2
; /* In 1 */
902 case 3: return METEOR_INPUT_DEV3
; /* In 2 */
903 case 4: return METEOR_INPUT_DEV_RGB
; /* RGB */
904 case 5: return METEOR_INPUT_DEV_SVIDEO
; /* SVid */