aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-04-12 10:40:38 +0000
committerGravatar arpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-04-12 10:40:38 +0000
commite40b5a0509ebee9406e4651c99f3c7f89bd89ac8 (patch)
tree4bbc67311223c1ba0d746b9cf4a375e119220ad3
parent90bfc582ca7c54b57c2c303ec8b43b00dd45d8d9 (diff)
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
-rw-r--r--cfg-common.h4
-rwxr-xr-xconfigure22
-rw-r--r--libmpdemux/aviwrite.c1
-rw-r--r--libmpdemux/aviwrite.h2
-rw-r--r--libmpdemux/demuxer.c4
-rw-r--r--libmpdemux/tv.c104
-rw-r--r--libmpdemux/tv.h13
-rw-r--r--libmpdemux/tvi_bsdbt848.c900
-rw-r--r--libmpdemux/tvi_def.h10
-rw-r--r--libmpdemux/tvi_dummy.c12
-rw-r--r--libmpdemux/tvi_v4l.c11
-rw-r--r--libmpdemux/video.c4
-rw-r--r--mencoder.c64
-rw-r--r--mplayer.c4
14 files changed, 703 insertions, 452 deletions
diff --git a/cfg-common.h b/cfg-common.h
index bbc08cfb81..d1670bf742 100644
--- a/cfg-common.h
+++ b/cfg-common.h
@@ -107,7 +107,11 @@
#ifdef USE_TV
struct config tvopts_conf[]={
{"on", &tv_param_on, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+#ifdef HAVE_TV_BSDBT848
+ {"immediatemode", &tv_param_immediate, CONF_TYPE_FLAG, 0, 0, 0, NULL},
+#endif
{"noaudio", &tv_param_noaudio, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ {"audiorate", &tv_param_audiorate, CONF_TYPE_INT, 0, 0, 0, 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},
diff --git a/configure b/configure
index 4d1a0c764a..4958a62869 100755
--- a/configure
+++ b/configure
@@ -3228,6 +3228,21 @@ if test "$_largefiles" = yes || freebsd ; then
fi
fi
+echocheck "ftello()"
+# if we dont have ftello map it to ftell
+cat > $TMPC << EOF
+#include <stdio.h>
+int main (void) { ftello(stdin); return 0; }
+EOF
+_ftello=no
+cc_check && _ftello=yes
+if test "$_ftello" = yes ; then
+ _def_ftello='#define HAVE_FTELLO 1'
+else
+ _def_ftello='#undef HAVE_FTELLO'
+fi
+echores "$_ftello"
+
# Determine OS dependent libs
if cygwin ; then
_confcygwin='TARGET_CYGWIN = yes'
@@ -3507,6 +3522,13 @@ $_def_rtc
/* Define this if your system has the header file for the OSS sound interface */
$_def_sys_soundcard
+/* Define this if your system uses ftello() for off_t seeking */
+
+$_def_ftello
+#ifndef HAVE_FTELLO
+# define ftello(a) ftell(a)
+#endif
+
/* Define this if your system has the "malloc.h" header file */
$_def_malloc
diff --git a/libmpdemux/aviwrite.c b/libmpdemux/aviwrite.c
index be5f5977ae..d0e7f513e3 100644
--- a/libmpdemux/aviwrite.c
+++ b/libmpdemux/aviwrite.c
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include "config.h"
diff --git a/libmpdemux/aviwrite.h b/libmpdemux/aviwrite.h
index f1a9fb6bb6..7973649747 100644
--- a/libmpdemux/aviwrite.h
+++ b/libmpdemux/aviwrite.h
@@ -10,7 +10,7 @@ typedef struct {
int id; // stream no
unsigned int ckid; // chunk id (00dc 01wb etc)
double timer;
- unsigned int size;
+ off_t size;
// buffering:
unsigned char *buffer;
unsigned int buffer_size;
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index 4585d1f046..18f1739d42 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -214,7 +214,7 @@ int demux_nuv_fill_buffer(demuxer_t *demux);
extern tvi_handle_t *tv_handler;
extern int tv_param_on;
-extern int demux_tv_fill_buffer(demuxer_t *demux, tvi_handle_t *tvh);
+extern int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds, tvi_handle_t *tvh);
extern int demux_open_tv(demuxer_t *demuxer, tvi_handle_t *tvh);
#endif
int demux_y4m_fill_buffer(demuxer_t *demux);
@@ -242,7 +242,7 @@ int demux_fill_buffer(demuxer_t *demux,demux_stream_t *ds){
case DEMUXER_TYPE_REAL: return demux_real_fill_buffer(demux);
case DEMUXER_TYPE_NUV: return demux_nuv_fill_buffer(demux);
#ifdef USE_TV
- case DEMUXER_TYPE_TV: return demux_tv_fill_buffer(demux, tv_handler);
+ case DEMUXER_TYPE_TV: return demux_tv_fill_buffer(demux, ds, tv_handler);
#endif
case DEMUXER_TYPE_Y4M: return demux_y4m_fill_buffer(demux);
case DEMUXER_TYPE_AUDIO: return demux_audio_fill_buffer(ds);
diff --git a/libmpdemux/tv.c b/libmpdemux/tv.c
index 13a3a12e78..a7ad398055 100644
--- a/libmpdemux/tv.c
+++ b/libmpdemux/tv.c
@@ -6,7 +6,7 @@
API idea based on libvo2
Feb 19, 2002: Significant rewrites by Charles R. Henrich (henrich@msu.edu)
- try to fix audio support, and bktr *BSD support.
+ to add support for audio, and bktr *BSD support.
*/
@@ -37,7 +37,11 @@ int tv_param_on = 0;
#include "frequencies.h"
/* some default values */
+int tv_param_audiorate = 44100;
int tv_param_noaudio = 0;
+#ifdef HAVE_TV_BSDBT848
+int tv_param_immediate = 0;
+#endif
char *tv_param_freq = NULL;
char *tv_param_channel = NULL;
char *tv_param_norm = "pal";
@@ -58,57 +62,39 @@ float tv_param_fps = -1.0;
*/
/* fill demux->video and demux->audio */
-int demux_tv_fill_buffer(demuxer_t *demux, tvi_handle_t *tvh)
+int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds, tvi_handle_t *tvh)
{
demux_packet_t* dp;
sh_video_t *sh_video = demux->video->sh;
u_int len;
- u_int cframe;
int aframeswaiting;
- len = cframe = -1;
+ len = 0;
/* ================== ADD AUDIO PACKET =================== */
- if (tv_param_noaudio == 0 &&
+ if (ds==demux->audio && 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);
+ dp=new_demux_packet(len);
+ dp->pts=tvh->functions->grab_audio_frame(tvh->priv, dp->buffer,len);
+ ds_add_packet(demux->audio,dp);
}
/* ================== ADD VIDEO PACKET =================== */
- if (tvh->functions->control(tvh->priv,
+ if (ds==demux->video && tvh->functions->control(tvh->priv,
TVI_CONTROL_IS_VIDEO, 0) == TVI_CONTROL_TRUE)
{
- len = tvh->functions->get_video_framesize(tvh->priv);
-
- dp=new_demux_packet(len);
-
- cframe=tvh->functions->grab_video_frame(tvh->priv, dp->buffer,
- len);
-
- 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);
- }
+ len = tvh->functions->get_video_framesize(tvh->priv);
+ dp=new_demux_packet(len);
+ dp->pts=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len);
+ ds_add_packet(demux->video,dp);
+ }
return 1;
}
@@ -190,7 +176,7 @@ int stream_open_tv(stream_t *stream, tvi_handle_t *tvh)
if (funcs->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) != TVI_CONTROL_TRUE)
{
mp_msg(MSGT_TV, MSGL_WARN, "Selected input hasn't got a tuner!\n");
- goto start_device;
+ goto done;
}
/* select channel list */
@@ -214,7 +200,7 @@ int stream_open_tv(stream_t *stream, tvi_handle_t *tvh)
if (tv_param_freq && tv_param_channel)
{
mp_msg(MSGT_TV, MSGL_WARN, "You can't set frequency and channel simultanly!\n");
- goto start_device;
+ goto done;
}
/* we need to set frequency */
@@ -251,9 +237,9 @@ int stream_open_tv(stream_t *stream, tvi_handle_t *tvh)
}
}
-start_device:
+done:
/* also start device! */
- return(funcs->start(tvh->priv));
+ return 1;
}
int demux_open_tv(demuxer_t *demuxer, tvi_handle_t *tvh)
@@ -286,6 +272,15 @@ int demux_open_tv(demuxer_t *demuxer, tvi_handle_t *tvh)
printf("fps: %f, frametime: %f\n", sh_video->fps, sh_video->frametime);
+#ifdef HAVE_TV_BSDBT848
+ /* If playback only mode, go to immediate mode, fail silently */
+ if(tv_param_immediate == 1)
+ {
+ funcs->control(tvh->priv, TVI_CONTROL_IMMEDIATE, 0);
+ tv_param_noaudio = 1;
+ }
+#endif
+
/* set width */
funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w);
@@ -308,6 +303,10 @@ int demux_open_tv(demuxer_t *demuxer, tvi_handle_t *tvh)
int sh_audio_format;
/* yeah, audio is present */
+
+ funcs->control(tvh->priv, TVI_CONTROL_AUD_SET_SAMPLERATE,
+ &tv_param_audiorate);
+
if (funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_FORMAT, &audio_format) != TVI_CONTROL_TRUE)
goto no_audio;
@@ -334,7 +333,6 @@ int demux_open_tv(demuxer_t *demuxer, tvi_handle_t *tvh)
}
sh_audio = new_sh_audio(demuxer, 0);
- sh_audio->wf = (WAVEFORMATEX *)malloc(sizeof(WAVEFORMATEX));
funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE,
&sh_audio->samplerate);
@@ -347,33 +345,21 @@ int demux_open_tv(demuxer_t *demuxer, tvi_handle_t *tvh)
sh_audio->sample_format = audio_format;
sh_audio->i_bps = sh_audio->o_bps =
- sh_audio->samplerate * sh_audio->samplesize/8 *
+ sh_audio->samplerate * sh_audio->samplesize *
sh_audio->channels;
+ // emulate WF for win32 codecs:
+ sh_audio->wf = (WAVEFORMATEX *)malloc(sizeof(WAVEFORMATEX));
sh_audio->wf->wFormatTag = sh_audio->format;
sh_audio->wf->nChannels = sh_audio->channels;
- switch(audio_format)
- {
- case AFMT_U8:
- case AFMT_S8:
- sh_audio->wf->wBitsPerSample = 8;
- break;
- case AFMT_U16_LE:
- case AFMT_U16_BE:
- case AFMT_S16_LE:
- case AFMT_S16_BE:
- sh_audio->wf->wBitsPerSample = 16;
- break;
- case AFMT_S32_LE:
- case AFMT_S32_BE:
- sh_audio->wf->wBitsPerSample = 32;
- break;
- }
+ sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8;
sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
- sh_audio->wf->nBlockAlign = sh_audio->wf->nAvgBytesPerSec;
- sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nChannels *
- sh_audio->samplesize/8 *
- sh_audio->samplerate;
+ sh_audio->wf->nBlockAlign = sh_audio->samplesize * sh_audio->channels;
+ sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps;
+
+ 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);
demuxer->audio->sh = sh_audio;
sh_audio->ds = demuxer->audio;
@@ -381,7 +367,7 @@ int demux_open_tv(demuxer_t *demuxer, tvi_handle_t *tvh)
}
no_audio:
- return(1);
+ return(funcs->start(tvh->priv));
}
/* ================== STREAM_TV ===================== */
diff --git a/libmpdemux/tv.h b/libmpdemux/tv.h
index ab42ec1e9c..5893c8a46d 100644
--- a/libmpdemux/tv.h
+++ b/libmpdemux/tv.h
@@ -21,6 +21,8 @@ extern int tv_param_input;
extern char *tv_param_outfmt;
extern float tv_param_fps;
extern int tv_param_noaudio;
+extern int tv_param_immediate;
+extern int tv_param_audiorate;
typedef struct tvi_info_s
{
@@ -36,9 +38,12 @@ typedef struct tvi_functions_s
int (*uninit)();
int (*control)();
int (*start)();
- int (*grab_video_frame)();
+ double (*grab_video_frame)();
+#ifdef HAVE_TV_BSDBT848
+ double (*grabimmediate_video_frame)();
+#endif
int (*get_video_framesize)();
- int (*grab_audio_frame)();
+ double (*grab_audio_frame)();
int (*get_audio_framesize)();
} tvi_functions_t;
@@ -67,6 +72,9 @@ typedef struct tvi_handle_s {
#define TVI_CONTROL_IS_AUDIO 0x1
#define TVI_CONTROL_IS_VIDEO 0x2
#define TVI_CONTROL_IS_TUNER 0x3
+#ifdef HAVE_TV_BSDBT848
+#define TVI_CONTROL_IMMEDIATE 0x4
+#endif
/* VIDEO controls */
#define TVI_CONTROL_VID_GET_FPS 0x101
@@ -107,6 +115,7 @@ typedef struct tvi_handle_s {
#define TVI_CONTROL_AUD_GET_SAMPLERATE 0x302
#define TVI_CONTROL_AUD_GET_SAMPLESIZE 0x303
#define TVI_CONTROL_AUD_GET_CHANNELS 0x304
+#define TVI_CONTROL_AUD_SET_SAMPLERATE 0x305
/* SPECIFIC controls */
#define TVI_CONTROL_SPC_GET_INPUT 0x401 /* set input channel (tv,s-video,composite..) */
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;
}
diff --git a/libmpdemux/tvi_def.h b/libmpdemux/tvi_def.h
index 6086049fc7..aaa1f68c85 100644
--- a/libmpdemux/tvi_def.h
+++ b/libmpdemux/tvi_def.h
@@ -4,9 +4,12 @@ static int init(priv_t *priv);
static int uninit(priv_t *priv);
static int control(priv_t *priv, int cmd, void *arg);
static int start(priv_t *priv);
-static int grab_video_frame(priv_t *priv, char *buffer, int len);
+static double grab_video_frame(priv_t *priv, char *buffer, int len);
+#ifdef HAVE_TV_BSDBT848
+static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len);
+#endif
static int get_video_framesize(priv_t *priv);
-static int grab_audio_frame(priv_t *priv, char *buffer, int len);
+static double grab_audio_frame(priv_t *priv, char *buffer, int len);
static int get_audio_framesize(priv_t *priv);
static tvi_functions_t functions =
@@ -16,6 +19,9 @@ static tvi_functions_t functions =
control,
start,
grab_video_frame,
+#ifdef HAVE_TV_BSDBT848
+ grabimmediate_video_frame,
+#endif
get_video_framesize,
grab_audio_frame,
get_audio_framesize
diff --git a/libmpdemux/tvi_dummy.c b/libmpdemux/tvi_dummy.c
index 6642f084d1..f938eed058 100644
--- a/libmpdemux/tvi_dummy.c
+++ b/libmpdemux/tvi_dummy.c
@@ -86,7 +86,15 @@ static int control(priv_t *priv, int cmd, void *arg)
return(TVI_CONTROL_UNKNOWN);
}
-static int grab_video_frame(priv_t *priv, char *buffer, int len)
+#ifdef HAVE_TV_BSDBT848
+static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
+{
+ memset(buffer, 0xCC, len);
+ return(1);
+}
+#endif
+
+static double grab_video_frame(priv_t *priv, char *buffer, int len)
{
memset(buffer, 0x42, len);
return(1);
@@ -98,7 +106,7 @@ static int get_video_framesize(priv_t *priv)
return(priv->width*priv->height*12/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)
{
memset(buffer, 0x42, len);
return(1);
diff --git a/libmpdemux/tvi_v4l.c b/libmpdemux/tvi_v4l.c
index d6df62d35d..c5a05aff83 100644
--- a/libmpdemux/tvi_v4l.c
+++ b/libmpdemux/tvi_v4l.c
@@ -63,7 +63,6 @@ typedef struct {
struct video_mmap *buf;
int nbuf;
int queue;
- int currentframe;
/* audio */
int audio_id;
@@ -807,13 +806,11 @@ static int control(priv_t *priv, int cmd, void *arg)
return(TVI_CONTROL_UNKNOWN);
}
-static int grab_video_frame(priv_t *priv, char *buffer, int len)
+static double grab_video_frame(priv_t *priv, char *buffer, int len)
{
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);
@@ -841,7 +838,7 @@ static int grab_video_frame(priv_t *priv, char *buffer, int len)
/* copy the actual frame */
memcpy(buffer, priv->mmap+priv->mbuf.offsets[frame], len);
- return(priv->currentframe);
+ return(0);
}
static int get_video_framesize(priv_t *priv)
@@ -849,7 +846,7 @@ static int get_video_framesize(priv_t *priv)
return(priv->bytesperline * priv->height);
}
-static int grab_audio_frame(priv_t *priv, char *buffer, int len)
+static double grab_audio_frame(priv_t *priv, char *buffer, int len)
{
int in_len = 0;
// int max_tries = 128;
@@ -874,7 +871,7 @@ static int grab_audio_frame(priv_t *priv, char *buffer, int len)
}
// printf("tries: %d\n", 128-max_tries);
- return(in_len);
+ return 0; //(in_len); // FIXME!
}
static int get_audio_framesize(priv_t *priv)
diff --git a/libmpdemux/video.c b/libmpdemux/video.c
index 3e9af04cba..a532a77093 100644
--- a/libmpdemux/video.c
+++ b/libmpdemux/video.c
@@ -291,6 +291,10 @@ int video_read_frame(sh_video_t* sh_video,float* frame_time_ptr,unsigned char**
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;
diff --git a/mencoder.c b/mencoder.c
index 299a4b9b92..67a11eb48e 100644
--- a/mencoder.c
+++ b/mencoder.c
@@ -15,6 +15,7 @@
#include <stdlib.h>
#include <string.h>
#include <signal.h>
+#include <sys/time.h>
#include "config.h"
#include "mp_msg.h"
@@ -212,6 +213,7 @@ void parse_cfgfiles( m_config_t* conf )
}
}
+
//---------------------------------------------------------------------------
void *vo_spudec=NULL;
@@ -278,9 +280,17 @@ sh_video_t *sh_video=NULL;
int file_format=DEMUXER_TYPE_UNKNOWN;
int i;
+uint32_t ptimer_start;
+uint32_t audiorate=0;
+uint32_t videorate=0;
+uint32_t audiosamples=1;
+uint32_t videosamples=1;
+uint32_t skippedframes=0;
+uint32_t duplicatedframes=0;
+
aviwrite_stream_t* mux_a=NULL;
aviwrite_stream_t* mux_v=NULL;
-int muxer_f_size=0;
+off_t muxer_f_size=0;
#ifdef HAVE_MP3LAME
lame_global_flags *lame;
@@ -714,6 +724,13 @@ if (seek_to_sec) {
demux_seek(demuxer, d, 1);
}
+if(tv_param_on == 1)
+ {
+ fprintf(stderr,"Forcing audio preload to 0, max pts correction to 0\n");
+ audio_preload = 0.0;
+ default_max_pts_correction = 0;
+ }
+
while(!eof){
float frame_time=0;
@@ -724,7 +741,7 @@ while(!eof){
int in_size;
int skip_flag=0; // 1=skip -1=duplicate
- if((end_at_type == END_AT_SIZE && end_at <= ftell(muxer_f)) ||
+ if((end_at_type == END_AT_SIZE && end_at <= ftello(muxer_f)) ||
(end_at_type == END_AT_TIME && end_at < sh_video->timer))
break;
@@ -737,6 +754,9 @@ if(sh_audio){
// get audio:
while(mux_a->timer-audio_preload<mux_v->timer){
int len=0;
+
+ ptimer_start = GetTimerMS();
+
if(mux_a->h.dwSampleSize){
// CBR - copy 0.5 sec of audio
switch(mux_a->codec){
@@ -796,14 +816,19 @@ if(sh_audio){
mux_a->buffer_len-=len;
memcpy(mux_a->buffer,mux_a->buffer+len,mux_a->buffer_len);
}
+
+
+ audiosamples++;
+ audiorate+= (GetTimerMS() - ptimer_start);
}
}
// 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;
-
+
v_timer_corr-=frame_time-(float)mux_v->h.dwScale/mux_v->h.dwRate;
if(demuxer2){ // 3-pass encoding, read control file (frameno.avi)
@@ -816,7 +841,7 @@ if(demuxer2){ // 3-pass encoding, read control file (frameno.avi)
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){
@@ -868,6 +893,8 @@ if( (v_pts_corr>=(float)mux_v->h.dwScale/mux_v->h.dwRate && skip_flag<0)
}
#endif
+ptimer_start = GetTimerMS();
+
switch(mux_v->codec){
case VCODEC_COPY:
mux_v->buffer=start;
@@ -884,17 +911,22 @@ default:
if(!blit_frame) aviwrite_write_chunk(muxer,mux_v,muxer_f,0,0); // empty.
}
+videosamples++;
+videorate+=(GetTimerMS() - ptimer_start);
+
if(skip_flag<0){
// duplicate frame
- printf("\nduplicate %d frame(s)!!! \n",-skip_flag);
+ if(!tv_param_on && !verbose) 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");
+ if(!tv_param_on && !verbose) printf("\nskip frame!!! \n");
+ skippedframes++;
--skip_flag;
}
@@ -961,6 +993,19 @@ if(sh_audio && !demuxer2){
(int)demuxer->filepos,
(int)demuxer->movi_end);
#else
+ if(verbose) {
+ 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)(ftello(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,
+ audiorate/audiosamples, videorate/videosamples,
+ duplicatedframes, skippedframes
+ );
+ } else
mp_msg(MSGT_AVSYNC,MSGL_STATUS,"Pos:%6.1fs %6df (%2d%%) %3dfps Trem:%4dmin %3dmb A-V:%5.3f [%d:%d]\r",
mux_v->timer, decoded_frameno, (int)(p*100),
(t>1) ? (int)(decoded_frameno/t) : 0,
@@ -972,7 +1017,6 @@ if(sh_audio && !demuxer2){
);
#endif
}
-
fflush(stdout);
@@ -992,7 +1036,7 @@ if(sh_audio && mux_a->codec==ACODEC_VBRMP3 && !lame_param_vbr){
printf("\nWriting AVI index...\n");
aviwrite_write_index(muxer,muxer_f);
-muxer_f_size=ftell(muxer_f);
+muxer_f_size=ftello(muxer_f);
printf("Fixup AVI header...\n");
fseek(muxer_f,0,SEEK_SET);
aviwrite_write_header(muxer,muxer_f); // update header
@@ -1005,10 +1049,10 @@ if(out_video_codec==VCODEC_FRAMENO && mux_v->timer>100){
}
printf("\nVideo stream: %8.3f kbit/s (%d bps) size: %d bytes %5.3f secs %d frames\n",
- (float)(mux_v->size/mux_v->timer*8.0f/1000.0f), (int)(mux_v->size/mux_v->timer), mux_v->size, (float)mux_v->timer, decoded_frameno);
+ (float)(mux_v->size/mux_v->timer*8.0f/1000.0f), (int)(mux_v->size/mux_v->timer), (int)mux_v->size, (float)mux_v->timer, decoded_frameno);
if(sh_audio)
printf("\nAudio stream: %8.3f kbit/s (%d bps) size: %d bytes %5.3f secs\n",
- (float)(mux_a->size/mux_a->timer*8.0f/1000.0f), (int)(mux_a->size/mux_a->timer), mux_a->size, (float)mux_a->timer);
+ (float)(mux_a->size/mux_a->timer*8.0f/1000.0f), (int)(mux_a->size/mux_a->timer), (int)mux_a->size, (float)mux_a->timer);
if(stream) free_stream(stream); // kill cache thread
diff --git a/mplayer.c b/mplayer.c
index ed645e18d5..2d1c8d88d9 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -546,6 +546,10 @@ int gui_no_filename=0;
#endif
+#ifdef HAVE_TV_BSDBT848
+ tv_param_immediate = 1;
+#endif
+
if ( argv[0] )
if(!strcmp(argv[0],"gmplayer") ||
(strrchr(argv[0],'/') && !strcmp(strrchr(argv[0],'/'),"/gmplayer") ) )