[MPlayer-dev-eng] bt848 patches

Charles Henrich henrich at sigbus.com
Mon Feb 25 00:55:49 CET 2002


Here is my tv_bt848.c patch set and .c, can you please commit them?  Thanks!

-Crh

       Charles Henrich         Eon Entertainment         henrich at msu.edu

                       http://www.sigbus.com:81/~henrich
-------------- next part --------------
Index: main/cfg-common.h
===================================================================
RCS file: /cvsroot/mplayer/main/cfg-common.h,v
retrieving revision 1.29
diff -u -u -r1.29 cfg-common.h
--- main/cfg-common.h	6 Feb 2002 20:16:35 -0000	1.29
+++ main/cfg-common.h	19 Feb 2002 05:32:19 -0000
@@ -98,6 +98,7 @@
 #ifdef USE_TV
 struct config tvopts_conf[]={
 	{"on", &tv_param_on, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"noaudio", &tv_param_noaudio, CONF_TYPE_FLAG, 0, 0, 1, NULL},
 	{"driver", &tv_param_driver, CONF_TYPE_STRING, 0, 0, 0, NULL},
 	{"device", &tv_param_device, CONF_TYPE_STRING, 0, 0, 0, NULL},
 	{"freq", &tv_param_freq, CONF_TYPE_STRING, 0, 0, 0, NULL},
Index: main/configure
===================================================================
RCS file: /cvsroot/mplayer/main/configure,v
retrieving revision 1.390
diff -u -u -r1.390 configure
--- main/configure	13 Feb 2002 03:14:45 -0000	1.390
+++ main/configure	19 Feb 2002 05:32:20 -0000
@@ -760,6 +760,7 @@
 _select=yes
 _tv=yes
 _tv_v4l=auto
+_tv_bt848=auto
 _streaming=yes
 _vidix=yes
 _new_input=no
@@ -861,6 +862,8 @@
   --disable-alsa)	_alsa=no	;;
   --enable-tv)		_tv=yes		;;
   --disable-tv)		_tv=no		;;
+  --enable-tv-bt848)	_tv_bt848=yes	;;
+  --disable-tv-bt848)	_tv_bt848=no	;;
   --enable-tv-v4l)	_tv_v4l=yes	;;
   --disable-tv-v4l)	_tv_v4l=no	;;
   --enable-fastmemcpy)	_fastmemcpy=yes	;;
@@ -2729,6 +2732,26 @@
 fi
 echores "$_tv"
 
+echocheck "BrookTree 848 TV interface"
+if test "$_tv_bt848" = auto ; then
+ _tv_bt848=no
+ if test "$_tv" = yes ; then
+    cat > $TMPC <<EOF
+#include <sys/types.h>
+#include <machine/ioctl_bt848.h>
+int main(void) { return 0; }
+EOF
+    cc_check && _tv_bt848=yes
+ fi
+fi
+if test "$_tv_bt848" = yes ; then
+  _def_tv_bt848='#define HAVE_TV_BT848 1'
+  _inputmodules="tv-bt848 $_inputmodules"
+else
+  _def_tv_bt848='#undef HAVE_TV_BT848'
+fi
+echores "$_tv_bt848"
+
 echocheck "Video 4 Linux TV interface"
 if test "$_tv_v4l" = auto ; then
  _tv_v4l=no
@@ -3225,6 +3248,9 @@
 
 /* Enable Video 4 Linux TV interface support */
 $_def_tv_v4l
+
+/* Enable *BSD BrookTree TV interface support */
+$_def_tv_bt848
 
 /* Define if your processor stores words with the most significant
    byte first (like Motorola and SPARC, unlike Intel and VAX).  */
Index: main/mencoder.c
===================================================================
RCS file: /cvsroot/mplayer/main/mencoder.c,v
retrieving revision 1.90
diff -u -u -r1.90 mencoder.c
--- main/mencoder.c	18 Feb 2002 20:17:36 -0000	1.90
+++ main/mencoder.c	19 Feb 2002 05:32:20 -0000
@@ -16,6 +16,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
+#include <sys/time.h>
 
 #include "config.h"
 #include "mp_msg.h"
@@ -250,6 +251,25 @@
   }
 }
 
+u_long timediff (struct timeval *start, struct timeval *end)
+{
+struct timeval tmp;
+
+    tmp.tv_sec = end->tv_sec - start->tv_sec;
+    tmp.tv_usec = end->tv_usec - start->tv_usec;
+
+    if(tmp.tv_usec < 0) {
+        tmp.tv_usec += 1000000;
+        tmp.tv_sec -= 1;
+    }
+    if(tmp.tv_usec < 0 || tmp.tv_sec < 0) {
+        tmp.tv_usec = tmp.tv_sec = 0;
+    }
+
+return tmp.tv_sec * 1000 + tmp.tv_usec / 1000;
+}
+
+
 //---------------------------------------------------------------------------
 
 // mini dummy libvo:
@@ -370,6 +390,15 @@
 int i,pitches[3];
 unsigned int out_fmt;
 
+struct timeval ptimer_start;
+struct timeval ptimer_stop;
+u_long audiorate=0;
+u_long videorate=0;
+u_long audiosamples=1;
+u_long videosamples=1;
+u_long skippedframes=0;
+u_long duplicatedframes=0;
+
 aviwrite_t* muxer=NULL;
 aviwrite_stream_t* mux_a=NULL;
 aviwrite_stream_t* mux_v=NULL;
@@ -1267,6 +1296,9 @@
     // get audio:
     while(mux_a->timer-audio_preload<mux_v->timer){
 	int len=0;
+
+	gettimeofday(&ptimer_start, NULL);
+
 	if(mux_a->h.dwSampleSize){
 	    // CBR - copy 0.5 sec of audio
 	    switch(mux_a->codec){
@@ -1326,10 +1358,16 @@
 	    mux_a->buffer_len-=len;
 	    memcpy(mux_a->buffer,mux_a->buffer+len,mux_a->buffer_len);
 	}
+
+	gettimeofday(&ptimer_stop, NULL);
+
+	audiosamples++;
+	audiorate+=timediff(&ptimer_start, &ptimer_stop);
     }
 }
 
     // get video frame!
+
     in_size=video_read_frame(sh_video,&frame_time,&start,force_fps);
     if(in_size<0){ eof=1; break; }
     sh_video->timer+=frame_time; ++decoded_frameno;
@@ -1346,7 +1384,7 @@
 	    if(len==4) next_frameno=start[0];
 	}
     if(eof) break;
-	if(skip_flag) printf("!!!!!!!!!!!!\n");
+	// if(skip_flag) printf("!!!!!!!!!!!!\n");
 	skip_flag=next_frameno-decoded_frameno;
     // find next frame:
 	while(next_frameno<=decoded_frameno){
@@ -1398,6 +1436,8 @@
  }
 #endif
 
+gettimeofday(&ptimer_start, NULL);
+
 switch(mux_v->codec){
 case VCODEC_COPY:
     mux_v->buffer=start;
@@ -1554,17 +1594,23 @@
     }
 }
 
+gettimeofday(&ptimer_stop, NULL);
+videosamples++;
+videorate+=timediff(&ptimer_start, &ptimer_stop);
+
 if(skip_flag<0){
     // duplicate frame
-    printf("\nduplicate %d frame(s)!!!    \n",-skip_flag);
+    // printf("\nduplicate %d frame(s)!!!    \n",-skip_flag);
     while(skip_flag<0){
+	duplicatedframes++;
 	aviwrite_write_chunk(muxer,mux_v,muxer_f,0,0);
 	++skip_flag;
     }
 } else
 if(skip_flag>0){
     // skip frame
-    printf("\nskip frame!!!    \n");
+    // printf("\nskip frame!!!    \n");
+	skippedframes++;
     --skip_flag;
 }
 
@@ -1631,14 +1677,16 @@
 	    (int)demuxer->filepos,
 	    (int)demuxer->movi_end);
 #else
-	mp_msg(MSGT_AVSYNC,MSGL_STATUS,"Pos:%6.1fs %6df (%2d%%) %3dfps Trem:%4dmin %3dmb  A-V:%5.3f [%d:%d]\r",
+	mp_msg(MSGT_AVSYNC,MSGL_STATUS,"Pos:%6.1fs %6df (%2d%%) %3dfps Trem:%4dmin %3dmb  A-V:%5.3f [%d:%d] A/Vms %d/%d D/S %d/%d\r",
 	    mux_v->timer, decoded_frameno, (int)(p*100),
 	    (t>1) ? (int)(decoded_frameno/t) : 0,
 	    (p>0.001) ? (int)((t/p-t)/60) : 0, 
 	    (p>0.001) ? (int)(ftell(muxer_f)/p/1024/1024) : 0,
 	    v_pts_corr,
 	    (mux_v->timer>1) ? (int)(mux_v->size/mux_v->timer/125) : 0,
-	    (mux_a && mux_a->timer>1) ? (int)(mux_a->size/mux_a->timer/125) : 0
+	    (mux_a && mux_a->timer>1) ? (int)(mux_a->size/mux_a->timer/125) : 0,
+		audiorate/audiosamples, videorate/videosamples,
+		duplicatedframes, skippedframes
 	);
 #endif
     }
Index: main/libmpdemux/Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/Makefile,v
retrieving revision 1.20
diff -u -u -r1.20 Makefile
--- main/libmpdemux/Makefile	14 Feb 2002 13:04:35 -0000	1.20
+++ main/libmpdemux/Makefile	19 Feb 2002 05:32:20 -0000
@@ -3,7 +3,7 @@
 
 include ../config.mak
 
- SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c demux_mpg.c demux_viv.c demuxer.c dvdauth.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c opt-reg.c
+ SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c demux_mpg.c demux_viv.c demuxer.c dvdauth.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c tvi_bt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c opt-reg.c
 ifeq ($(STREAMING),yes)
 SRCS += asf_streaming.c url.c http.c network.c rtp.c
 endif
Index: main/libmpdemux/demuxer.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demuxer.h,v
retrieving revision 1.30
diff -u -u -r1.30 demuxer.h
--- main/libmpdemux/demuxer.h	14 Feb 2002 13:04:35 -0000	1.30
+++ main/libmpdemux/demuxer.h	19 Feb 2002 05:32:20 -0000
@@ -1,6 +1,6 @@
 
 #define MAX_PACKS 4096
-#define MAX_PACK_BYTES 0x800000
+#define MAX_PACK_BYTES 0x2000000
 
 #define DEMUXER_TYPE_UNKNOWN 0
 #define DEMUXER_TYPE_MPEG_ES 1
Index: main/libmpdemux/tv.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/tv.c,v
retrieving revision 1.24
diff -u -u -r1.24 tv.c
--- main/libmpdemux/tv.c	26 Jan 2002 15:43:31 -0000	1.24
+++ main/libmpdemux/tv.c	19 Feb 2002 05:32:20 -0000
@@ -5,13 +5,16 @@
  
  API idea based on libvo2
 
- UNDER HEAVY DEVELOPEMENT, NO FEATURE REQUESTS PLEASE! :)
+ Feb 19, 2002: Significant rewrites by Charles R. Henrich (henrich at msu.edu)
+				to add support for audio, and bktr *BSD support.
+
 */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <sys/time.h>
 
 #include "config.h"
 
@@ -34,6 +37,7 @@
 #include "frequencies.h"
 
 /* some default values */
+int tv_param_noaudio = 0;
 char *tv_param_freq = NULL;
 char *tv_param_channel = NULL;
 char *tv_param_norm = "pal";
@@ -53,44 +57,58 @@
     1 = successfully read a packet
 */
 /* fill demux->video and demux->audio */
+
 int demux_tv_fill_buffer(demuxer_t *demux, tvi_handle_t *tvh)
 {
-    int seq = tvh->seq++;
     demux_packet_t* dp;
-    int len;
+
     sh_video_t *sh_video = demux->video->sh;
+    u_int len;
+    u_int cframe;
+    int aframeswaiting;
 
-    mp_dbg(MSGT_DEMUX, MSGL_DBG2, "demux_tv_fill_buffer(sequence:%d) called!\n", seq);
+    len = cframe = -1;
 
-//    demux->filepos = -1;
+    /* ================== ADD AUDIO PACKET =================== */
 
-//    seq++;
-//    tvh->seq++;
+    if (tv_param_noaudio == 0 && 
+        tvh->functions->control(tvh->priv, 
+                                TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
+        {
+        len = tvh->functions->get_audio_framesize(tvh->priv);
+
+        do {
+            dp=new_demux_packet(len);
+            aframeswaiting=tvh->functions->grab_audio_frame(tvh->priv,
+                                                            dp->buffer,len);
+            dp->pts=tvh->seq/sh_video->fps;
+            dp->pos=tvh->seq*len;
+            ds_add_packet(demux->audio,dp);
+
+            tvh->seq++;
+
+           } while (aframeswaiting > 0);
+        }
 
     /* ================== ADD VIDEO PACKET =================== */
-    len = tvh->functions->get_video_framesize(tvh->priv);
 
-    dp=new_demux_packet(len);
-    tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len);
-    dp->pts=seq/sh_video->fps; //(float)pts/90000.0f;
-    //dp->pos=pos;
-    //dp->flags=flags;
-    // append packet to DS stream:
-    ds_add_packet(demux->video,dp);
+    if (tvh->functions->control(tvh->priv, 
+                            TVI_CONTROL_IS_VIDEO, 0) == TVI_CONTROL_TRUE)
+        {
+        len = tvh->functions->get_video_framesize(tvh->priv);
 
-    /* ================== ADD AUDIO PACKET =================== */
-    if (tvh->functions->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) != TVI_CONTROL_TRUE)
-	return 1; /* no audio, only video */
+        dp=new_demux_packet(len);
 
-    len = tvh->functions->get_audio_framesize(tvh->priv);
+        cframe=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, 
+                                                len);
 
-    dp=new_demux_packet(len);
-    tvh->functions->grab_audio_frame(tvh->priv, dp->buffer, len);
-    //dp->pts=pts; //(float)pts/90000.0f;
-    //dp->pos=pos;
-    //dp->flags=flags;
-    // append packet to DS stream:
-    ds_add_packet(demux->audio,dp);
+        if(tv_param_noaudio == 1) tvh->seq = cframe;
+
+        dp->pos=tvh->seq*len;
+        dp->pts=tvh->seq/sh_video->fps;
+
+        ds_add_packet(demux->video,dp);
+        }
 
     return 1;
 }
@@ -167,6 +185,7 @@
 	tvh->norm = TV_NORM_SECAM;
 
     mp_msg(MSGT_TV, MSGL_INFO, "Selected norm: %s\n", tv_param_norm);
+    funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tvh->norm);
 
     if (funcs->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) != TVI_CONTROL_TRUE)
     {
@@ -251,13 +270,18 @@
 //	sh_video->format = 0x0;
 
     /* set FPS and FRAMETIME */
+
     if(!sh_video->fps)
     {
-	if (funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FPS, &sh_video->fps) != TVI_CONTROL_TRUE)
-	    sh_video->fps = 25.0f; /* on PAL */
-    }    
+        int tmp;
+        if (funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FPS, &tmp) != TVI_CONTROL_TRUE)
+             sh_video->fps = 25.0f; /* on PAL */
+        else sh_video->fps = tmp;
+    }
+
     if (tv_param_fps != -1.0f)
-	sh_video->fps = tv_param_fps;
+        sh_video->fps = tv_param_fps;
+
     sh_video->frametime = 1.0f/sh_video->fps;
 
     printf("fps: %f, frametime: %f\n", sh_video->fps, sh_video->frametime);
@@ -277,20 +301,16 @@
 //    demuxer->seekable = 0;
 
     /* here comes audio init */
-    if (funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
+
+    if (tv_param_noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
     {
 	int audio_format;
+	int sh_audio_format;
 
-	sh_audio = new_sh_audio(demuxer, 0);
-	
-	sh_audio->wf = malloc(sizeof(WAVEFORMATEX));
-	memset(sh_audio->wf, 0, sizeof(WAVEFORMATEX));
-	
 	/* yeah, audio is present */
 	if (funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_FORMAT, &audio_format) != TVI_CONTROL_TRUE)
 	    goto no_audio;
-	sh_audio->sample_format = audio_format;
-	sh_audio->wf->wBitsPerSample = 16;
+
 	switch(audio_format)
 	{
 	    case AFMT_U8:
@@ -301,7 +321,7 @@
 	    case AFMT_S16_BE:
 	    case AFMT_S32_LE:
 	    case AFMT_S32_BE:
-		sh_audio->format = 0x1; /* PCM */
+		sh_audio_format = 0x1; /* PCM */
 		break;
 	    case AFMT_IMA_ADPCM:
 	    case AFMT_MU_LAW:
@@ -313,13 +333,42 @@
 		goto no_audio;
 	}
 	
-	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, &sh_audio->wf->nChannels);
-	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, &sh_audio->wf->nSamplesPerSec);
-	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLESIZE, &sh_audio->wf->nAvgBytesPerSec);
+	sh_audio = new_sh_audio(demuxer, 0);
+    sh_audio->wf = (WAVEFORMATEX *)malloc(sizeof(WAVEFORMATEX));
 
+    sh_audio->format = sh_audio_format;
+	sh_audio->sample_format = audio_format;
+
+    sh_audio->o_bps = sh_audio->samplerate * sh_audio->samplesize/8 * 
+                      sh_audio->channels;
+
+/*    sh_audio->i_bps = 0  */ /* Unknown what this is for XXX:CRH */
+	
+	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, 
+                   &sh_audio->samplerate);
+	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLESIZE, 
+                   &sh_audio->samplesize);
+	funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, 
+                   &sh_audio->channels);
+
+    sh_audio->wf->nBlockAlign = sh_audio->wf->nAvgBytesPerSec;
 	demuxer->audio->sh = sh_audio;
 	sh_audio->ds = demuxer->audio;
 	demuxer->audio->id = 0;
+
+    // uncompressed PCM format
+    sh_audio->wf->wFormatTag = sh_audio->format;
+    sh_audio->wf->nChannels = sh_audio->channels;
+    sh_audio->wf->wBitsPerSample = sh_audio->samplesize;
+    sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
+    sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nChannels * 
+                                    sh_audio->samplesize/8 * 
+                                    sh_audio->samplerate;
+
+    mp_msg(MSGT_DECVIDEO, MSGL_V, "  TV audio: %d channels, %d bits, %d Hz\n",
+          sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample,
+          sh_audio->wf->nSamplesPerSec);
+
     }
 no_audio:
 
@@ -334,6 +383,10 @@
 #ifdef HAVE_TV_V4L
     if (!strcmp(tv_param_driver, "v4l"))
 	return (tvi_handle_t *)tvi_init_v4l(tv_param_device);
+#endif
+#ifdef HAVE_TV_BT848
+    if (!strcmp(tv_param_driver, "bt848"))
+	return (tvi_handle_t *)tvi_init_bt848(tv_param_device);
 #endif
 
     mp_msg(MSGT_TV, MSGL_ERR, "No such driver: %s\n", tv_param_driver); 
Index: main/libmpdemux/tv.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/tv.h,v
retrieving revision 1.12
diff -u -u -r1.12 tv.h
--- main/libmpdemux/tv.h	27 Dec 2001 23:52:48 -0000	1.12
+++ main/libmpdemux/tv.h	19 Feb 2002 05:32:21 -0000
@@ -20,6 +20,7 @@
 extern int tv_param_input;
 extern char *tv_param_outfmt;
 extern float tv_param_fps;
+extern int tv_param_noaudio;
 
 typedef struct tvi_info_s
 {
Index: main/libmpdemux/tvi_v4l.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/tvi_v4l.c,v
retrieving revision 1.18
diff -u -u -r1.18 tvi_v4l.c
--- main/libmpdemux/tvi_v4l.c	27 Dec 2001 23:52:48 -0000	1.18
+++ main/libmpdemux/tvi_v4l.c	19 Feb 2002 05:32:21 -0000
@@ -63,6 +63,7 @@
     struct video_mmap		*buf;
     int				nbuf;
     int				queue;
+	int				currentframe;
 
     /* audio */
     int				audio_id;
@@ -808,6 +809,8 @@
     int frame = priv->queue % priv->nbuf;
     int nextframe = (priv->queue+1) % priv->nbuf;
 
+	priv->currentframe++;
+
     mp_dbg(MSGT_TV, MSGL_DBG2, "grab_video_frame(priv=%p, buffer=%p, len=%d)\n",
 	priv, buffer, len);
 
@@ -835,7 +838,7 @@
     /* copy the actual frame */
     memcpy(buffer, priv->mmap+priv->mbuf.offsets[frame], len);
 
-    return(len);
+    return(priv->currentframe);
 }
 
 static int get_video_framesize(priv_t *priv)
Index: main/libmpdemux/video.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/video.c,v
retrieving revision 1.10
diff -u -u -r1.10 video.c
--- main/libmpdemux/video.c	14 Feb 2002 22:15:53 -0000	1.10
+++ main/libmpdemux/video.c	19 Feb 2002 05:32:21 -0000
@@ -278,6 +278,10 @@
           sh_video->fps=1.0f/d;
         }
     } else
+    if(demuxer->file_format==DEMUXER_TYPE_TV && !force_fps){
+        // TV has variable video frame rate, fixed audio...
+	frame_time=d_video->pts-pts1;
+	} else
     if(demuxer->file_format==DEMUXER_TYPE_MOV && !force_fps){
         // .MOV files has no fixed FPS - just frame durations!
 	frame_time=d_video->pts-pts1;
-------------- next part --------------
/*
	(C)2002 Charles R. Henrich (henrich at 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_BT848)

#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_bt848(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 */


More information about the MPlayer-dev-eng mailing list