From b6a7934eb5ae4d2bbf435aca79a51ffa4b8ff6c3 Mon Sep 17 00:00:00 2001 From: albeu Date: Mon, 13 May 2002 13:15:40 +0000 Subject: Initial support for dxr2. Based on patch from Tobias Diedrich . git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6070 b3059339-0415-0410-9bf9-f77b7e298cf2 --- configure | 38 +++ libao2/ao_dxr2.c | 143 +++++++++++ libao2/audio_out.c | 6 + libvo/Makefile | 2 +- libvo/video_out.c | 16 ++ libvo/vo_dxr2.c | 739 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mp-opt-reg.c | 3 +- 7 files changed, 945 insertions(+), 2 deletions(-) create mode 100644 libao2/ao_dxr2.c create mode 100644 libvo/vo_dxr2.c 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 +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 +#include +#include +#include + +#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 ", + "" +}; + +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>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; @@ -49,6 +52,9 @@ ao_functions_t* audio_out_drivers[] = #endif #ifdef USE_SGI_AUDIO &audio_out_sgi, +#endif +#ifdef HAVE_DXR2 + &audio_out_dxr2, #endif &audio_out_null, #ifdef HAVE_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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "video_out.h" +#include "video_out_internal.h" +#include "mp_msg.h" +#include "cfgparser.h" + +#include + +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 and Tobias Diedrich ", + "" +}; + +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); } -- cgit v1.2.3