# HG changeset patch # User alex # Date 1016204372 0 # Node ID 7473fca49ca052d7d5c0979717b814bfc6a23051 # Parent f333b10ec34f511f7d91305c28b50d1dafb3f33f initial diff -r f333b10ec34f -r 7473fca49ca0 libmpdemux/tvi_bsdbt848.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/tvi_bsdbt848.c Fri Mar 15 14:59:32 2002 +0000 @@ -0,0 +1,634 @@ +/* + (C)2002 Charles R. Henrich (henrich@msu.edu) + *BSD (hopefully, requires working driver!) BrookTree capture support. + + Still in (active) development! + + v1.0 Feb 19 2002 First Release, need to add support for changing + audio parameters. +*/ + +#include "config.h" + +#if defined(USE_TV) && defined(HAVE_TV_BSDBT848) + +#define TRUE (1==1) +#define FALSE (1==0) + +#define PAL_WIDTH 768 +#define PAL_HEIGHT 576 +#define PAL_FPS 25 + +#define NTSC_WIDTH 640 +#define NTSC_HEIGHT 480 +#define NTSC_FPS 30 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../libvo/img_format.h" +#include "tv.h" + +/* information about this file */ +static tvi_info_t info = { + "Brooktree848 Support", + "bt848", + "Charles Henrich", + "in development" +}; + +/* private data's */ +typedef struct { + +/* Audio */ + char *dspdev; + int dspready; + int dspfd; + int dspsamplesize; + int dspstereo; + int dspspeed; + int dspfmt; + int dspframesize; + +/* Video */ + char *btdev; + int videoready; + int btfd; + int source; + int maxfps; + int fps; + int iformat; + int maxheight; + int maxwidth; + struct meteor_geomet geom; + struct meteor_capframe capframe; + int buffersize; + unsigned char *buffer; + int currentframe; + +/* Inputs */ + + int input; + +/* Tuner */ + + char *tunerdev; + int tunerfd; + int tunerready; + u_long tunerfreq; + struct bktr_chnlset cset; + +} priv_t; + +#include "tvi_def.h" + +static priv_t *G_private=NULL; + + +static void processframe(int signal) +{ +G_private->currentframe++; + +return; +} + +/* handler creator - entry point ! */ +tvi_handle_t *tvi_init_bsdbt848(char *device) +{ + return(new_handle()); +} + +static int control(priv_t *priv, int cmd, void *arg) +{ + switch(cmd) + { + +/* Tuner Controls */ + + case TVI_CONTROL_IS_TUNER: + if(priv->tunerready == FALSE) return TVI_CONTROL_FALSE; + return(TVI_CONTROL_TRUE); + + case TVI_CONTROL_TUN_GET_FREQ: + { + if(ioctl(priv->tunerfd, TVTUNER_GETFREQ, &priv->tunerfreq) < 0) + { + perror("GETFREQ:ioctl"); + return(TVI_CONTROL_FALSE); + } + + (int)*(void **)arg = priv->tunerfreq; + return(TVI_CONTROL_TRUE); + } + + case TVI_CONTROL_TUN_SET_FREQ: + { + priv->tunerfreq = (int)*(void **)arg; + + if(ioctl(priv->tunerfd, TVTUNER_SETFREQ, &priv->tunerfreq) < 0) + { + perror("SETFREQ:ioctl"); + return(0); + } + + return(TVI_CONTROL_TRUE); + } + + case TVI_CONTROL_TUN_GET_TUNER: + case TVI_CONTROL_TUN_SET_TUNER: + +/* Inputs */ + + case TVI_CONTROL_SPC_GET_INPUT: + { + if(ioctl(priv->btfd, METEORGINPUT, &priv->input) < 0) + { + perror("GINPUT:ioctl"); + return(TVI_CONTROL_FALSE); + } + + (int)*(void **)arg = priv->input; + return(TVI_CONTROL_TRUE); + } + + case TVI_CONTROL_SPC_SET_INPUT: + { + priv->input = getinput((int)*(void **)arg); + + if(ioctl(priv->btfd, METEORSINPUT, &priv->input) < 0) + { + perror("tunerfreq:ioctl"); + return(0); + } + + return(TVI_CONTROL_TRUE); + } + +/* Audio Controls */ + + case TVI_CONTROL_IS_AUDIO: + if(priv->dspready == FALSE) return TVI_CONTROL_FALSE; + return(TVI_CONTROL_TRUE); + + case TVI_CONTROL_AUD_GET_FORMAT: + { + (int)*(void **)arg = AFMT_S16_LE; + return(TVI_CONTROL_TRUE); + } + case TVI_CONTROL_AUD_GET_CHANNELS: + { + (int)*(void **)arg = 2; + return(TVI_CONTROL_TRUE); + } + case TVI_CONTROL_AUD_GET_SAMPLERATE: + { + (int)*(void **)arg = 44100; + return(TVI_CONTROL_TRUE); + } + case TVI_CONTROL_AUD_GET_SAMPLESIZE: + { + (int)*(void **)arg = priv->dspsamplesize; + return(TVI_CONTROL_TRUE); + } + +/* Video Controls */ + + case TVI_CONTROL_IS_VIDEO: + if(priv->videoready == FALSE) return TVI_CONTROL_FALSE; + return(TVI_CONTROL_TRUE); + + case TVI_CONTROL_TUN_SET_NORM: + { + int req_mode = (int)*(void **)arg; + + priv->iformat = METEOR_FMT_AUTOMODE; + + if(req_mode == TV_NORM_PAL) + { + priv->iformat = METEOR_FMT_PAL; + priv->maxheight = PAL_HEIGHT; + priv->maxwidth = PAL_WIDTH; + priv->maxfps = PAL_FPS; + priv->fps = PAL_FPS; + + if(priv->fps > priv->maxfps) priv->fps = priv->maxfps; + + if(priv->geom.rows > priv->maxheight) + { + priv->geom.rows = priv->maxheight; + } + + if(priv->geom.columns > priv->maxwidth) + { + priv->geom.columns = priv->maxwidth; + } + } + + if(req_mode == TV_NORM_NTSC) + { + priv->iformat = METEOR_FMT_NTSC; + priv->maxheight = NTSC_HEIGHT; + priv->maxwidth = NTSC_WIDTH; + priv->maxfps = NTSC_FPS; + priv->fps = NTSC_FPS; + + priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/ + priv->fps * (priv->dspstereo+1); + + if(priv->fps > priv->maxfps) priv->fps = priv->maxfps; + + if(priv->geom.rows > priv->maxheight) + { + priv->geom.rows = priv->maxheight; + } + + if(priv->geom.columns > priv->maxwidth) + { + priv->geom.columns = priv->maxwidth; + } + } + + if(req_mode == TV_NORM_SECAM) priv->iformat = METEOR_FMT_SECAM; + + if(ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0) + { + perror("format:ioctl"); + return(TVI_CONTROL_FALSE); + } + + if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) + { + perror("geo:ioctl"); + return(0); + } + + if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0) + { + perror("fps:ioctl"); + return(0); + } + + return(TVI_CONTROL_TRUE); + } + + case TVI_CONTROL_VID_GET_FORMAT: + (int)*(void **)arg = IMGFMT_UYVY; + return(TVI_CONTROL_TRUE); + + case TVI_CONTROL_VID_SET_FORMAT: + { + int req_fmt = (int)*(void **)arg; + + if(req_fmt != IMGFMT_UYVY) return(TVI_CONTROL_FALSE); + + return(TVI_CONTROL_TRUE); + } + case TVI_CONTROL_VID_SET_WIDTH: + priv->geom.columns = (int)*(void **)arg; + + if(priv->geom.columns > priv->maxwidth) + { + priv->geom.columns = priv->maxwidth; + } + + if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) + { + perror("width:ioctl"); + return(0); + } + + return(TVI_CONTROL_TRUE); + + case TVI_CONTROL_VID_GET_WIDTH: + (int)*(void **)arg = priv->geom.columns; + return(TVI_CONTROL_TRUE); + + case TVI_CONTROL_VID_SET_HEIGHT: + priv->geom.rows = (int)*(void **)arg; + + if(priv->geom.rows > priv->maxheight) + { + priv->geom.rows = priv->maxheight; + } + + if(priv->geom.rows <= priv->maxheight / 2) + { + priv->geom.oformat |= METEOR_GEO_EVEN_ONLY; + } + + if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) + { + perror("height:ioctl"); + return(0); + } + + return(TVI_CONTROL_TRUE); + + case TVI_CONTROL_VID_GET_HEIGHT: + (int)*(void **)arg = priv->geom.rows; + return(TVI_CONTROL_TRUE); + + case TVI_CONTROL_VID_GET_FPS: + (int)*(void **)arg = (int)priv->fps; + return(TVI_CONTROL_TRUE); + +/* + case TVI_CONTROL_VID_SET_FPS: + priv->fps = (int)*(void **)arg; + + if(priv->fps > priv->maxfps) priv->fps = priv->maxfps; + + if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0) + { + perror("fps:ioctl"); + return(0); + } + + return(TVI_CONTROL_TRUE); +*/ + + case TVI_CONTROL_VID_CHK_WIDTH: + case TVI_CONTROL_VID_CHK_HEIGHT: + return(TVI_CONTROL_TRUE); + + } + return(TVI_CONTROL_UNKNOWN); +} + +static int init(priv_t *priv) +{ +int marg; + +G_private = priv; /* Oooh, sick */ + +/* Video Configuration */ + +priv->videoready = TRUE; +priv->btdev = strdup("/dev/bktr0"); +priv->iformat = METEOR_FMT_PAL; +priv->maxheight = PAL_HEIGHT; +priv->maxwidth = PAL_WIDTH; +priv->maxfps = PAL_FPS; +priv->source = METEOR_INPUT_DEV0; +priv->fps = priv->maxfps; + +priv->currentframe=0; + +priv->geom.columns = priv->maxwidth; +priv->geom.rows = priv->maxheight; +priv->geom.frames = 1; +priv->geom.oformat = METEOR_GEO_YUV_PACKED; + +priv->btfd = open(priv->btdev, O_RDONLY); + +if(priv->btfd < 0) + { + perror("bktr open"); + priv->videoready = FALSE; + } + +if(priv->videoready == TRUE && + ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0) + { + perror("FMT:ioctl"); + } + +if(priv->videoready == TRUE && + ioctl(priv->btfd, METEORSINPUT, &priv->source) < 0) + { + perror("SINPUT:ioctl"); + } + +if(priv->videoready == TRUE && + ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0) + { + perror("SFPS:ioctl"); + } + +if(priv->videoready == TRUE && + ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) + { + perror("SGEO:ioctl"); + } + +if(priv->videoready == TRUE) + { + priv->buffersize = (priv->geom.columns * priv->geom.rows * 2); + + priv->buffer = (u_char *)mmap((caddr_t)0, priv->buffersize, PROT_READ, + MAP_SHARED, priv->btfd, (off_t)0); + + if(priv->buffer == (u_char *) MAP_FAILED) + { + perror("mmap"); + priv->videoready = FALSE; + } + + } + +/* Tuner Configuration */ + +priv->tunerdev = strdup("/dev/tuner0"); +priv->tunerready = TRUE; + +priv->tunerfd = open(priv->tunerdev, O_RDONLY); + +if(priv->tunerfd < 0) + { + perror("tune open"); + priv->tunerready = FALSE; + } + +/* Audio Configuration */ + +priv->dspready = TRUE; +priv->dspdev = strdup("/dev/dsp"); +priv->dspsamplesize = 16; +priv->dspstereo = 1; +priv->dspspeed = 44100; +priv->dspfmt = AFMT_S16_LE; +priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/priv->fps * + (priv->dspstereo+1); + +if((priv->dspfd = open ("/dev/dsp", O_RDWR, 0)) < 0) + { + perror("/dev/dsp open"); + priv->dspready = FALSE; + } + +marg = (256 << 16) | 13; + +if (ioctl(priv->dspfd, SNDCTL_DSP_SETFRAGMENT, &marg ) < 0 ) + { + perror("setfrag"); + priv->dspready = FALSE; + } + +if((priv->dspready == TRUE) && + (ioctl(priv->dspfd, SNDCTL_DSP_SAMPLESIZE, &priv->dspsamplesize) == -1) || + (ioctl(priv->dspfd, SNDCTL_DSP_STEREO, &priv->dspstereo) == -1) || + (ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &priv->dspspeed) == -1) || + (ioctl(priv->dspfd, SNDCTL_DSP_SETFMT, &priv->dspfmt) == -1)) + { + perror ("configuration of /dev/dsp failed"); + close(priv->dspfd); + priv->dspready = FALSE; + } + +return(1); +} + +/* that's the real start, we'got the format parameters (checked with control) */ +static int start(priv_t *priv) +{ +int marg; + +if(priv->videoready == FALSE) return(0); + +signal(SIGUSR1, processframe); +signal(SIGALRM, processframe); + +marg = SIGUSR1; + +if(ioctl(priv->btfd, METEORSSIGNAL, &marg) < 0) + { + perror("METEORSSIGNAL failed"); + return(0); + } + +marg = METEOR_CAP_CONTINOUS; + +if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0) + { + perror("METEORCAPTUR failed"); + return(0); + } + +return(1); +} + +static int uninit(priv_t *priv) +{ +int marg; + +if(priv->videoready == FALSE) return(0); + +marg = METEOR_SIG_MODE_MASK; + +if(ioctl( priv->btfd, METEORSSIGNAL, &marg) < 0 ) + { + perror("METEORSSIGNAL"); + return(0); + } + +marg = METEOR_CAP_STOP_CONT; + +if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0 ) + { + perror("METEORCAPTUR STOP"); + return(0); + } + +close(priv->btfd); +close(priv->dspfd); + +priv->dspfd = -1; +priv->btfd = -1; + +priv->dspready = priv->videoready = FALSE; + +return(1); +} + + +static int grab_video_frame(priv_t *priv, char *buffer, int len) +{ +sigset_t sa_mask; + +if(priv->videoready == FALSE) return(0); + +alarm(1); +sigfillset(&sa_mask); +sigdelset(&sa_mask,SIGINT); +sigdelset(&sa_mask,SIGUSR1); +sigdelset(&sa_mask,SIGALRM); +sigsuspend(&sa_mask); +alarm(0); + +memcpy(buffer, priv->buffer, len); + +return(priv->currentframe); +} + +static int get_video_framesize(priv_t *priv) +{ +return(priv->geom.columns*priv->geom.rows*16/8); +} + +static int grab_audio_frame(priv_t *priv, char *buffer, int len) +{ +struct audio_buf_info abi; +int bytesread; +int ret; + +if(priv->dspready == FALSE) return 0; + +/* Get exactly one frame of audio, which forces video sync to audio.. */ + +bytesread=read(priv->dspfd, buffer, len); + +while(bytesread < len) + { + ret=read(priv->dspfd, &buffer[bytesread], len-bytesread); + + if(ret == -1) + { + perror("Audio read failed!"); + return 0; + } + + bytesread+=ret; + } + +if(ioctl(priv->dspfd, SNDCTL_DSP_GETISPACE, &abi) < 0) + { + perror("abi:ioctl"); + return(TVI_CONTROL_FALSE); + } + +return(abi.bytes/len); +} + +static int get_audio_framesize(priv_t *priv) +{ +if(priv->dspready == FALSE) return 0; + +return(priv->dspframesize); +} + +static int getinput(int innumber) +{ +switch(innumber) + { + case 0: return METEOR_INPUT_DEV0; /* RCA */ + case 1: return METEOR_INPUT_DEV1; /* Tuner */ + case 2: return METEOR_INPUT_DEV2; /* In 1 */ + case 3: return METEOR_INPUT_DEV3; /* In 2 */ + case 4: return METEOR_INPUT_DEV_RGB; /* RGB */ + case 5: return METEOR_INPUT_DEV_SVIDEO; /* SVid */ + } + +return 0; +} + +#endif /* USE_TV */