[MPlayer-dev-eng] [PATCH] DXR2 video output
Tobias Diedrich
td at informatik.uni-hannover.de
Fri May 10 18:39:21 CEST 2002
This patch adds DXR2 video + audio output plugins
(based on mpegpes output plugin).
configure will autodetect it if the headers are in
/usr/src/dxr2/sysinclude
It adds the switch --with-dxr2incdir to change this path.
It also adds two new cmdline switches:
-dxr2norm NORM and -dxr2ucode PATH_TO_UCODE_FILE
(The default for former depends on the resolution and is pal
for h==288 || h==576, the latter has /usr/src/dvd12.ux as default)
--
Tobias PGP: 0x9AC7E0BC
-------------- next part --------------
diff -urN main.vanilla/cfg-mplayer.h main/cfg-mplayer.h
--- main.vanilla/cfg-mplayer.h Fri May 10 14:07:44 2002
+++ main/cfg-mplayer.h Fri May 10 14:33:07 2002
@@ -39,6 +39,11 @@
extern int fakemono; // defined in dec_audio.c
#endif
+#ifdef HAVE_DXR2
+extern char *vo_dxr2_norm;
+extern char *vo_dxr2_ucode;
+#endif
+
#ifdef HAVE_LIRC
extern char *lirc_configfile;
#endif
@@ -274,6 +279,10 @@
#ifdef HAVE_ZR
// -vo zr
{"zr*", vo_zr_parseoption, CONF_TYPE_FUNC_FULL, 0, 0, 0, &vo_zr_revertoption },
+#endif
+#ifdef HAVE_DXR2
+ {"dxr2norm", &vo_dxr2_norm, CONF_TYPE_STRING, 0, 0, 0, NULL},
+ {"dxr2ucode", &vo_dxr2_ucode, CONF_TYPE_STRING, 0, 0, 0, NULL},
#endif
//---------------------- mplayer-only options ------------------------
diff -urN main.vanilla/cfg-mplayer.h.orig main/cfg-mplayer.h.orig
--- main.vanilla/cfg-mplayer.h.orig Fri May 10 14:03:29 2002
+++ main/cfg-mplayer.h.orig Thu May 9 00:26:01 2002
@@ -39,10 +39,6 @@
extern int fakemono; // defined in dec_audio.c
#endif
-#ifdef HAVE_DXR2
-extern char *vo_dxr2_norm;
-#endif
-
#ifdef HAVE_LIRC
extern char *lirc_configfile;
#endif
@@ -278,9 +274,6 @@
#ifdef HAVE_ZR
// -vo zr
{"zr*", vo_zr_parseoption, CONF_TYPE_FUNC_FULL, 0, 0, 0, &vo_zr_revertoption },
-#endif
-#ifdef HAVE_DXR2
- {"dxr2norm", &vo_dxr2_norm, CONF_TYPE_STRING, 0, 0, 0, NULL},
#endif
//---------------------- mplayer-only options ------------------------
diff -urN main.vanilla/configure main/configure
--- main.vanilla/configure Fri May 10 14:07:44 2002
+++ main/configure Fri May 10 14:31:01 2002
@@ -161,6 +161,7 @@
--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
--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
@@ -214,6 +215,7 @@
--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)
@@ -777,6 +779,7 @@
_fbdev_nocopy=no
_dvb=auto
_dxr3=auto
+_dxr2=auto
_iconv=auto
_rtc=auto
_ossaudio=auto
@@ -874,6 +877,8 @@
--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 ;;
@@ -1037,6 +1042,9 @@
--enable-dshow) _win32=yes _dshow=yes ;;
--disable-dshow) _dshow=no ;;
+ --with-dxr2incdir=*)
+ _inc_dxr2=-I`echo $ac_option | cut -d '=' -f 2 | sed 's,:, -I,g'`
+ ;;
--with-x11incdir=*)
_inc_x11=-I`echo $ac_option | cut -d '=' -f 2 | sed 's,:, -I,g'`
;;
@@ -2411,6 +2419,30 @@
fi
echores "$_nas"
+echocheck "DXR2"
+_inc_dxr2=${_inc_dxr2--I /usr/src/dxr2/sysinclude}
+if test "$_dxr2" = auto; then
+ cat > $TMPC << EOF
+#include <dxr2ioctl.h>
+int main(void) { return 0; }
+EOF
+ _dxr2=no
+ cc_check $_inc_dxr2 && _dxr2=yes
+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
@@ -2457,6 +2489,7 @@
if test "$_fame" = auto ; then
_fame=no
test "$_dxr3" = yes && _fame=auto
+ test "$_dxr2" = yes && _fame=auto
test "$_dvb" = yes && _fame=auto
fi
if test "$_fame" = auto ; then
@@ -3633,6 +3666,7 @@
MLIB_LIB = $_ld_mlib
MLIB_INC = $_inc_mlib
DVB_INC = $_inc_dvb
+DXR2_INC = $_inc_dxr2
PNG_LIB = $_ld_png
JPEG_LIB = $_ld_jpg
SDL_LIB = $_ld_sdl
@@ -4035,6 +4069,7 @@
$_def_syncfb
$_def_fbdev
$_def_fbdev_nocopy
+$_def_dxr2
$_def_dxr3
$_def_dvb
$_def_svga
diff -urN main.vanilla/configure.orig main/configure.orig
--- main.vanilla/configure.orig Fri May 10 14:07:19 2002
+++ main/configure.orig Fri May 10 03:50:17 2002
@@ -161,7 +161,6 @@
--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
--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
@@ -778,7 +777,6 @@
_fbdev_nocopy=no
_dvb=auto
_dxr3=auto
-_dxr2=no
_iconv=auto
_rtc=auto
_ossaudio=auto
@@ -876,8 +874,6 @@
--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 ;;
@@ -2415,20 +2411,6 @@
fi
echores "$_nas"
-echocheck "DXR2"
-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"
-else
- _def_dxr2='#undef HAVE_DXR2'
- _noaomodules="dxr2 $_noaomodules"
- _novomodules="dxr2 $_novomodules"
-fi
-echores "$_dxr2"
-
echocheck "DXR3/H+"
if test "$_dxr3" = auto ; then
cat > $TMPC << EOF
@@ -4053,7 +4035,6 @@
$_def_syncfb
$_def_fbdev
$_def_fbdev_nocopy
-$_def_dxr2
$_def_dxr3
$_def_dvb
$_def_svga
diff -urN main.vanilla/libao2/ao_dxr2.c main/libao2/ao_dxr2.c
--- main.vanilla/libao2/ao_dxr2.c Thu Jan 1 01:00:00 1970
+++ main/libao2/ao_dxr2.c Fri May 10 14:03:29 2002
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+
+#include "../config.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 at 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;
+ default:
+ fprintf(stderr,"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;
+
+// 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;
+// printf("diff: %5.3f -> %d \n",x,y);
+ 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){
+ if(ao_data.format==AFMT_MPEG)
+ dxr2_send_packet(data,len,0xC0,ao_data.pts);
+ else {
+ int i;
+ unsigned short *s=data;
+// if(len>2000) len=2000;
+// printf("ao_mpegpes: len=%d \n",len);
+ for(i=0;i<len/2;i++) s[i]=(s[i]>>8)|(s[i]<<8); // le<->be
+ 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 -urN main.vanilla/libao2/audio_out.c main/libao2/audio_out.c
--- main.vanilla/libao2/audio_out.c Fri May 10 14:07:44 2002
+++ main/libao2/audio_out.c Fri May 10 14:03:29 2002
@@ -25,6 +25,9 @@
#ifdef HAVE_NAS
extern ao_functions_t audio_out_nas;
#endif
+#ifdef HAVE_DXR2
+extern ao_functions_t audio_out_dxr2;
+#endif
#ifdef HAVE_SDL
extern ao_functions_t audio_out_sdl;
#endif
@@ -62,6 +65,9 @@
#endif
#ifdef HAVE_NAS
&audio_out_nas,
+#endif
+#ifdef HAVE_DXR2
+ &audio_out_dxr2,
#endif
#ifdef HAVE_SDL
&audio_out_sdl,
Binary files main.vanilla/libmpcodecs/.vf_scale.c.swp and main/libmpcodecs/.vf_scale.c.swp differ
diff -urN main.vanilla/libvo/Makefile main/libvo/Makefile
--- main.vanilla/libvo/Makefile Sat Apr 13 21:14:33 2002
+++ main/libvo/Makefile Fri May 10 14:31:27 2002
@@ -10,7 +10,7 @@
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) $(DVB_INC) $(DXR2_INC) -DMPG12PLAY #-Wall
ifeq ($(VIDIX),yes)
CFLAGS += -DVIDIX_PATH='"$(prefix)/lib/mplayer/vidix/"'
endif
diff -urN main.vanilla/libvo/video_out.c main/libvo/video_out.c
--- main.vanilla/libvo/video_out.c Fri May 10 14:07:44 2002
+++ main/libvo/video_out.c Fri May 10 14:03:29 2002
@@ -99,6 +99,7 @@
extern vo_functions_t video_out_aa;
extern vo_functions_t video_out_mpegpes;
extern vo_functions_t video_out_yuv4mpeg;
+extern vo_functions_t video_out_dxr2;
extern vo_functions_t video_out_dxr3;
#ifdef HAVE_JPEG
extern vo_functions_t video_out_jpeg;
@@ -156,6 +157,9 @@
#endif
#ifdef HAVE_AA
&video_out_aa,
+#endif
+#ifdef HAVE_DXR2
+ &video_out_dxr2,
#endif
#ifdef HAVE_DXR3
&video_out_dxr3,
diff -urN main.vanilla/libvo/vo_dxr2.c main/libvo/vo_dxr2.c
--- main.vanilla/libvo/vo_dxr2.c Thu Jan 1 01:00:00 1970
+++ main/libvo/vo_dxr2.c Fri May 10 18:11:16 2002
@@ -0,0 +1,684 @@
+#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 "dxr2ioctl.h"
+#include "config.h"
+#include "video_out.h"
+#include "video_out_internal.h"
+#include "../postproc/rgb2rgb.h"
+#include "../libfame/fame.h"
+
+LIBVO_EXTERN (dxr2)
+
+char *vo_dxr2_norm;
+char *vo_dxr2_ucode;
+extern float monitor_aspect;
+
+static int dxr2_fd = -1;
+static int out_fd = -1;
+static int out2_fd = -1;
+
+static int frame = 0;
+static int pulldown = 0;
+static int pulldownctr = 0;
+
+static int src_fps_num;
+static int src_fps_den;
+static int dst_fps_num;
+static int dst_fps_den;
+
+static unsigned char *picture_buf=NULL;
+static unsigned char *outbuf=NULL;
+static int outbuf_size = 1000000;
+
+static int s_pos_x,s_pos_y;
+static int d_pos_x,d_pos_y;
+
+static int osd_w,osd_h;
+
+static fame_parameters_t params;
+static fame_yuv_t yuv;
+static fame_context_t *ctx=NULL;
+
+static vo_info_t vo_info =
+{
+ "DXR2 video out",
+ "dxr2",
+ "Tobias Diedrich <ranma at gmx.at>",
+ ""
+};
+
+#define BUF_SIZE 2048
+
+static unsigned char dxr2buf[BUF_SIZE];
+static unsigned int dxr2bufpos;
+
+
+static void write_dxr2(void *data, int len)
+{
+ while (len>0) if ((dxr2bufpos+len) <= BUF_SIZE) {
+ memcpy(dxr2buf+dxr2bufpos, data, len);
+ dxr2bufpos+=len;
+ len=0;
+ } else {
+ int copylen=BUF_SIZE-dxr2bufpos;
+ memcpy(dxr2buf+dxr2bufpos, data, copylen);
+ if (dxr2_fd)
+ write(dxr2_fd, dxr2buf, BUF_SIZE);
+ if (out_fd)
+ write(out_fd, dxr2buf, BUF_SIZE);
+ dxr2bufpos=0;
+ data+=copylen;
+ len-=copylen;
+ }
+}
+
+static void flush_dxr2()
+{
+ if (dxr2bufpos) {
+ write(out_fd, dxr2buf, dxr2bufpos);
+ dxr2bufpos=0;
+ }
+}
+
+#define PACK_MAX_SIZE 2048
+
+static unsigned char pack[PACK_MAX_SIZE];
+
+struct dxr2_pack_queue_entry {
+ void *data;
+ int len;
+ int timestamp;
+ struct dxr2_pack_queue_entry *next;
+};
+
+struct dxr2_pack_queue_head {
+ struct dxr2_pack_queue_entry *head;
+ int entries;
+};
+
+struct dxr2_pack_queue_head pack_queue;
+
+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 (dst_fps_num!=src_fps_num)
+ timestamp=((float)frame)*((float)dst_fps_den)*((float)90000.0)/((float)dst_fps_num);
+
+ 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;
+
+ 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;
+ }
+ ioctl(dxr2_fd, DXR2_IOC_SET_AUDIO_SAMPLE_FREQUENCY, &arg);
+ freq_id=0;
+
+ if (((int) timestamp)<0)
+ timestamp=0;
+
+// printf("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 at 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 fullscreen, char *title, uint32_t format, const vo_tune_info_t *info)
+{
+ int uCodeFD;
+ int uCodeSize;
+ int arg;
+ float aspect=(float)width/(float)height;
+ char *ucode="/usr/src/dvd12.ux";
+ dxr2_uCode_t* uCode;
+ dxr2_threeArg_t arg3;
+ dxr2_fourArg_t crop;
+
+ if (vo_dxr2_ucode)
+ ucode=vo_dxr2_ucode;
+
+ picture_buf=NULL;
+ if (format == IMGFMT_YV12) {
+ int size;
+
+ ctx=fame_open();
+ if (!ctx) {
+ printf("VO: [dxr2] Could not open libFAME!\n");
+ return -1;
+ }
+
+ if (s_width<=352)
+ params.width=352;
+ else params.width=704;
+
+ if (s_height<=240)
+ params.height=240;
+ else if (s_height<=288)
+ params.height=288;
+ else if (s_height<=480)
+ params.height=480;
+ else params.height=576;
+
+ if (vo_fps>23.99 && vo_fps<24.01) {
+ src_fps_num=24;
+ src_fps_den=1;
+ } else if (vo_fps>23.96 && vo_fps<23.98) {
+ src_fps_num=24000;
+ src_fps_den=1001;
+ } else if (vo_fps>24.9 && vo_fps<25.1) {
+ src_fps_num=25;
+ src_fps_den=1;
+ } else if (vo_fps>29.96 && vo_fps<29.98) {
+ src_fps_num=30000;
+ src_fps_den=1001;
+ } else if (vo_fps>29.99 && vo_fps<30.01) {
+ src_fps_num=30;
+ src_fps_den=1;
+ } else {
+ printf("VO: [dxr2] unsupported fps rate, using 30fps!\n");
+ src_fps_num=30;
+ src_fps_den=1;
+ }
+ printf("VO: [dxr2] source fps rate %2.2f\n",
+ (float)src_fps_num/(float)src_fps_den);
+
+ if (params.height == 288 ||
+ params.height == 576) {
+ dst_fps_num=25;
+ dst_fps_den=1;
+ } else {
+ dst_fps_num=30000;
+ dst_fps_den=1001;
+ }
+
+ printf("VO: [dxr2] destination fps rate %2.2f\n",
+ (float)dst_fps_num/(float)dst_fps_den);
+
+ if (src_fps_num==24 || src_fps_num==24000)
+ if (dst_fps_num==25)
+ pulldown=24;
+ else pulldown=4;
+ if (pulldown)
+ printf("VO: [dxr2] rate adaption enabled (doubling every %dth frame)\n", pulldown);
+
+ printf("VO: [dxr2] output size %dx%d\n",
+ params.width, params.height);
+
+ osd_w=s_width;
+ d_pos_x=(params.width-(int)s_width)/2;
+ if (d_pos_x<0) {
+ s_pos_x=-d_pos_x;d_pos_x=0;
+ osd_w=params.width;
+ } else s_pos_x=0;
+
+ d_pos_y=(params.height-(int)s_height)/2;
+ if (d_pos_y<0) {
+ s_pos_y=-d_pos_y;d_pos_y=0;
+ osd_h=params.height;
+ } else {
+ s_pos_y=0;
+ osd_h=s_height+d_pos_y;
+ }
+
+/* params.coding="IPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
+ "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
+ "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
+ "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"
+ "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPP";
+ params.bitrate=1000000; //0;*/
+ params.coding="I";
+ params.bitrate=5000000; //0;
+ params.quality=0; //80
+ params.slices_per_frame=1;
+ params.frames_per_sequence=30*5;
+ params.frame_rate_num=dst_fps_num;
+ params.frame_rate_den=dst_fps_den;
+ params.shape_quality=100;
+// params.search_range=8;
+ params.search_range=0;
+ params.verbose=0;
+ params.profile=NULL;
+
+ outbuf_size=10000+width*height;
+ outbuf=malloc(outbuf_size);
+
+ fame_init(ctx, ¶ms, outbuf, outbuf_size);
+
+ size=params.width*params.height;
+ picture_buf=malloc(size*3/2);
+ memset(picture_buf, 0, size);
+ memset(picture_buf+size, 128, size/2);
+
+ yuv.w=params.width;
+ yuv.h=params.height;
+ yuv.y=picture_buf;
+ yuv.u=yuv.y+size;
+ yuv.v=yuv.u+size/4;
+ }
+
+ dxr2_fd = open( "/dev/dxr2", O_WRONLY );
+// out_fd = open( "dxr2.mpg", O_WRONLY | O_TRUNC | O_CREAT, 0644);
+// out2_fd = open( "dxr2.m1v", O_WRONLY | O_TRUNC | O_CREAT, 0644);
+ if( dxr2_fd < 1 )
+ {
+ printf( "VO: [dxr2] Error opening /dev/dxr2 for writing!\n" );
+ return -1;
+ }
+
+ if ((uCodeFD = open(ucode, O_RDONLY)) < 0) {
+
+ printf("VO: [dxr2] Could not open uCode (%s): %s\n", ucode, strerror(errno));
+ return -1;
+ }
+
+ uCodeSize = lseek(uCodeFD, 0, SEEK_END);
+ if ((uCode = malloc(uCodeSize + 4)) == NULL) {
+
+ printf("VO: [dxr2] Could not allocate memory for uCode: %s\n", strerror(errno));
+ return -1;
+ }
+ lseek(uCodeFD, 0, SEEK_SET);
+ if (read(uCodeFD, uCode+4, uCodeSize) != uCodeSize) {
+
+ printf("VO: [dxr2] Could not read uCode uCode: %s\n", strerror(errno));
+ return -1;
+ }
+ close(uCodeFD);
+ uCode->uCodeLength = uCodeSize;
+
+ // upload ucode
+ ioctl(dxr2_fd, DXR2_IOC_INIT_ZIVADS, uCode);
+
+ // reset card
+ ioctl(dxr2_fd, DXR2_IOC_RESET, NULL);
+
+ arg3.arg1 = DXR2_STREAM_VIDEO;
+ arg3.arg2 = 0;
+ ioctl(dxr2_fd, DXR2_IOC_SELECT_STREAM, &arg3);
+
+ if (dst_fps_num==30 || dst_fps_num==30000)
+ 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);
+ if (1.76 <= aspect && aspect <= 1.80) {
+ arg = DXR2_ASPECTRATIO_16_9;
+ printf("VO: [dxr2] source aspect ratio 16:9\n");
+ } else {
+ arg = DXR2_ASPECTRATIO_4_3;
+ printf("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;
+ printf("VO: [dxr2] monitor aspect ratio 16:9\n");
+ } else {
+ arg = DXR2_ASPECTRATIO_4_3;
+ printf("VO: [dxr2] monitor aspect ratio 4:3\n");
+ }
+ ioctl(dxr2_fd, DXR2_IOC_SET_OUTPUT_ASPECT_RATIO, &arg);
+ arg = DXR2_ASPECTRATIOMODE_LETTERBOX;
+ ioctl(dxr2_fd, DXR2_IOC_SET_ASPECT_RATIO_MODE, &arg);
+ arg = DXR2_MACROVISION_OFF;
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_MACROVISION_MODE, &arg);
+ arg = DXR2_PIXEL_CCIR601;
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_PIXEL_MODE, &arg);
+ arg = DXR2_INTERLACED_ON;
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_INTERLACED_MODE, &arg);
+ arg = DXR2_75IRE_OFF;
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_75IRE_MODE, &arg);
+ if (vo_dxr2_norm) {
+ if (strcmp(vo_dxr2_norm, "ntsc")==0)
+ arg = DXR2_OUTPUTFORMAT_NTSC;
+ else if (strcmp(vo_dxr2_norm, "pal")==0) {
+ if (dst_fps_num==30 || dst_fps_num==30000) {
+ printf("VO: [dxr2] you want pal, but we play at 30 fps, selecting pal60 instead\n");
+ arg = DXR2_OUTPUTFORMAT_PAL_60;
+ vo_dxr2_norm="pal60";
+ } else arg = DXR2_OUTPUTFORMAT_PAL_BDGHI;
+ } else if (strcmp(vo_dxr2_norm, "pal60")==0) {
+ if (dst_fps_num==30 || dst_fps_num==30000)
+ arg = DXR2_OUTPUTFORMAT_PAL_60;
+ else {
+ printf("VO: [dxr2] you want pal60, but we play at 25 fps, selecting pal instead\n");
+ arg = DXR2_OUTPUTFORMAT_PAL_BDGHI;
+ vo_dxr2_norm="pal";
+ }
+ } else if (strcmp(vo_dxr2_norm, "palm")==0)
+ arg = DXR2_OUTPUTFORMAT_PAL_M;
+ else if (strcmp(vo_dxr2_norm, "paln")==0)
+ arg = DXR2_OUTPUTFORMAT_PAL_N;
+ else if (strcmp(vo_dxr2_norm, "palnc")==0)
+ arg = DXR2_OUTPUTFORMAT_PAL_Nc;
+ else {
+ printf("[dxr2] invalid norm %s\n", vo_dxr2_norm);
+ printf("Valid values are ntsc,pal,pal60,palm,paln,palnc\n\n");
+ vo_dxr2_norm="ntsc";
+ }
+ } else {
+ if (dst_fps_num==30 || dst_fps_num==30000) {
+ arg = DXR2_OUTPUTFORMAT_NTSC;
+ vo_dxr2_norm="ntsc";
+ } else {
+ arg = DXR2_OUTPUTFORMAT_PAL_BDGHI;
+ vo_dxr2_norm="pal";
+ }
+ }
+ printf("VO: [dxr2] output norm set to %s\n", vo_dxr2_norm);
+ ioctl(dxr2_fd, DXR2_IOC_SET_TV_OUTPUT_FORMAT, &arg);
+ arg = DXR2_IEC958_ENCODED;
+ ioctl(dxr2_fd, DXR2_IOC_IEC958_OUTPUT_MODE, &arg);
+ arg3.arg1 = DXR2_STREAM_SUBPICTURE;
+ arg3.arg2 = 0;
+ ioctl(dxr2_fd, DXR2_IOC_SELECT_STREAM, &arg3);
+ 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 = DXR2_AUDIO_MUTE_OFF;
+ ioctl(dxr2_fd, DXR2_IOC_AUDIO_MUTE, &arg);
+
+ crop.arg1=0;
+ crop.arg2=0;
+ crop.arg3=0;
+ crop.arg4=0;
+ ioctl(dxr2_fd, DXR2_IOC_SET_OVERLAY_CROPPING, &crop);
+
+ // start playing
+ ioctl(dxr2_fd, DXR2_IOC_PLAY, NULL);
+
+// dxr2_send_header();
+
+ return 0;
+}
+
+static const vo_info_t* get_info(void)
+{
+ return &vo_info;
+}
+
+static void draw_alpha(int x0, int y0, int w, int h, unsigned char* src, unsigned char *srca, int stride)
+{
+ if (picture_buf) {
+ vo_draw_alpha_yv12(w, h, src, srca, stride, yuv.y+params.width*(y0+d_pos_y)+x0+d_pos_x, params.width);
+ }
+}
+
+static void draw_osd(void)
+{
+ vo_draw_text(osd_w, osd_h, &draw_alpha);
+}
+
+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)
+{
+ if (picture_buf) {
+ int out_size;
+ out_size = fame_encode_frame(ctx, &yuv, NULL);
+ dxr2_send_packet(outbuf, out_size, 0xE0, vo_pts);
+ if (out2_fd)
+ write(out2_fd, outbuf, out_size);
+ frame++;
+ pulldownctr++;
+ if (pulldown && pulldownctr>=pulldown) {
+ pulldownctr=0;
+ out_size = fame_encode_frame(ctx, &yuv, NULL);
+ dxr2_send_packet(outbuf, out_size, 0xE0, vo_pts);
+ if (out2_fd)
+ write(out2_fd, outbuf, out_size);
+ frame++;
+ }
+ }
+}
+
+static uint32_t draw_slice( uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0 )
+{
+ int y;
+ unsigned char* s;
+ unsigned char* d;
+
+ x0+=d_pos_x;
+ y0+=d_pos_y;
+
+ if (x0+w>yuv.w) w=yuv.w-x0;
+ if (y0+h>params.height) h=params.height-y0;
+
+ // Y
+ s=srcimg[0]+s_pos_x+s_pos_y*stride[0];
+ d=yuv.y+x0+y0*yuv.w;
+ for (y=0; y<h; y++) {
+ memcpy(d, s, w);
+ s+=stride[0];
+ d+=yuv.w;
+ }
+
+ w/=2; h/=2; x0/=2; y0/=2;
+
+ // U
+ s=srcimg[1]+(s_pos_x/2)+(s_pos_y/2)*stride[1];
+ d=yuv.u+x0+y0*(yuv.w/2);
+ for (y=0; y<h; y++) {
+ memcpy(d, s, w);
+ s+=stride[1];
+ d+=yuv.w/2;
+ }
+
+ // V
+ s=srcimg[2]+(s_pos_x/2)+(s_pos_y/2)*stride[2];
+ d=yuv.v+x0+y0*(yuv.w/2);
+ for (y=0; y<h; y++) {
+ memcpy(d, s, w);
+ s+=stride[2];
+ d+=yuv.w/2;
+ }
+
+ return 0;
+}
+
+
+static uint32_t query_format(uint32_t format)
+{
+ if (format==IMGFMT_MPEGPES) return 3|VFCAP_TIMER;
+ if (format==IMGFMT_YV12) return 1|VFCAP_TIMER|VFCAP_OSD;
+ return 0;
+}
+
+static void uninit(void)
+{
+ printf( "VO: [dxr2] Uninitializing\n" );
+
+ dxr2_send_eof();
+ flush_dxr2();
+ if (dxr2_fd) close(dxr2_fd);
+ if (out_fd) close(out_fd);
+ if (out2_fd) close(out2_fd);
+ if (outbuf) free(outbuf);
+ if (picture_buf) free(picture_buf);
+}
+
+
+static void check_events(void)
+{
+}
+
+static uint32_t preinit(const char *arg)
+{
+ if (arg)
+ {
+ printf("vo_dxr2: Unknown subdevice: %s\n", arg);
+ return ENOSYS;
+ }
+ return 0;
+}
+
+static uint32_t control(uint32_t request, void *data, ...)
+{
+ switch (request) {
+ case VOCTRL_QUERY_FORMAT:
+ return query_format(*((uint32_t*)data));
+ }
+ return VO_NOTIMPL;
+}
More information about the MPlayer-dev-eng
mailing list