diff options
author | arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-04-12 10:40:38 +0000 |
---|---|---|
committer | arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2002-04-12 10:40:38 +0000 |
commit | e40b5a0509ebee9406e4651c99f3c7f89bd89ac8 (patch) | |
tree | 4bbc67311223c1ba0d746b9cf4a375e119220ad3 /libmpdemux/tvi_bsdbt848.c | |
parent | 90bfc582ca7c54b57c2c303ec8b43b00dd45d8d9 (diff) | |
download | mpv-e40b5a0509ebee9406e4651c99f3c7f89bd89ac8.tar.bz2 mpv-e40b5a0509ebee9406e4651c99f3c7f89bd89ac8.tar.xz |
BSD-BT848 TV update patch by Charles Henrich <henrich@sigbus.com>
- tvi interface changes, grab_audio/video now returns timestamp!
- tv demuxer gets 'ds' hint too
- some verbose skip/dup counters to mencoder
- tvi_bsdbt848.c updates
- aviwrite/mencoder size types int->off_t
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@5573 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux/tvi_bsdbt848.c')
-rw-r--r-- | libmpdemux/tvi_bsdbt848.c | 900 |
1 files changed, 533 insertions, 367 deletions
diff --git a/libmpdemux/tvi_bsdbt848.c b/libmpdemux/tvi_bsdbt848.c index 5718bb3b9a..6e7e4967f1 100644 --- a/libmpdemux/tvi_bsdbt848.c +++ b/libmpdemux/tvi_bsdbt848.c @@ -1,27 +1,32 @@ /* - (C)2002 Charles R. Henrich (henrich@msu.edu) - *BSD (hopefully, requires working driver!) BrookTree capture support. + (C)2002 Charles R. Henrich (henrich@msu.edu) + *BSD (hopefully, requires working driver!) BrookTree capture support. - Still in (active) development! + Still in (active) development! - v1.0 Feb 19 2002 First Release, need to add support for changing - audio parameters. + v1.1 Mar 13 2002 Fully functional, need to move ring buffer to + the kernel driver. + 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 RINGSIZE 8 +#define FRAGSIZE 4096 /* (2^12 see SETFRAGSIZE below) */ + #define TRUE (1==1) #define FALSE (1==0) #define PAL_WIDTH 768 #define PAL_HEIGHT 576 -#define PAL_FPS 25 +#define PAL_FPS 25 #define NTSC_WIDTH 640 #define NTSC_HEIGHT 480 -#define NTSC_FPS 30 +#define NTSC_FPS 30 #include <stdio.h> #include <stdlib.h> @@ -29,11 +34,14 @@ #include <fcntl.h> #include <sys/types.h> #include <sys/mman.h> +#include <sys/filio.h> +#include <sys/time.h> #include <signal.h> #include <string.h> #include <machine/ioctl_meteor.h> #include <machine/ioctl_bt848.h> + #ifdef HAVE_SYS_SOUNDCARD_H #include <sys/soundcard.h> #else @@ -45,52 +53,71 @@ /* information about this file */ static tvi_info_t info = { - "Brooktree848 Support", - "bt848", - "Charles Henrich", - "in development" + "Brooktree848 Support", + "bsdbt848", + "Charles Henrich", + "in development" }; +typedef struct { + int dirty; + double timestamp; + char *buf; +} RBFRAME; + /* private data's */ typedef struct { /* Audio */ - char *dspdev; - int dspready; - int dspfd; - int dspsamplesize; - int dspstereo; - int dspspeed; - int dspfmt; - int dspframesize; + char *dspdev; + int dspready; + int dspfd; + int dspsamplesize; + int dspstereo; + int dspspeed; + int dspfmt; + int dspframesize; + int dsprate; + long long dspbytesread; /* 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; + 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; + +/* Frame Buffer */ + + int framebufsize; + float timestamp; + int curpaintframe; + int curbufframe; + unsigned char *livebuf; + RBFRAME framebuf[RINGSIZE]; /* Inputs */ - int input; + int input; /* Tuner */ - char *tunerdev; - int tunerfd; - int tunerready; - u_long tunerfreq; - struct bktr_chnlset cset; + char *tunerdev; + int tunerfd; + int tunerready; + u_long tunerfreq; + struct bktr_chnlset cset; + +/* Other */ + + int immediatemode; + double starttime; } priv_t; @@ -98,10 +125,30 @@ typedef struct { static priv_t *G_private=NULL; +static int getinput(int innumber); static void processframe(int signal) { -G_private->currentframe++; +struct timeval curtime; + +if(G_private->immediatemode == TRUE) return; + +gettimeofday(&curtime, NULL); + +if(G_private->framebuf[G_private->curpaintframe].dirty == TRUE) + { + memcpy(G_private->framebuf[G_private->curpaintframe].buf, + G_private->livebuf, G_private->framebufsize); + + G_private->framebuf[G_private->curpaintframe].dirty = FALSE; + + G_private->framebuf[G_private->curpaintframe].timestamp = + curtime.tv_sec + curtime.tv_usec*.000001; + + G_private->curpaintframe++; + + if(G_private->curpaintframe >= RINGSIZE) G_private->curpaintframe = 0; + } return; } @@ -109,269 +156,295 @@ return; /* handler creator - entry point ! */ tvi_handle_t *tvi_init_bsdbt848(char *device) { - return(new_handle()); + return(new_handle()); } static int control(priv_t *priv, int cmd, void *arg) { - switch(cmd) - { + 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: + 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); - } - + { + 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); + { + priv->input = getinput((int)*(void **)arg); - if(ioctl(priv->btfd, METEORSINPUT, &priv->input) < 0) - { - perror("tunerfreq:ioctl"); - return(0); - } + if(ioctl(priv->btfd, METEORSINPUT, &priv->input) < 0) + { + perror("tunerfreq:ioctl"); + return(0); + } - return(TVI_CONTROL_TRUE); - } + 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); - } + 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_SET_SAMPLERATE: + { + int dspspeed = (int)*(void **)arg; + + if(ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &dspspeed) == -1) + { + perror("invalidaudiorate"); + return(TVI_CONTROL_FALSE); + } + + priv->dspspeed = dspspeed; + + priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/ + priv->fps * (priv->dspstereo+1); + priv->dsprate = priv->dspspeed * priv->dspsamplesize/8* + (priv->dspstereo+1); + + return(TVI_CONTROL_TRUE); + } + case TVI_CONTROL_AUD_GET_SAMPLERATE: + { + (int)*(void **)arg = priv->dspspeed; + return(TVI_CONTROL_TRUE); + } + case TVI_CONTROL_AUD_GET_SAMPLESIZE: + { + (int)*(void **)arg = priv->dspsamplesize/8; + 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_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); + priv->dsprate = priv->dspspeed * priv->dspsamplesize/8 * + (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; + case TVI_CONTROL_VID_SET_FPS: + priv->fps = (int)*(void **)arg; - if(priv->fps > priv->maxfps) priv->fps = priv->maxfps; + if(priv->fps > priv->maxfps) priv->fps = priv->maxfps; - if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0) - { - perror("fps:ioctl"); - return(0); - } + if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0) + { + perror("fps:ioctl"); + return(0); + } - return(TVI_CONTROL_TRUE); + return(TVI_CONTROL_TRUE); */ - case TVI_CONTROL_VID_CHK_WIDTH: - case TVI_CONTROL_VID_CHK_HEIGHT: - return(TVI_CONTROL_TRUE); + case TVI_CONTROL_VID_CHK_WIDTH: + case TVI_CONTROL_VID_CHK_HEIGHT: + return(TVI_CONTROL_TRUE); - } - return(TVI_CONTROL_UNKNOWN); + case TVI_CONTROL_IMMEDIATE: + priv->immediatemode = TRUE; + return(TVI_CONTROL_TRUE); + } + + return(TVI_CONTROL_UNKNOWN); } static int init(priv_t *priv) { int marg; +int count; G_private = priv; /* Oooh, sick */ @@ -379,6 +452,7 @@ G_private = priv; /* Oooh, sick */ priv->videoready = TRUE; priv->btdev = strdup("/dev/bktr0"); +priv->immediatemode = FALSE; priv->iformat = METEOR_FMT_PAL; priv->maxheight = PAL_HEIGHT; priv->maxwidth = PAL_WIDTH; @@ -386,7 +460,9 @@ priv->maxfps = PAL_FPS; priv->source = METEOR_INPUT_DEV0; priv->fps = priv->maxfps; -priv->currentframe=0; +priv->starttime=0; +priv->curpaintframe=0; +priv->curbufframe=0; priv->geom.columns = priv->maxwidth; priv->geom.rows = priv->maxheight; @@ -396,49 +472,63 @@ priv->geom.oformat = METEOR_GEO_YUV_PACKED; priv->btfd = open(priv->btdev, O_RDONLY); if(priv->btfd < 0) - { - perror("bktr open"); - priv->videoready = FALSE; - } + { + perror("bktr open"); + priv->videoready = FALSE; + } if(priv->videoready == TRUE && ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0) - { - perror("FMT:ioctl"); - } + { + perror("FMT:ioctl"); + } if(priv->videoready == TRUE && ioctl(priv->btfd, METEORSINPUT, &priv->source) < 0) - { - perror("SINPUT:ioctl"); - } + { + perror("SINPUT:ioctl"); + } if(priv->videoready == TRUE && ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0) - { - perror("SFPS:ioctl"); - } + { + perror("SFPS:ioctl"); + } if(priv->videoready == TRUE && ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) - { - perror("SGEO:ioctl"); - } + { + 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; - } - - } + { + priv->framebufsize = (priv->geom.columns * priv->geom.rows * 2); + + priv->livebuf = (u_char *)mmap((caddr_t)0, priv->framebufsize, PROT_READ, + MAP_SHARED, priv->btfd, (off_t)0); + + if(priv->livebuf == (u_char *) MAP_FAILED) + { + perror("mmap"); + priv->videoready = FALSE; + } + + for(count=0;count<RINGSIZE;count++) + { + priv->framebuf[count].buf = malloc(priv->framebufsize); + + if(priv->framebuf[count].buf == NULL) + { + perror("framebufmalloc"); + priv->videoready = FALSE; + break; + } + + priv->framebuf[count].dirty = TRUE; + priv->framebuf[count].timestamp = 0; + } + } /* Tuner Configuration */ @@ -448,10 +538,10 @@ priv->tunerready = TRUE; priv->tunerfd = open(priv->tunerdev, O_RDONLY); if(priv->tunerfd < 0) - { - perror("tune open"); - priv->tunerready = FALSE; - } + { + perror("tune open"); + priv->tunerready = FALSE; + } /* Audio Configuration */ @@ -461,33 +551,35 @@ priv->dspsamplesize = 16; priv->dspstereo = 1; priv->dspspeed = 44100; priv->dspfmt = AFMT_S16_LE; +priv->dspbytesread = 0; +priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*(priv->dspstereo+1); priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/priv->fps * - (priv->dspstereo+1); + (priv->dspstereo+1); -if((priv->dspfd = open ("/dev/dsp", O_RDWR, 0)) < 0) - { - perror("/dev/dsp open"); - priv->dspready = FALSE; - } +if((priv->dspfd = open ("/dev/dsp", O_RDONLY, 0)) < 0) + { + perror("/dev/dsp open"); + priv->dspready = FALSE; + } -marg = (256 << 16) | 13; +marg = (256 << 16) | 12; if (ioctl(priv->dspfd, SNDCTL_DSP_SETFRAGMENT, &marg ) < 0 ) - { - perror("setfrag"); - priv->dspready = FALSE; - } + { + perror("setfrag"); + priv->dspready = FALSE; + } if((priv->dspready == TRUE) && - (ioctl(priv->dspfd, SNDCTL_DSP_SAMPLESIZE, &priv->dspsamplesize) == -1) || + ((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; - } + (ioctl(priv->dspfd, SNDCTL_DSP_SETFMT, &priv->dspfmt) == -1))) + { + perror ("configuration of /dev/dsp failed"); + close(priv->dspfd); + priv->dspready = FALSE; + } return(1); } @@ -495,8 +587,11 @@ return(1); /* that's the real start, we'got the format parameters (checked with control) */ static int start(priv_t *priv) { +int tmp; +struct timeval curtime; int marg; +fprintf(stderr,"START\n"); if(priv->videoready == FALSE) return(0); signal(SIGUSR1, processframe); @@ -505,18 +600,24 @@ signal(SIGALRM, processframe); marg = SIGUSR1; if(ioctl(priv->btfd, METEORSSIGNAL, &marg) < 0) - { - perror("METEORSSIGNAL failed"); - return(0); - } + { + perror("METEORSSIGNAL failed"); + return(0); + } + +read(priv->dspfd, &tmp, 2); + +gettimeofday(&curtime, NULL); + +priv->starttime = curtime.tv_sec + (curtime.tv_usec *.000001); marg = METEOR_CAP_CONTINOUS; if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0) - { - perror("METEORCAPTUR failed"); - return(0); - } + { + perror("METEORCAPTUR failed"); + return(0); + } return(1); } @@ -530,18 +631,18 @@ if(priv->videoready == FALSE) return(0); marg = METEOR_SIG_MODE_MASK; if(ioctl( priv->btfd, METEORSSIGNAL, &marg) < 0 ) - { - perror("METEORSSIGNAL"); - return(0); - } + { + perror("METEORSSIGNAL"); + return(0); + } marg = METEOR_CAP_STOP_CONT; if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0 ) - { - perror("METEORCAPTUR STOP"); - return(0); - } + { + perror("METEORCAPTUR STOP"); + return(0); + } close(priv->btfd); close(priv->dspfd); @@ -555,8 +656,9 @@ return(1); } -static int grab_video_frame(priv_t *priv, char *buffer, int len) +static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len) { +struct timeval curtime; sigset_t sa_mask; if(priv->videoready == FALSE) return(0); @@ -569,9 +671,43 @@ sigdelset(&sa_mask,SIGALRM); sigsuspend(&sa_mask); alarm(0); -memcpy(buffer, priv->buffer, len); +memcpy(buffer, priv->livebuf, len); -return(priv->currentframe); +/* PTS = 0, show the frame NOW, this routine is only used in playback mode + without audio capture .. */ + +return(0); +} + +static double grab_video_frame(priv_t *priv, char *buffer, int len) +{ +struct timeval curtime; +double timestamp=0; +sigset_t sa_mask; + +if(priv->videoready == FALSE) return(0); + +if(priv->immediatemode == TRUE) + { + return grabimmediate_video_frame(priv, buffer, len); + } + +while(priv->framebuf[priv->curbufframe].dirty == TRUE) + { + alarm(1); + sigemptyset(&sa_mask); + sigsuspend(&sa_mask); + alarm(0); + } + +memcpy(buffer, priv->framebuf[priv->curbufframe].buf, len); +timestamp = priv->framebuf[priv->curbufframe].timestamp; +priv->framebuf[priv->curbufframe].dirty = TRUE; + +priv->curbufframe++; +if(priv->curbufframe >= RINGSIZE) priv->curbufframe = 0; + +return(timestamp-priv->starttime); } static int get_video_framesize(priv_t *priv) @@ -579,58 +715,88 @@ 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) +static double grab_audio_frame(priv_t *priv, char *buffer, int len) { -struct audio_buf_info abi; +struct timeval curtime; +double curpts; +double timeskew; +int bytesavail; int bytesread; int ret; if(priv->dspready == FALSE) return 0; +gettimeofday(&curtime, NULL); + /* 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); + { + ret=read(priv->dspfd, &buffer[bytesread], len-bytesread); + + if(ret == -1) + { + perror("Audio read failed!"); + return 0; + } + + bytesread+=ret; + } - if(ret == -1) - { - perror("Audio read failed!"); - return 0; - } +priv->dspbytesread += bytesread; - bytesread+=ret; - } +curpts = curtime.tv_sec + curtime.tv_usec * .000001; -if(ioctl(priv->dspfd, SNDCTL_DSP_GETISPACE, &abi) < 0) - { - perror("abi:ioctl"); - return(TVI_CONTROL_FALSE); - } +timeskew = priv->dspbytesread * 1.0 / priv->dsprate - (curpts-priv->starttime); -return(abi.bytes/len); +if(timeskew > .125/priv->fps) + { + priv->starttime -= timeskew; + } +else + { + if(timeskew < -.125/priv->fps) + { + priv->starttime -= timeskew; + } + } + +return(priv->dspbytesread * 1.0 / priv->dsprate); } static int get_audio_framesize(priv_t *priv) { +int bytesavail; + if(priv->dspready == FALSE) return 0; -return(priv->dspframesize); +if(ioctl(priv->dspfd, FIONREAD, &bytesavail) < 0) + { + perror("FIONREAD"); + return(TVI_CONTROL_FALSE); + } + +/* When mencoder wants audio data, it wants data.. + it wont go do anything else until it gets it :( */ + +if(bytesavail == 0) return FRAGSIZE; + +return(bytesavail); } 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 */ - } + { + 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; } |