summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralbeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-05-13 13:15:40 +0000
committeralbeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-05-13 13:15:40 +0000
commitb6a7934eb5ae4d2bbf435aca79a51ffa4b8ff6c3 (patch)
tree1749ec73ed03b2746589ab8bb73cf7c6cea8349d
parent927c55fb02d927e45b0f41580f822ec28404442b (diff)
downloadmpv-b6a7934eb5ae4d2bbf435aca79a51ffa4b8ff6c3.tar.bz2
mpv-b6a7934eb5ae4d2bbf435aca79a51ffa4b8ff6c3.tar.xz
Initial support for dxr2. Based on patch from Tobias Diedrich <ranma@gmx.at>.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6070 b3059339-0415-0410-9bf9-f77b7e298cf2
-rwxr-xr-xconfigure38
-rw-r--r--libao2/ao_dxr2.c143
-rw-r--r--libao2/audio_out.c6
-rw-r--r--libvo/Makefile2
-rw-r--r--libvo/video_out.c16
-rw-r--r--libvo/vo_dxr2.c739
-rw-r--r--mp-opt-reg.c3
7 files changed, 945 insertions, 2 deletions
diff --git a/configure b/configure
index 9c4504546a..143fd79f06 100755
--- a/configure
+++ b/configure
@@ -162,6 +162,7 @@ Video:
--enable-sdl build with SDL render support [autodetect]
--enable-aa build with AAlib render support [autodetect]
--enable-ggi build with GGI render support [autodetect]
+ --enable-dxr2 build with DXR2 render support [autodetect]
--enable-dxr3 build with DXR3/H+ render support [autodetect]
--enable-dvb build with support for output via DVB-Card [autodetect]
--enable-mga build with mga_vid support
@@ -215,6 +216,7 @@ Use these options if autodetection fails:
--with-extralibdir=DIR extra library files (png, SDL, ...) in DIR
--with-x11incdir=DIR X headers in DIR
--with-x11libdir=DIR X library files in DIR
+ --with-dxr2incdir=DIR DXR2 headers in DIR
--with-csslibdir=DIR libcss in DIR
--with-madlibdir=DIR libmad (libmad shared lib.) in DIR
--with-mlibdir=DIR libmlib (MLIB support) in DIR (Solaris only)
@@ -778,6 +780,7 @@ _vesa=auto
_fbdev=auto
_fbdev_nocopy=no
_dvb=auto
+_dxr2=auto
_dxr3=auto
_iconv=auto
_rtc=auto
@@ -878,6 +881,8 @@ for ac_option do
--disable-fbdev) _fbdev=no ;;
--enable-dvb) _dvb=yes ;;
--disable-dvb) _dvb=no ;;
+ --enable-dxr2) _dxr2=yes ;;
+ --disable-dxr2) _dxr2=no ;;
--enable-dxr3) _dxr3=yes ;;
--disable-dxr3) _dxr3=no ;;
--enable-iconv) _iconv=yes ;;
@@ -1047,6 +1052,9 @@ for ac_option do
--with-x11libdir=*)
_ld_x11=-L`echo $ac_option | cut -d '=' -f 2 | sed 's,:, -L,g'`
;;
+ --with-dxr2incdir=*)
+ _inc_dxr2=-I`echo $ac_option | cut -d '=' -f 2 | sed 's,:, -I,g'`
+ ;;
--with-xvidcore=*)
_xvidcore=`echo $ac_option | cut -d '=' -f 2`
;;
@@ -2447,6 +2455,33 @@ else
fi
echores "$_nas"
+echocheck "DXR2"
+if test "$_dxr2" = auto; then
+ _dxr2=no
+ for _inc_dxr2 in "$_inc_dxr2" \
+ "-I /usr/local/include/dxr2" \
+ "-I /usr/include/dxr2"; do
+ cat > $TMPC << EOF
+#include <dxr2ioctl.h>
+int main(void) { return 0; }
+EOF
+ cc_check $_inc_dxr2 && _dxr2=yes && break
+ done
+fi
+if test "$_dxr2" = yes; then
+ _def_dxr2='#define HAVE_DXR2 1'
+ _vosrc="$_vosrc vo_dxr2.c"
+ _aosrc="$_aosrc ao_dxr2.c"
+ _aomodules="dxr2 $_aomodules"
+ _vomodules="dxr2 $_vomodules"
+ echores "yes (using $_inc_dxr2)"
+else
+ _def_dxr2='#undef HAVE_DXR2'
+ _noaomodules="dxr2 $_noaomodules"
+ _novomodules="dxr2 $_novomodules"
+ echores "no"
+fi
+
echocheck "DXR3/H+"
if test "$_dxr3" = auto ; then
cat > $TMPC << EOF
@@ -2492,6 +2527,7 @@ echores "$_mp1e"
echocheck "libfame"
if test "$_fame" = auto ; then
_fame=no
+ test "$_dxr2" = yes && _fame=auto
test "$_dxr3" = yes && _fame=auto
test "$_dvb" = yes && _fame=auto
fi
@@ -3669,6 +3705,7 @@ X_LIB = $_ld_x11 $_ld_gl $_ld_dga $_ld_xv $_ld_vm $_ld_xinerama $_ld_mad $_ld_so
GGI_LIB = $_ld_ggi
MLIB_LIB = $_ld_mlib
MLIB_INC = $_inc_mlib
+DXR2_INC = $_inc_dxr2
DVB_INC = $_inc_dvb
PNG_LIB = $_ld_png
JPEG_LIB = $_ld_jpg
@@ -4076,6 +4113,7 @@ $_def_xmga
$_def_syncfb
$_def_fbdev
$_def_fbdev_nocopy
+$_def_dxr2
$_def_dxr3
$_def_dvb
$_def_svga
diff --git a/libao2/ao_dxr2.c b/libao2/ao_dxr2.c
new file mode 100644
index 0000000000..63ca4c28cb
--- /dev/null
+++ b/libao2/ao_dxr2.c
@@ -0,0 +1,143 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <inttypes.h>
+
+#include "../config.h"
+#include "mp_msg.h"
+#include "bswap.h"
+
+#include "audio_out.h"
+#include "audio_out_internal.h"
+
+#include "afmt.h"
+
+
+static ao_info_t info =
+{
+ "DXR2 audio output",
+ "dxr2",
+ "Tobias Diedrich <ranma@gmx.at>",
+ ""
+};
+
+LIBAO_EXTERN(dxr2)
+
+// to set/get/query special features/parameters
+static int control(int cmd,int arg){
+ return CONTROL_UNKNOWN;
+}
+
+static int freq=0;
+static int freq_id=0;
+
+// open & setup audio device
+// return: 1=success 0=fail
+static int init(int rate,int channels,int format,int flags){
+
+ ao_data.outburst=2048;
+ ao_data.samplerate=rate;
+ ao_data.channels=channels;
+ ao_data.buffersize=2048;
+ ao_data.bps=rate*4;
+ ao_data.format=format;
+ freq=rate;
+
+ switch(rate){
+ case 48000:
+ freq_id=0;
+ break;
+ case 96000:
+ freq_id=1;
+ break;
+ case 44100:
+ freq_id=2;
+ break;
+ case 32000:
+ freq_id=3;
+ break;
+ case 22050:
+ freq_id=4;
+ break;
+#if 0
+ case 24000:
+ freq_id=5;
+ break;
+ case 64000:
+ freq_id=6;
+ break;
+ case 88200:
+ freq_id=7;
+ break;
+#endif
+ default:
+ mp_msg(MSGT_AO,MSGL_ERR,"[AO] dxr2: %d Hz not supported, try \"-aop list=resample\"\n",rate);
+ return 0;
+ }
+
+ return 1;
+}
+
+// close audio device
+static void uninit(){
+
+}
+
+// stop playing and empty buffers (for seeking/pause)
+static void reset(){
+
+}
+
+// stop playing, keep buffers (for pause)
+static void audio_pause()
+{
+ // for now, just call reset();
+ reset();
+}
+
+// resume playing, after audio_pause()
+static void audio_resume()
+{
+}
+
+extern void dxr2_send_packet(unsigned char* data,int len,int id,int timestamp);
+extern void dxr2_send_lpcm_packet(unsigned char* data,int len,int id,int timestamp,int freq_id);
+extern int vo_pts;
+static int preload = 1;
+// return: how many bytes can be played without blocking
+static int get_space(){
+ float x=(float)(vo_pts-ao_data.pts)/90000.0;
+ int y;
+ if(x<=0) return 0;
+ y=freq*4*x;y/=ao_data.outburst;y*=ao_data.outburst;
+ if(y>32768) y=32768;
+ return y;
+}
+
+// plays 'len' bytes of 'data'
+// it should round it down to outburst*n
+// return: number of bytes played
+static int play(void* data,int len,int flags){
+ // MPEG and AC3 don't work :-(
+ if(ao_data.format==AFMT_MPEG)
+ dxr2_send_packet(data,len,0xC0,ao_data.pts);
+ else if(ao_data.format==AFMT_AC3)
+ dxr2_send_packet(data,len,0x80,ao_data.pts);
+ else {
+ int i;
+ //unsigned short *s=data;
+ uint16_t *s=data;
+#ifndef WORDS_BIGENDIAN
+ for(i=0;i<len/2;i++) s[i] = bswap_16(s[i]); // (s[i]>>8)|(s[i]<<8); // le<->be bswap_16(s[i]);
+#endif
+ dxr2_send_lpcm_packet(data,len,0xA0,ao_data.pts-10000,freq_id);
+ }
+ return len;
+}
+
+// return: delay in seconds between first and last sample in buffer
+static float get_delay(){
+
+ return 0.0;
+}
+
diff --git a/libao2/audio_out.c b/libao2/audio_out.c
index f2d1c87c7e..e1c8d6dd7c 100644
--- a/libao2/audio_out.c
+++ b/libao2/audio_out.c
@@ -34,6 +34,9 @@ extern ao_functions_t audio_out_sun;
#ifdef USE_SGI_AUDIO
extern ao_functions_t audio_out_sgi;
#endif
+#ifdef HAVE_DXR2
+extern ao_functions_t audio_out_dxr2;
+#endif
extern ao_functions_t audio_out_mpegpes;
extern ao_functions_t audio_out_pcm;
extern ao_functions_t audio_out_pss;
@@ -50,6 +53,9 @@ ao_functions_t* audio_out_drivers[] =
#ifdef USE_SGI_AUDIO
&audio_out_sgi,
#endif
+#ifdef HAVE_DXR2
+ &audio_out_dxr2,
+#endif
&audio_out_null,
#ifdef HAVE_ALSA5
&audio_out_alsa5,
diff --git a/libvo/Makefile b/libvo/Makefile
index c621b9e294..e6b8747ee5 100644
--- a/libvo/Makefile
+++ b/libvo/Makefile
@@ -10,7 +10,7 @@ ifeq ($(VIDIX),yes)
SRCS += vosub_vidix.c
endif
-CFLAGS = $(OPTFLAGS) -I. -I.. $(SDL_INC) $(X11_INC) $(EXTRA_INC) $(DVB_INC) -DMPG12PLAY #-Wall
+CFLAGS = $(OPTFLAGS) -I. -I.. $(SDL_INC) $(X11_INC) $(EXTRA_INC) $(DXR2_INC) $(DVB_INC) -DMPG12PLAY #-Wall
ifeq ($(VIDIX),yes)
CFLAGS += -DVIDIX_PATH='"$(prefix)/lib/mplayer/vidix/"'
endif
diff --git a/libvo/video_out.c b/libvo/video_out.c
index f681a43bc9..3a15467771 100644
--- a/libvo/video_out.c
+++ b/libvo/video_out.c
@@ -99,6 +99,9 @@ extern vo_functions_t video_out_ggi;
extern vo_functions_t video_out_aa;
extern vo_functions_t video_out_mpegpes;
extern vo_functions_t video_out_yuv4mpeg;
+#ifdef HAVE_DXR2
+extern vo_functions_t video_out_dxr2;
+#endif
extern vo_functions_t video_out_dxr3;
#ifdef HAVE_JPEG
extern vo_functions_t video_out_jpeg;
@@ -160,6 +163,9 @@ vo_functions_t* video_out_drivers[] =
#ifdef HAVE_AA
&video_out_aa,
#endif
+#ifdef HAVE_DXR2
+ &video_out_dxr2,
+#endif
#ifdef HAVE_DXR3
&video_out_dxr3,
#endif
@@ -193,3 +199,13 @@ vo_functions_t* video_out_drivers[] =
#endif
NULL
};
+
+#ifdef HAVE_DXR2
+extern void vo_dxr2_register_options(void*);
+#endif
+
+void libvo_register_options(void* cfg) {
+#ifdef HAVE_DXR2
+ vo_dxr2_register_options(cfg);
+#endif
+}
diff --git a/libvo/vo_dxr2.c b/libvo/vo_dxr2.c
new file mode 100644
index 0000000000..9db04eb165
--- /dev/null
+++ b/libvo/vo_dxr2.c
@@ -0,0 +1,739 @@
+
+#include "fastmemcpy.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+
+#include "config.h"
+#include "video_out.h"
+#include "video_out_internal.h"
+#include "mp_msg.h"
+#include "cfgparser.h"
+
+#include <dxr2ioctl.h>
+
+LIBVO_EXTERN (dxr2)
+
+extern float monitor_aspect;
+extern float movie_aspect;
+
+static int dxr2_fd = -1;
+
+static int movie_w,movie_h;
+static int fs = 0;
+static int playing = 0;
+static int last_freq_id = -1;
+
+// vo device used to blank the screen for the overlay init
+static vo_functions_t* sub_vo = NULL;
+
+
+static int use_ol = 1;
+static char *norm = NULL;
+static char *ucode = NULL;
+static int ar_mode = DXR2_ASPECTRATIOMODE_LETTERBOX;
+static int mv_mode = DXR2_MACROVISION_OFF;
+static int _75ire_mode = DXR2_75IRE_OFF;
+static int bw_mode = DXR2_BLACKWHITE_OFF;
+static int interlaced_mode = DXR2_INTERLACED_ON;
+static int pixel_mode = DXR2_PIXEL_CCIR601;
+static int iec958_mode = DXR2_IEC958_DECODED;
+static int mute_mode = DXR2_AUDIO_MUTE_OFF;
+
+static config_t dxr2_opts[] = {
+ { "overlay", &use_ol, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ { "nooverlay", &use_ol, CONF_TYPE_FLAG, 0, 1, 0, NULL},
+ { "ucode", &ucode, CONF_TYPE_STRING,0, 0, 0, NULL},
+
+ { "norm", &norm, CONF_TYPE_STRING,0, 0, 0, NULL},
+
+ { "ar-mode",&ar_mode, CONF_TYPE_INT, CONF_RANGE,0,2,NULL },
+
+ { "macrovision",&mv_mode,CONF_TYPE_INT,CONF_RANGE,0,3, NULL },
+
+ { "75ire",&_75ire_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ { "no75ire",&_75ire_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL},
+
+ { "bw",&bw_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ { "color",&bw_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL},
+
+ { "interlaced",&interlaced_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ { "nointerlaced",&interlaced_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL},
+
+ { "square-pixel",&pixel_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ { "ccir601-pixel",&pixel_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL},
+
+ { "iec958-encoded",&iec958_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ { "iec958-decoded",&iec958_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL},
+
+ { "mute", &mute_mode,CONF_TYPE_FLAG, 0, 1, 0, NULL},
+ { "nomute",&mute_mode,CONF_TYPE_FLAG, 0, 0, 1, NULL},
+ { NULL,NULL, 0, 0, 0, 0, NULL}
+};
+
+static config_t dxr2_opt[] = {
+ { "dxr2", &dxr2_opts, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
+ { NULL,NULL, 0, 0, 0, 0, NULL}
+};
+
+void vo_dxr2_register_options(m_config_t* cfg) {
+ m_config_register_options(cfg,dxr2_opt);
+}
+
+static vo_info_t vo_info = {
+ "DXR2 video out",
+ "dxr2",
+ "Alban Bedel <albeu@free.fr> and Tobias Diedrich <ranma@gmx.at>",
+ ""
+};
+
+static char *ucodesearchpath[] = {
+ "/usr/local/lib/dxr2/dvd12.ux",
+ "/usr/lib/dxr2/dvd12.ux",
+ "/usr/src/dvd12.ux",
+ NULL,
+};
+
+#define BUF_SIZE 2048
+
+static unsigned char dxr2buf[BUF_SIZE];
+static unsigned int dxr2bufpos = 0;
+
+static void write_dxr2(void *data, int len)
+{
+ int w = 0;
+ while (len>0) if ((dxr2bufpos+len) <= BUF_SIZE) {
+ memcpy(dxr2buf+dxr2bufpos, data, len);
+ dxr2bufpos+=len;
+ len=0;
+ } else {
+ int copylen=BUF_SIZE-dxr2bufpos;
+ if(copylen > 0) {
+ memcpy(dxr2buf+dxr2bufpos, data, copylen);
+ dxr2bufpos += copylen;
+ data+=copylen;
+ len-=copylen;
+ }
+ w = write(dxr2_fd, dxr2buf, BUF_SIZE);
+ if(w < 0) {
+ mp_msg(MSGT_VO,MSGL_WARN,"DXR2 : write failed : %s \n",strerror(errno));
+ dxr2bufpos = 0;
+ break;
+ }
+ dxr2bufpos -= w;
+ if(dxr2bufpos)
+ memmove(dxr2buf,dxr2buf + w,dxr2bufpos);
+ }
+}
+
+static void flush_dxr2()
+{
+ int w;
+ while (dxr2bufpos) {
+ w = write(dxr2_fd, dxr2buf, dxr2bufpos);
+ if(w < 0) {
+ mp_msg(MSGT_VO,MSGL_WARN,"DXR2 : write failed %s \n",strerror(errno));
+ dxr2bufpos = 0;
+ break;
+ }
+ dxr2bufpos -= w;
+ }
+}
+
+#define PACK_MAX_SIZE 2048
+
+static unsigned char pack[PACK_MAX_SIZE];
+
+static unsigned char mpg_header[]={
+ 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x04, 0x00,
+ 0x04, 0x01, 0x01, 0x86, 0xa3, 0xf8
+};
+
+static unsigned char mpg_eof[]={
+ 0x00, 0x00, 0x01, 0xb9
+};
+
+static void dxr2_send_header(void)
+{
+ write_dxr2(&mpg_header, sizeof(mpg_header));
+}
+
+static void dxr2_send_eof(void)
+{
+ write_dxr2(&mpg_eof, sizeof(mpg_eof));
+}
+
+void dxr2_send_packet(unsigned char* data,int len,int id,int timestamp)
+{
+ int ptslen=5;
+
+ if(dxr2_fd < 0) {
+ mp_msg(MSGT_VO,MSGL_ERR,"DXR2 isn't ready\n");
+ return;
+ }
+
+ mp_msg(MSGT_VO,MSGL_DBG2,"DXR2 packet : 0x%x => %d \n",id,timestamp);
+ dxr2_send_header();
+
+ // startcode:
+ pack[0]=pack[1]=0;pack[2]=0x01;
+ // stream id
+ pack[3]=id;
+
+ while(len>0){
+ int payload_size=len; // data + PTS
+ if(9+ptslen+payload_size>PACK_MAX_SIZE) payload_size=PACK_MAX_SIZE-(6+ptslen);
+
+ // construct PES header: (code from ffmpeg's libav)
+ // packetsize:
+ pack[4]=(3+ptslen+payload_size)>>8;
+ pack[5]=(3+ptslen+payload_size)&255;
+
+ pack[6]=0x81;
+ if(ptslen){
+ int x;
+ pack[7]=0x80;
+ pack[8]=ptslen;
+ // presentation time stamp:
+ x=(0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1;
+ pack[9]=x;
+ x=((((timestamp >> 15) & 0x7fff) << 1) | 1);
+ pack[10]=x>>8; pack[11]=x&255;
+ x=((((timestamp) & 0x7fff) << 1) | 1);
+ pack[12]=x>>8; pack[13]=x&255;
+ } else {
+ pack[7]=0x00;
+ pack[8]=0x00;
+ }
+
+ write_dxr2(pack, 9+ptslen);
+ write_dxr2(data, payload_size);
+
+ len-=payload_size; data+=payload_size;
+ ptslen=0; // store PTS only once, at first packet!
+ }
+}
+
+void dxr2_send_lpcm_packet(unsigned char* data,int len,int id,unsigned int timestamp,int freq_id)
+{
+ int arg;
+ int ptslen=5;
+
+ if(dxr2_fd < 0) {
+ mp_msg(MSGT_VO,MSGL_ERR,"DXR2 isn't ready\n");
+ return;
+ }
+
+ if(last_freq_id != freq_id) {
+ switch (freq_id) {
+ case 0: arg=DXR2_AUDIO_FREQ_48; break;
+ case 1: arg=DXR2_AUDIO_FREQ_96; break;
+ case 2: arg=DXR2_AUDIO_FREQ_441; break;
+ case 3: arg=DXR2_AUDIO_FREQ_32; break;
+ case 4: arg=DXR2_AUDIO_FREQ_2205; break;
+#if 0
+ // This is not is the dxr2 driver, but in a Tobias Diedrich patch
+ case 5: arg=DXR2_AUDIO_FREQ_24; break;
+ case 6: arg=DXR2_AUDIO_FREQ_64; break;
+ case 7: arg=DXR2_AUDIO_FREQ_882; break;
+#endif
+ }
+ ioctl(dxr2_fd, DXR2_IOC_SET_AUDIO_SAMPLE_FREQUENCY, &arg);
+ last_freq_id = freq_id;
+ }
+ freq_id=0;
+
+ if (((int) timestamp)<0)
+ timestamp=0;
+
+ mp_msg(MSGT_VO,MSGL_DBG2,"dxr2_send_lpcm_packet(timestamp=%d)\n", timestamp);
+ // startcode:
+ pack[0]=pack[1]=0;pack[2]=0x01;
+
+ // stream id
+ pack[3]=0xBD;
+
+ while(len>=4){
+ int payload_size;
+
+ payload_size=PACK_MAX_SIZE-6-3-ptslen-7; // max possible data len
+ if(payload_size>len) payload_size=len;
+ payload_size&=(~3); // align!
+
+ // packetsize:
+ pack[4]=(payload_size+3+ptslen+7)>>8;
+ pack[5]=(payload_size+3+ptslen+7)&255;
+
+ // stuffing:
+ pack[6]=0x81;
+ // pack[7]=0x00; //0x80
+
+ // hdrlen:
+ pack[8]=ptslen;
+
+ if(ptslen){
+ int x;
+ pack[7]=0x80;
+ // presentation time stamp:
+ x=(0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1;
+ pack[9]=x;
+ x=((((timestamp >> 15) & 0x7fff) << 1) | 1);
+ pack[10]=x>>8; pack[11]=x&255;
+ x=((((timestamp) & 0x7fff) << 1) | 1);
+ pack[12]=x>>8; pack[13]=x&255;
+ } else {
+ pack[7]=0x00;
+ }
+
+ // ============ LPCM header: (7 bytes) =================
+ // Info by mocm@convergence.de
+
+ // ID:
+ pack[ptslen+9]=id;
+
+ // number of frames:
+ pack[ptslen+10]=0x07;
+
+ // first acces unit pointer, i.e. start of audio frame:
+ pack[ptslen+11]=0x00;
+ pack[ptslen+12]=0x04;
+
+ // audio emphasis on-off 1 bit
+ // audio mute on-off 1 bit
+ // reserved 1 bit
+ // audio frame number 5 bit
+ pack[ptslen+13]=0x0C;
+
+ // quantization word length 2 bit
+ // audio sampling frequency (48khz = 0, 96khz = 1) 2 bit
+ // reserved 1 bit
+ // number of audio channels - 1 (e.g. stereo = 1) 3 bit
+ pack[ptslen+14]=1|(freq_id<<4);
+
+ // dynamic range control (0x80 if off)
+ pack[ptslen+15]=0x80;
+
+ write_dxr2(pack, 6+3+ptslen+7);
+ write_dxr2(data, payload_size);
+
+ len-=payload_size; data+=payload_size;
+ timestamp+=90000/4*payload_size/48000;
+ // ptslen=0; // store PTS only once, at first packet!
+ }
+}
+
+static uint32_t config(uint32_t s_width, uint32_t s_height, uint32_t width, uint32_t height, uint32_t flags, char *title, uint32_t format, const vo_tune_info_t *info)
+{
+ int arg;
+ dxr2_threeArg_t arg3;
+
+ if(dxr2_fd < 0) {
+ mp_msg(MSGT_VO,MSGL_ERR,"DXR2 fd is not valid\n");
+ return VO_ERROR;
+ }
+
+ if(playing) {
+ dxr2_send_eof();
+ flush_dxr2();
+ ioctl(dxr2_fd, DXR2_IOC_STOP, NULL);
+ playing = 0;
+ }
+
+ last_freq_id = -1;
+
+ // Video stream setup
+ arg3.arg1 = DXR2_STREAM_VIDEO;
+ arg3.arg2 = 0;
+ ioctl(dxr2_fd, DXR2_IOC_SELECT_STREAM, &arg3);
+ if (vo_fps > 28)
+ arg3.arg1 = DXR2_SRC_VIDEO_FREQ_30;
+ else arg3.arg1 = DXR2_SRC_VIDEO_FREQ_25;
+ arg3.arg2 = 0;
+ arg3.arg3 = 0;
+ ioctl(dxr2_fd, DXR2_IOC_SET_SOURCE_VIDEO_FORMAT, &arg3);
+ arg = DXR2_BITSTREAM_TYPE_MPEG_VOB;
+ ioctl(dxr2_fd, DXR2_IOC_SET_BITSTREAM_TYPE, &arg);
+
+ // Aspect ratio
+ if (1.76 <= movie_aspect && movie_aspect <= 1.80) {
+ arg = DXR2_ASPECTRATIO_16_9;
+ mp_msg(MSGT_VO,MSGL_V,"VO: [dxr2] source aspect ratio 16:9\n");
+ } else {
+ arg = DXR2_ASPECTRATIO_4_3;
+ mp_msg(MSGT_VO,MSGL_V,"VO: [dxr2] source aspect ratio 4:3\n");
+ }
+ ioctl(dxr2_fd, DXR2_IOC_SET_SOURCE_ASPECT_RATIO, &arg);
+ if (1.76 <= monitor_aspect && monitor_aspect <=1.80) {
+ arg = DXR2_ASPECTRATIO_16_9;
+ mp_msg(MSGT_VO,MSGL_V,"VO: [dxr2] monitor aspect ratio 16:9\n");
+ } else {
+ arg = DXR2_ASPECTRATIO_4_3;
+ mp_msg(MSGT_VO,MSGL_V,"VO: [dxr2] monitor aspect ratio 4:3\n");
+ }
+ ioctl(dxr2_fd, DXR2_IOC_SET_OUTPUT_ASPECT_RATIO, &arg);
+
+ arg = ar_mode;
+ ioctl(dxr2_fd, DXR2_IOC_SET_ASPECT_RATIO_MODE, &arg);
+
+ // TV setup
+ arg = mv_mode;
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_MACROVISION_MODE, &arg);
+ arg = _75ire_mode;
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_75IRE_MODE, &arg);
+ arg = bw_mode;
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_BLACKWHITE_MODE, &arg);
+ arg = interlaced_mode;
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_INTERLACED_MODE, &arg);
+ arg = pixel_mode;
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_PIXEL_MODE, &arg);
+
+ if (norm) {
+ if (strcmp(norm, "ntsc")==0)
+ arg = DXR2_OUTPUTFORMAT_NTSC;
+ else if (strcmp(norm, "pal")==0) {
+ if (vo_fps > 28) {
+ mp_msg(MSGT_VO,MSGL_WARN,"VO: [dxr2] you want pal, but we play at 30 fps, selecting pal60 instead\n");
+ arg = DXR2_OUTPUTFORMAT_PAL_60;
+ norm="pal60";
+ } else arg = DXR2_OUTPUTFORMAT_PAL_BDGHI;
+ } else if (strcmp(norm, "pal60")==0) {
+ if (vo_fps > 28)
+ arg = DXR2_OUTPUTFORMAT_PAL_60;
+ else {
+ mp_msg(MSGT_VO,MSGL_WARN,"VO: [dxr2] you want pal60, but we play at 25 fps, selecting pal instead\n");
+ arg = DXR2_OUTPUTFORMAT_PAL_BDGHI;
+ norm="pal";
+ }
+ } else if (strcmp(norm, "palm")==0)
+ arg = DXR2_OUTPUTFORMAT_PAL_M;
+ else if (strcmp(norm, "paln")==0)
+ arg = DXR2_OUTPUTFORMAT_PAL_N;
+ else if (strcmp(norm, "palnc")==0)
+ arg = DXR2_OUTPUTFORMAT_PAL_Nc;
+ else {
+ mp_msg(MSGT_VO,MSGL_WARN,"[dxr2] invalid norm %s\n", norm);
+ mp_msg(MSGT_VO,MSGL_WARN,"Valid values are ntsc,pal,pal60,palm,paln,palnc\n");
+ mp_msg(MSGT_VO,MSGL_WARN,"Using ntsc\n");
+ norm="ntsc";
+ }
+ } else {
+ if (vo_fps > 28) {
+ arg = DXR2_OUTPUTFORMAT_NTSC;
+ norm="ntsc";
+ } else {
+ arg = DXR2_OUTPUTFORMAT_PAL_BDGHI;
+ norm="pal";
+ }
+ }
+ mp_msg(MSGT_VO,MSGL_V,"VO: [dxr2] output norm set to %s\n", norm);
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_OUTPUT_FORMAT, &arg);
+
+ // Subtitles
+ arg3.arg1 = DXR2_STREAM_SUBPICTURE;
+ arg3.arg2 = 0;
+ ioctl(dxr2_fd, DXR2_IOC_SELECT_STREAM, &arg3);
+
+ // Audio
+ arg = iec958_mode;
+ ioctl(dxr2_fd, DXR2_IOC_IEC958_OUTPUT_MODE, &arg);
+ arg = DXR2_AUDIO_WIDTH_16;
+ ioctl(dxr2_fd, DXR2_IOC_SET_AUDIO_DATA_WIDTH, &arg);
+ arg = DXR2_AUDIO_FREQ_48;
+ ioctl(dxr2_fd, DXR2_IOC_SET_AUDIO_SAMPLE_FREQUENCY, &arg);
+ arg3.arg1 = DXR2_STREAM_AUDIO_LPCM;
+ arg3.arg2 = 0;
+ ioctl(dxr2_fd, DXR2_IOC_SELECT_STREAM, &arg3);
+ arg = 19;
+ ioctl(dxr2_fd, DXR2_IOC_SET_AUDIO_VOLUME, &arg);
+ arg = mute_mode;
+ ioctl(dxr2_fd, DXR2_IOC_AUDIO_MUTE, &arg);
+
+ // Overlay
+ if(use_ol) {
+ dxr2_twoArg_t win;
+ win.arg1 = flags & VOFLAG_FULLSCREEN ? vo_screenwidth : width;
+ win.arg2 = flags & VOFLAG_FULLSCREEN ? vo_screenheight : height;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_DIMENSION, &win);
+ win.arg1 = (vo_screenwidth - win.arg1) / 2;
+ win.arg2 = (vo_screenheight - win.arg2) / 2;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_POSITION,&win);
+ }
+ fs = flags & VOFLAG_FULLSCREEN ? 1 : 0;
+ movie_w = width;
+ movie_h = height;
+
+ // start playing
+ if(ioctl(dxr2_fd, DXR2_IOC_PLAY, NULL) == 0) {
+ playing = 1;
+ return 0;
+ } else
+ return VO_ERROR;
+}
+
+static const vo_info_t* get_info(void)
+{
+ return &vo_info;
+}
+
+static void draw_osd(void)
+{
+}
+
+static uint32_t draw_frame(uint8_t * src[])
+{
+ vo_mpegpes_t *p=(vo_mpegpes_t *)src[0];
+ dxr2_send_packet(p->data, p->size, p->id, p->timestamp);
+
+ return 0;
+}
+
+static void flip_page (void)
+{
+}
+
+static uint32_t draw_slice( uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0 )
+{
+ return 0;
+}
+
+
+static uint32_t query_format(uint32_t format)
+{
+ if (format==IMGFMT_MPEGPES)
+ return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW|VFCAP_TIMER;
+ return 0;
+}
+
+
+static void query_vaa(vo_vaa_t *vaa) {
+ memset(vaa,0,sizeof(vo_vaa_t));
+}
+
+static void uninit(void)
+{
+ mp_msg(MSGT_VO,MSGL_DBG2, "VO: [dxr2] Uninitializing\n" );
+
+ dxr2_send_eof();
+ flush_dxr2();
+ if (dxr2_fd > 0) {
+ close(dxr2_fd);
+ dxr2_fd = -1;
+ }
+ if(sub_vo) {
+ sub_vo->uninit();
+ sub_vo = NULL;
+ }
+}
+
+
+static void check_events(void)
+{
+}
+
+static uint32_t preinit(const char *arg) {
+ int uCodeFD = -1;
+ int uCodeSize;
+ dxr2_uCode_t* uCode;
+ dxr2_fourArg_t crop;
+ int n=0;
+
+ sub_vo = NULL;
+ if(use_ol) {
+ if (arg) {
+ for(n = 0 ; video_out_drivers[n] != NULL ; n++) {
+ const vo_info_t* vi = video_out_drivers[n]->get_info();
+ if(!vi)
+ continue;
+ if(strcasecmp(arg,vi->short_name) == 0)
+ break;
+ }
+ sub_vo = video_out_drivers[n];
+ } else {
+ mp_msg(MSGT_VO,MSGL_WARN,"VO: [dxr2] We need a sub driver to initialize the overlay\n");
+ use_ol = 0;
+ }
+ }
+
+ if(use_ol && !sub_vo) {
+ if(arg)
+ mp_msg(MSGT_VO,MSGL_WARN,"VO: [dxr2] Sub driver '%s' not found => no overlay\n",arg);
+ use_ol = 0;
+ } else {
+ if(sub_vo->preinit(NULL) != 0) {
+ mp_msg(MSGT_VO,MSGL_WARN,"VO: [dxr2] Sub vo %s preinit failed => no overlay\n",arg);
+ sub_vo = NULL;
+ use_ol = 0;
+ } else
+ mp_msg(MSGT_VO,MSGL_V,"VO: [dxr2] Sub vo %s inited\n",arg);
+ }
+
+ dxr2_fd = open( "/dev/dxr2", O_WRONLY);
+ if( dxr2_fd < 0 ) {
+ mp_msg(MSGT_VO,MSGL_V, "VO: [dxr2] Error opening /dev/dxr2 for writing!\n" );
+ return VO_ERROR;
+ }
+
+ if(ucode)
+ uCodeFD = open(ucode, O_RDONLY);
+ else for (n=0; ucodesearchpath[n] != NULL; n++) {
+ mp_msg(MSGT_VO,MSGL_V,"VO: [dxr2] Looking for microcode in %s... ",
+ ucodesearchpath[n]);
+ if ((uCodeFD = open(ucodesearchpath[n], O_RDONLY))>0) {
+ mp_msg(MSGT_VO,MSGL_V,"ok\n");
+ break;
+ } else {
+ mp_msg(MSGT_VO,MSGL_V,"failed (%s)\n", strerror(errno));
+ }
+ }
+ if (uCodeFD < 0) {
+ mp_msg(MSGT_VO,MSGL_ERR,"VO: [dxr2] Could not open microcode\n");
+ return VO_ERROR;
+ }
+
+ uCodeSize = lseek(uCodeFD, 0, SEEK_END);
+ if ((uCode = malloc(uCodeSize + 4)) == NULL) {
+
+ mp_msg(MSGT_VO,MSGL_FATAL,"VO: [dxr2] Could not allocate memory for uCode: %s\n", strerror(errno));
+ return VO_ERROR;
+ }
+ lseek(uCodeFD, 0, SEEK_SET);
+ if (read(uCodeFD, uCode+4, uCodeSize) != uCodeSize) {
+
+ mp_msg(MSGT_VO,MSGL_ERR,"VO: [dxr2] Could not read uCode uCode: %s\n", strerror(errno));
+ return VO_ERROR;
+ }
+ close(uCodeFD);
+ uCode->uCodeLength = uCodeSize;
+
+ // upload ucode
+ ioctl(dxr2_fd, DXR2_IOC_INIT_ZIVADS, uCode);
+
+ // reset card
+ ioctl(dxr2_fd, DXR2_IOC_RESET, NULL);
+ playing = 0;
+
+ if(!use_ol) {
+ crop.arg1=0;
+ crop.arg2=0;
+ crop.arg3=0;
+ crop.arg4=0;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_CROPPING, &crop);
+ } else while(1) {
+ // Init the overlay, don't ask me how it work ;-)
+ dxr2_sixArg_t oc;
+ dxr2_oneArg_t om;
+ dxr2_vgaParams_t vga;
+ dxr2_twoArg_t win;
+
+ // First we need a white screen
+ uint8_t* img = malloc(vo_screenwidth*vo_screenheight*3);
+ uint8_t* src[] = { img, NULL, NULL };
+
+ memset(img,255,vo_screenwidth*vo_screenheight*3);
+
+ if(sub_vo->config(vo_screenwidth,vo_screenheight,vo_screenwidth,vo_screenheight,
+ VOFLAG_FULLSCREEN ,"DXR2 sub vo",IMGFMT_BGR24,NULL) != 0) {
+ mp_msg(MSGT_VO,MSGL_WARN,"VO: [dxr2] sub vo config failed => No overlay\n");
+ sub_vo->uninit();
+ sub_vo = NULL;
+ use_ol = 0;
+ break;
+ }
+ sub_vo->draw_frame(src);
+ sub_vo->flip_page();
+ free(img);
+
+ crop.arg1=0;
+ crop.arg2=0;
+ crop.arg3=55;
+ crop.arg4=300;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_CROPPING, &crop);
+
+ oc.arg1 = 0x40;
+ oc.arg2 = 0xff;
+ oc.arg3 = 0x40;
+ oc.arg4 = 0xff;
+ oc.arg5 = 0x40;
+ oc.arg6 = 0xff;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_COLOUR, &oc);
+
+ om.arg = 1000;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_RATIO,&om);
+
+ win.arg1 = 100;
+ win.arg2 = 3;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_POSITION,&win);
+
+ win.arg1 = vo_screenwidth;
+ win.arg2 = vo_screenheight;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_DIMENSION,&win);
+
+ om.arg = 3;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_IN_DELAY,&om);
+
+ om.arg = DXR2_OVERLAY_WINDOW_COLOUR_KEY;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_MODE,&om);
+
+ vga.xScreen = vo_screenwidth;
+ vga.yScreen = vo_screenheight;
+ vga.hOffWinKey = 100;
+ vga.vOffWinKey = 3;
+ ioctl(dxr2_fd, DXR2_IOC_CALCULATE_VGA_PARAMETERS, &vga);
+ ioctl(dxr2_fd, DXR2_IOC_SET_VGA_PARAMETERS, &vga);
+
+ // Remove the white screen
+ sub_vo->check_events(); // at least x11 need this to remove his window
+ sub_vo->uninit();
+ sub_vo = NULL;
+
+ om.arg = DXR2_OVERLAY_WINDOW_KEY;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_MODE,&om);
+
+ break;
+ }
+ return 0;
+}
+
+static uint32_t control(uint32_t request, void *data, ...)
+{
+ switch (request) {
+ case VOCTRL_QUERY_FORMAT:
+ return query_format(*((uint32_t*)data));
+ case VOCTRL_PAUSE:
+ ioctl(dxr2_fd,DXR2_IOC_PAUSE, NULL);
+ return VO_TRUE;
+ case VOCTRL_RESUME:
+ ioctl(dxr2_fd, DXR2_IOC_PLAY, NULL);
+ return VO_TRUE;
+ case VOCTRL_RESET:
+ flush_dxr2();
+ ioctl(dxr2_fd, DXR2_IOC_PLAY, NULL);
+ return VO_TRUE;
+ case VOCTRL_FULLSCREEN:
+ if(!use_ol)
+ return VO_NOTIMPL;
+ else {
+ dxr2_twoArg_t win;
+ fs = !fs;
+ win.arg1 = fs ? vo_screenwidth : movie_w;
+ win.arg2 = fs ? vo_screenheight : movie_h;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_DIMENSION, &win);
+ win.arg1 = (vo_screenwidth - win.arg1) / 2;
+ win.arg2 = (vo_screenheight - win.arg2) / 2;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_POSITION,&win);
+ return VO_TRUE;
+ }
+ case VOCTRL_QUERY_VAA:
+ query_vaa((vo_vaa_t*)data);
+ return VO_TRUE;
+ }
+ return VO_NOTIMPL;
+}
diff --git a/mp-opt-reg.c b/mp-opt-reg.c
index 372ad9a15d..7ec1e4c11d 100644
--- a/mp-opt-reg.c
+++ b/mp-opt-reg.c
@@ -8,6 +8,7 @@
extern void mp_input_register_options(m_config_t* cfg);
#endif
extern void libmpdemux_register_options(m_config_t* cfg);
+extern void libvo_register_options(m_config_t* cfg);
void
mp_register_options(m_config_t* cfg) {
@@ -16,5 +17,5 @@ mp_register_options(m_config_t* cfg) {
mp_input_register_options(cfg);
#endif
libmpdemux_register_options(cfg);
-
+ libvo_register_options(cfg);
}