summaryrefslogtreecommitdiffstats
path: root/libmpdemux
diff options
context:
space:
mode:
authoralex <alex@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-03-15 14:59:32 +0000
committeralex <alex@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-03-15 14:59:32 +0000
commit0aaf99fab25ed26c4271e1d00e003373a54f6914 (patch)
tree6ee586e2ca393d258776e99d34f19cf67150ffdd /libmpdemux
parentb2b1105129d8a915357d8132df1abcb256926bad (diff)
downloadmpv-0aaf99fab25ed26c4271e1d00e003373a54f6914.tar.bz2
mpv-0aaf99fab25ed26c4271e1d00e003373a54f6914.tar.xz
initial
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@5082 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux')
-rw-r--r--libmpdemux/tvi_bsdbt848.c634
1 files changed, 634 insertions, 0 deletions
diff --git a/libmpdemux/tvi_bsdbt848.c b/libmpdemux/tvi_bsdbt848.c
new file mode 100644
index 0000000000..0769aa4b35
--- /dev/null
+++ b/libmpdemux/tvi_bsdbt848.c
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <string.h>
+
+#include <machine/ioctl_meteor.h>
+#include <machine/ioctl_bt848.h>
+#include <machine/soundcard.h>
+
+#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 */