diff -Naur -x CVS -x .* main/DOCS/DXR3 main-dxr3/DOCS/DXR3 --- main/DOCS/DXR3 Wed Nov 28 16:33:38 2001 +++ main-dxr3/DOCS/DXR3 Wed Nov 28 18:24:11 2001 @@ -1,6 +1,12 @@ DXR3/H+ video/audio output plugins manual by David Holm ======================================================= +2001-11-28: ffmpeg replaced with mp1e, divx playback + won't get much faster than this, huge thanks + goes out to Ivan Kalvachev for helping me + fix the final mp1e bugs (and contributing + to the libvo2 development) + 2001-11-27: -ao dxr3 now works, still a few bugs though you might have to reload the em8300 modules after a playback or you might get static the @@ -45,20 +51,13 @@ the CVS version since most of the time I use the latest features which are only available through cvs) - * /libavcodec from ffmpeg (only required if you intend to - play formats other than mpeg-(1/2), highly recommended!) there are - two ways of doing this: - 1. Download and install ffmpeg from ffmpeg.sourceforge.net. - Configure it with --enable-shared - 2. Download ffmpeg from ffmpeg.sourceforge.net, copy the entire - contents from /libavcodec into /libavcodec - (symlinking won't work!). Then edit /libavcodec/utils.c - and move the line containing register_avcodec(&mpeg1video_encoder); - out of the CONFIG_ENCODERS #ifdef block and place it outside, for - instance below register_avcodec(&rawvideo_encoder); - + * Second, if you want DivX playback you need to download and install + RTE from zapping.sourceforge.net compile and install it BEFORE + running configure in the mplayer dir. + * Run /configure and make sure that DXR3/H+ support =yes - and optionally that libavcodec or ffmpeg.so = yes + and optionally that mp1e rte = yes, if it's = no, please mail me + your configure.log and I'll fix it. From here on compilation (of at least my code ;) should go without problems. @@ -83,9 +82,8 @@ any of these video types _without_ "-vo dxr3"! DIVX Notes -When playing divx's add "-vc odivx", if you get any other divx codec -to run faster tell me which one because I'll be interested in how it -could possibly be any faster than OpenDivX4Linux... +When playing divx's add "-vc odivx" +I've switched to mp1e from ffmpeg so it should be lightning fast now. Other codecs: Currently they don't work. I'm working on implementing libvo2 which diff -Naur -x CVS -x .* main/Makefile main-dxr3/Makefile --- main/Makefile Wed Nov 28 13:34:10 2001 +++ main-dxr3/Makefile Wed Nov 28 09:41:15 2001 @@ -146,14 +146,14 @@ endif $(PRG): $(MPLAYER_DEP) - $(CC) $(CFLAGS) -o $(PRG) $(OBJS_MPLAYER) -Llibmpdemux -lmpdemux $(AV_LIB) $(EXTRA_LIB) $(LIRC_LIB) $(LIB_LOADER) -Llibmpeg2 -lmpeg2 -Llibao2 -lao2 $(A_LIBS) $(VO_LIBS) $(CSS_LIB) $(ARCH_LIB) $(OSDEP_LIBS) $(PP_LIBS) $(XA_LIBS) $(DECORE_LIB) $(TERMCAP_LIB) -lm $(STATIC_LIB) $(GUI_LIBS) $(PNG_LIB) $(Z_LIB) + $(CC) $(CFLAGS) -o $(PRG) $(OBJS_MPLAYER) -Llibmpdemux -lmpdemux $(EXTRA_LIB) $(LIRC_LIB) $(LIB_LOADER) $(AV_LIB) $(MP1E_LIB) -Llibmpeg2 -lmpeg2 -Llibao2 -lao2 $(A_LIBS) $(VO_LIBS) $(CSS_LIB) $(ARCH_LIB) $(OSDEP_LIBS) $(PP_LIBS) $(XA_LIBS) $(DECORE_LIB) $(TERMCAP_LIB) -lm $(STATIC_LIB) $(GUI_LIBS) $(PNG_LIB) $(Z_LIB) $(PRG_FIBMAP): fibmap_mplayer.o $(CC) -o $(PRG_FIBMAP) fibmap_mplayer.o ifeq ($(MENCODER),yes) $(PRG_MENCODER): $(MENCODER_DEP) - $(CC) $(CFLAGS) -o $(PRG_MENCODER) $(OBJS_MENCODER) -Llibmpeg2 -lmpeg2 -Llibmpdemux -lmpdemux $(X_LIBS) $(LIB_LOADER) $(AV_LIB) -lmp3lame $(A_LIBS) $(CSS_LIB) $(GUI_LIBS) $(PNG_LIB) $(Z_LIB) $(ARCH_LIB) $(OSDEP_LIBS) $(PP_LIBS) $(XA_LIBS) $(DECORE_LIB) $(ENCORE_LIB) $(TERMCAP_LIB) -lm + $(CC) $(CFLAGS) -o $(PRG_MENCODER) $(OBJS_MENCODER) -Llibmpeg2 -lmpeg2 -Llibmpdemux -lmpdemux $(X_LIBS) $(LIB_LOADER) $(AV_LIB) $(MP1E_LIB) -lmp3lame $(A_LIBS) $(CSS_LIB) $(GUI_LIBS) $(PNG_LIB) $(Z_LIB) $(ARCH_LIB) $(OSDEP_LIBS) $(PP_LIBS) $(XA_LIBS) $(DECORE_LIB) $(ENCORE_LIB) $(TERMCAP_LIB) -lm endif # $(PRG_HQ): depfile mplayerHQ.o $(OBJS) loader/libloader.a libmpeg2/libmpeg2.a opendivx/libdecore.a $(COMMONLIBS) encore/libencore.a diff -Naur -x CVS -x .* main/libao2/ao_dxr3.c main-dxr3/libao2/ao_dxr3.c --- main/libao2/ao_dxr3.c Wed Nov 28 16:33:37 2001 +++ main-dxr3/libao2/ao_dxr3.c Wed Nov 28 14:15:47 2001 @@ -146,6 +146,7 @@ static void audio_pause() { int ioval; + reset(); fd_control = open( "/dev/em8300", O_WRONLY ); if( fd_control < 0 ) printf( "AO: [dxr3] Oops, unable to pause playback\n" ); @@ -184,25 +185,28 @@ return ao_data.outburst; } space = ao_data.buffersize - space; + space /= ao_data.outburst; /* This is a smart way of doing a fast modulo reduction */ + space *= ao_data.outburst; /* fetched from ao_mpegpes.c */ return space; } static int play(void* data,int len,int flags) { if( ioctl( fd_audio, EM8300_IOCTL_AUDIO_SETPTS, &ao_data.pts ) < 0 ) - printf( "AO: [dxr3] Unable to set pts\n" ); + printf( "AO: [dxr3] Unable to set PTS\n" ); return write(fd_audio,data,len); } // return: how many unplayed bytes are in the buffer static float get_delay() { - int r=0; +/* int r=0; if( ioctl(fd_audio, SNDCTL_DSP_GETODELAY, &r) < 0 ) { printf( "AO: [dxr3] Unable to get unplayed bytes in buffer\n" ); return ((float)ao_data.buffersize)/(float)ao_data.bps; } - return (((float)r)/(float)ao_data.bps); + return (((float)r)/(float)ao_data.bps);*/ + return 0.0; } diff -Naur -x CVS -x .* main/libvo/video_out.c main-dxr3/libvo/video_out.c --- main/libvo/video_out.c Mon Nov 5 03:58:47 2001 +++ main-dxr3/libvo/video_out.c Wed Nov 28 10:08:24 2001 @@ -44,6 +44,7 @@ int vo_fsmode = 0; int vo_pts=0; // for hw decoding +float vo_fps=0; // for mp1e rte char *vo_subdevice = NULL; diff -Naur -x CVS -x .* main/libvo/video_out.h main-dxr3/libvo/video_out.h --- main/libvo/video_out.h Mon Nov 5 03:58:47 2001 +++ main-dxr3/libvo/video_out.h Wed Nov 28 09:59:14 2001 @@ -115,6 +115,7 @@ extern int vo_fsmode; extern int vo_pts; +extern float vo_fps; extern char *vo_subdevice; diff -Naur -x CVS -x .* main/libvo/vo_dxr3.c main-dxr3/libvo/vo_dxr3.c --- main/libvo/vo_dxr3.c Wed Nov 28 16:33:38 2001 +++ main-dxr3/libvo/vo_dxr3.c Wed Nov 28 18:31:49 2001 @@ -33,25 +33,19 @@ LIBVO_EXTERN (dxr3) -#ifdef USE_LIBAVCODEC - -#ifdef USE_LIBAVCODEC_SO -#include -#else -#include "../libavcodec/avcodec.h" -#endif -static AVPicture picture; -static AVCodec *codec=NULL; -static AVCodecContext codec_context; -extern int avcodec_inited; +#ifdef USE_MP1E +#include +rte_context* mp1e_context = NULL; +rte_codec* mp1e_codec = NULL; +rte_buffer mp1e_buffer; #endif -static unsigned char *picture_buf=NULL; -static unsigned char *outbuf=NULL; +static unsigned char *picture_data[3]; +static unsigned int picture_linesize[3]; static unsigned char *spubuf=NULL; -static int outbuf_size = 0; static int v_width,v_height; static int s_width,s_height; +static int c_width,c_height; static int s_pos_x,s_pos_y; static int d_pos_x,d_pos_y; static int osd_w,osd_h; @@ -70,12 +64,18 @@ "" }; +#ifdef USE_MP1E +void write_dxr3( rte_context* context, void* data, size_t size, void* user_data ) +{ + if( ioctl( fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts ) < 0 ) + printf( "VO: [dxr3] Unable to set PTS\n" ); + write( fd_video, data, size ); +} +#endif + static uint32_t init(uint32_t scr_width, uint32_t scr_height, uint32_t width, uint32_t height, uint32_t fullscreen, char *title, uint32_t format) { - int i; - char tmp; - fd_control = open( "/dev/em8300", O_WRONLY ); if( fd_control < 1 ) { @@ -120,283 +120,124 @@ img_format = format; v_width = width; v_height = height; + s_width = scr_width; + s_height = scr_height; spubuf = malloc(53220); /* 53220 bytes is the standardized max size of a subpic */ - picture_buf=NULL; if( format == IMGFMT_YV12 ) { -#ifdef USE_LIBAVCODEC - +#ifdef USE_MP1E int size; + enum rte_frame_rate frame_rate; - printf("VO: [dxr3] Format: YV12\n"); - - if(!avcodec_inited){ - avcodec_init(); - avcodec_register_all(); - avcodec_inited=1; - } - - /* find the mpeg1 video encoder */ - codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); - if (!codec) + if( !rte_init() ) { - printf( "VO: [dxr3] mpeg1 codec not found! Read DOCS/DXR3!\n"); - return -1; - } - - memset(&codec_context,0,sizeof(codec_context)); - codec_context.bit_rate=100000; // not used - codec_context.frame_rate=25*FRAME_RATE_BASE; - codec_context.gop_size=0; - codec_context.flags=CODEC_FLAG_QSCALE; - codec_context.quality=1; - codec_context.pix_fmt = PIX_FMT_YUV420P; + printf( "VO: [dxr3] Unable to initialize RTE!\n" ); + return -1; + } + if(width<=352 && height<=288){ - codec_context.width=352; - codec_context.height=288; + c_width=352; + c_height=288; } else if(width<=352 && height<=576){ - codec_context.width=352; - codec_context.height=576; + c_width=352; + c_height=576; } else if(width<=480 && height<=576){ - codec_context.width=480; - codec_context.height=576; + c_width=480; + c_height=576; } else if(width<=544 && height<=576){ - codec_context.width=544; - codec_context.height=576; + c_width=544; + c_height=576; } else { - codec_context.width=704; - codec_context.height=576; - } - s_width = codec_context.width; - s_height = codec_context.height;; - - - osd_w=scr_width; - d_pos_x=(codec_context.width-(int)scr_width)/2; - if(d_pos_x<0){ - s_pos_x=-d_pos_x;d_pos_x=0; - osd_w=codec_context.width; - } else s_pos_x=0; - - osd_h=scr_height; - d_pos_y=(codec_context.height-(int)scr_height)/2; - if(d_pos_y<0){ - s_pos_y=-d_pos_y;d_pos_y=0; - osd_h=codec_context.height; - } else s_pos_y=0; - - printf("VO: [dxr3] position mapping: %d;%d => %d;%d\n",s_pos_x,s_pos_y,d_pos_x,d_pos_y); - - /* open it */ - if (avcodec_open(&codec_context, codec) < 0) - { - printf( "VO: [dxr3] Could not open codec\n"); - return -1; + c_width=704; + c_height=576; } - - outbuf_size=10000+width*height; - outbuf = malloc(outbuf_size); - - size = codec_context.width*codec_context.height; - picture_buf = malloc((size * 3)/2); /* size for YUV 420 */ - - picture.data[0] = picture_buf; - picture.data[1] = picture.data[0] + size; - picture.data[2] = picture.data[1] + size / 4; - picture.linesize[0] = codec_context.width; - picture.linesize[1] = codec_context.width / 2; - picture.linesize[2] = codec_context.width / 2; - - return 0; -#endif - return -1; - } - else if(format==IMGFMT_BGR24) - { -#ifdef USE_LIBAVCODEC - int size = 0; - printf("VO: [dxr3] Format: BGR24\n"); - - if(!avcodec_inited) - { - avcodec_init(); - avcodec_register_all(); - avcodec_inited=1; - } - - /* find the mpeg1 video encoder */ - codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); - if (!codec) + + mp1e_context = rte_context_new( c_width, c_height, "mp1e", (void*)0xdeadbeef ); + rte_set_verbosity( mp1e_context, 0 ); + + if( !mp1e_context ) { - printf( "VO: [dxr3] mpeg1 codec not found! Read DOCS/DXR3!\n"); - return -1; - } - - outbuf_size=10000+width*height; - outbuf = malloc(outbuf_size); + printf( "VO: [dxr3] Unable to create context!\n" ); + return -1; + } - memset(&codec_context,0,sizeof(codec_context)); - codec_context.bit_rate=100000; - codec_context.frame_rate=25*FRAME_RATE_BASE; - codec_context.gop_size=0; - codec_context.flags=CODEC_FLAG_QSCALE; - codec_context.quality=1; - codec_context.pix_fmt = PIX_FMT_YUV420P; - - if(width<=352 && height<=288){ - codec_context.width=352; - codec_context.height=288; - } else - if(width<=352 && height<=576){ - codec_context.width=352; - codec_context.height=576; - } else - if(width<=480 && height<=576){ - codec_context.width=480; - codec_context.height=576; - } else - if(width<=544 && height<=576){ - codec_context.width=544; - codec_context.height=576; - } else { - codec_context.width=704; - codec_context.height=576; - } -/* s_width = codec_context.width = width; - s_height = codec_context.height = height; -*/ - osd_w=scr_width; - d_pos_x=(codec_context.width-(int)scr_width)/2; - if(d_pos_x<0){ - s_pos_x=-d_pos_x;d_pos_x=0; - osd_w=codec_context.width; - } else s_pos_x=0; - - osd_h=scr_height; - d_pos_y=(codec_context.height-(int)scr_height)/2; - if(d_pos_y<0){ - s_pos_y=-d_pos_y;d_pos_y=0; - osd_h=codec_context.height; - } else s_pos_y=0; - - printf("VO: [dxr3] position mapping: %d;%d => %d;%d\n",s_pos_x,s_pos_y,d_pos_x,d_pos_y); - - /* open it */ - if (avcodec_open(&codec_context, codec) < 0) + if( !rte_set_format( mp1e_context, "mpeg1" ) ) { - printf( "VO: [dxr3] could not open codec\n"); - return -1; - } + printf( "VO: [dxr3] Unable to set format\n" ); + return -1; + } - size = 10000+codec_context.width*codec_context.height; - picture_buf = malloc((size * 3)/2); - - picture.data[0] = picture_buf; - picture.data[1] = picture.data[0] + size; - picture.data[2] = picture.data[1] + size / 4; - picture.linesize[0] = codec_context.width; - picture.linesize[1] = codec_context.width / 2; - picture.linesize[2] = codec_context.width / 2; - return 0; -#endif - return -1; - } - else if(format==IMGFMT_YUY2) - { -#ifdef USE_LIBAVCODEC - int size = 0; - printf("VO: [dxr3] Format: YUY2\n"); + rte_set_mode( mp1e_context, RTE_VIDEO ); + mp1e_codec = rte_codec_set( mp1e_context, RTE_STREAM_VIDEO, 0, "mpeg1-video" ); - if(!avcodec_inited) - { - avcodec_init(); - avcodec_register_all(); - avcodec_inited=1; - } - - /* find the mpeg1 video encoder */ - codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); - if (!codec) + if( vo_fps < 24.0 ) frame_rate = RTE_RATE_1; + else if( vo_fps < 25.0 ) frame_rate = RTE_RATE_2; + else if( vo_fps < 29.97 ) frame_rate = RTE_RATE_3; + else if( vo_fps < 30.0 ) frame_rate = RTE_RATE_4; + else if( vo_fps < 50.0 ) frame_rate = RTE_RATE_5; + else if( vo_fps < 59.97 ) frame_rate = RTE_RATE_6; + else if( vo_fps < 60.0 ) frame_rate = RTE_RATE_7; + else frame_rate = RTE_RATE_8; + + if( !rte_set_video_parameters( mp1e_context, RTE_YUV420, mp1e_context->width, + mp1e_context->height, frame_rate, + mp1e_context->output_video_bits, "IIIP" ) ) + { + printf( "VO: [dxr3] Unable to set RTE context!\n" ); + rte_context_destroy( mp1e_context ); + return -1; + } + + rte_set_input( mp1e_context, RTE_VIDEO, RTE_PUSH, TRUE, NULL, NULL, NULL ); + rte_set_output( mp1e_context, write_dxr3, NULL, NULL ); + + if( !rte_init_context( mp1e_context ) ) { - printf( "VO: [dxr3] mpeg1 codec not found! Read DOCS/DXR3!\n"); + printf( "VO: [dxr3] Unable to init RTE context!\n" ); + rte_context_delete( mp1e_context ); return -1; - } - - outbuf_size=10000+width*height; - outbuf = malloc(outbuf_size); + } - memset(&codec_context,0,sizeof(codec_context)); - codec_context.bit_rate=100000; - codec_context.frame_rate=25*FRAME_RATE_BASE; - codec_context.gop_size=0; - codec_context.flags=CODEC_FLAG_QSCALE; - codec_context.quality=1; - codec_context.pix_fmt = PIX_FMT_YUV420P; - - if(width<=352 && height<=288){ - codec_context.width=352; - codec_context.height=288; - } else - if(width<=352 && height<=576){ - codec_context.width=352; - codec_context.height=576; - } else - if(width<=480 && height<=576){ - codec_context.width=480; - codec_context.height=576; - } else - if(width<=544 && height<=576){ - codec_context.width=544; - codec_context.height=576; - } else { - codec_context.width=704; - codec_context.height=576; - } - s_width = codec_context.width; - s_height = codec_context.height;; - /* FOR DEBUGGING ONLY!! */ - codec_context.width = width; - codec_context.height = height; osd_w=scr_width; - d_pos_x=(codec_context.width-(int)scr_width)/2; + d_pos_x=(c_width-(int)scr_width)/2; if(d_pos_x<0){ s_pos_x=-d_pos_x;d_pos_x=0; - osd_w=codec_context.width; + osd_w=c_width; } else s_pos_x=0; osd_h=scr_height; - d_pos_y=(codec_context.height-(int)scr_height)/2; + d_pos_y=(c_height-(int)scr_height)/2; if(d_pos_y<0){ s_pos_y=-d_pos_y;d_pos_y=0; - osd_h=codec_context.height; + osd_h=c_height; } else s_pos_y=0; printf("VO: [dxr3] position mapping: %d;%d => %d;%d\n",s_pos_x,s_pos_y,d_pos_x,d_pos_y); - - /* open it */ - if (avcodec_open(&codec_context, codec) < 0) + + size = c_width*c_height; + + picture_data[0] = malloc((size * 3)/2); + picture_data[1] = picture_data[0] + size; + picture_data[2] = picture_data[1] + size / 4; + picture_linesize[0] = c_width; + picture_linesize[1] = c_width / 2; + picture_linesize[2] = c_width / 2; + + if( !rte_start_encoding( mp1e_context ) ) { - printf( "VO: [dxr3] Could not open codec\n" ); - return -1; - } - - size = 10000+codec_context.width*codec_context.height; - picture_buf = malloc((size * 3)/2); - - picture.data[0] = picture_buf; - picture.data[1] = picture.data[0] + size; - picture.data[2] = picture.data[1] + size / 4; - picture.linesize[0] = codec_context.width; - picture.linesize[1] = codec_context.width / 2; - picture.linesize[2] = codec_context.width / 2; + printf( "VO: [dxr3] Unable to start mp1e encoding!\n" ); + uninit(); + return -1; + } + return 0; #endif - return -1; + return -1; } else if(format==IMGFMT_MPEGPES) { @@ -419,7 +260,6 @@ static void draw_osd(void) { -// vo_draw_text(osd_w,osd_h,draw_alpha); } static uint32_t draw_frame(uint8_t * src[]) @@ -428,120 +268,16 @@ { int data_left; vo_mpegpes_t *p=(vo_mpegpes_t *)src[0]; - unsigned char *data = p->data; + + if( ioctl( fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts ) < 0 ) + printf( "VO: [dxr3] Unable to set PTS\n" ); data_left = p->size; - if( ioctl( fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts ) < 0 ) - printf( "VO: [dxr3] Unable to set PTS in draw_frame\n" ); while( data_left ) data_left -= write( fd_video, &((unsigned char*)p->data)[p->size-data_left], data_left ); return 0; } -#ifdef USE_LIBAVCODEC - else if( img_format == IMGFMT_YV12 ) - { - printf("VO: [dxr3] ERROR: Uninplemented\n"); - } - else if( img_format == IMGFMT_BGR24 ) - { - int tmp_size, out_size; - int wrap, wrap3, x, y; - int r, g, b, R, G, B, h = v_height, w = v_width; - unsigned char *s, *Y, *U, *V; - - if(d_pos_x+w>picture.linesize[0]) w=picture.linesize[0]-d_pos_x; - if(d_pos_y+h>codec_context.height) h=codec_context.height-d_pos_y; - - Y = picture.data[0]+d_pos_x+(d_pos_y*picture.linesize[0]); - U = picture.data[1]+(d_pos_x/2)+((d_pos_y/2)*picture.linesize[1]); - V = picture.data[2]+(d_pos_x/2)+((d_pos_y/2)*picture.linesize[2]); - - //BGR24->YUV420P from ffmpeg, see ffmpeg.sourceforge.net for terms of license -#define SCALEBITS 8 -#define ONE_HALF (1 << (SCALEBITS - 1)) -#define FIX(x) ((int) ((x) * (1L<> SCALEBITS; - b = s[3]; - g = s[4]; - r = s[5]; - R += r; - G += g; - B += b; - Y[1] = (FIX(0.29900) * r + FIX(0.58700) * g + FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; - s += wrap3; - Y += wrap; - - b = s[0]; - g = s[1]; - r = s[2]; - R += r; - G += g; - B += b; - Y[0] = (FIX(0.29900) * r + FIX(0.58700) * g + FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; - b = s[3]; - g = s[4]; - r = s[5]; - R += r; - G += g; - B += b; - Y[1] = (FIX(0.29900) * r + FIX(0.58700) * g + FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; - U[0] = ((- FIX(0.16874) * R - FIX(0.33126) * G - FIX(0.50000) * B + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; - V[0] = ((FIX(0.50000) * R - FIX(0.41869) * G - FIX(0.08131) * B + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; - - U++; - V++; - s -= (wrap3-6); - Y -= (wrap-(3/2)); - } - s += wrap3; - Y += wrap; - } -#undef SCALEBITS -#undef ONE_HALF -#undef FIX(x) - //End of ffmpeg code, see ffmpeg.sourceforge.net for terms of license - if( ioctl( fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts ) < 0 ) - printf( "VO: [dxr3] Unable to set PTS in draw_frame\n" ); - tmp_size = out_size = avcodec_encode_video(&codec_context, outbuf, outbuf_size, &picture); - while( out_size ) - out_size -= write( fd_video, &outbuf[tmp_size-out_size], out_size ); - return 0; - } - else if( img_format == IMGFMT_YUY2 ) - { - int tmp_size, out_size; - int x, y, w = v_width, h = v_height; - - for( y = 0; y < h; y++ ) - { - for( x = 0; x < w; x++ ) - { - } - } - - if( ioctl( fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vo_pts ) < 0 ) - printf( "VO: [dxr3] Unable to set PTS in draw_frame\n" ); - tmp_size = out_size = avcodec_encode_video(&codec_context, outbuf, outbuf_size, &picture); - while( out_size ) - out_size -= write( fd_video, &outbuf[tmp_size-out_size], out_size ); - - return 0; - } -#endif printf( "VO: [dxr3] Error in draw_frame(...)\n" ); return -1; @@ -549,67 +285,61 @@ static void flip_page (void) { + mp1e_buffer.data = picture_data[0]; + mp1e_buffer.time = vo_pts/90000.0; + mp1e_buffer.user_data = NULL; + rte_push_video_buffer( mp1e_context, &mp1e_buffer ); } static uint32_t draw_slice( uint8_t *srcimg[], int stride[], int w, int h, int x0, int y0 ) { - int y, pts; + int y; unsigned char* s; unsigned char* d; - int data_left; - vo_mpegpes_t *p = (vo_mpegpes_t *)srcimg[0]; - + if( img_format == IMGFMT_YV12 ) - { -#ifdef USE_LIBAVCODEC - int out_size, tmp_size; + { +#ifdef USE_MP1E x0+=d_pos_x; y0+=d_pos_y; - if(x0+w>picture.linesize[0]) w=picture.linesize[0]-x0; // !! - if(y0+h>codec_context.height) h=codec_context.height-y0; + if(x0+w>picture_linesize[0]) w=picture_linesize[0]-x0; + if(y0+h>c_height) h=c_height-y0; // Y s=srcimg[0]+s_pos_x+s_pos_y*stride[0]; - d=picture.data[0]+x0+y0*picture.linesize[0]; + d=picture_data[0]+x0+y0*picture_linesize[0]; for( y = 0; y < h; y++) { - memcpy(d,s,w); - s+=stride[0]; - d+=picture.linesize[0]; + memcpy(d,s,w); + s+=stride[0]; + d+=picture_linesize[0]; } w/=2;h/=2;x0/=2;y0/=2; // U s=srcimg[1]+(s_pos_x/2)+(s_pos_y/2)*stride[1]; - d=picture.data[1]+x0+y0*picture.linesize[1]; + d=picture_data[1]+x0+y0*picture_linesize[1]; for( y = 0; y < h; y++) { memcpy(d,s,w); s+=stride[1]; - d+=picture.linesize[1]; + d+=picture_linesize[1]; } // V s=srcimg[2]+(s_pos_x/2)+(s_pos_y/2)*stride[2]; - d=picture.data[2]+x0+y0*picture.linesize[2]; + d=picture_data[2]+x0+y0*picture_linesize[2]; for(y=0;yRGB24, or BGR24->MPEGPES etc */ + int (*format_conversion)(int format, unsigned char* src[3], int stride[3] ); + /* If it needs software scaling */ + int (*scale_frame)(int format, unsigned char* src[3], int stride[3], int w, int h ); +} vo2_context_t; + // HACK typedef struct { int dummy; @@ -122,3 +127,78 @@ extern char *vo_subdevice; + +/* It's quite possible there'll be ALOT of these, so it's better to put + them at the end of the file to make it more readable */ + +// return true if surface is in fast system ram, false if slow (video?) memory +// USED for storing mpeg2 I/P frames only if it's fast enough +#define VO2CTRL_QUERY_SURFACE_FAST 0x101 + +// return true if surface is direct rendered, false if indirect (copied first) +// Note: it's usually same as VO2CTRL_GET_SURFACE_SPEED, except for some +// special cases, when video card does the copy from video ram (opengl...) +// USED for deciding external double buffering mode (using 2 surfaces) +#define VO2CTRL_QUERY_SURFACE_DIRECT 0x102 + +// Get the upper hardware/Driver limitation (used for double buffering) +#define VO2CTRL_GET_MAX_SURFACES 0x103 + +// Query support of a given video pixel format (use IMGFMT_ constants) +#define VO2CTRL_QUERY_FORMAT 0x111 + +// Query whether software and/or hardware scaling is supported by driver +#define VO2CTRL_QUERY_SWSCALE 0x121 +#define VO2CTRL_QUERY_HWSCALE 0x122 + +// Device configuration-options interface +// GET_OPTIONS should return a copy and not the original!! +// SET_OPTIONS takes only char **values +typedef struct +{ + int numoptions; /* Number of options for this device */ + char **options; /* List of optionnames + optionally option-mode + + Option Modes: (always preceeded by \t) + + 1. i.e. options[0]="Outdevice\t[5]" means the + option has 5 different choices, which are read + through options[optionnum+1 through optionnum+5] + i.e. options[1]="/dev/dev3" + + 2. options[2]="Flags\t[5,5]" means the option + has 5 different choices of which up to 5 may + be selected (at one time, like a multiple choice + listbox) + choices are specified like in mode 1 + + 3. options[3]="Buffersize\t{128-512} means the + option is a value in the range of 128-512 + */ + char **option_types;/* Option type: (\0 terminated strings) + "b" = byte (8-bits) + "s" = short (16-bits) + "l" = long (32-bits) + "i" = int + "ub" = unsigned byte (8-bits) + "us" = unsigned short (16-bits) + "ul" = unsigned long (32-bits) + "ui" = unsigned int + "s" = \0 terminated string + "c" = character + */ + char **values; /* Option value: + mode: form: + 1 use the int of the selected option (not the string) + 2 as mode 1 but a \t separated list of selected options + 3 option_type + */ +} vo2_devconfig_t; +#define VO2CTRL_GET_OPTIONS 0x131 +#define VO2CTRL_SET_OPTIONS 0x132 + +//Query the overlay mode (used for osd and sub) +#define VO2CTRL_QUERY_OVERLAY 0x141 + //Return values +#define VO2OVERLAY_SUPERIMPOSE 0x142 //Let libvo2 core superimpose it on the frame +#define VO2OVERLAY_SUBPICTURE 0x143 //The device wants it as a subpicture channel diff -Naur -x CVS -x .* main/libvo2/vo2_dxr3.c main-dxr3/libvo2/vo2_dxr3.c --- main/libvo2/vo2_dxr3.c Thu Jan 1 01:00:00 1970 +++ main-dxr3/libvo2/vo2_dxr3.c Tue Nov 27 21:44:52 2001 @@ -0,0 +1,184 @@ + +#include +#include + +#include "libvo2.h" +#include "img_format.h" + +// Driver info: +static vo2_info_t info = +{ + "DXR3/Hollywood Plus VO2 Device", + "dxr3", + "David Holm ", + "in development" +}; + +// Local, driver-dependent data: (do not use globals! -> reentrancy) +typedef struct +{ + int width, height, format; + int fd_control; + int fd_video; + int fd_spu; + unsigned char *spubuf; + vo2_devconfig_t config; + vo2_surface_t surface; +} priv_t; + +static priv_t dxr3; + +#include "vo2_def.h" + +// open hardware/lib, get capabilities +// this function will be called first, before any other control() or start() calls +// return: 1=success 0=failed +vo2_handle_t* vo2_init_dxr3() +{ + int ioval; + printf("VO2_DXR3: init()\n"); + /* fd_control is only opened when needed and must be closed before the end + of the function so that ao_dxr3 may use it as well */ + if( (dxr3.fd_control = open( "/dev/em8300", O_WRONLY )) < 0 ) + { + printf( "VO2_DXR3: unable to open /dev/em8300\n" ); + return 0; + } + if( (dxr3.fd_video = open( "/dev/em8300_mv", O_WRONLY )) < 0 ) + { + printf( "VO2_DXR3: unable to open /dev/em8300_mv\n" ); + return 0; + } + if( (dxr3.fd_spu = open( "/dev/em8300_sp", O_WRONLY )) < 0 ) + { + printf( "VO2_DXR3: unable to open /dev/em8300_sp\n" ); + return 0; + } + + ioval = EM8300_SPUMODE_OFF; + if( ioctl( dxr3.fd_control, EM8300_IOCTL_SET_SPUMODE, &ioval ) < 0 ) + { + printf( "VO2_DXR3: unable to set subpicture mode\n" ); + return 0; + } + + ioval = EM8300_PLAYMODE_PLAY; + if( ioctl( dxr3.fd_control, EM8300_IOCTL_SET_PLAYMODE, &ioval ) < 0 ) + printf( "VO2_DXR3: unable to set playmode\n" ); + + dxr3.spubuf = malloc( 53220 ); + + /* Yeah, I know you are anxious to see how the hell this is implemented + but hold your breath, I'll do it soon */ + dxr3.config.numoptions = 0; + dxr3.config.options = NULL; + dxr3.option_types = NULL; + dxr3.values = NULL; + + return new_handle(&dxr3); +} + +// control (get/set/query) device parameters +// for example: query supported pixel formats, en/disable double buffering, +// query hw/sw scaling capabilities, switch window/fullscreen, +// get best matching resolution for a given image size etc... +static int control(void *p, int cmd, void* param) +{ + switch( cmd ) + { + case VO2CTRL_QUERY_SURFACE_FAST: + case VO2CTRL_QUERY_SURFACE_DIRECT: + return VO2_FALSE; //Surface has to be pushed... + break; + case VO2CTRL_GET_MAX_SURFACES: + *((int*)param) = 1; + break; + case VO2CTRL_QUERY_FORMAT: + *((int*)param) = IMGFMT_MPEG12; + break; + case VO2CTRL_QUERY_SWSCALE: + case VO2CTRL_QUERY_HWSCALE: + return VO2_TRUE; + break; + case VO2CTRL_GET_OPTIONS: + vo2_devconfig_t returnconf; + returnconf.numoptions = 0; + (vo2_devconfig_t*)param = &vo2_devconfig_t; + break; + case VO2CTRL_SET_OPTIONS: + dxr3.config.values = (char**)*param; + break; + case VO2CTRL_QUERY_OVERLAY: + return VO2OVERLAY_SUBPICTURE; + break; /* yeah, I'm pedantic ;) */ + default: + return VO2_UNKNOWN; + } + + return VO2_UNKNOWN; +} + +// start drawing (set video mode, allocate image buffers etc.) +// w,h: requested surface size (actual size may be larger!!!) +// format: IMGFMT_* requested surface pixel format +// buffering: 0 - single temporary frame buffer (for draw_* stuff) +// 1 - single static buffer (for win32 direct rendering) +// 2 - 2 static + 1 temp buffer (for mpeg direct rendering) +// flags: various things, like fullscreen, sw/hw zoom and vidmode change +// return: 1=success 0=fail (fail if pixel format or buffering not supported) +static int start(void *p, int w,int h,int format,int buffering,int flags) +{ + + // open window / switch vidmode, set up surfaces etc... + printf("vo2_sample: start() %dx%d %s %d 0x%X\n",w,h,vo_format_name(format),buffering,flags); + dxr3.width = w; + dxr3.height = h; + dxr3.format = format; + + dxr3.surface.w = w; + dxr3.surface.h = h; + dxr3.surface.format = IMGFMT_MPEG12; + dxr3.surface.img[0] = malloc((w*h*3)/2); /* YUV420 Size */ + dxr3.surface.img[1] = dxr3.surface.img[0] + (w*h); + dxr3.surface.img[2] = dxr3.surface.img[1} + (w*h)/4; + dxr3.surface.stride[0] = w; + dxr3.surface.stride[1] = w/2; + dxr3.surface.stride[2] = dxr3.surface.stride[1]; + return 1; +} + +static int stop(void *p) +{ + // stop rendering, close device + printf("VO2_DXR3: stop()\n"); + delete dxr3.spubuf; + close( dxr3.fd_control ); + close( dxr3.fd_video ); + close( dxr3.fd_spu ); + return 1; +} + +// get destination surface (for direct rendering or generic draw_ functions) +// num: number of frame. 0 = temporary frame - can be dropped/modified +// 1-2 = static frames - should not be modified +// Note: mpeg will use 0,1,2 frames for B,Pf,Pb (or fallback to 0-only) +// win32 will use only 0 +static vo2_surface_t* get_surface(void *p, int num) +{ + printf("VO2_DXR3: get_surface(%d)\n",num); + return &dxr3.surface; +} + +static void flip_image(void *p, int num) +{ + // we can assume that num is valid (get_surface(num) will return non-NULL) + printf("VO2_DXR3: flip_image(%d)\n",num); + + // Direct rendering is not available with a dxr3 so we use push instead... + if( ioctl( dxr3.fd_video, EM8300_IOCTL_VIDEO_SETPS, &dxr3.surface.pts ) < 0 ) + printf( "VO2_DXR3: Unable to set frame pts\n" ); + write( dxr3.fd_video, dxr3.surface.img[0], dxr3.surface.w*dxr3.surface.h ); +} + + + diff -Naur -x CVS -x .* main/mplayer.c main-dxr3/mplayer.c --- main/mplayer.c Wed Nov 28 13:44:38 2001 +++ main-dxr3/mplayer.c Wed Nov 28 09:54:06 2001 @@ -1242,6 +1236,7 @@ } vo_pts=sh_video->timer*90000.0; + vo_fps=sh_video->fps; /*========================== PLAY AUDIO ============================*/ while(sh_audio){ --- main/configure Wed Nov 28 16:34:31 2001 +++ main-dxr3/configure Wed Nov 28 13:56:18 2001 @@ -150,6 +150,7 @@ --disable-alsa disable alsa sound support [autodetect] --disable-sunaudio disable Sun sound support [autodetect] --disable-mad disable mad audio support [autodetect] + --disable-mp1e disable mp1e codec support [autodetect] --disable-select disable using select() on OSS audio device [enable] Miscellaneous options: @@ -733,6 +733,8 @@ --disable-ossaudio) _ossaudio=no ;; --enable-mad) _mad=yes ;; --disable-mad) _mad=no ;; + --enable-mp1e) _mp1e=yes ;; + --disable-mp1e) _mp1e=no ;; --enable-vorbis) _vorbis=yes ;; --disable-vorbis) _vorbis=no ;; --enable-css) _css=yes ;; @@ -1978,9 +1969,9 @@ if test "$_mp1e" = auto ; then _mp1e=no cat > $TMPC << EOF -#include #include -#include +#include +//#include int main(void) { return 0; } EOF cc_check -lrte && _mp1e=yes @@ -1990,6 +1981,7 @@ _ld_mp1e='-lrte' else _def_mp1e='#undef USE_MP1E' + _ld_mp1e='' fi echores "$_mp1e" @@ -2521,7 +2506,6 @@ DS_LIB = $_ld_dshow AV_DEP = $_dep_libavcodec AV_LIB = $_ld_libavcodec -MP1E_DEP = $_dep_mp1e MP1E_LIB = $_ld_mp1e ARCH_LIB = $_ld_arch $_ld_iconv DIVX4LINUX = $_divx4linux