--- Makefile	2006-04-03 09:16:10.000000000 +0200
+++ Makefile	2006-04-04 01:58:44.000000000 +0200
@@ -129,6 +129,10 @@
               $(FONTCONFIG_LIB) \
               $(ENCA_LIB) \
 
+ifeq ($(LIBMPDVDNAV),yes)
+COMMON_LIBS += libmpdvdnav/libmpdvdnav.a
+endif
+
 CFLAGS = $(OPTFLAGS) -I. \
          $(CACA_INC) \
          $(CDPARANOIA_INC) \
@@ -194,6 +198,9 @@
 PARTS += libmpdvdkit2
 else
 endif
+ifeq ($(LIBMPDVDNAV),yes)
+PARTS += libmpdvdnav
+endif
 ifeq ($(GUI),yes)
 PARTS += Gui
 endif
@@ -253,6 +260,9 @@
 ifeq ($(DVDKIT2),yes)
 COMMON_DEPS += libmpdvdkit2/libmpdvdkit.a
 endif
+ifeq ($(LIBMPDVDNAV),yes)
+COMMON_DEPS += libmpdvdnav/libmpdvdnav.a
+endif
 
 ifeq ($(GUI),yes)
 COMMON_DEPS += Gui/libgui.a
@@ -274,6 +284,9 @@
 libmpdvdkit2/libmpdvdkit.a:
 	$(MAKE) -C libmpdvdkit2
 
+libmpdvdnav/libmpdvdnav.a:
+	$(MAKE) -C libmpdvdnav
+
 loader/libloader.a:
 	$(MAKE) -C loader
 
--- mplayer.c	2006-03-31 01:47:03.000000000 +0200
+++ mplayer.c	2006-04-04 01:33:20.000000000 +0200
@@ -64,8 +64,19 @@
 #include "codec-cfg.h"
 
 #ifdef USE_DVDNAV
+#ifdef USE_MPDVDNAV
+#include <libmpdemux/stream_dvdnav.h>
+
+int dvdnav_wait = 0;
+int dvdnav_still = 0;
+int dvdnav_decodeok = 0;
+int dvdnav_seek_counter = 0;
+int dvdnav_menu_visible = 0;
+int dvdnav_color_spu_flg = -1;
+#else
 #include <dvdnav.h>
 #endif
+#endif
 
 #ifdef USE_EDL
 #include "edl.h"
@@ -187,6 +198,9 @@
 
 #include "libmpcodecs/dec_audio.h"
 #include "libmpcodecs/dec_video.h"
+#ifdef USE_MPDVDNAV
+#include "libmpcodecs/vd_videostill.h"
+#endif
 #include "libmpcodecs/mp_image.h"
 #include "libmpcodecs/vf.h"
 #include "libmpcodecs/vd.h"
@@ -1763,6 +1777,11 @@
         if (vo_spudec && dvdsub_id >= 0) {
             char lang[3] = "\0\0\0";
             int code = 0;
+#ifdef USE_MPDVDNAV
+	    if(stream->type==STREAMTYPE_DVDNAV)
+	      code = dvdnav_lang_from_sid((dvdnav_priv_t*)(stream->priv), dvdsub_id);
+	    else
+#endif
             code = dvd_lang_from_sid(stream, dvdsub_id);
             if (code) {
                 lang[0] = code >> 8;
@@ -1834,6 +1853,12 @@
                 spudec_reset(vo_spudec);
             }
 #endif
+#ifdef USE_MPDVDNAV
+            if (vo_spudec && stream->type == STREAMTYPE_DVDNAV) {
+                d_dvdsub->id = dvdsub_id;
+                spudec_reset(vo_spudec);
+            }
+#endif
 #ifdef HAVE_OGGVORBIS
             if (demuxer->type == DEMUXER_TYPE_OGG)
                 d_dvdsub->id = demux_ogg_sub_id(demuxer, dvdsub_id);
@@ -1877,6 +1902,13 @@
         spudec_reset(vo_spudec);
     }
 #endif
+#ifdef USE_MPDVDNAV
+    if (vo_spudec && stream->type == STREAMTYPE_DVDNAV && dvdsub_id < 0 && reset_spu) {
+        dvdsub_id = -2;
+        d_dvdsub->id = dvdsub_id;
+        spudec_reset(vo_spudec);
+    }
+#endif
 
     return 1;
 }
@@ -2805,6 +2837,16 @@
 
 #ifdef USE_DVDNAV
   if (stream->type==STREAMTYPE_DVDNAV) stream_cache_size=0;	// must disable caching...
+#ifdef USE_MPDVDNAV
+if(stream->type==STREAMTYPE_DVDNAV){
+  current_module="dvd lang->id";
+  if(audio_id==-1) audio_id=dvd_aid_from_lang(stream,audio_lang);
+  if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=dvd_sid_from_lang(stream,dvdsub_lang);
+  global_sub_indices[SUB_SOURCE_DEMUX] = global_sub_size; // the global # of the first demux-specific sub.
+  global_sub_size += dvdnav_number_of_subs((dvdnav_priv_t*)(stream->priv));
+  current_module=NULL;
+}
+#endif
 #endif
 
 // CACHE2: initial prefill: 20%  later: 5%  (should be set by -cacheopts)
@@ -2822,7 +2864,11 @@
 //============ Open DEMUXERS --- DETECT file type =======================
 current_module="demux_open";
 
-demuxer=demux_open(stream,file_format,audio_id,video_id,dvdsub_id,filename);
+#ifdef USE_MPDVDNAV
+if (stream->type==STREAMTYPE_DVDNAV)
+    demuxer=demux_open(stream,file_format,audio_id,video_id,dvdsub_id,filename,0,0,1); else
+#endif
+demuxer=demux_open(stream,file_format,audio_id,video_id,dvdsub_id,filename,0,0,0);
 
 // HACK to get MOV Reference Files working
 
@@ -3036,6 +3082,9 @@
 //================== Read SUBTITLES (DVD & TEXT) ==========================
 if(vo_spudec==NULL && sh_video &&
      (stream->type==STREAMTYPE_DVD || demuxer->type==DEMUXER_TYPE_MATROSKA ||
+#ifdef USE_MPDVDNAV
+	stream->type==STREAMTYPE_DVDNAV ||
+#endif
       d_dvdsub->id >= 0)){
 
 if (spudec_ifo) {
@@ -3051,6 +3100,7 @@
   vo_spudec=spudec_new_scaled(dvdnav_stream_get_palette((dvdnav_priv_t*)(stream->priv)),
 			    sh_video->disp_w, sh_video->disp_h);
 }
+if (dvdsub_id>=0 && stream->type==STREAMTYPE_DVDNAV) dvdnav_go_spu=2;
 #endif
 
 #ifdef USE_DVDREAD
@@ -3430,6 +3480,11 @@
 #ifdef USE_DVDNAV
 if (stream->type==STREAMTYPE_DVDNAV) {
   dvdnav_stream_fullstart((dvdnav_priv_t *)stream->priv);
+#ifdef USE_MPDVDNAV
+  dvdnav_set_language((dvdnav_priv_t *)stream->priv, dvdsub_lang, audio_lang, NULL);
+  clearsmpi(); /* clear correct still image */
+
+#endif
 }
 #endif
 
@@ -3515,6 +3570,9 @@
   vo_pts=sh_video->timer*90000.0;
   vo_fps=sh_video->fps;
 
+#ifdef USE_MPDVDNAV
+if (stream->type==STREAMTYPE_DVDNAV && dvdnav_still) frame_time_remaining=0;
+#endif
   if(!frame_time_remaining){
     //--------------------  Decode a frame: -----------------------
     vdecode_time=video_time_usage;
@@ -3523,8 +3581,19 @@
 	int in_size;
 	// get it!
 	current_module="video_read_frame";
+#ifdef USE_MPDVDNAV
+//printf("\t\t\t\t\t\t\t\tAV_delay: %8.3f < %8.3f vpts: %8.3f \n",AV_delay,next_frame_time*-1.1f,sh_video->pts);
+//	if (AV_delay<next_frame_time*-1.1f && d_audio && d_audio->pts>0.0 && 0) {in_size=-1; sh_video->pts-=next_frame_time; sh_video->timer-=frame_time; /*printf("duplicate frame\n");*/} else 
+        in_size=video_read_frame(sh_video,&next_frame_time,&start,force_fps);
+	if (stream->type==STREAMTYPE_DVDNAV) { if (dvdnav_reallyeof((dvdnav_priv_t*)(stream->priv))) {eof=1; break;}
+	  if (in_size<0) {sh_video->num_frames++; sh_video->num_frames_decoded++; sh_video->pts+=next_frame_time;}
+	  sh_video->config_lock=1;
+	  } else {if(in_size<0) {eof=1; break;}} 
+//printf("\t\t\t\t\t\t\t\tAV_delay: %8.3f < %8.3f vpts: %8.3f \n",AV_delay,next_frame_time*-1.1f,sh_video->pts);
+#else
         in_size=video_read_frame(sh_video,&next_frame_time,&start,force_fps);
 	if(in_size<0){ eof=1; break; }
+#endif
 	if(in_size>max_framesize) max_framesize=in_size; // stats
 	sh_video->timer+=frame_time;
 	if(sh_audio) sh_audio->delay-=frame_time;
@@ -3553,6 +3622,24 @@
 	// decode:
 	current_module="decode_video";
 //	printf("Decode! %p  %d  \n",start,in_size);
+#ifdef USE_MPDVDNAV
+	if (stream->type==STREAMTYPE_DVDNAV)
+	    {
+	    dvdnav_decodeok=0;
+	    blit_frame=decode_video_still(sh_video,start,in_size,drop_frame,MP_NOPTS_VALUE,1);
+//printf("decode_video_still: blit_frame: %i size: %d <<<<<<<<--------------------\n",blit_frame,in_size);
+	    if (!blit_frame && in_size>0)
+		{
+		if (vd_mpeg2_reset(sh_video,0)) {
+		blit_frame=decode_video_still(sh_video,start,in_size,drop_frame,MP_NOPTS_VALUE,1);
+		/*printf("mpeg2 reset %d \n",blit_frame);*/ }
+//		printf("decode_video_still: blit_frame: %i size: %d !!!!!!!!--------------------\n",blit_frame,in_size);
+		}
+//	    if (blit_frame && in_size<0 && sh_video && sh_audio) sh_video->pts=d_video->pts=d_audio->pts;
+	    if (blit_frame && in_size>0) dvdnav_decodeok=1;
+	    }
+	    else
+#endif
 	blit_frame=decode_video(sh_video,start,in_size,drop_frame, MP_NOPTS_VALUE);
 	break;
     }
@@ -3567,6 +3654,8 @@
     }
 
   }
+//if (stream->type==STREAMTYPE_DVDNAV && d_video->eof || d_audio->eof) {d_video->eof=0; d_audio->eof=0; stream->eof=0;}
+//printf("decode frame... %5.3f ****\n",frame_time);
 
 // ==========================================================================
     
@@ -3935,9 +4024,11 @@
 }
 
 #ifdef USE_DVDNAV
+#ifndef USE_MPDVDNAV
 if (stream->type==STREAMTYPE_DVDNAV && dvd_nav_still)
     dvdnav_stream_sleeping((dvdnav_priv_t*)stream->priv);
 #endif
+#endif
 
 //================= EDL =========================================
 
@@ -3967,6 +4058,353 @@
  }
 #endif
 
+#ifdef USE_MPDVDNAV
+current_module="dvdnav_event";
+if (stream->type==STREAMTYPE_DVDNAV) {
+if (((dvdnav_priv_t*)(stream->priv))->event.eventflag.stop) { 
+  eof=1; 
+  mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_MPDVDNAV_StopEvent); } 
+  else {
+int nav_menu = 0;
+
+if (demuxer->audio->sh && !sh_audio)	// Hot init audio
+    {
+    d_audio=demuxer->audio;
+    sh_audio=d_audio->sh;
+    sh_audio->ds=d_audio;
+
+    current_module="hot init_audio_codec";
+    if(!init_best_audio_codec(sh_audio,audio_codec_list,audio_fm_list)){
+      sh_audio=d_audio->sh=NULL; // failed to init :(
+      } else
+      inited_flags|=INITED_ACODEC;
+//================ SETUP AUDIO ==========================
+
+    if(sh_audio){
+    //const ao_info_t *info=audio_out->info;
+      current_module="hot af_preinit";
+      ao_data.samplerate=force_srate;
+      ao_data.channels=0;
+      ao_data.format=audio_output_format;
+#if 1
+      // first init to detect best values
+      if(!preinit_audio_filters(sh_audio,
+	    // input:
+            (int)(sh_audio->samplerate*playback_speed),
+    	    sh_audio->channels, sh_audio->sample_format,
+	    // output:
+	    &ao_data.samplerate, &ao_data.channels, &ao_data.format)){
+          mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_AudioFilterChainPreinitError);
+          exit_player(MSGTR_Exit_error);
+      }
+#endif  
+    current_module="hot ao2_init";
+      if(!(audio_out=init_best_audio_out(audio_driver_list,
+	  0, // plugin flag
+          ao_data.samplerate,
+	  ao_data.channels,
+      ao_data.format,0))){
+        // FAILED:
+	mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CannotInitAO);
+        uninit_player(INITED_ACODEC); // close codec
+	sh_audio=d_audio->sh=NULL; // -> nosound
+      } else {
+	// SUCCESS:
+        inited_flags|=INITED_AO;
+	mp_msg(MSGT_CPLAYER,MSGL_INFO,"AO: [%s] %dHz %dch %s (%d bytes per sample)\n",
+          audio_out->info->short_name,
+	  ao_data.samplerate, ao_data.channels,
+          af_fmt2str_short(ao_data.format),
+	  af_fmt2bits(ao_data.format)/8 );
+        mp_msg(MSGT_CPLAYER,MSGL_V,"AO: Description: %s\nAO: Author: %s\n",
+	  audio_out->info->name, audio_out->info->author);
+        if(strlen(audio_out->info->comment) > 0)
+	  mp_msg(MSGT_CPLAYER,MSGL_V,"AO: Comment: %s\n", audio_out->info->comment);
+        // init audio filters:
+#if 1
+        current_module="hot af_init";
+	if(!build_afilter_chain(sh_audio, &ao_data)) {
+          mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_NoMatchingFilter);
+//      mp_msg(MSGT_CPLAYER,MSGL_ERR,"Couldn't find matching filter / ao format! -> NOSOUND\n");
+//      uninit_player(INITED_ACODEC|INITED_AO); // close codec & ao
+//      sh_audio=d_audio->sh=NULL; // -> nosound
+	}
+#endif
+    }
+      mixer.audio_out = audio_out;
+      mixer.volstep = volstep;
+    }
+}
+
+if (!sh_audio) {demuxer->audio->id=-1; }	// force hot add audio
+if (dvdnav_seek_counter && vd_decode_mp_preserve()) dvdnav_seek_counter=1;
+
+if (((dvdnav_priv_t*)(stream->priv))->event.eventflag.wait)
+    {
+    mp_msg(MSGT_CPLAYER,MSGL_V,MSGTR_MPDVDNAV_WaitEvent);
+    }
+if (((dvdnav_priv_t*)(stream->priv))->event.eventflag.still_frame)
+    {
+    mp_msg(MSGT_CPLAYER,MSGL_V,MSGTR_MPDVDNAV_StillFrameEvent);
+    ds_free_packs(demuxer->audio);
+    ds_free_packs(demuxer->video);
+    if (dvdnav_decodeok) dvdnav_seek_counter=1;
+//    if (dvdnav_decodeok) ((dvdnav_priv_t*)(stream->priv))->stillcounter=DVDNAV_MAX_STILL_FRAME;
+    dvdnav_still=1;				// still mode on
+    }
+if (((dvdnav_priv_t*)(stream->priv))->event.eventflag.vts_change)
+    {
+    dvdnav_still=0;				// still mode off
+    mp_msg(MSGT_CPLAYER,MSGL_V,MSGTR_MPDVDNAV_VtsChangeEvent);
+    if (((dvdnav_priv_t*)(stream->priv))->vts_domain) {
+        audio_id=((dvdnav_priv_t*)(stream->priv))->alang;		// set new audio id
+    	if (((dvdnav_priv_t*)(stream->priv))->slang==128) {
+	  dvdsub_id=-2; d_dvdsub->id = dvdsub_id; }
+	  else {dvdsub_id=((dvdnav_priv_t*)(stream->priv))->slang; d_dvdsub->id = dvdsub_id;} }		// set new sub id
+    dvdnav_seek_counter=5;
+#ifdef HAVE_NEW_GUI
+    if ( use_gui ) guiGetEvent( guiSetStream,(char *)stream );
+#endif
+    }
+if (((dvdnav_priv_t*)(stream->priv))->event.eventflag.cell_change)
+    {
+    dvdnav_still=0;				// still mode off
+    mp_msg(MSGT_CPLAYER,MSGL_V,MSGTR_MPDVDNAV_CellChangeEvent);
+
+    if (!(((dvdnav_priv_t*)(stream->priv))->vts_domain)) {
+	if (((dvdnav_priv_t*)(stream->priv))->event.cell_really_change) dvdnav_seek_counter=5;
+	} else {
+	if (((dvdnav_priv_t*)(stream->priv))->lasttitle!=((dvdnav_priv_t*)(stream->priv))->title) {
+	  dvdnav_seek_counter=2;
+	  audio_id=((dvdnav_priv_t*)(stream->priv))->alang;		// set new audio id
+    	  if (((dvdnav_priv_t*)(stream->priv))->slang==128) {
+	  dvdsub_id=-2;  d_dvdsub->id = dvdsub_id; }
+	  else {dvdsub_id=((dvdnav_priv_t*)(stream->priv))->slang; d_dvdsub->id = dvdsub_id;} }		// set new sub id
+	}
+    ((dvdnav_priv_t*)(stream->priv))->lasttitle=((dvdnav_priv_t*)(stream->priv))->title;
+    ((dvdnav_priv_t*)(stream->priv))->lastpart=((dvdnav_priv_t*)(stream->priv))->part;
+    ((dvdnav_priv_t*)(stream->priv))->old_vts_domain=((dvdnav_priv_t*)(stream->priv))->vts_domain;
+
+
+    nav_menu=1;
+#ifdef HAVE_NEW_GUI
+    if ( use_gui ) guiGetEvent( guiSetStream,(char *)stream );
+#endif
+    }
+
+if (((dvdnav_priv_t*)(stream->priv))->event.eventflag.spu_clut_change)
+    {
+    mp_msg(MSGT_CPLAYER,MSGL_V,MSGTR_MPDVDNAV_SpuClutChangeEvent);
+    if (vo_spudec) {
+	spudec_update_palette(vo_spudec, ((dvdnav_priv_t*)(stream->priv))->event.spu_clut);
+	if(!((dvdnav_priv_t*)(stream->priv))->vts_domain && (dvdnav_menutype==DVDNAV_MENUTYPE_SPU || dvdnav_menutype==DVDNAV_MENUTYPE_SPU_BOX)) {
+	    spudec_dvdnav_palette(vo_spudec,((dvdnav_priv_t*)(stream->priv))->event.spu_palette); 
+    	    vo_osd_changed(OSDTYPE_SPU); }
+       if (((dvdnav_priv_t*)(stream->priv))->vts_domain) spudec_reset(vo_spudec);
+	}
+    nav_menu=1;
+    }
+if (((dvdnav_priv_t*)(stream->priv))->event.eventflag.highlight)
+    {
+    mp_msg(MSGT_CPLAYER,MSGL_V,MSGTR_MPDVDNAV_HighlightEvent);
+// dvdnav menu button update
+    nav_menu=1;
+    }
+if (((dvdnav_priv_t*)(stream->priv))->event.eventflag.nav_packet)
+    {
+    mp_msg(MSGT_CPLAYER,MSGL_DBG2,MSGTR_MPDVDNAV_NavPacketEvent);
+    if (!(((dvdnav_priv_t*)(stream->priv))->vts_domain)) nav_menu=1;
+    }
+
+((dvdnav_priv_t*)(stream->priv))->lasttitle=((dvdnav_priv_t*)(stream->priv))->title;
+((dvdnav_priv_t*)(stream->priv))->lastpart=((dvdnav_priv_t*)(stream->priv))->part;
+((dvdnav_priv_t*)(stream->priv))->old_vts_domain=((dvdnav_priv_t*)(stream->priv))->vts_domain;
+d_video->eof=0;
+d_audio->eof=0;
+stream->eof=0;
+demuxer->stream->eof=0;
+demuxer->audio->eof=0;
+demuxer->video->eof=0;
+
+// dvdnav event clear
+dvdnav_event_clear((dvdnav_priv_t*)(stream->priv));
+
+if (dvdnav_menu_visible && dvdnav_force_menu) {
+    if (!vo_spudec || !spudec_visible(vo_spudec)) {
+	dvdnav_highlight_event_t highlight;
+	dvdnav_get_highlight((dvdnav_priv_t*)(stream->priv),&highlight);
+	dvdnav_box_area(highlight.sx,highlight.sy,highlight.ex,highlight.ey,1,0x7f,0x7f); /* set box button area & on */
+	vo_osd_changed(OSDTYPE_DVDNAV);
+	} else {
+	dvdnav_box_area(0,0,0,0,0,0x00,0x00);
+	vo_osd_changed(OSDTYPE_DVDNAV);
+	dvdnav_menu_visible=0;
+	}
+    }
+if (nav_menu)
+    {
+    if (dvdnav_color_spu_flg==-1) {
+      dvdnav_color_spu_flg=0;
+      if (dvdnav_color_spu && video_out) {
+	if (!dvdnav_color_spu_flg && video_out->control(VOCTRL_YUVSPU_SUPPORT,NULL)==VO_TRUE) dvdnav_color_spu_flg=DVDNAV_SPU_YUV;
+	if (!dvdnav_color_spu_flg && video_out->control(VOCTRL_YUYSPU_SUPPORT,NULL)==VO_TRUE) dvdnav_color_spu_flg=DVDNAV_SPU_YUY;
+	if (!dvdnav_color_spu_flg && video_out->control(VOCTRL_RGBSPU_SUPPORT,NULL)==VO_TRUE) dvdnav_color_spu_flg=DVDNAV_SPU_RGB;
+	if (!dvdnav_color_spu_flg && video_out->control(VOCTRL_BGRSPU_SUPPORT,NULL)==VO_TRUE) dvdnav_color_spu_flg=DVDNAV_SPU_BGR;
+	if (!dvdnav_color_spu_flg) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_MPDVDNAV_NoColorSpu);
+	}
+      }
+    dvdnav_menu_visible=0;
+    if (!(((dvdnav_priv_t*)(stream->priv))->vts_domain)) {
+// vts0 - set menu button
+	dvdnav_highlight_event_t highlight;
+	dvdnav_get_highlight((dvdnav_priv_t*)(stream->priv),&highlight);	/* get spu botton area & palette */
+	if (vo_spudec && (dvdnav_menutype==DVDNAV_MENUTYPE_SPU || dvdnav_menutype==DVDNAV_MENUTYPE_SPU_BOX)) {
+	    if(d_dvdsub->id!=((dvdnav_priv_t*)(stream->priv))->menu_sid) {d_dvdsub->id=((dvdnav_priv_t*)(stream->priv))->menu_sid; spudec_reset(vo_spudec); }
+	    spudec_dvdnav_mode(vo_spudec, 1, dvdnav_color_spu_flg);	/* spu menu button on */
+	    spudec_dvdnav_area(vo_spudec,highlight.sx,highlight.sy,highlight.ex,highlight.ey,highlight.palette); /* set spu button area & palette */
+	    vo_osd_changed(OSDTYPE_SPU); }
+	if (dvdnav_menutype==DVDNAV_MENUTYPE_BOX || dvdnav_menutype==DVDNAV_MENUTYPE_SPU_BOX) {
+	    dvdnav_box_area(highlight.sx,highlight.sy,highlight.ex,highlight.ey,1,0x7f,0x7f); /* set box button area & on */
+	    vo_osd_changed(OSDTYPE_DVDNAV); }
+	if (dvdnav_menutype==DVDNAV_MENUTYPE_SPU && highlight.buttonN) dvdnav_menu_visible=1;
+	} else {
+// reset spu info
+        global_sub_size = 0;
+        { int i; for (i = 0; i < SUB_SOURCES; i++) global_sub_indices[i] = -1; }
+//        global_sub_quiet_osd_hack = 1;
+        global_sub_indices[SUB_SOURCE_DEMUX] = global_sub_size; // the global # of the first demux-specific sub.
+        global_sub_size += dvdnav_number_of_subs((dvdnav_priv_t*)(stream->priv));
+        if (dvdnav_menutype==DVDNAV_MENUTYPE_BOX || dvdnav_menutype==DVDNAV_MENUTYPE_SPU_BOX) {
+	    dvdnav_box_area(0,0,0,0,0,0x00,0x00);	/* nav box button off */
+	    vo_osd_changed(OSDTYPE_DVDNAV); }
+	spudec_dvdnav_mode(vo_spudec, 0, 0);	/* spu menu button off */
+	spudec_reset(vo_spudec);
+	}
+    }
+//if (nav_demux_seek && (!((dvdnav_priv_t*)(stream->priv))->stillok || !dvdnav_still))
+if (dvdnav_seek_counter && (!((dvdnav_priv_t*)(stream->priv))->stillok))
+    {
+//printf("seek couter: %d \n",dvdnav_seek_counter);
+//printf("demux seek: %i \n",blit_frame);
+    if (((dvdnav_priv_t*)(stream->priv))->aspect!=((dvdnav_priv_t*)(stream->priv))->lastaspect && sh_video)
+      {
+	switch (((dvdnav_priv_t*)(stream->priv))->aspect) {	/* set current ascpet */
+    	    case 0 : { // 4:3
+#ifdef USE_MPDVDNAV_TRACE
+	    if (dvdnav_trace) mp_msg(MSGT_CPLAYER,MSGL_INFO, "dvdnav: set aspect 4:3\n");
+#endif
+    		movie_aspect = (float) 4 / 3;
+    		mpcodecs_config_vo (sh_video, sh_video->disp_w, sh_video->disp_h, 0);
+    		break; }
+    	    case 3 :   // FIXME: 16:9???
+    	    case 2 : { // 16:9
+#ifdef USE_MPDVDNAV_TRACE
+	    if (dvdnav_trace) mp_msg(MSGT_CPLAYER,MSGL_INFO, "dvdnav: set aspect 16:9\n");
+#endif
+    		movie_aspect = (float) 16 / 9;
+    		mpcodecs_config_vo (sh_video, sh_video->disp_w, sh_video->disp_h, 0);
+    		break; } 
+	    default: {
+#ifdef USE_MPDVDNAV_TRACE
+	    if (dvdnav_trace) mp_msg(MSGT_CPLAYER,MSGL_INFO, "dvdnav: unknow aspect %i\n",((dvdnav_priv_t*)(stream->priv))->aspect);
+#endif
+		break; }}
+	((dvdnav_priv_t*)(stream->priv))->lastaspect=((dvdnav_priv_t*)(stream->priv))->aspect;
+	}
+
+//    if (dvdnav_seek_counter) dvdnav_seek_counter--;
+    if (sh_audio) {
+    audio_id=((dvdnav_priv_t*)(stream->priv))->alang;
+    int v = demuxer_switch_audio(demuxer, audio_id);} // switch audio channel
+//	if(sh_video) sh_video->pts=d_video->pts;
+//    ds_free_packs(demuxer->video);
+    rel_seek_secs = 0.00;
+    abs_seek_pos = 0;
+    if(sh_video) sh_video->pts=0.0f;
+    ((dvdnav_priv_t*)(stream->priv))->lockseek=1;
+    if(demux_seek(demuxer,rel_seek_secs,0.0,abs_seek_pos)){	// demuxer reset???
+	rel_seek_secs = 0.00;
+        abs_seek_pos = 0;
+    	if(sh_video){
+    	    current_module="seek_video_reset";
+//	    vd_mpeg2_reset(sh_video,0);
+    	    resync_video_stream(sh_video);
+    	    if(vo_config_count) video_out->control(VOCTRL_RESET,NULL); 
+	    sh_video->pts=0.0f;
+	    sh_video->num_frames=0; 
+	    sh_video->num_frames_decoded=0;
+	    sh_video->timer=0.0f;
+	    sh_video->stream_delay=0.0f;
+	    frame_time_remaining=0;
+	    audio_delay=0.0f;
+	    sh_video->timer=0;
+	    audio_delay += sh_video->stream_delay;
+	    }
+    	if(sh_audio){
+	    audio_delay -= sh_audio->stream_delay;
+	    sh_audio->delay=-audio_delay;
+    	    current_module="seek_audio_reset";
+    	    audio_out->reset(); 
+    	    resync_audio_stream(sh_audio);
+	    } // stop audio, throwing away buffered data
+    	if(vo_spudec) spudec_reset(vo_spudec);
+	} 
+    
+    current_module="demuxer_update_time_pts";
+    if (((dvdnav_priv_t*)(stream->priv))->vts_domain) {
+	demuxer_update_time_pts(demuxer, ((dvdnav_priv_t*)(stream->priv))->final_pts, ((dvdnav_priv_t*)(stream->priv))->tlen*2048);
+	} else {
+	demuxer_update_time_pts(demuxer, 0.0, 0);
+	}
+    ((dvdnav_priv_t*)(stream->priv))->lockseek=0;
+    }
+if (dvdnav_seek_counter) dvdnav_seek_counter--;
+#ifdef HAVE_NEW_GUI
+if (!(((dvdnav_priv_t*)(stream->priv))->vts_domain) && sh_video)
+    {
+    dvdnav_window_orig_width=sh_video->disp_w;		/* set original video window size */
+    dvdnav_window_orig_height=sh_video->disp_h;		/* required on calculate mouse position */
+    dvdnav_mouse((dvdnav_priv_t*)(stream->priv));	/* process mouse positon: set menu button */
+    }
+#endif
+// play to new title
+if (dvdnav_go_title>0)
+    {
+    dvdnav_title_play((dvdnav_t*)((dvdnav_priv_t*)(stream->priv))->dvdnav, dvdnav_go_title);
+    dvdnav_go_title=dvdnav_go_part=dvdnav_go_menu=dvdnav_go_audio=dvdnav_go_spu=0;
+    }
+// play to new chapter
+if (dvdnav_go_part>0)
+    {
+    dvdnav_part_play((dvdnav_t*)((dvdnav_priv_t*)(stream->priv))->dvdnav, ((dvdnav_priv_t*)(stream->priv))->title, dvdnav_go_part);
+    dvdnav_go_title=dvdnav_go_part=dvdnav_go_menu=dvdnav_go_audio=dvdnav_go_spu=0;
+    }
+// go main DVD menu
+if (dvdnav_go_menu>0)
+    {
+    dvdnav_menu_call((dvdnav_t*)((dvdnav_priv_t*)(stream->priv))->dvdnav,DVD_MENU_Root);
+    dvdnav_go_title=dvdnav_go_part=dvdnav_go_menu=dvdnav_go_audio=dvdnav_go_spu=0;
+    }
+if (dvdnav_go_menu_force)
+    {
+    dvdnav_menu_force((dvdnav_priv_t*)(stream->priv));	/* go main menu with skip intro */
+    dvdnav_go_title=dvdnav_go_part=dvdnav_go_menu=dvdnav_go_menu_force=dvdnav_go_audio=dvdnav_go_spu=0;
+    }
+// switch audio channel
+if (dvdnav_go_audio)
+    {
+    if (sh_audio) demuxer_switch_audio(demuxer, audio_id); 
+    dvdnav_go_audio=0;
+    }
+// switch spu subtitle
+if (dvdnav_go_spu)
+    {
+    d_dvdsub->id = dvdsub_id;
+    if (vo_spudec) { spudec_reset(vo_spudec); dvdnav_go_spu--; }
+    }
+} }
+#endif
+
 //================= Keyboard events, SEEKing ====================
 
   current_module="key_events";
@@ -4456,6 +4894,7 @@
           /* be silent about this one */
                 break;
           }
+#ifndef USE_MPDVDNAV
       case DVDNAV_HIGHLIGHT: {
           dvdnav_highlight_event_t *hevent = (dvdnav_highlight_event_t*)(dvdnav_event->details);
           if (!hevent) {
@@ -4494,6 +4933,7 @@
             usec_sleep(1000); /* 1ms */
           }
           dvdnav_stream_sleep(dvdnav_priv,still_event->length);
+//    	  dvdnav_still_skip(dvdnav_priv->dvdnav); // don't let dvdnav stall on this image
         break;
         }
       case DVDNAV_STOP: {
@@ -4559,6 +4999,7 @@
                 d_audio->id=dvdsub_id=aid_temp;
                 if(sh_audio) resync_audio_stream(sh_audio);
         }
+        if(sh_audio) resync_audio_stream(sh_audio);
 
         break;
       }
@@ -4603,8 +5044,8 @@
         mp_msg(MSGT_FIXME, MSGL_FIXME, MSGTR_DvdnavNavSeekDone);
         break;
         }
+#endif
       }
-
       // free the dvdnav event
       free(dvdnav_event->details);
       free(dvdnav_event);
@@ -4612,10 +5053,22 @@
     }
     case MP_CMD_DVDNAV: {
       dvdnav_priv_t * dvdnav_priv=(dvdnav_priv_t*)stream->priv;
-
       /* ignore these events if we're not in dvd_nav mode */
       if (stream->type != STREAMTYPE_DVDNAV) break;
-
+#ifdef USE_MPDVDNAV
+      switch (cmd->args[0].v.i) {
+        case MP_CMD_DVDNAV_UP:
+        case MP_CMD_DVDNAV_DOWN:
+        case MP_CMD_DVDNAV_LEFT:
+        case MP_CMD_DVDNAV_RIGHT:
+        case MP_CMD_DVDNAV_MENU:
+        case MP_CMD_DVDNAV_SELECT:
+	  dvdnav_menu_action(dvdnav_priv, cmd->args[0].v.i);
+	  break;
+        default:
+//          mp_msg(MSGT_CPLAYER, MSGL_V, "Weird DVD Nav cmd %d\n",cmd->args[0].v.i);
+          break; }
+#else
       switch (cmd->args[0].v.i) {
         case MP_CMD_DVDNAV_UP:
           dvdnav_upper_button_select(dvdnav_priv->dvdnav);
@@ -4640,6 +5093,7 @@
           mp_msg(MSGT_CPLAYER, MSGL_V, "Weird DVD Nav cmd %d\n",cmd->args[0].v.i);
           break;
       }
+#endif
       break;
     }
 #endif /* USE_DVDNAV */
@@ -4875,8 +5329,13 @@
       if(timestamp < 0) timestamp = 0;
       else spudec_assemble(vo_spudec,packet,len,timestamp);
   }
-  
+//printf("spudec_visible: %i\n",spudec_visible(vo_spudec));  
   /* detect wether the sub has changed or not */
+#ifdef USE_MPDVDNAV
+    /* still image now process data, because next frame reseek: delete read spu packet */
+  if(stream->type==STREAMTYPE_DVDNAV) {
+   if(dvdnav_still || !((dvdnav_priv_t*)(stream->priv))->vts_domain) spudec_heartbeat(vo_spudec,90000*sh_video->timer); }
+#endif
   if(spudec_changed(vo_spudec))
     vo_osd_changed(OSDTYPE_SPU);
   current_module=NULL;
--- mencoder.c	2006-03-31 01:44:35.000000000 +0200
+++ mencoder.c	2006-04-04 01:27:36.000000000 +0200
@@ -50,6 +50,9 @@
 #include "parser-mecmd.h"
 
 #include "libmpdemux/stream.h"
+#ifdef USE_MPDVDNAV
+#include "libmpdemux/stream_dvdnav.h"
+#endif
 #include "libmpdemux/demuxer.h"
 #include "libmpdemux/stheader.h"
 #include "libmpdemux/mp3_hdr.h"
@@ -63,6 +66,9 @@
 #include "libmpcodecs/mp_image.h"
 #include "libmpcodecs/dec_audio.h"
 #include "libmpcodecs/dec_video.h"
+#ifdef USE_MPDVDNAV
+#include "libmpcodecs/vd_videostill.h"
+#endif
 #include "libmpcodecs/vf.h"
 
 // for MPEGLAYER3WAVEFORMAT:
@@ -495,7 +501,7 @@
 if (frameno_filename) {
   stream2=open_stream(frameno_filename,0,&i);
   if(stream2){
-    demuxer2=demux_open(stream2,DEMUXER_TYPE_AVI,-1,-1,-2,NULL);
+    demuxer2=demux_open(stream2,DEMUXER_TYPE_AVI,-1,-1,-2,NULL,0,0,0);
     if(demuxer2) mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_UsingPass3ControllFile, frameno_filename);
     else mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_FormatNotRecognized);
   }
@@ -574,7 +580,7 @@
   if(demuxer2) audio_id=-2; /* do NOT read audio packets... */
 
   //demuxer=demux_open(stream,file_format,video_id,audio_id,dvdsub_id);
-  demuxer=demux_open(stream,file_format,audio_id,video_id,dvdsub_id,filename);
+  demuxer=demux_open(stream,file_format,audio_id,video_id,dvdsub_id,filename,0,0,0);
   if(!demuxer){
     mp_msg(MSGT_DEMUXER, MSGL_FATAL, MSGTR_FormatNotRecognized);
     mp_msg(MSGT_DEMUXER, MSGL_FATAL, MSGTR_CannotOpenDemuxer);
--- spudec.h	2003-09-21 16:21:11.000000000 +0200
+++ spudec.h	2006-04-04 01:27:36.000000000 +0200
@@ -5,8 +5,25 @@
 
 void spudec_heartbeat(void *this, unsigned int pts100);
 void spudec_assemble(void *this, unsigned char *packet, unsigned int len, unsigned int pts100);
-void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
-void spudec_draw_scaled(void *this, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+#ifdef USE_MPDVDNAV
+#define DVDNAV_SPU_YUV	1
+#define DVDNAV_SPU_RGB	2
+#define DVDNAV_SPU_BGR	3
+#define DVDNAV_SPU_YUY	4
+
+void spu_yuv_to_rgb(unsigned int y,unsigned int u,unsigned int v,unsigned int *r,unsigned int *g,unsigned int *b);
+void spudec_dvdnav_mode(void *this, int mode, int cflg);
+void spudec_dvdnav_area(void *this, uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t palette);
+void spudec_dvdnav_palette(void *this, uint32_t palette);
+int spudec_dvdnav_menu_box(void *this, int scaled, unsigned int scalex, unsigned int scaley);
+void spudec_new_scaled_yuv(unsigned int *palette, unsigned int frame_width, unsigned int frame_height);
+void spudec_new_scaled_rgb(unsigned int *palette, unsigned int frame_width, unsigned int frame_height);
+void spudec_draw_scaled_yuv(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride));
+void spudec_draw_scaled_rgb(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride));
+void spudec_create_yuy(void *this, int spu_scaled);
+#endif
+void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride));
+void spudec_draw_scaled(void *this, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride));
 void spudec_update_palette(void *this, unsigned int *palette);
 void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height);
 void *spudec_new_scaled_vobsub(unsigned int *palette, unsigned int *cuspal, unsigned int custom, unsigned int frame_width, unsigned int frame_height);
@@ -18,7 +35,7 @@
 void spudec_set_hw_spu(void *this, vo_functions_t *hw_spu);
 int spudec_changed(void *this);
 void spudec_calc_bbox(void *me, unsigned int dxs, unsigned int dys, unsigned int* bbox);
-void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride));
 void spudec_set_forced_subs_only(void * const this, const unsigned int flag);
 #endif
 
--- spudec.c	2005-06-19 15:50:50.000000000 +0200
+++ spudec.c	2006-04-04 01:27:36.000000000 +0200
@@ -91,6 +91,53 @@
   int spu_changed;
   unsigned int forced_subs_only;     /* flag: 0=display all subtitle, !0 display only forced subtitles */
   unsigned int is_forced_sub;         /* true if current subtitle is a forced subtitle */
+#ifdef USE_MPDVDNAV
+  packet_t *last_packet;
+  unsigned int widthuv, heightuv, strideuv;
+  unsigned int start_coluv, end_coluv;
+  unsigned int start_rowuv, end_rowuv;
+  size_t image_sizeuv;
+  size_t scaled_image_sizeuv;
+  size_t image_sizeyuy;
+
+  unsigned int scaled_frame_widthuv, scaled_frame_heightuv;
+  unsigned int scaled_start_coluv, scaled_start_rowuv;
+  unsigned int scaled_widthuv, scaled_heightuv, scaled_strideuv;
+  unsigned char *scaled_imageu;
+  unsigned char *scaled_imagev;
+  unsigned char *scaled_aimageuv;
+
+  unsigned int hpalette[4];
+  unsigned int halpha[4];
+  unsigned int hcuspal[4];
+
+  unsigned char *imageu;		/* u value from yUv */
+  unsigned char *imagev;		/* v value from yuV*/
+  unsigned char *aimageuv;		/* alpha with uv*/
+  unsigned char *imageyuy;		/* yuy2 */
+  unsigned char *aimageyuy;		/* alpha with yuy2*/
+  unsigned int strideyuy;
+
+  int dvdnav_color_spu;		/* flag: 0 = grayscale SPU, 1 = YUV color SPU 2 = RGB 3 = BGR */
+
+  int dvdnav_menu;		/* flag: 0=normal subtitle, 1=dvdnav menu */
+  unsigned int dvdnav_sx;	/* dvdnav menu item box */
+  unsigned int dvdnav_ex;
+  unsigned int dvdnav_sy;
+  unsigned int dvdnav_ey;
+  unsigned int dvdnav_modify;	/* dvdnav menu item box is modify */
+  uint32_t     dvdnav_palette;	/* dvdnav menu button palette */
+  unsigned int dvdnav_x0;	/* dvdnav menu item draw_alpha coordinates */
+  unsigned int dvdnav_y0;
+  unsigned int dvdnav_w;
+  unsigned int dvdnav_h;
+  unsigned char *dvdnav_image;	/* dvdnav menu item image */
+  unsigned char *dvdnav_aimage;	/* dvdnav menu item alpha */
+  unsigned int dvdnav_stride;
+  unsigned int dvdnav_allocated;
+  unsigned int dvdnav_scalex;
+  unsigned int dvdnav_scaley;
+#endif
 } spudec_handle_t;
 
 static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet)
@@ -210,11 +257,127 @@
   } else {
     mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: update_spu: malloc requested %d bytes\n", 2 * this->stride * this->height);
   }
+#ifdef USE_MPDVDNAV
+  unsigned char *imageu;
+  unsigned char *imagev;
+  switch (this->dvdnav_color_spu) {
+    case DVDNAV_SPU_YUV:
+    case DVDNAV_SPU_YUY:
+      for (fy = 0; fy < this->image_sizeuv && !this->aimageuv[fy]; fy++);
+      for (ly = this->strideuv * this->heightuv-1; ly && !this->aimageuv[ly]; ly--);
+      first_y = fy / this->strideuv;
+      last_y = ly / this->strideuv;
+      this->start_rowuv += first_y;
+      // Some subtitles trigger this condition
+      if (last_y + 1 > first_y ) {
+	  this->heightuv = last_y - first_y +1;
+        } else {
+	  this->heightuv = 0;
+	  this->image_sizeuv = 0;
+	  return;
+        }
+      //  printf("new h %d new start %d (sz %d st %d)---\n\n", this->height, this->start_row, this->image_size, this->stride);
+      imageu = malloc(3 * this->strideuv * this->heightuv);
+      if(imageu){
+        this->image_sizeuv = this->strideuv * this->heightuv;
+        imagev = imageu + this->image_sizeuv;
+        aimage = imagev + this->image_sizeuv;
+        memcpy(imageu, this->imageu + this->strideuv * first_y, this->image_sizeuv);
+        memcpy(imagev, this->imagev + this->strideuv * first_y, this->image_sizeuv);
+        memcpy(aimage, this->aimageuv + this->strideuv * first_y, this->image_sizeuv);
+        free(this->imageu);
+        this->imageu = imageu;
+        this->imagev = imagev;
+        this->aimageuv = aimage;
+        } else {
+          mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: update_spu: malloc requested %d bytes\n", 3 * this->strideuv * this->height);
+        }
+      break;
+    case DVDNAV_SPU_RGB:
+    case DVDNAV_SPU_BGR:
+      this->image_sizeuv = this->stride * this->height;
+      imageu = malloc(2 * this->stride * this->height);
+      if(imageu){
+        imagev = imageu + this->image_size;
+        memcpy(imageu, this->imageu + this->stride * first_y, this->image_size);
+        memcpy(imagev, this->imagev + this->stride * first_y, this->image_size);
+        free(this->imageu);
+        this->imageu = imageu;
+        this->imagev = imagev;
+        this->aimageuv = NULL;
+      } else {
+        mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: update_spu: malloc requested %d bytes\n", 2 * this->stride * this->height);
+      }
+      break;
+    }      
+#endif
+}
+
+#ifdef USE_MPDVDNAV
+void spu_yuv_to_rgb(unsigned int y,unsigned int u,unsigned int v,unsigned int *r,unsigned int *g,unsigned int *b)
+{
+  int ty,tu,tv;
+  int tr,tg,tb;
+  ty=y;tv=u;tu=v;
+  tr = (298*(ty-16)+408*(tv-128))/256;
+  tg = (298*(ty-16)-100*(tu-128)-208*(tv-128))/256;
+  tb = (298*(ty-16)+516*(tu-128))/256;
+  if(tr>255) tr=255; if(tr<0) tr=0;
+  if(tg>255) tg=255; if(tg<0) tg=0;
+  if(tb>255) tb=255; if(tb<0) tb=0;
+  *r=tr; *g=tg; *b=tb;
+//  printf("y:%i u:%i v:%i => r:%i g:%i b:%i \n",y,u,v,*r,*g,*b);
+  return;
+}
+#endif
+
+#ifdef USE_MPDVDNAV
+static void spudec_process_fill(spudec_handle_t *this, int x, int y, int len, unsigned char color, unsigned char coloru, unsigned char colorv, unsigned char alpha)
+{
+unsigned int corrx, corry, corrl;
+//printf("x: %i y: %i len: %i  (%i)\n",x,y,len,this->stride-x-len);
+if (this->stride-x-len<0) return;
+if (len<0) return;
+switch (this->dvdnav_color_spu) {
+  case DVDNAV_SPU_YUV: 
+  case DVDNAV_SPU_YUY: 
+    corry=y & 0x01;
+    corrx=x & 0x01;
+    corrl=len & 0x01;
+    memset(this->image + y * this->stride + x, color, len);
+    memset(this->aimage + y * this->stride + x, alpha, len);
+    memset(this->imageu + (y-corry)/2 * this->strideuv + (x+corrx)/2, coloru, (len-corrl)/2);
+    memset(this->imagev + (y-corry)/2 * this->strideuv + (x+corrx)/2, colorv, (len-corrl)/2);
+    memset(this->aimageuv + (y-corry)/2 * this->strideuv + (x+corrx)/2, alpha, (len-corrl)/2);
+    break;
+  case DVDNAV_SPU_RGB: 
+  case DVDNAV_SPU_BGR: 
+    memset(this->image + y * this->stride + x, color, len);
+    memset(this->imageu + y * this->stride + x, coloru, len);
+    memset(this->imagev + y * this->stride + x, colorv, len);
+    memset(this->aimage + y * this->stride + x, alpha, len);
+    break;
+  default:
+    memset(this->image + y * this->stride + x, color, len);
+    memset(this->aimage + y * this->stride + x, alpha, len);
+    break;
+  }
 }
+#endif
 
 static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
 {
   unsigned int cmap[4], alpha[4];
+#ifdef USE_MPDVDNAV
+  unsigned int thpalette[4], thalpha[4];
+  unsigned int hcmap[4], halpha[4];
+  unsigned int cmapu[4], cmapv[4];
+  unsigned int hcmapu[4], hcmapv[4];
+  unsigned int control_start;
+  unsigned int current_nibble[2];
+  unsigned int ty,tu,tv,tr,tg,tb;
+  int deinterlace_oddness;	
+#endif
   unsigned int i, x, y;
 
   this->scaled_frame_width = 0;
@@ -226,6 +389,20 @@
   this->height = packet->height;
   this->width = packet->width;
   this->stride = packet->stride;
+#ifdef USE_MPDVDNAV
+  this->strideuv = packet->stride;
+  control_start = packet->control_start;
+  current_nibble[0]=packet->current_nibble[0];
+  current_nibble[1]=packet->current_nibble[1];
+  deinterlace_oddness=packet->deinterlace_oddness;	
+
+  this->start_coluv = packet->start_col/2;
+  this->end_coluv = packet->end_col/2;
+  this->start_rowuv = packet->start_row/2;
+  this->end_rowuv = packet->end_row/2;
+  this->heightuv = packet->height/2+1;
+  this->widthuv = packet->width/2+1;
+#endif
   for (i = 0; i < 4; ++i) {
     alpha[i] = mkalpha(packet->alpha[i]);
     if (alpha[i] == 0)
@@ -241,7 +418,93 @@
 	cmap[i] = 256 - alpha[i];
     }
   }
-
+#ifdef USE_MPDVDNAV
+  if (this->dvdnav_menu)
+    for (i = 0; i < 4; ++i) {	/* use button palette */
+      thalpha[i]=(this->dvdnav_palette >> ((3-i)*4)) & 0x0f;
+      thpalette[i]=(this->dvdnav_palette >> (16+(3-i)*4)) & 0x0f;
+      halpha[i] = mkalpha(thalpha[i]);
+      hcmap[i] = ((this->global_palette[thpalette[i]] >> 16) & 0xff);
+      if (alpha[i] == 0) {cmap[i] = 0; cmapu[i] = 0; cmapv[i] = 0;} else {
+        if (cmap[i] + alpha[i] > 255)
+	  cmap[i] = 256 - alpha[i];
+	  switch (this->dvdnav_color_spu) {
+    	    case DVDNAV_SPU_YUV: 
+    	    case DVDNAV_SPU_YUY: 
+    	      cmap[i] = ((this->global_palette[packet->palette[i]] >> 16) & 0xff);	// Y
+	      cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8;
+              cmapu[i] = ((this->global_palette[packet->palette[i]] >> 8) & 0xff);	// u
+	      cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8;
+              cmapv[i] = ((this->global_palette[packet->palette[i]] >> 0) & 0xff);	// v
+	      cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8;
+	      break;
+    	    case DVDNAV_SPU_RGB: 
+    	      ty = ((this->global_palette[packet->palette[i]] >> 16) & 0xff);	// Y
+              tu = ((this->global_palette[packet->palette[i]] >> 8) & 0xff);	// u
+              tv = ((this->global_palette[packet->palette[i]] >> 0) & 0xff);	// v
+	      spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb);
+	      cmap[i] = tr;
+	      cmapu[i] = tg;
+	      cmapv[i] = tb;
+	      cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8;
+	      cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8;
+	      cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8;
+	      break;
+    	    case DVDNAV_SPU_BGR: 
+    	      ty = ((this->global_palette[packet->palette[i]] >> 16) & 0xff);	// Y
+              tu = ((this->global_palette[packet->palette[i]] >> 8) & 0xff);	// u
+              tv = ((this->global_palette[packet->palette[i]] >> 0) & 0xff);	// v
+	      spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb);
+	      cmap[i] = tb;
+	      cmapu[i] = tg;
+	      cmapv[i] = tr;
+	      cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8;
+	      cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8;
+	      cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8;
+	      break;
+	    }
+	  }
+      if (halpha[i] == 0) {hcmap[i] = 0; hcmapu[i] = 0; hcmapv[i] = 0;} else {
+        if (hcmap[i] + halpha[i] > 255)
+	  hcmap[i] = 256 - halpha[i];
+	  switch (this->dvdnav_color_spu) {
+    	    case DVDNAV_SPU_YUV: 
+    	    case DVDNAV_SPU_YUY: 
+              hcmap[i] = ((this->global_palette[thpalette[i]] >> 16) & 0xff);	// Y
+	      hcmap[i] = ((0x100-halpha[i])*hcmap[i]) >> 8;
+              hcmapu[i] = ((this->global_palette[thpalette[i]] >> 8) & 0xff);	// u
+	      hcmapu[i] = ((0x100-halpha[i])*hcmapu[i]) >> 8;
+              hcmapv[i] = ((this->global_palette[thpalette[i]] >> 0) & 0xff);	// v
+	      hcmapv[i] = ((0x100-halpha[i])*hcmapv[i]) >> 8;
+	      break;
+    	    case DVDNAV_SPU_RGB: 
+              ty = ((this->global_palette[thpalette[i]] >> 16) & 0xff);	// Y
+              tu = ((this->global_palette[thpalette[i]] >> 8) & 0xff);	// u
+              tv = ((this->global_palette[thpalette[i]] >> 0) & 0xff);	// v
+	      spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb);
+	      hcmap[i] = tr;
+	      hcmapu[i] = tg;
+	      hcmapv[i] = tb;
+	      hcmap[i] = ((0x100-halpha[i])*hcmap[i]) >> 8;
+	      hcmapu[i] = ((0x100-halpha[i])*hcmapu[i]) >> 8;
+	      hcmapv[i] = ((0x100-halpha[i])*hcmapv[i]) >> 8;
+	      break;
+    	    case DVDNAV_SPU_BGR: 
+              ty = ((this->global_palette[thpalette[i]] >> 16) & 0xff);	// Y
+              tu = ((this->global_palette[thpalette[i]] >> 8) & 0xff);	// u
+              tv = ((this->global_palette[thpalette[i]] >> 0) & 0xff);	// v
+	      spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb);
+	      hcmap[i] = tb;
+	      hcmapu[i] = tg;
+	      hcmapv[i] = tr;
+	      hcmap[i] = ((0x100-halpha[i])*hcmap[i]) >> 8;
+	      hcmapu[i] = ((0x100-halpha[i])*hcmapu[i]) >> 8;
+	      hcmapv[i] = ((0x100-halpha[i])*hcmapv[i]) >> 8;
+	      break;
+	    }
+	}
+      }
+#endif
   if (this->image_size < this->stride * this->height) {
     if (this->image != NULL) {
       free(this->image);
@@ -255,6 +518,46 @@
   }
   if (this->image == NULL)
     return;
+#ifdef USE_MPDVDNAV
+if(this->dvdnav_menu && this->dvdnav_color_spu) {
+  if (this->imageyuy) {free(this->imageyuy); this->imageyuy=NULL; this->aimageyuy=NULL;}
+  if (this->dvdnav_color_spu==DVDNAV_SPU_YUV || this->dvdnav_color_spu==DVDNAV_SPU_YUY) {
+    if (this->image_sizeuv < this->strideuv * this->heightuv) {
+      if (this->imageu != NULL) {
+        free(this->imageu);
+        this->image_sizeuv = 0;
+        }
+      this->imageu = malloc(3 * this->strideuv * this->heightuv);
+      if (this->imageu) {
+        this->image_sizeuv = this->strideuv * this->heightuv;
+        this->imagev = this->imageu + this->image_sizeuv;
+        this->aimageuv = this->imagev + this->image_sizeuv;
+	}
+      }
+    memset(this->imageu,0,3 * this->strideuv * this->heightuv);
+    } else {
+    if (this->image_sizeuv < this->stride * this->height) {
+      if (this->imageu != NULL) {
+        free(this->imageu);
+        this->image_sizeuv = 0;
+        }
+      this->imageu = malloc(2 * this->stride * this->height);
+      if (this->imageu) {
+        this->image_sizeuv = this->stride * this->height;
+        this->imagev = this->imageu + this->image_sizeuv;
+        this->aimageuv = this->imagev + this->image_sizeuv;
+	}
+      }
+    memset(this->imageu,0,2 * this->stride * this->height);
+    }
+  if (this->imageu == NULL)
+    return;
+  } else {
+  if (this->imageu) free(this->imageu);
+  this->imageu=NULL;
+  this->image_sizeuv=0;
+  }
+#endif
 
   /* Kludge: draw_alpha needs width multiple of 8. */
   if (this->width < this->stride)
@@ -289,8 +592,35 @@
     if (len > this->width - x || len == 0)
       len = this->width - x;
     /* FIXME have to use palette and alpha map*/
+#ifdef USE_MPDVDNAV
+    if (this->dvdnav_menu)
+      {
+      if (this->start_row+y>=this->dvdnav_sy && this->start_row+y<=this->dvdnav_ey) {
+	if (this->start_col+x>=this->dvdnav_sx && this->start_col+x+len<=this->dvdnav_ex)
+	  spudec_process_fill(this, x, y, len, hcmap[color], hcmapu[color], hcmapv[color], halpha[color]);
+	else if(this->start_col+x<this->dvdnav_sx && this->start_col+x+len>this->dvdnav_sx && this->start_col+x+len<=this->dvdnav_ex) {
+	  spudec_process_fill(this, x, y, this->dvdnav_sx-this->start_col-x, cmap[color], cmapu[color], cmapv[color], alpha[color]);
+	  spudec_process_fill(this, this->dvdnav_sx-this->start_col, y, len+this->start_col+x-this->dvdnav_sx, hcmap[color], hcmapu[color], hcmapv[color], halpha[color]); }
+	else if(this->start_col+x<this->dvdnav_sx && this->start_col+x+len>this->dvdnav_sx && this->start_col+x+len>this->dvdnav_ex) {
+	  spudec_process_fill(this, x, y, this->dvdnav_sx-this->start_col-x, cmap[color], cmapu[color], cmapv[color], alpha[color]);
+	  spudec_process_fill(this, this->dvdnav_sx-this->start_col, y, this->dvdnav_ex-this->dvdnav_sx, hcmap[color], hcmapu[color], hcmapv[color], halpha[color]); 
+	  spudec_process_fill(this, this->dvdnav_ex-this->start_col, y, x+len+this->start_col-this->dvdnav_ex, cmap[color], cmapu[color], cmapv[color], alpha[color]);}
+	else if(this->start_col+x>=this->dvdnav_sx && this->start_col+x<this->dvdnav_ex && this->start_col+x+len>this->dvdnav_ex) {
+	  spudec_process_fill(this, x, y, this->dvdnav_ex-this->start_col-x, hcmap[color], hcmapu[color], hcmapv[color], halpha[color]);
+	  spudec_process_fill(this, this->dvdnav_ex-this->start_col, y, len+this->start_col+x-this->dvdnav_ex, cmap[color], cmapu[color], cmapv[color], alpha[color]); }
+	else
+	  spudec_process_fill(this, x, y, len, cmap[color], cmapu[color], cmapv[color], alpha[color]);
+	} else spudec_process_fill(this, x, y, len, cmap[color], cmapu[color], cmapv[color], alpha[color]);
+      }
+      else
+      {
+      memset(this->image + y * this->stride + x, cmap[color], len);
+      memset(this->aimage + y * this->stride + x, alpha[color], len);
+      }
+#else
     memset(this->image + y * this->stride + x, cmap[color], len);
     memset(this->aimage + y * this->stride + x, alpha[color], len);
+#endif
     x += len;
     if (x >= this->width) {
       next_line(packet);
@@ -298,7 +628,14 @@
       ++y;
     }
   }
+#ifdef USE_MPDVDNAV
+  packet->control_start = control_start;
+  packet->current_nibble[0]=current_nibble[0];
+  packet->current_nibble[1]=current_nibble[1];
+  packet->deinterlace_oddness=deinterlace_oddness;	
+#endif
   spudec_cut_image(this);
+//printf("spudec_process_data: w: %i h: %i end\n",this->height,this->width);
 }
 
 
@@ -377,6 +714,10 @@
 	end_pts = UINT_MAX;
 	display = 1;
 	this->is_forced_sub=~0; // current subtitle is forced
+#ifdef USE_MPDVDNAV
+//printf("spu packet cmd=00 start_pts: %i pts100: %i date: %i \n",start_pts,pts100,date);
+	mp_msg(MSGT_CPLAYER,MSGL_DBG2,"spu packet cmd=00\n");
+#endif
 	break;
       case 0x01:
 	/* Start display */
@@ -385,6 +726,10 @@
 	end_pts = UINT_MAX;
 	display = 1;
 	this->is_forced_sub=0;
+#ifdef USE_MPDVDNAV
+//printf("spu packet cmd=01\n");
+	mp_msg(MSGT_CPLAYER,MSGL_DBG2,"spu packet cmd=01\n");
+#endif
 	break;
       case 0x02:
 	/* Stop display */
@@ -583,6 +928,7 @@
   spu->now_pts = 0;
   spu->end_pts = 0;
   spu->packet_size = spu->packet_offset = 0;
+//  if (spu->last_packet) {printf("free4\n");spudec_free_packet(spu->last_packet); spu->last_packet=NULL;}
 }
 
 void spudec_heartbeat(void *this, unsigned int pts100)
@@ -590,6 +936,11 @@
   spudec_handle_t *spu = (spudec_handle_t*) this;
   spu->now_pts = pts100;
 
+//  while (spu->queue_head != NULL && (pts100 >= spu->queue_head->start_pts || spu->dvdnav_menu)) {
+#ifdef USE_MPDVDNAV
+//  if(spu->queue_head && !spu->last_packet) spu->queue_head->start_pts=0;
+  if(spu->queue_head) spu->queue_head->start_pts=0;
+#endif
   while (spu->queue_head != NULL && pts100 >= spu->queue_head->start_pts) {
     packet_t *packet = spudec_dequeue_packet(spu);
     spu->start_pts = packet->start_pts;
@@ -597,6 +948,12 @@
     if (spu->auto_palette)
       compute_palette(spu, packet);
     spudec_process_data(spu, packet);
+#ifdef USE_MPDVDNAV
+    if (spu->dvdnav_menu)
+      {
+      if(spu->last_packet) {spudec_free_packet(spu->last_packet);} spu->last_packet=packet;
+      } else
+#endif
     spudec_free_packet(packet);
     spu->spu_changed = 1;
   }
@@ -602,12 +959,17 @@
   }
 }
 
+
 int spudec_visible(void *this){
     spudec_handle_t *spu = (spudec_handle_t *)this;
+#ifdef USE_MPDVDNAV
+    if(!spu) return 0;
+//printf("spudec_visible: dvdnav_menu: %i spu->height: %i <<<<<\n",spu->dvdnav_menu,spu->height);
+    if (spu->dvdnav_menu && spu->height > 0) { if(spu->height>0) spu->end_pts=UINT_MAX; return 1; }
+#endif
     int ret=(spu->start_pts <= spu->now_pts &&
 	     spu->now_pts < spu->end_pts &&
 	     spu->height > 0);
-//    printf("spu visible: %d  \n",ret);
     return ret;
 }
 
@@ -619,12 +981,42 @@
   }
 }
 
-void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
+void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride))
 {
     spudec_handle_t *spu = (spudec_handle_t *)this;
     if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts && spu->image)
     {
-	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+#ifdef USE_MPDVDNAV
+	if (spu->dvdnav_menu) {	/* spu menu mode? */
+	  switch (spu->dvdnav_color_spu) {
+    	    case DVDNAV_SPU_YUV:
+	      draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,0,
+		    spu->image, spu->aimage, spu->stride);
+	      draw_alpha(spu->start_coluv, spu->start_rowuv, spu->widthuv, spu->heightuv,1,
+		   spu->imageu, spu->aimageuv, spu->strideuv);
+	      draw_alpha(spu->start_coluv, spu->start_rowuv, spu->widthuv, spu->heightuv,2,
+		   spu->imagev, spu->aimageuv, spu->strideuv);
+	      break;
+    	    case DVDNAV_SPU_YUY:
+	      if (!spu->imageyuy) spudec_create_yuy(spu,0);
+	      if (spu->imageyuy) draw_alpha(spu->start_col, spu->start_row, spu->width*2, spu->height/2,6,
+		    spu->imageyuy, spu->aimageyuy, spu->strideyuy);
+    	    case DVDNAV_SPU_RGB:
+    	    case DVDNAV_SPU_BGR:
+	      draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,5,
+		   spu->imagev, spu->aimage, spu->stride);
+	      draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,4,
+		   spu->imageu, spu->aimage, spu->stride);
+	      draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,3,
+		    spu->image, spu->aimage, spu->stride);
+	      break;
+	    default:
+	      draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,0,
+		    spu->image, spu->aimage, spu->stride);
+    	    }
+	  } else
+#endif
+	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,0,
 		   spu->image, spu->aimage, spu->stride);
 	spu->spu_changed = 0;
     }
@@ -736,6 +1128,98 @@
   }
 }
 
+#ifdef USE_MPDVDNAV
+static void scale_image_uv(int x, int y, scale_pixel* table_x, scale_pixel* table_y, spudec_handle_t * spu)
+{
+  int alpha[4];
+  int coloru[4];
+  int colorv[4];
+  unsigned int scale[4];
+  int base = table_y[y].position * spu->strideuv + table_x[x].position;
+  int scaled = y * spu->scaled_strideuv + x;
+  alpha[0] = canon_alpha(spu->aimageuv[base]);
+  alpha[1] = canon_alpha(spu->aimageuv[base + 1]);
+  alpha[2] = canon_alpha(spu->aimageuv[base + spu->strideuv]);
+  alpha[3] = canon_alpha(spu->aimageuv[base + spu->strideuv + 1]);
+  coloru[0] = spu->imageu[base];
+  coloru[1] = spu->imageu[base + 1];
+  coloru[2] = spu->imageu[base + spu->strideuv];
+  coloru[3] = spu->imageu[base + spu->strideuv + 1];
+  colorv[0] = spu->imagev[base];
+  colorv[1] = spu->imagev[base + 1];
+  colorv[2] = spu->imagev[base + spu->strideuv];
+  colorv[3] = spu->imagev[base + spu->strideuv + 1];
+// FIXME: color hack!!!
+//  scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0];
+//  scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * alpha[1];
+//  scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * alpha[2];
+//  scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * alpha[3];
+  scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * 0x100;
+  scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * 0x100;
+  scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * 0x100;
+  scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * 0x100;
+  spu->scaled_imageu[scaled] = (coloru[0] * scale[0] + coloru[1] * scale[1] + coloru[2] * scale[2] + coloru[3] * scale[3])>>24;
+  spu->scaled_imagev[scaled] = (colorv[0] * scale[0] + colorv[1] * scale[1] + colorv[2] * scale[2] + colorv[3] * scale[3])>>24;
+  scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0];
+  scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * alpha[1];
+  scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * alpha[2];
+  scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * alpha[3];
+  spu->scaled_aimageuv[scaled] = (scale[0] + scale[1] + scale[2] + scale[3]) >> 16;
+  if (spu->scaled_aimageuv[scaled]){
+    spu->scaled_aimageuv[scaled] = 256 - spu->scaled_aimageuv[scaled];
+    if(spu->scaled_aimageuv[scaled] + spu->scaled_imageu[scaled] > 255)
+      spu->scaled_imageu[scaled] = 256 - spu->scaled_aimageuv[scaled];
+    if(spu->scaled_aimageuv[scaled] + spu->scaled_imagev[scaled] > 255)
+      spu->scaled_imagev[scaled] = 256 - spu->scaled_aimageuv[scaled];
+  }
+}
+
+static void scale_image_rgb(int x, int y, scale_pixel* table_x, scale_pixel* table_y, spudec_handle_t * spu)
+{
+  int alpha[4];
+  int colorr[4];
+  int colorg[4];
+  int colorb[4];
+  unsigned int scale[4];
+  int base = table_y[y].position * spu->stride + table_x[x].position;
+  int scaled = y * spu->scaled_stride + x;
+  alpha[0] = canon_alpha(spu->aimage[base]);
+  alpha[1] = canon_alpha(spu->aimage[base + 1]);
+  alpha[2] = canon_alpha(spu->aimage[base + spu->stride]);
+  alpha[3] = canon_alpha(spu->aimage[base + spu->stride + 1]);
+  colorr[0] = spu->image[base];
+  colorr[1] = spu->image[base + 1];
+  colorr[2] = spu->image[base + spu->stride];
+  colorr[3] = spu->image[base + spu->stride + 1];
+  colorg[0] = spu->imageu[base];
+  colorg[1] = spu->imageu[base + 1];
+  colorg[2] = spu->imageu[base + spu->stride];
+  colorg[3] = spu->imageu[base + spu->stride + 1];
+  colorb[0] = spu->imagev[base];
+  colorb[1] = spu->imagev[base + 1];
+  colorb[2] = spu->imagev[base + spu->stride];
+  colorb[3] = spu->imagev[base + spu->stride + 1];
+  scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0];
+  scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * alpha[1];
+  scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * alpha[2];
+  scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * alpha[3];
+  spu->scaled_image[scaled] = (colorr[0] * scale[0] + colorr[1] * scale[1] + colorr[2] * scale[2] + colorr[3] * scale[3])>>24;
+  spu->scaled_imageu[scaled] = (colorg[0] * scale[0] + colorg[1] * scale[1] + colorg[2] * scale[2] + colorg[3] * scale[3])>>24;
+  spu->scaled_imagev[scaled] = (colorb[0] * scale[0] + colorb[1] * scale[1] + colorb[2] * scale[2] + colorb[3] * scale[3])>>24;
+  spu->scaled_aimage[scaled] = (scale[0] + scale[1] + scale[2] + scale[3]) >> 16;
+  if (spu->scaled_aimage[scaled]){
+    spu->scaled_aimage[scaled] = 256 - spu->scaled_aimage[scaled];
+    if(spu->scaled_aimage[scaled] + spu->scaled_image[scaled] > 255)
+      spu->scaled_image[scaled] = 256 - spu->scaled_aimage[scaled];
+    if(spu->scaled_aimage[scaled] + spu->scaled_imageu[scaled] > 255)
+      spu->scaled_imageu[scaled] = 256 - spu->scaled_aimage[scaled];
+    if(spu->scaled_aimage[scaled] + spu->scaled_imagev[scaled] > 255)
+      spu->scaled_imagev[scaled] = 256 - spu->scaled_aimage[scaled];
+  }
+}
+
+#endif
+
 void sws_spu_image(unsigned char *d1, unsigned char *d2, int dw, int dh, int ds,
 	unsigned char *s1, unsigned char *s2, int sw, int sh, int ss)
 {
@@ -762,11 +1246,187 @@
 	sws_freeContext(ctx);
 }
 
-void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
+#ifdef USE_MPDVDNAV
+void spudec_create_yuy(void *this, int spu_scaled)
+{
+spudec_handle_t *spu = this;
+unsigned char *dptr;
+unsigned char *daptr;
+unsigned char *sptry;
+unsigned char *sptru;
+unsigned char *sptrv;
+unsigned char *saptr;
+unsigned char *saptruv;
+int y,x;
+
+if (spu_scaled) {
+  spu->strideyuy=spu->scaled_stride*2;
+  spu->imageyuy=malloc(spu->strideyuy*(spu->height+2)*2);
+  memset(spu->imageyuy,0,spu->strideyuy*(spu->height+2)*2);
+  spu->aimageyuy=spu->imageyuy+spu->strideyuy*spu->scaled_height;
+  for(y=0;y<spu->scaled_height;y++) {
+    dptr=spu->imageyuy+y*spu->strideyuy;
+    daptr=spu->aimageyuy+y*spu->strideyuy;
+    sptry=spu->image+y*spu->scaled_stride;
+    sptru=spu->imageu+y/2*spu->scaled_strideuv;
+    sptrv=spu->imagev+y/2*spu->scaled_strideuv;
+    saptr=spu->aimage+y*spu->scaled_stride;
+    saptruv=spu->aimageuv+y/2*spu->scaled_strideuv;
+    for(x=0;x<spu->scaled_widthuv-1;x++) {
+      *dptr++=*sptry++;
+      *dptr++=*sptrv++;
+      *dptr++=*sptry++;
+      *dptr++=*sptru++;
+      *daptr++=*saptr++;
+      *daptr++=*saptruv;
+      *daptr++=*saptr++;
+      *daptr++=*saptruv++; 
+      } }
+  } else {
+  spu->strideyuy=spu->stride*2;
+  spu->imageyuy=malloc(spu->strideyuy*(spu->height+2)*2);
+  memset(spu->imageyuy,0,spu->strideyuy*(spu->height+2)*2);
+  spu->aimageyuy=spu->imageyuy+spu->strideyuy*spu->height;
+  for(y=0;y<spu->height;y++) {
+    dptr=spu->imageyuy+y*spu->strideyuy;
+    daptr=spu->aimageyuy+y*spu->strideyuy;
+    sptry=spu->image+y*spu->stride;
+    sptru=spu->imageu+y/2*spu->strideuv;
+    sptrv=spu->imagev+y/2*spu->strideuv;
+    saptr=spu->aimage+y*spu->stride;
+    saptruv=spu->aimageuv+y/2*spu->strideuv;
+    for(x=0;x<spu->widthuv-1;x++) {
+      *dptr++=*sptry++;
+      *dptr++=*sptrv++;
+      *dptr++=*sptry++;
+      *dptr++=*sptru++;
+      *daptr++=*saptr++;
+      *daptr++=*saptruv;
+      *daptr++=*saptr++;
+      *daptr++=*saptruv++; 
+      } }
+  }
+}
+
+void sws_spu_image_uv(unsigned char *du, unsigned char *dv, unsigned char *d2, int dw, int dh, int ds,
+	unsigned char *su, unsigned char *sv, unsigned char *s2, int sw, int sh, int ss)
+{
+	struct SwsContext *ctx;
+	static SwsFilter filter;
+	static int firsttime = 1;
+	static float oldvar;
+	int i;
+
+	if (!firsttime && oldvar != spu_gaussvar) sws_freeVec(filter.lumH);
+	if (firsttime) {
+		filter.lumH = filter.lumV =
+			filter.chrH = filter.chrV = sws_getGaussianVec(spu_gaussvar, 3.0);
+		sws_normalizeVec(filter.lumH, 1.0);
+		firsttime = 0;
+		oldvar = spu_gaussvar;
+	}
+	
+	ctx=sws_getContext(sw, sh, IMGFMT_Y800, dw, dh, IMGFMT_Y800, SWS_GAUSS, &filter, NULL, NULL);
+	sws_scale(ctx,&su,&ss,0,sh,&du,&ds);
+	sws_scale(ctx,&sv,&ss,0,sh,&dv,&ds);
+	for (i=ss*sh-1; i>=0; i--) if (!s2[i]) s2[i] = 255; //else s2[i] = 1;
+	sws_scale(ctx,&s2,&ss,0,sh,&d2,&ds);
+	for (i=ds*dh-1; i>=0; i--) if (d2[i]==0) d2[i] = 1; else if (d2[i]==255) d2[i] = 0;
+	sws_freeContext(ctx);
+}
+
+void sws_spu_image_rgb(unsigned char *dr, unsigned char *dg, unsigned char *db, unsigned char *d2, int dw, int dh, int ds,
+	unsigned char *sr,unsigned char *sg,unsigned char *sb, unsigned char *s2, int sw, int sh, int ss)
+{
+	struct SwsContext *ctx;
+	static SwsFilter filter;
+	static int firsttime = 1;
+	static float oldvar;
+	int i;
+
+	if (!firsttime && oldvar != spu_gaussvar) sws_freeVec(filter.lumH);
+	if (firsttime) {
+		filter.lumH = filter.lumV =
+			filter.chrH = filter.chrV = sws_getGaussianVec(spu_gaussvar, 3.0);
+		sws_normalizeVec(filter.lumH, 1.0);
+		firsttime = 0;
+		oldvar = spu_gaussvar;
+	}
+	
+	ctx=sws_getContext(sw, sh, IMGFMT_Y800, dw, dh, IMGFMT_Y800, SWS_GAUSS, &filter, NULL, NULL);
+	sws_scale(ctx,&sr,&ss,0,sh,&dr,&ds);
+	sws_scale(ctx,&sg,&ss,0,sh,&dg,&ds);
+	sws_scale(ctx,&sb,&ss,0,sh,&db,&ds);
+	for (i=ss*sh-1; i>=0; i--) if (!s2[i]) s2[i] = 255; //else s2[i] = 1;
+	sws_scale(ctx,&s2,&ss,0,sh,&d2,&ds);
+	for (i=ds*dh-1; i>=0; i--) if (d2[i]==0) d2[i] = 1; else if (d2[i]==255) d2[i] = 0;
+	sws_freeContext(ctx);
+}
+
+#undef max
+#define max(x,y) ((x) > (y) ? (x) : (y))
+#undef min
+#define min(x,y) ((x) < (y) ? (x) : (y))
+
+void spudec_dvdnav_mode(void *this, int mode, int cflg){		/* set/clear spu menu mode */
+  spudec_handle_t *spu = (spudec_handle_t *)this;
+  if (!spu) return;
+  spu->dvdnav_menu=mode;
+  spu->dvdnav_color_spu=cflg;
+  if (!spu->dvdnav_menu && spu->last_packet) {spudec_free_packet(spu->last_packet); spu->last_packet=NULL;}
+  return;
+}
+
+void spudec_dvdnav_area(void *this, uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t palette)
+{
+  spudec_handle_t *spu = this;
+  if (!spu) return;
+  if (spu->dvdnav_sx==min(sx,ex) && spu->dvdnav_ex==max(sx,ex) && spu->dvdnav_sy==min(sy,ey) && spu->dvdnav_ey==max(sy,ey) && spu->dvdnav_palette==palette) return;
+  spu->dvdnav_sx=min(sx,ex);		/* set spu button area, palette & on */
+  spu->dvdnav_ex=max(sx,ex);
+  spu->dvdnav_sy=min(sy,ey);
+  spu->dvdnav_ey=max(sy,ey);
+  spu->dvdnav_palette=palette;
+  spu->dvdnav_modify=1;
+  if (spu->dvdnav_menu && spu->last_packet)
+    {
+    if (spu->auto_palette)
+      compute_palette(spu, spu->last_packet);
+    spudec_process_data(spu, spu->last_packet);
+    }
+  return;
+}
+
+void spudec_dvdnav_palette(void *this, uint32_t palette)
+{
+  spudec_handle_t *spu = this;
+  if (!spu) return;
+  spu->dvdnav_palette=palette;		/* set spu button palette */
+  return;
+}
+#endif
+
+void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride))
 {
   spudec_handle_t *spu = (spudec_handle_t *)me;
   scale_pixel *table_x;
   scale_pixel *table_y;
+#ifdef USE_MPDVDNAV
+  if (spu->dvdnav_menu) {
+    switch (spu->dvdnav_color_spu) {
+      case DVDNAV_SPU_YUV: 
+      case DVDNAV_SPU_YUY: 
+        spudec_draw_scaled_yuv(me,dxs,dys,draw_alpha); 
+	return; 
+	break;
+      case DVDNAV_SPU_RGB:
+      case DVDNAV_SPU_BGR: 
+        spudec_draw_scaled_rgb(me,dxs,dys,draw_alpha); 
+	return; 
+	break;
+      }
+    }
+#endif
 
   if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) {
 
@@ -779,7 +1439,7 @@
 	|| (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) {
       if (spu->image)
       {
-	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,0,
 		   spu->image, spu->aimage, spu->stride);
 	spu->spu_changed = 0;
       }
@@ -1085,7 +1745,7 @@
 	  if (spu->scaled_start_row < 0) spu->scaled_start_row = 0;
 	  break;
 	}
-	draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,
+	draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,0,
 		   spu->scaled_image, spu->scaled_aimage, spu->scaled_stride);
 	spu->spu_changed = 0;
       }
@@ -1098,59 +1758,1054 @@
   }
 }
 
-void spudec_update_palette(void * this, unsigned int *palette)
+#ifdef USE_MPDVDNAV
+void spudec_draw_scaled_yuv(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride))
 {
-  spudec_handle_t *spu = (spudec_handle_t *) this;
-  if (spu && palette) {
-    memcpy(spu->global_palette, palette, sizeof(spu->global_palette));
-    if(spu->hw_spu)
-      spu->hw_spu->control(VOCTRL_SET_SPU_PALETTE,spu->global_palette);
-  }
-}
+  spudec_handle_t *spu = (spudec_handle_t *)me;
+  scale_pixel *table_x;
+  scale_pixel *table_y;
+  unsigned int scalex = 0;
+  unsigned int scaley = 0;
 
-void spudec_set_font_factor(void * this, double factor)
-{
-  spudec_handle_t *spu = (spudec_handle_t *) this;
-  spu->font_start_level = (int)(0xF0-(0xE0*factor));
-}
+  if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) {
 
-void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height)
-{
-  return spudec_new_scaled_vobsub(palette, NULL, 0, frame_width, frame_height);
-}
+    // check if only forced subtitles are requested 
+    if( (spu->forced_subs_only) && !(spu->is_forced_sub) ){ 
+	return;}
 
-/* get palette custom color, width, height from .idx file */
-void *spudec_new_scaled_vobsub(unsigned int *palette, unsigned int *cuspal, unsigned int custom, unsigned int frame_width, unsigned int frame_height)
+    if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || spu->orig_frame_height == 0
+	|| (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) {
+      if (spu->image)
 {
-  spudec_handle_t *this = calloc(1, sizeof(spudec_handle_t));
-  if (this){
-    //(fprintf(stderr,"VobSub Custom Palette: %d,%d,%d,%d", this->cuspal[0], this->cuspal[1], this->cuspal[2],this->cuspal[3]);
-    this->packet = NULL;
-    this->image = NULL;
-    this->scaled_image = NULL;
-    /* XXX Although the video frame is some size, the SPU frame is
-       always maximum size i.e. 720 wide and 576 or 480 high */
-    this->orig_frame_width = 720;
-    this->orig_frame_height = (frame_height == 480 || frame_height == 240) ? 480 : 576;
-    this->custom = custom;
-    // set up palette:
-    this->auto_palette = 1;
-    if (palette){
-      memcpy(this->global_palette, palette, sizeof(this->global_palette));
-      this->auto_palette = 0;
+	if (spu->dvdnav_color_spu==DVDNAV_SPU_YUY) {
+	  if (!spu->imageyuy) spudec_create_yuy(spu,0);
+	  if (spu->imageyuy) draw_alpha(spu->start_col, spu->start_row, spu->width*2, spu->heightuv*2,6,
+		    spu->imageyuy, spu->aimageyuy, spu->strideyuy);
+	  } else {
+	  draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,0,
+	   spu->image, spu->aimage, spu->stride);
+	  if(spu->dvdnav_color_spu && spu->imageu && spu->aimageuv)
+	    draw_alpha(spu->start_coluv, spu->start_rowuv, spu->widthuv, spu->heightuv,1,
+		   spu->imageu, spu->aimageuv, spu->strideuv);
+	  if(spu->dvdnav_color_spu && spu->imagev && spu->aimageuv)
+	    draw_alpha(spu->start_coluv, spu->start_rowuv, spu->widthuv, spu->heightuv,2,
+		   spu->imagev, spu->aimageuv, spu->strideuv);
     }
-    this->custom = custom;
-    if (custom && cuspal) {
-      memcpy(this->cuspal, cuspal, sizeof(this->cuspal));
-      this->auto_palette = 0;
+	spu->spu_changed = 0;
     }
-    // forced subtitles default: show all subtitles
-    this->forced_subs_only=0;
-    this->is_forced_sub=0;
   }
-  else
-    mp_msg(MSGT_SPUDEC,MSGL_FATAL, "FATAL: spudec_init: calloc");
-  return this;
+    else {
+      if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) {	/* Resizing is needed */
+	/* scaled_x = scalex * x / 0x100
+	   scaled_y = scaley * y / 0x100
+	   order of operations is important because of rounding. */
+	scalex = 0x100 * dxs / spu->orig_frame_width;
+	scaley = 0x100 * dys / spu->orig_frame_height;
+
+	spu->scaled_start_col = spu->start_col * scalex / 0x100;
+	spu->scaled_start_row = spu->start_row * scaley / 0x100;
+	spu->scaled_width = spu->width * scalex / 0x100;
+	spu->scaled_height = spu->height * scaley / 0x100;
+	spu->scaled_start_coluv = spu->start_coluv * scalex / 0x100;
+	spu->scaled_start_rowuv = spu->start_rowuv * scaley / 0x100;
+	spu->scaled_widthuv = spu->widthuv * scalex / 0x100;
+	spu->scaled_heightuv = spu->heightuv * scaley / 0x100;
+	/* Kludge: draw_alpha needs width multiple of 8 */
+	spu->scaled_stride = (spu->scaled_width + 7) & ~7;
+	spu->scaled_strideuv = (spu->scaled_widthuv + 7) & ~7;
+	if (spu->scaled_image_size < spu->scaled_stride * (spu->scaled_height+2)) {
+	  if (spu->scaled_image) {
+	    free(spu->scaled_image);
+	    spu->scaled_image_size = 0;
+	    }
+	  spu->scaled_image = malloc(2 * spu->scaled_stride * (spu->scaled_height+2));
+	  if (spu->scaled_image) {
+	    memset(spu->scaled_image,0,2 * spu->scaled_stride * (spu->scaled_height+2));
+	    spu->scaled_image_size = spu->scaled_stride * (spu->scaled_height+2);
+	    spu->scaled_aimage = spu->scaled_image + spu->scaled_image_size;
+	    }
+	}
+	if (spu->scaled_image_sizeuv < spu->scaled_strideuv * (spu->scaled_heightuv+2)) {
+	  if (spu->scaled_imageu) {
+	    free(spu->scaled_imageu);
+	    spu->scaled_image_sizeuv = 0;
+	    }
+	  spu->scaled_imageu = malloc(3 * spu->scaled_strideuv * (spu->scaled_height+2));
+	  if (spu->scaled_imageu) {
+	    memset(spu->scaled_imageu,0,3 * spu->scaled_strideuv * (spu->scaled_height+2));
+	    spu->scaled_image_sizeuv = spu->scaled_strideuv * (spu->scaled_heightuv+2);
+	    spu->scaled_imagev = spu->scaled_imageu + spu->scaled_image_sizeuv;
+	    spu->scaled_aimageuv = spu->scaled_imagev + spu->scaled_image_sizeuv;
+	    }
+	}
+	if (spu->scaled_image) {
+	  unsigned int x, y;
+	  if (spu->scaled_width <= 1 || spu->scaled_height <= 1) {
+	    goto nothing_to_do;
+	    }
+	  if (spu->scaled_widthuv <= 1 || spu->scaled_heightuv <= 1) {
+	    goto nothing_to_do;
+	    }
+	  switch(spu_aamode&15) {
+	  case 4:
+	  sws_spu_image(spu->scaled_image, spu->scaled_aimage,
+		  spu->scaled_width, spu->scaled_height, spu->scaled_stride,
+		  spu->image, spu->aimage, spu->width, spu->height, spu->stride);
+	  sws_spu_image_uv(spu->scaled_imageu, spu->scaled_imagev, spu->scaled_aimageuv,
+		  spu->scaled_widthuv, spu->scaled_heightuv, spu->scaled_strideuv,
+		  spu->imageu, spu->imagev, spu->aimageuv, spu->widthuv, spu->heightuv, spu->strideuv);
+	  break;
+	  case 3:
+	  table_x = calloc(spu->scaled_width, sizeof(scale_pixel));
+	  table_y = calloc(spu->scaled_height, sizeof(scale_pixel));
+	  if (!table_x || !table_y) {
+	    mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: spudec_draw_scaled: calloc failed\n");
+	    }
+	  scale_table(0, 0, spu->width - 1, spu->scaled_width - 1, table_x);
+	  scale_table(0, 0, spu->height - 1, spu->scaled_height - 1, table_y);
+	  for (y = 0; y < spu->scaled_height; y++)
+	    for (x = 0; x < spu->scaled_width; x++)
+	      scale_image(x, y, table_x, table_y, spu);
+	  free(table_x);
+	  free(table_y);
+	  table_x = calloc(spu->scaled_widthuv, sizeof(scale_pixel));
+	  table_y = calloc(spu->scaled_heightuv, sizeof(scale_pixel));
+	  if (!table_x || !table_y) {
+	    mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: spudec_draw_scaled: calloc failed\n");
+	    }
+	  scale_table(0, 0, spu->widthuv - 1, spu->scaled_widthuv - 1, table_x);
+	  scale_table(0, 0, spu->heightuv - 1, spu->scaled_heightuv - 1, table_y);
+	  for (y = 0; y < spu->scaled_heightuv; y++)
+	    for (x = 0; x < spu->scaled_widthuv; x++)
+	      scale_image_uv(x, y, table_x, table_y, spu);
+	  free(table_x);
+	  free(table_y); 
+	  break;
+	  case 0:
+	  /* no antialiasing */
+	  for (y = 0; y < spu->scaled_height; ++y) {
+	    int unscaled_y = y * 0x100 / scaley;
+	    int strides = spu->stride * unscaled_y;
+	    int scaled_strides = spu->scaled_stride * y;
+	    for (x = 0; x < spu->scaled_width; ++x) {
+	      int unscaled_x = x * 0x100 / scalex;
+	      spu->scaled_image[scaled_strides + x] = spu->image[strides + unscaled_x];
+	      spu->scaled_aimage[scaled_strides + x] = spu->aimage[strides + unscaled_x];
+	    }
+	  }
+	  for (y = 0; y < spu->scaled_heightuv; ++y) {
+	    int unscaled_y = y * 0x100 / scaley;
+	    int strides = spu->strideuv * unscaled_y;
+	    int scaled_strides = spu->scaled_strideuv * y;
+	    for (x = 0; x < spu->scaled_widthuv; ++x) {
+	      int unscaled_x = x * 0x100 / scalex;
+	      spu->scaled_imageu[scaled_strides + x] = spu->imageu[strides + unscaled_x];
+	      spu->scaled_imagev[scaled_strides + x] = spu->imagev[strides + unscaled_x];
+	      spu->scaled_aimageuv[scaled_strides + x] = spu->aimageuv[strides + unscaled_x];
+	    }
+	  }
+	  break;
+	  case 1:
+	  {
+	    /* Intermediate antialiasing. */
+	    for (y = 0; y < spu->scaled_height; ++y) {
+	      const unsigned int unscaled_top = y * spu->orig_frame_height / dys;
+	      unsigned int unscaled_bottom = (y + 1) * spu->orig_frame_height / dys;
+	      if (unscaled_bottom >= spu->height)
+		unscaled_bottom = spu->height - 1;
+	      for (x = 0; x < spu->scaled_width; ++x) {
+		const unsigned int unscaled_left = x * spu->orig_frame_width / dxs;
+		unsigned int unscaled_right = (x + 1) * spu->orig_frame_width / dxs;
+		unsigned int color = 0;
+		unsigned int alpha = 0;
+		unsigned int walkx, walky;
+		unsigned int base, tmp;
+		if (unscaled_right >= spu->width)
+		  unscaled_right = spu->width - 1;
+		for (walky = unscaled_top; walky <= unscaled_bottom; ++walky)
+		  for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) {
+		    base = walky * spu->stride + walkx;
+		    tmp = canon_alpha(spu->aimage[base]);
+		    alpha += tmp;
+		    color += tmp * spu->image[base];
+		  }
+		base = y * spu->scaled_stride + x;
+		spu->scaled_image[base] = alpha ? color / alpha : 0;
+		spu->scaled_aimage[base] =
+		  alpha * (1 + unscaled_bottom - unscaled_top) * (1 + unscaled_right - unscaled_left);
+		/* spu->scaled_aimage[base] =
+		  alpha * dxs * dys / spu->orig_frame_width / spu->orig_frame_height; */
+		if (spu->scaled_aimage[base]) {
+		  spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base];
+		  if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255)
+		    spu->scaled_image[base] = 256 - spu->scaled_aimage[base];
+		}
+	      }
+	    }
+	    for (y = 0; y < spu->scaled_heightuv; ++y) {
+	      const unsigned int unscaled_top = y * (spu->orig_frame_height/2) / (dys/2);
+	      unsigned int unscaled_bottom = (y + 1) * (spu->orig_frame_height/2) / (dys/2);
+	      if (unscaled_bottom >= spu->heightuv)
+		unscaled_bottom = spu->heightuv - 1;
+	      for (x = 0; x < spu->scaled_widthuv; ++x) {
+		const unsigned int unscaled_left = x * (spu->orig_frame_width/2) / (dxs/2);
+		unsigned int unscaled_right = (x + 1) * (spu->orig_frame_width/2) / (dxs/2);
+		unsigned int coloru = 0;
+		unsigned int colorv = 0;
+		unsigned int alpha = 0;
+		unsigned int walkx, walky;
+		unsigned int base, tmp;
+		if (unscaled_right >= spu->widthuv)
+		  unscaled_right = spu->widthuv - 1;
+		for (walky = unscaled_top; walky <= unscaled_bottom; ++walky)
+		  for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) {
+		    base = walky * spu->strideuv + walkx;
+		    tmp = canon_alpha(spu->aimageuv[base]);
+		    alpha += tmp;
+		    coloru += tmp * spu->imageu[base];
+		    colorv += tmp * spu->imagev[base];
+		  }
+		base = y * spu->scaled_strideuv + x;
+		spu->scaled_imageu[base] = alpha ? coloru / alpha : 0;
+		spu->scaled_imagev[base] = alpha ? colorv / alpha : 0;
+		spu->scaled_aimageuv[base] =
+		  alpha * (1 + unscaled_bottom - unscaled_top) * (1 + unscaled_right - unscaled_left);
+		/* spu->scaled_aimage[base] =
+		  alpha * dxs * dys / spu->orig_frame_width / spu->orig_frame_height; */
+		if (spu->scaled_aimageuv[base]) {
+		  spu->scaled_aimageuv[base] = 256 - spu->scaled_aimageuv[base];
+		  if (spu->scaled_aimageuv[base] + spu->scaled_imageu[base] > 255)
+		    spu->scaled_imageu[base] = 256 - spu->scaled_aimageuv[base];
+		  if (spu->scaled_aimageuv[base] + spu->scaled_imagev[base] > 255)
+		    spu->scaled_imagev[base] = 256 - spu->scaled_aimageuv[base];
+		}
+	      }
+	    }
+	  }
+	  break;
+	  case 2:
+	  {
+	    /* Best antialiasing.  Very slow. */
+	    /* Any pixel (x, y) represents pixels from the original
+	       rectangular region comprised between the columns
+	       unscaled_y and unscaled_y + 0x100 / scaley and the rows
+	       unscaled_x and unscaled_x + 0x100 / scalex
+
+	       The original rectangular region that the scaled pixel
+	       represents is cut in 9 rectangular areas like this:
+	       
+	       +---+-----------------+---+
+	       | 1 |        2        | 3 |
+	       +---+-----------------+---+
+	       |   |                 |   |
+	       | 4 |        5        | 6 |
+	       |   |                 |   |
+	       +---+-----------------+---+
+	       | 7 |        8        | 9 |
+	       +---+-----------------+---+
+
+	       The width of the left column is at most one pixel and
+	       it is never null and its right column is at a pixel
+	       boundary.  The height of the top row is at most one
+	       pixel it is never null and its bottom row is at a
+	       pixel boundary. The width and height of region 5 are
+	       integral values.  The width of the right column is
+	       what remains and is less than one pixel.  The height
+	       of the bottom row is what remains and is less than
+	       one pixel.
+
+	       The row above 1, 2, 3 is unscaled_y.  The row between
+	       1, 2, 3 and 4, 5, 6 is top_low_row.  The row between 4,
+	       5, 6 and 7, 8, 9 is (unsigned int)unscaled_y_bottom.
+	       The row beneath 7, 8, 9 is unscaled_y_bottom.
+
+	       The column left of 1, 4, 7 is unscaled_x.  The column
+	       between 1, 4, 7 and 2, 5, 8 is left_right_column.  The
+	       column between 2, 5, 8 and 3, 6, 9 is (unsigned
+	       int)unscaled_x_right.  The column right of 3, 6, 9 is
+	       unscaled_x_right. */
+	    const double inv_scalex = (double) 0x100 / scalex;
+	    const double inv_scaley = (double) 0x100 / scaley;
+	    for (y = 0; y < spu->scaled_height; ++y) {
+	      const double unscaled_y = y * inv_scaley;
+	      const double unscaled_y_bottom = unscaled_y + inv_scaley;
+	      const unsigned int top_low_row = MIN(unscaled_y_bottom, unscaled_y + 1.0);
+	      const double top = top_low_row - unscaled_y;
+	      const unsigned int height = unscaled_y_bottom > top_low_row
+		? (unsigned int) unscaled_y_bottom - top_low_row
+		: 0;
+	      const double bottom = unscaled_y_bottom > top_low_row
+		? unscaled_y_bottom - floor(unscaled_y_bottom)
+		: 0.0;
+	      for (x = 0; x < spu->scaled_width; ++x) {
+		const double unscaled_x = x * inv_scalex;
+		const double unscaled_x_right = unscaled_x + inv_scalex;
+		const unsigned int left_right_column = MIN(unscaled_x_right, unscaled_x + 1.0);
+		const double left = left_right_column - unscaled_x;
+		const unsigned int width = unscaled_x_right > left_right_column
+		  ? (unsigned int) unscaled_x_right - left_right_column
+		  : 0;
+		const double right = unscaled_x_right > left_right_column
+		  ? unscaled_x_right - floor(unscaled_x_right)
+		  : 0.0;
+		double color = 0.0;
+		double alpha = 0.0;
+		double tmp;
+		unsigned int base;
+		/* Now use these informations to compute a good alpha,
+                   and lightness.  The sum is on each of the 9
+                   region's surface and alpha and lightness.
+
+		  transformed alpha = sum(surface * alpha) / sum(surface)
+		  transformed color = sum(surface * alpha * color) / sum(surface * alpha)
+		*/
+		/* 1: top left part */
+		base = spu->stride * (unsigned int) unscaled_y;
+		tmp = left * top * canon_alpha(spu->aimage[base + (unsigned int) unscaled_x]);
+		alpha += tmp;
+		color += tmp * spu->image[base + (unsigned int) unscaled_x];
+		/* 2: top center part */
+		if (width > 0) {
+		  unsigned int walkx;
+		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
+		    base = spu->stride * (unsigned int) unscaled_y + walkx;
+		    tmp = /* 1.0 * */ top * canon_alpha(spu->aimage[base]);
+		    alpha += tmp;
+		    color += tmp * spu->image[base];
+		  }
+		}
+		/* 3: top right part */
+		if (right > 0.0) {
+		  base = spu->stride * (unsigned int) unscaled_y + (unsigned int) unscaled_x_right;
+		  tmp = right * top * canon_alpha(spu->aimage[base]);
+		  alpha += tmp;
+		  color += tmp * spu->image[base];
+		}
+		/* 4: center left part */
+		if (height > 0) {
+		  unsigned int walky;
+		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
+		    base = spu->stride * walky + (unsigned int) unscaled_x;
+		    tmp = left /* * 1.0 */ * canon_alpha(spu->aimage[base]);
+		    alpha += tmp;
+		    color += tmp * spu->image[base];
+		  }
+		}
+		/* 5: center part */
+		if (width > 0 && height > 0) {
+		  unsigned int walky;
+		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
+		    unsigned int walkx;
+		    base = spu->stride * walky;
+		    for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
+		      tmp = /* 1.0 * 1.0 * */ canon_alpha(spu->aimage[base + walkx]);
+		      alpha += tmp;
+		      color += tmp * spu->image[base + walkx];
+		    }
+		  }		    
+		}
+		/* 6: center right part */
+		if (right > 0.0 && height > 0) {
+		  unsigned int walky;
+		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
+		    base = spu->stride * walky + (unsigned int) unscaled_x_right;
+		    tmp = right /* * 1.0 */ * canon_alpha(spu->aimage[base]);
+		    alpha += tmp;
+		    color += tmp * spu->image[base];
+		  }
+		}
+		/* 7: bottom left part */
+		if (bottom > 0.0) {
+		  base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x;
+		  tmp = left * bottom * canon_alpha(spu->aimage[base]);
+		  alpha += tmp;
+		  color += tmp * spu->image[base];
+		}
+		/* 8: bottom center part */
+		if (width > 0 && bottom > 0.0) {
+		  unsigned int walkx;
+		  base = spu->stride * (unsigned int) unscaled_y_bottom;
+		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
+		    tmp = /* 1.0 * */ bottom * canon_alpha(spu->aimage[base + walkx]);
+		    alpha += tmp;
+		    color += tmp * spu->image[base + walkx];
+		  }
+		}
+		/* 9: bottom right part */
+		if (right > 0.0 && bottom > 0.0) {
+		  base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x_right;
+		  tmp = right * bottom * canon_alpha(spu->aimage[base]);
+		  alpha += tmp;
+		  color += tmp * spu->image[base];
+		}
+		/* Finally mix these transparency and brightness information suitably */
+		base = spu->scaled_stride * y + x;
+		spu->scaled_image[base] = alpha > 0 ? color / alpha : 0;
+		spu->scaled_aimage[base] = alpha * scalex * scaley / 0x10000;
+		if (spu->scaled_aimage[base]) {
+		  spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base];
+		  if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255)
+		    spu->scaled_image[base] = 256 - spu->scaled_aimage[base];
+		}
+	      }
+	    }	    
+	    for (y = 0; y < spu->scaled_heightuv; ++y) {
+	      const double unscaled_y = y * inv_scaley;
+	      const double unscaled_y_bottom = unscaled_y + inv_scaley;
+	      const unsigned int top_low_row = MIN(unscaled_y_bottom, unscaled_y + 1.0);
+	      const double top = top_low_row - unscaled_y;
+	      const unsigned int height = unscaled_y_bottom > top_low_row
+		? (unsigned int) unscaled_y_bottom - top_low_row
+		: 0;
+	      const double bottom = unscaled_y_bottom > top_low_row
+		? unscaled_y_bottom - floor(unscaled_y_bottom)
+		: 0.0;
+	      for (x = 0; x < spu->scaled_widthuv; ++x) {
+		const double unscaled_x = x * inv_scalex;
+		const double unscaled_x_right = unscaled_x + inv_scalex;
+		const unsigned int left_right_column = MIN(unscaled_x_right, unscaled_x + 1.0);
+		const double left = left_right_column - unscaled_x;
+		const unsigned int width = unscaled_x_right > left_right_column
+		  ? (unsigned int) unscaled_x_right - left_right_column
+		  : 0;
+		const double right = unscaled_x_right > left_right_column
+		  ? unscaled_x_right - floor(unscaled_x_right)
+		  : 0.0;
+		double coloru = 0.0;
+		double colorv = 0.0;
+		double alpha = 0.0;
+		double tmp;
+		unsigned int base;
+		/* Now use these informations to compute a good alpha,
+                   and lightness.  The sum is on each of the 9
+                   region's surface and alpha and lightness.
+
+		  transformed alpha = sum(surface * alpha) / sum(surface)
+		  transformed color = sum(surface * alpha * color) / sum(surface * alpha)
+		*/
+		/* 1: top left part */
+		base = spu->strideuv * (unsigned int) unscaled_y;
+		tmp = left * top * canon_alpha(spu->aimageuv[base + (unsigned int) unscaled_x]);
+		alpha += tmp;
+		coloru += tmp * spu->imageu[base + (unsigned int) unscaled_x];
+		colorv += tmp * spu->imagev[base + (unsigned int) unscaled_x];
+		/* 2: top center part */
+		if (width > 0) {
+		  unsigned int walkx;
+		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
+		    base = spu->strideuv * (unsigned int) unscaled_y + walkx;
+		    tmp = /* 1.0 * */ top * canon_alpha(spu->aimageuv[base]);
+		    alpha += tmp;
+		    coloru += tmp * spu->imageu[base];
+		    colorv += tmp * spu->imagev[base];
+		  }
+		}
+		/* 3: top right part */
+		if (right > 0.0) {
+		  base = spu->strideuv * (unsigned int) unscaled_y + (unsigned int) unscaled_x_right;
+		  tmp = right * top * canon_alpha(spu->aimageuv[base]);
+		  alpha += tmp;
+		  coloru += tmp * spu->imageu[base];
+		  colorv += tmp * spu->imagev[base];
+		}
+		/* 4: center left part */
+		if (height > 0) {
+		  unsigned int walky;
+		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
+		    base = spu->strideuv * walky + (unsigned int) unscaled_x;
+		    tmp = left /* * 1.0 */ * canon_alpha(spu->aimageuv[base]);
+		    alpha += tmp;
+		    coloru += tmp * spu->imageu[base];
+		    colorv += tmp * spu->imagev[base];
+		  }
+		}
+		/* 5: center part */
+		if (width > 0 && height > 0) {
+		  unsigned int walky;
+		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
+		    unsigned int walkx;
+		    base = spu->strideuv * walky;
+		    for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
+		      tmp = /* 1.0 * 1.0 * */ canon_alpha(spu->aimageuv[base + walkx]);
+		      alpha += tmp;
+		      coloru += tmp * spu->imageu[base + walkx];
+		      colorv += tmp * spu->imagev[base + walkx];
+		    }
+		  }		    
+		}
+		/* 6: center right part */
+		if (right > 0.0 && height > 0) {
+		  unsigned int walky;
+		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
+		    base = spu->strideuv * walky + (unsigned int) unscaled_x_right;
+		    tmp = right /* * 1.0 */ * canon_alpha(spu->aimageuv[base]);
+		    alpha += tmp;
+		    coloru += tmp * spu->imageu[base];
+		    colorv += tmp * spu->imagev[base];
+		  }
+		}
+		/* 7: bottom left part */
+		if (bottom > 0.0) {
+		  base = spu->strideuv * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x;
+		  tmp = left * bottom * canon_alpha(spu->aimageuv[base]);
+		  alpha += tmp;
+		  coloru += tmp * spu->imageu[base];
+		  colorv += tmp * spu->imagev[base];
+		}
+		/* 8: bottom center part */
+		if (width > 0 && bottom > 0.0) {
+		  unsigned int walkx;
+		  base = spu->strideuv * (unsigned int) unscaled_y_bottom;
+		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
+		    tmp = /* 1.0 * */ bottom * canon_alpha(spu->aimageuv[base + walkx]);
+		    alpha += tmp;
+		    coloru += tmp * spu->imageu[base + walkx];
+		    colorv += tmp * spu->imagev[base + walkx];
+		  }
+		}
+		/* 9: bottom right part */
+		if (right > 0.0 && bottom > 0.0) {
+		  base = spu->strideuv * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x_right;
+		  tmp = right * bottom * canon_alpha(spu->aimageuv[base]);
+		  alpha += tmp;
+		  coloru += tmp * spu->imageu[base];
+		  colorv += tmp * spu->imagev[base];
+		}
+		/* Finally mix these transparency and brightness information suitably */
+		base = spu->scaled_strideuv * y + x;
+		spu->scaled_imageu[base] = alpha > 0 ? coloru / alpha : 0;
+		spu->scaled_imagev[base] = alpha > 0 ? colorv / alpha : 0;
+		spu->scaled_aimageuv[base] = alpha * scalex * scaley / 0x10000;
+		if (spu->scaled_aimageuv[base]) {
+		  spu->scaled_aimageuv[base] = 256 - spu->scaled_aimageuv[base];
+		  if (spu->scaled_aimageuv[base] + spu->scaled_imageu[base] > 255)
+		    spu->scaled_imageu[base] = 256 - spu->scaled_aimageuv[base];
+		  if (spu->scaled_aimageuv[base] + spu->scaled_imagev[base] > 255)
+		    spu->scaled_imagev[base] = 256 - spu->scaled_aimageuv[base];
+		}
+	      }
+	    }
+	  }
+	  }
+nothing_to_do:
+	  /* Kludge: draw_alpha needs width multiple of 8. */
+	  if (spu->scaled_width < spu->scaled_stride)
+	    for (y = 0; y < spu->scaled_height; ++y) {
+	      memset(spu->scaled_aimage + y * spu->scaled_stride + spu->scaled_width, 0,
+		     spu->scaled_stride - spu->scaled_width);
+	    }
+	  spu->scaled_frame_width = dxs;
+	  spu->scaled_frame_height = dys;
+	  if (spu->scaled_widthuv < spu->scaled_strideuv)
+	    for (y = 0; y < spu->scaled_heightuv; ++y) {
+	      memset(spu->scaled_aimageuv + y * spu->scaled_stride + spu->scaled_widthuv, 0,
+		     spu->scaled_strideuv - spu->scaled_widthuv);
+	    }
+	  spu->scaled_frame_widthuv = dxs/2;
+	  spu->scaled_frame_heightuv = dys/2;
+	}
+      }
+      if (spu->scaled_image){
+        switch (spu_alignment) {
+        case 0:
+          spu->scaled_start_row = dys*sub_pos/100;
+	  if (spu->scaled_start_row + spu->scaled_height > dys)
+	    spu->scaled_start_row = dys - spu->scaled_height;
+          spu->scaled_start_rowuv = (dys/2)*sub_pos/100;
+	  if (spu->scaled_start_rowuv + spu->scaled_heightuv > (dys/2))
+	    spu->scaled_start_rowuv = (dys/2) - spu->scaled_heightuv;
+	  break;
+	case 1:
+          spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height/2;
+          if (sub_pos < 50) {
+	    if (spu->scaled_start_row < 0) spu->scaled_start_row = 0;
+	  } else {
+	    if (spu->scaled_start_row + spu->scaled_height > dys)
+	      spu->scaled_start_row = dys - spu->scaled_height;
+	  }
+          spu->scaled_start_rowuv = (dys/2)*sub_pos/100 - spu->scaled_heightuv/2;
+          if (sub_pos < 50) {
+	    if (spu->scaled_start_rowuv < 0) spu->scaled_start_rowuv = 0;
+	  } else {
+	    if (spu->scaled_start_rowuv + spu->scaled_heightuv > (dys/2))
+	      spu->scaled_start_rowuv = (dys/2) - spu->scaled_heightuv;
+	  }
+	  break;
+        case 2:
+          spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height;
+	  if (spu->scaled_start_row < 0) spu->scaled_start_row = 0;
+          spu->scaled_start_rowuv = (dys/2)*sub_pos/100 - spu->scaled_heightuv;
+	  if (spu->scaled_start_rowuv < 0) spu->scaled_start_rowuv = 0;
+	  break;
+	}
+	if (spu->dvdnav_color_spu==DVDNAV_SPU_YUY) {
+	  if (!spu->imageyuy) spudec_create_yuy(spu,1);
+	  if (spu->imageyuy) draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width*2, spu->scaled_height,6,
+		    spu->imageyuy, spu->aimageyuy, spu->strideyuy);
+	  } else {
+	  draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,0,
+		   spu->scaled_image, spu->scaled_aimage, spu->scaled_stride);
+	  draw_alpha(spu->scaled_start_coluv, spu->scaled_start_rowuv, spu->scaled_widthuv, spu->scaled_heightuv,1,
+		   spu->scaled_imageu, spu->scaled_aimageuv, spu->scaled_strideuv);
+	  draw_alpha(spu->scaled_start_coluv, spu->scaled_start_rowuv, spu->scaled_widthuv, spu->scaled_heightuv,2,
+		   spu->scaled_imagev, spu->scaled_aimageuv, spu->scaled_strideuv);
+	  }
+	spu->spu_changed = 0;
+      }
+    }
+  }
+  else
+  {
+    mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPU not displayed: start_pts=%d  end_pts=%d  now_pts=%d\n",
+        spu->start_pts, spu->end_pts, spu->now_pts);
+  }
+}
+
+void spudec_draw_scaled_rgb(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride))
+{
+  spudec_handle_t *spu = (spudec_handle_t *)me;
+  scale_pixel *table_x;
+  scale_pixel *table_y;
+  unsigned int scalex = 0;
+  unsigned int scaley = 0;
+
+  if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) {
+
+    // check if only forced subtitles are requested 
+    if( (spu->forced_subs_only) && !(spu->is_forced_sub) ){ 
+	return;
+    }
+
+    if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || spu->orig_frame_height == 0
+	|| (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) {
+      if (spu->image)
+      {
+      draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,3,
+	    spu->image, spu->aimage, spu->stride);
+      draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,4,
+	   spu->imageu, spu->aimage, spu->stride);
+      draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,5,
+	   spu->imagev, spu->aimage, spu->stride);
+      spu->spu_changed = 0;
+      }
+    }
+    else {
+      if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) {	/* Resizing is needed */
+	/* scaled_x = scalex * x / 0x100
+	   scaled_y = scaley * y / 0x100
+	   order of operations is important because of rounding. */
+	scalex = 0x100 * dxs / spu->orig_frame_width;
+	scaley = 0x100 * dys / spu->orig_frame_height;
+
+	spu->scaled_start_col = spu->start_col * scalex / 0x100;
+	spu->scaled_start_row = spu->start_row * scaley / 0x100;
+	spu->scaled_width = spu->width * scalex / 0x100;
+	spu->scaled_height = spu->height * scaley / 0x100;
+	/* Kludge: draw_alpha needs width multiple of 8 */
+	spu->scaled_stride = (spu->scaled_width + 7) & ~7;
+	if (spu->scaled_image_size < spu->scaled_stride * spu->scaled_height) {
+	  if (spu->scaled_image) {
+	    free(spu->scaled_image);
+	  if (spu->scaled_imageu)
+	    free(spu->scaled_imageu);
+	    spu->scaled_image_size = 0;
+	  }
+	  spu->scaled_image = malloc(2 * spu->scaled_stride * spu->scaled_height);
+	  spu->scaled_imageu = malloc(3 * spu->scaled_stride * spu->scaled_height);
+	  if (spu->scaled_image) {
+	    spu->scaled_image_size = spu->scaled_stride * spu->scaled_height;
+	    spu->scaled_aimage = spu->scaled_image + spu->scaled_image_size;
+	  }
+	  if (spu->scaled_imageu) {
+	    spu->scaled_imagev = spu->scaled_imageu + spu->scaled_image_size;
+	  }
+	}
+	if (spu->scaled_image) {
+	  unsigned int x, y;
+	  if (spu->scaled_width <= 1 || spu->scaled_height <= 1) {
+	    goto nothing_to_do;
+	  }
+	  switch(spu_aamode&15) {
+	  case 4:
+	  sws_spu_image_rgb(spu->scaled_image,spu->scaled_imageu,spu->scaled_imagev, spu->scaled_aimage,
+		  spu->scaled_width, spu->scaled_height, spu->scaled_stride,
+		  spu->image, spu->imageu, spu->imagev, spu->aimage, spu->width, spu->height, spu->stride);
+	  break;
+	  case 3:
+	  table_x = calloc(spu->scaled_width, sizeof(scale_pixel));
+	  table_y = calloc(spu->scaled_height, sizeof(scale_pixel));
+	  if (!table_x || !table_y) {
+	    mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: spudec_draw_scaled: calloc failed\n");
+	  }
+	  scale_table(0, 0, spu->width - 1, spu->scaled_width - 1, table_x);
+	  scale_table(0, 0, spu->height - 1, spu->scaled_height - 1, table_y);
+	  for (y = 0; y < spu->scaled_height; y++)
+	    for (x = 0; x < spu->scaled_width; x++)
+	      scale_image_rgb(x, y, table_x, table_y, spu);
+	  free(table_x);
+	  free(table_y);
+	  break;
+	  case 0:
+	  /* no antialiasing */
+	  for (y = 0; y < spu->scaled_height; ++y) {
+	    int unscaled_y = y * 0x100 / scaley;
+	    int strides = spu->stride * unscaled_y;
+	    int scaled_strides = spu->scaled_stride * y;
+	    for (x = 0; x < spu->scaled_width; ++x) {
+	      int unscaled_x = x * 0x100 / scalex;
+	      spu->scaled_image[scaled_strides + x] = spu->image[strides + unscaled_x];
+	      spu->scaled_imageu[scaled_strides + x] = spu->imageu[strides + unscaled_x];
+	      spu->scaled_imagev[scaled_strides + x] = spu->imagev[strides + unscaled_x];
+	      spu->scaled_aimage[scaled_strides + x] = spu->aimage[strides + unscaled_x];
+	    }
+	  }
+	  break;
+	  case 1:
+	  {
+	    /* Intermediate antialiasing. */
+	    for (y = 0; y < spu->scaled_height; ++y) {
+	      const unsigned int unscaled_top = y * spu->orig_frame_height / dys;
+	      unsigned int unscaled_bottom = (y + 1) * spu->orig_frame_height / dys;
+	      if (unscaled_bottom >= spu->height)
+		unscaled_bottom = spu->height - 1;
+	      for (x = 0; x < spu->scaled_width; ++x) {
+		const unsigned int unscaled_left = x * spu->orig_frame_width / dxs;
+		unsigned int unscaled_right = (x + 1) * spu->orig_frame_width / dxs;
+		unsigned int colorr = 0;
+		unsigned int colorg = 0;
+		unsigned int colorb = 0;
+		unsigned int alpha = 0;
+		unsigned int walkx, walky;
+		unsigned int base, tmp;
+		if (unscaled_right >= spu->width)
+		  unscaled_right = spu->width - 1;
+		for (walky = unscaled_top; walky <= unscaled_bottom; ++walky)
+		  for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) {
+		    base = walky * spu->stride + walkx;
+		    tmp = canon_alpha(spu->aimage[base]);
+		    alpha += tmp;
+		    colorr += tmp * spu->image[base];
+		    colorg += tmp * spu->imageu[base];
+		    colorb += tmp * spu->imagev[base];
+		  }
+		base = y * spu->scaled_stride + x;
+		spu->scaled_image[base] = alpha ? colorr / alpha : 0;
+		spu->scaled_imageu[base] = alpha ? colorg / alpha : 0;
+		spu->scaled_imagev[base] = alpha ? colorb / alpha : 0;
+		spu->scaled_aimage[base] =
+		  alpha * (1 + unscaled_bottom - unscaled_top) * (1 + unscaled_right - unscaled_left);
+		/* spu->scaled_aimage[base] =
+		  alpha * dxs * dys / spu->orig_frame_width / spu->orig_frame_height; */
+		if (spu->scaled_aimage[base]) {
+		  spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base];
+		  if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255)
+		    spu->scaled_image[base] = 256 - spu->scaled_aimage[base];
+		  if (spu->scaled_aimage[base] + spu->scaled_imageu[base] > 255)
+		    spu->scaled_imageu[base] = 256 - spu->scaled_aimage[base];
+		  if (spu->scaled_aimage[base] + spu->scaled_imagev[base] > 255)
+		    spu->scaled_imagev[base] = 256 - spu->scaled_aimage[base];
+		}
+	      }
+	    }
+	  }
+	  break;
+	  case 2:
+	  {
+	    /* Best antialiasing.  Very slow. */
+	    /* Any pixel (x, y) represents pixels from the original
+	       rectangular region comprised between the columns
+	       unscaled_y and unscaled_y + 0x100 / scaley and the rows
+	       unscaled_x and unscaled_x + 0x100 / scalex
+
+	       The original rectangular region that the scaled pixel
+	       represents is cut in 9 rectangular areas like this:
+	       
+	       +---+-----------------+---+
+	       | 1 |        2        | 3 |
+	       +---+-----------------+---+
+	       |   |                 |   |
+	       | 4 |        5        | 6 |
+	       |   |                 |   |
+	       +---+-----------------+---+
+	       | 7 |        8        | 9 |
+	       +---+-----------------+---+
+
+	       The width of the left column is at most one pixel and
+	       it is never null and its right column is at a pixel
+	       boundary.  The height of the top row is at most one
+	       pixel it is never null and its bottom row is at a
+	       pixel boundary. The width and height of region 5 are
+	       integral values.  The width of the right column is
+	       what remains and is less than one pixel.  The height
+	       of the bottom row is what remains and is less than
+	       one pixel.
+
+	       The row above 1, 2, 3 is unscaled_y.  The row between
+	       1, 2, 3 and 4, 5, 6 is top_low_row.  The row between 4,
+	       5, 6 and 7, 8, 9 is (unsigned int)unscaled_y_bottom.
+	       The row beneath 7, 8, 9 is unscaled_y_bottom.
+
+	       The column left of 1, 4, 7 is unscaled_x.  The column
+	       between 1, 4, 7 and 2, 5, 8 is left_right_column.  The
+	       column between 2, 5, 8 and 3, 6, 9 is (unsigned
+	       int)unscaled_x_right.  The column right of 3, 6, 9 is
+	       unscaled_x_right. */
+	    const double inv_scalex = (double) 0x100 / scalex;
+	    const double inv_scaley = (double) 0x100 / scaley;
+	    for (y = 0; y < spu->scaled_height; ++y) {
+	      const double unscaled_y = y * inv_scaley;
+	      const double unscaled_y_bottom = unscaled_y + inv_scaley;
+	      const unsigned int top_low_row = MIN(unscaled_y_bottom, unscaled_y + 1.0);
+	      const double top = top_low_row - unscaled_y;
+	      const unsigned int height = unscaled_y_bottom > top_low_row
+		? (unsigned int) unscaled_y_bottom - top_low_row
+		: 0;
+	      const double bottom = unscaled_y_bottom > top_low_row
+		? unscaled_y_bottom - floor(unscaled_y_bottom)
+		: 0.0;
+	      for (x = 0; x < spu->scaled_width; ++x) {
+		const double unscaled_x = x * inv_scalex;
+		const double unscaled_x_right = unscaled_x + inv_scalex;
+		const unsigned int left_right_column = MIN(unscaled_x_right, unscaled_x + 1.0);
+		const double left = left_right_column - unscaled_x;
+		const unsigned int width = unscaled_x_right > left_right_column
+		  ? (unsigned int) unscaled_x_right - left_right_column
+		  : 0;
+		const double right = unscaled_x_right > left_right_column
+		  ? unscaled_x_right - floor(unscaled_x_right)
+		  : 0.0;
+		double colorr = 0.0;
+		double colorg = 0.0;
+		double colorb = 0.0;
+		double alpha = 0.0;
+		double tmp;
+		unsigned int base;
+		/* Now use these informations to compute a good alpha,
+                   and lightness.  The sum is on each of the 9
+                   region's surface and alpha and lightness.
+
+		  transformed alpha = sum(surface * alpha) / sum(surface)
+		  transformed color = sum(surface * alpha * color) / sum(surface * alpha)
+		*/
+		/* 1: top left part */
+		base = spu->stride * (unsigned int) unscaled_y;
+		tmp = left * top * canon_alpha(spu->aimage[base + (unsigned int) unscaled_x]);
+		alpha += tmp;
+		colorr += tmp * spu->image[base + (unsigned int) unscaled_x];
+		colorg += tmp * spu->imageu[base + (unsigned int) unscaled_x];
+		colorb += tmp * spu->imagev[base + (unsigned int) unscaled_x];
+		/* 2: top center part */
+		if (width > 0) {
+		  unsigned int walkx;
+		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
+		    base = spu->stride * (unsigned int) unscaled_y + walkx;
+		    tmp = /* 1.0 * */ top * canon_alpha(spu->aimage[base]);
+		    alpha += tmp;
+		    colorr += tmp * spu->image[base];
+		    colorg += tmp * spu->imageu[base];
+		    colorb += tmp * spu->imagev[base];
+		  }
+		}
+		/* 3: top right part */
+		if (right > 0.0) {
+		  base = spu->stride * (unsigned int) unscaled_y + (unsigned int) unscaled_x_right;
+		  tmp = right * top * canon_alpha(spu->aimage[base]);
+		  alpha += tmp;
+		  colorr += tmp * spu->image[base];
+		  colorg += tmp * spu->imageu[base];
+		  colorb += tmp * spu->imagev[base];
+		}
+		/* 4: center left part */
+		if (height > 0) {
+		  unsigned int walky;
+		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
+		    base = spu->stride * walky + (unsigned int) unscaled_x;
+		    tmp = left /* * 1.0 */ * canon_alpha(spu->aimage[base]);
+		    alpha += tmp;
+		    colorr += tmp * spu->image[base];
+		    colorg += tmp * spu->imageu[base];
+		    colorb += tmp * spu->imagev[base];
+		  }
+		}
+		/* 5: center part */
+		if (width > 0 && height > 0) {
+		  unsigned int walky;
+		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
+		    unsigned int walkx;
+		    base = spu->stride * walky;
+		    for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
+		      tmp = /* 1.0 * 1.0 * */ canon_alpha(spu->aimage[base + walkx]);
+		      alpha += tmp;
+		      colorr += tmp * spu->image[base + walkx];
+		      colorg += tmp * spu->imageu[base + walkx];
+		      colorb += tmp * spu->imagev[base + walkx];
+		    }
+		  }		    
+		}
+		/* 6: center right part */
+		if (right > 0.0 && height > 0) {
+		  unsigned int walky;
+		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
+		    base = spu->stride * walky + (unsigned int) unscaled_x_right;
+		    tmp = right /* * 1.0 */ * canon_alpha(spu->aimage[base]);
+		    alpha += tmp;
+		    colorr += tmp * spu->image[base];
+		    colorg += tmp * spu->imageu[base];
+		    colorb += tmp * spu->imagev[base];
+		  }
+		}
+		/* 7: bottom left part */
+		if (bottom > 0.0) {
+		  base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x;
+		  tmp = left * bottom * canon_alpha(spu->aimage[base]);
+		  alpha += tmp;
+		  colorr += tmp * spu->image[base];
+		  colorg += tmp * spu->imageu[base];
+		  colorb += tmp * spu->imagev[base];
+		}
+		/* 8: bottom center part */
+		if (width > 0 && bottom > 0.0) {
+		  unsigned int walkx;
+		  base = spu->stride * (unsigned int) unscaled_y_bottom;
+		  for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) {
+		    tmp = /* 1.0 * */ bottom * canon_alpha(spu->aimage[base + walkx]);
+		    alpha += tmp;
+		    colorr += tmp * spu->image[base + walkx];
+		    colorg += tmp * spu->imageu[base + walkx];
+		    colorb += tmp * spu->imagev[base + walkx];
+		  }
+		}
+		/* 9: bottom right part */
+		if (right > 0.0 && bottom > 0.0) {
+		  base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x_right;
+		  tmp = right * bottom * canon_alpha(spu->aimage[base]);
+		  alpha += tmp;
+		  colorr += tmp * spu->image[base];
+		  colorg += tmp * spu->imageu[base];
+		  colorb += tmp * spu->imagev[base];
+		}
+		/* Finally mix these transparency and brightness information suitably */
+		base = spu->scaled_stride * y + x;
+		spu->scaled_image[base] = alpha > 0 ? colorr / alpha : 0;
+		spu->scaled_imageu[base] = alpha > 0 ? colorg / alpha : 0;
+		spu->scaled_imagev[base] = alpha > 0 ? colorb / alpha : 0;
+		spu->scaled_aimage[base] = alpha * scalex * scaley / 0x10000;
+		if (spu->scaled_aimage[base]) {
+		  spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base];
+		  if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255)
+		    spu->scaled_image[base] = 256 - spu->scaled_aimage[base];
+		  if (spu->scaled_aimage[base] + spu->scaled_imageu[base] > 255)
+		    spu->scaled_imageu[base] = 256 - spu->scaled_aimage[base];
+		  if (spu->scaled_aimage[base] + spu->scaled_imagev[base] > 255)
+		    spu->scaled_imagev[base] = 256 - spu->scaled_aimage[base];
+		}
+	      }
+	    }
+	  }
+	  }
+nothing_to_do:
+	  /* Kludge: draw_alpha needs width multiple of 8. */
+	  if (spu->scaled_width < spu->scaled_stride)
+	    for (y = 0; y < spu->scaled_height; ++y) {
+	      memset(spu->scaled_aimage + y * spu->scaled_stride + spu->scaled_width, 0,
+		     spu->scaled_stride - spu->scaled_width);
+	    }
+	  spu->scaled_frame_width = dxs;
+	  spu->scaled_frame_height = dys;
+	}
+      }
+      if (spu->scaled_image){
+        switch (spu_alignment) {
+        case 0:
+          spu->scaled_start_row = dys*sub_pos/100;
+	  if (spu->scaled_start_row + spu->scaled_height > dys)
+	    spu->scaled_start_row = dys - spu->scaled_height;
+	  break;
+	case 1:
+          spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height/2;
+          if (sub_pos < 50) {
+	    if (spu->scaled_start_row < 0) spu->scaled_start_row = 0;
+	  } else {
+	    if (spu->scaled_start_row + spu->scaled_height > dys)
+	      spu->scaled_start_row = dys - spu->scaled_height;
+	  }
+	  break;
+        case 2:
+          spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height;
+	  if (spu->scaled_start_row < 0) spu->scaled_start_row = 0;
+	  break;
+	}
+	draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,3,
+		   spu->scaled_image, spu->scaled_aimage, spu->scaled_stride);
+	draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,4,
+		   spu->scaled_imageu, spu->scaled_aimage, spu->scaled_stride);
+	draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,5,
+		   spu->scaled_imagev, spu->scaled_aimage, spu->scaled_stride);
+	spu->spu_changed = 0;
+      }
+    }
+  }
+  else
+  {
+    mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPU not displayed: start_pts=%d  end_pts=%d  now_pts=%d\n",
+        spu->start_pts, spu->end_pts, spu->now_pts);
+  }
+}
+#endif
+
+void spudec_update_palette(void * this, unsigned int *palette)
+{
+  spudec_handle_t *spu = (spudec_handle_t *) this;
+  if (spu && palette) {
+    memcpy(spu->global_palette, palette, sizeof(spu->global_palette));
+    if(spu->hw_spu)
+      spu->hw_spu->control(VOCTRL_SET_SPU_PALETTE,spu->global_palette);
+  }
+}
+
+void spudec_set_font_factor(void * this, double factor)
+{
+  spudec_handle_t *spu = (spudec_handle_t *) this;
+  spu->font_start_level = (int)(0xF0-(0xE0*factor));
+}
+
+void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height)
+{
+  return spudec_new_scaled_vobsub(palette, NULL, 0, frame_width, frame_height);
+}
+
+/* get palette custom color, width, height from .idx file */
+void *spudec_new_scaled_vobsub(unsigned int *palette, unsigned int *cuspal, unsigned int custom, unsigned int frame_width, unsigned int frame_height)
+{
+  spudec_handle_t *this = calloc(1, sizeof(spudec_handle_t));
+  if (this){
+    //(fprintf(stderr,"VobSub Custom Palette: %d,%d,%d,%d", this->cuspal[0], this->cuspal[1], this->cuspal[2],this->cuspal[3]);
+    this->packet = NULL;
+    this->image = NULL;
+    this->scaled_image = NULL;
+    /* XXX Although the video frame is some size, the SPU frame is
+       always maximum size i.e. 720 wide and 576 or 480 high */
+    this->orig_frame_width = 720;
+    this->orig_frame_height = (frame_height == 480 || frame_height == 240) ? 480 : 576;
+    this->custom = custom;
+    // set up palette:
+    this->auto_palette = 1;
+    if (palette){
+      memcpy(this->global_palette, palette, sizeof(this->global_palette));
+      this->auto_palette = 0;
+    }
+    this->custom = custom;
+    if (custom && cuspal) {
+      memcpy(this->cuspal, cuspal, sizeof(this->cuspal));
+      this->auto_palette = 0;
+    }
+    // forced subtitles default: show all subtitles
+    this->forced_subs_only=0;
+    this->is_forced_sub=0;
+  }
+  else
+    mp_msg(MSGT_SPUDEC,MSGL_FATAL, "FATAL: spudec_init: calloc");
+  return this;
 }
 
 void *spudec_new(unsigned int *palette)
@@ -1170,6 +2825,23 @@
 	free(spu->scaled_image);
     if (spu->image)
       free(spu->image);
+#ifdef USE_MPDVDNAV
+    if (spu->dvdnav_image)
+      free(spu->dvdnav_image);
+    if (spu->dvdnav_aimage)
+      free(spu->dvdnav_aimage);
+
+    if (spu->imageu)
+      free(spu->imageu);
+    if (spu->imageyuy)
+      free(spu->imageyuy);
+    spu->imageyuy=NULL;
+    if (spu->scaled_imageu)
+	free(spu->scaled_imageu);
+
+    if (spu->last_packet) {spudec_free_packet(spu->last_packet); spu->last_packet=NULL;}
+    spu->dvdnav_allocated = 0;
+#endif
     free(spu);
   }
 }
--- cfg-common.h	2006-03-26 13:09:17.000000000 +0200
+++ cfg-common.h	2006-04-04 01:27:36.000000000 +0200
@@ -31,6 +31,23 @@
 	{"dvdnav", "-dvdnav is deprecated, use dvdnav:// instead.\n", CONF_TYPE_PRINT, 0, 0, 1, NULL},
 	{"skipopening", &dvd_nav_skip_opening, CONF_TYPE_FLAG, 0, 0, 1, NULL},
 	{"noskipopening", &dvd_nav_skip_opening, CONF_TYPE_FLAG, 0, 1, 0, NULL},
+#ifdef USE_MPDVDNAV
+	{"mlang", &dvdmenu_lang, CONF_TYPE_STRING, 0, 0, 0, NULL},
+	{"dvdnav-menutype", &dvdnav_menutype, CONF_TYPE_INT, CONF_RANGE|CONF_GLOBAL, 0, 2, NULL},
+	{"dvdnav-color-spu", &dvdnav_color_spu, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"dvdnav-nocolor-spu", &dvdnav_color_spu, CONF_TYPE_FLAG, 0, 1, 0, NULL},
+	{"dvdnav-force-menu", &dvdnav_force_menu, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"dvdnav-noforce-menu", &dvdnav_force_menu, CONF_TYPE_FLAG, 0, 1, 0, NULL},
+//	{"dvdnav-skipintro", &dvdnav_skipintro, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+//	{"dvdnav-noskipintro", &dvdnav_skipintro, CONF_TYPE_FLAG, 0, 1, 0, NULL},
+#ifdef USE_MPDVDNAV_TRACE
+	{"dvdnav-trace", &dvdnav_trace, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"dvdnav-notrace", &dvdnav_trace, CONF_TYPE_FLAG, 0, 1, 0, NULL},
+#else
+	{"dvdnav-trace", "MPlayer was compiled without dvdnav trace support.\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
+	{"dvdnav-notrace", "MPlayer was compiled without dvdnav trace support.\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
+#endif
+#endif
 #endif
 #ifdef USE_DVDREAD
 	{"dvd-device", &dvd_device,  CONF_TYPE_STRING, 0, 0, 0, NULL}, 
--- configure	2006-04-02 15:31:02.000000000 +0200
+++ configure	2006-04-04 01:27:36.000000000 +0200
@@ -204,7 +204,7 @@
   --enable-smb           enable Samba (SMB) input support [autodetect]
   --enable-live          enable LIVE555 Streaming Media support [autodetect]
   --disable-dvdread      Disable libdvdread support [autodetect]
-  --disable-mpdvdkit     Disable mpdvdkit2 support [autodetect]
+  --disable-mpdvdkit     Disable mpdvdkit/mpdvdkit2 support [autodetect]
   --disable-cdparanoia   Disable cdparanoia support [autodetect]
   --disable-freetype     Disable freetype2 font rendering support [autodetect]
   --disable-fontconfig   Disable fontconfig font lookup support [autodetect]
@@ -774,7 +774,7 @@
   _cpuinfo="hostinfo"
 elif aix; then
   # use 'lsattr' on AIX
-  _cpuinfo="lsattr -E -l proc0 -a type"
+  _cpuinfo="lsattr -E -l proc0"
 elif x86; then
   # all other OSes try to extract CPU information from a small helper
   # program TOOLS/cpuinfo instead
@@ -1197,7 +1197,7 @@
 	esac
         ;;
       AIX)
-	proc=`$_cpuinfo | grep 'type' | cut -f 2 -d ' ' | sed 's/PowerPC_//'`
+	proc=`$_cpuinfo | grep 'type' | cut -f 7 -d ' ' | sed 's/PowerPC_//'`
 	;;
     esac
     if test "$_altivec" = yes; then
@@ -1534,6 +1534,8 @@
 _have_dvd=no
 # dvdnav disabled, it does not work
 #_dvdnav=no
+_dvdnav=yes
+_dvdnav_trace=yes
 _dvdread=auto
 _dvdkit=auto
 _xanim=auto
@@ -1587,7 +1589,7 @@
 _linux_devfs=no
 #_charset=utf8
 _dynamic_plugins=no
-_crash_debug=no
+_crash_debug=auto
 _sighandler=yes
 _libdv=auto
 _cdparanoia=auto
@@ -1754,6 +1756,10 @@
 # dvdnav disabled, it does not work
 #  --enable-dvdnav)	_dvdnav=yes	;;
 #  --disable-dvdnav)	_dvdnav=no	;;
+  --enable-dvdnav)	_dvdnav=yes	;;
+  --disable-dvdnav)	_dvdnav=no	;;
+  --enable-dvdnav-trace) 	_dvdnav_trace=yes	;;
+  --disable-dvdnav-trace)	_dvdnav_trace=no	;;
   --enable-xanim)	_xanim=yes	;;
   --disable-xanim)	_xanim=no	;;
   --enable-real)	_real=yes	;;
@@ -4971,16 +4977,22 @@
  _dvdkit=no
  if linux || freebsd || netbsd || darwin || openbsd || win32 || sunos || hpux; then
   test -f "./libmpdvdkit2/Makefile" && _dvdkit=yes
+  test -f "./libmpdvdkit/Makefile" && _dvdkit=yes
  fi
 fi
 if test "$_dvdkit" = yes ; then
   if test "$_dvd" = yes || test "$_cdrom" = yes || test "$_cdio" = yes || test "$_dvdio" = yes || test "$_bsdi_dvd" = yes || test "$_hpux_scsi_h" = yes || darwin || win32 ; then
+   if test -f "./libmpdvdkit2/Makefile" ; then
     _inputmodules="mpdvdkit2 $_inputmodules"
     _dvdread=libmpdvdkit2
     _dvdkit2=yes
     _dvdkit=no
   else
-    _noinputmodules="mpdvdkit2 $_noinputmodules"
+    _inputmodules="mpdvdkit $_inputmodules"
+    _dvdread=libmpdvdkit
+   fi
+  else
+    _noinputmodules="mpdvdkit $_noinputmodules"
   fi
   _def_dvd_linux='#undef HAVE_LINUX_DVD_STRUCT'
   _def_dvd_bsd='#undef HAVE_BSD_DVD_STRUCT'
@@ -5001,9 +5013,9 @@
     fi
   fi
 else
-  _noinputmodules="mpdvdkit2 $_noinputmodules"
+  _noinputmodules="mpdvdkit $_noinputmodules"
 fi
-if test "$_dvdkit2" = yes; then
+if test "$_dvdkit" = yes || test "$_dvdkit2" = yes; then
   _have_dvd=yes
   echores "yes"
 else
@@ -5042,6 +5054,15 @@
 	_noinputmodules="dvdread $_noinputmodules"
 	echores "no"
 	;;
+  libmpdvdkit)
+	_largefiles=yes
+	_def_dvdread='#define USE_DVDREAD 1'
+	_ld_dvdread='-Llibmpdvdkit -lmpdvdkit'
+	_noinputmodules="dvdread $_noinputmodules"
+	_def_mpdvdkit="#define USE_MPDVDKIT 1"
+	_have_dvd=yes
+	echores "disabled by libmpdvdkit"
+	;;
   libmpdvdkit2)
 	_largefiles=yes
 	_def_dvdread='#define USE_DVDREAD 1'
@@ -5102,6 +5123,25 @@
 #   _noinputmodules="dvdnav $_noinputmodules"
 #   echores "no"
 # fi
+echocheck "DVDNAV support"
+if test "$_dvdnav" = yes ; then
+  _largefiles=yes
+  _def_dvdnav='#define USE_DVDNAV 1'
+  _def_mpdvdnav='#define USE_MPDVDNAV 1'
+if test "$_dvdnav_trace" = yes ; then
+  _def_mpdvdnav_trace='#define USE_MPDVDNAV_TRACE 1'
+  _inputmodules="dvdnav(dvdnav-trace) $_inputmodules"
+else
+  _inputmodules="dvdnav $_inputmodules"
+fi
+  _dvdnav_version='0110'
+  _def_dvdnav_version="#define DVDNAVVERSION $_dvdnav_version"
+  _def_dvdnav_sversion="#define DVDNAVSVERSION \"0.1.10\""
+  echores "yes"
+else
+  _noinputmodules="dvdnav $_noinputmodules"
+fi
+echores "$_dvdnav"
 
 echocheck "cdparanoia"
 if test "$_cdparanoia" = auto ; then
@@ -6964,6 +7004,14 @@
   _stripbinaries=no
 elif test -z "$CFLAGS" ; then
     CFLAGS="-O4 $_march $_mcpu $_pipe -ffast-math -fomit-frame-pointer"
+  # always compile with '-g' if .developer:
+  if test -f ".developer" ; then
+    CFLAGS="-g $CFLAGS"
+    if test "$_crash_debug" = auto && not mingw32 ; then
+      _crash_debug=yes
+    fi
+    _stripbinaries=no
+  fi
 else
   _warn_CFLAGS=yes
 fi
@@ -7303,7 +7351,10 @@
 HAVE_DVD = $_have_dvd
 DVDREAD = $_dvdread
 DVDREAD_LIB = $_ld_dvdread
+DVDKIT = $_dvdkit
 DVDKIT2 = $_dvdkit2
+DVDKIT_SHARED = no
+LIBMPDVDNAV = $_dvdnav
 SDL_INC = $_inc_sdl
 W32_DEP = $_dep_win32
 W32_LIB = $_ld_win32
@@ -7684,6 +7735,9 @@
 /* DVD navigation support using libdvdnav */
 $_def_dvdnav
 $_def_dvdnav_version
+$_def_dvdnav_sversion
+$_def_mpdvdnav
+$_def_mpdvdnav_trace
 
 /* Define this to enable MPEG 1/2 image postprocessing (requires a FAST CPU!) */
 #define MPEG12_POSTPROC 1
--- libmpdemux/Makefile	2006-03-25 11:38:36.000000000 +0100
+++ libmpdemux/Makefile	2006-04-04 01:27:36.000000000 +0200
@@ -23,12 +23,15 @@
         cddb.c \
         cdinfo.c \
         cue_read.c \
-        dvdnav_stream.c \
+        stream_dvdnav.c \
         parse_es.c \
         parse_mp4.c \
         yuv4mpeg.c \
         yuv4mpeg_ratio.c \
 
+#	dvdnav_stream replaced: stream_dvdnav
+#        dvdnav_stream.c \
+
 # Stream readers/writers
 SRCS += stream.c \
         stream_file.c \
--- libmpdemux/demuxer.c	2006-03-24 09:12:02.000000000 +0100
+++ libmpdemux/demuxer.c	2006-04-04 01:27:36.000000000 +0200
@@ -16,6 +16,9 @@
 #include "libvo/fastmemcpy.h"
 
 #include "stream.h"
+#ifdef USE_MPDVDNAV
+#include "stream_dvdnav.h"
+#endif
 #include "demuxer.h"
 #include "stheader.h"
 #include "mf.h"
@@ -147,7 +150,6 @@
   ds->pos=0;
   ds->dpos=0;
   ds->pack_no=0;
-//---------------
   ds->packs=0;
   ds->bytes=0;
   ds->first=ds->last=ds->current=NULL;
@@ -182,7 +184,7 @@
 }
 
 
-demuxer_t* new_demuxer(stream_t *stream,int type,int a_id,int v_id,int s_id,char *filename){
+demuxer_t* new_demuxer(stream_t *stream,int type,int a_id,int v_id,int s_id,char *filename,int maxvpacks, int maxapacks, int hideerrmess){
   demuxer_t *d=malloc(sizeof(demuxer_t));
   memset(d,0,sizeof(demuxer_t));
   d->stream=stream;
@@ -195,6 +197,13 @@
   d->video=new_demuxer_stream(d,v_id);
   d->sub=new_demuxer_stream(d,s_id);
   d->type=type;
+// --------------
+  if (maxvpacks==0) d->max_video_packs=MAX_PACKS; else d->max_video_packs=maxvpacks;
+  d->max_video_bytes=MAX_PACK_BYTES;
+  if (maxapacks==0) d->max_audio_packs=MAX_PACKS; else d->max_audio_packs=maxapacks;
+  d->max_audio_bytes=MAX_PACK_BYTES;
+  d->hide_packs_err_mess=hideerrmess;
+// --------------
   if(type)
     if (!(d->desc = get_demuxer_desc_from_type(type)))
       mp_msg(MSGT_DEMUXER,MSGL_ERR,"BUG! Invalid demuxer type in new_demuxer(), big troubles ahead.");
@@ -252,6 +261,13 @@
         if (identify && !demux_aid_vid_mismatch)
           mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_VIDEO_ID=%d\n", id);
     }
+#ifdef USE_MPDVDNAV
+  ((sh_video_t*)demuxer->v_streams[id])->config_lock=0;
+  ((sh_video_t*)demuxer->v_streams[id])->config_w=0;
+  ((sh_video_t*)demuxer->v_streams[id])->config_h=0;
+  ((sh_video_t*)demuxer->v_streams[id])->config_outfmt=0;
+  ((sh_video_t*)demuxer->v_streams[id])->enable_mpeg2_reset=0;
+#endif
     return demuxer->v_streams[id];
 }
 
@@ -370,14 +386,16 @@
       --ds->packs;
       return 1; //ds->buffer_size;
     }
-    if(demux->audio->packs>=MAX_PACKS || demux->audio->bytes>=MAX_PACK_BYTES){
+    if(demux->audio->packs>=demux->max_audio_packs || demux->audio->bytes>=demux->max_audio_bytes){
+      if (!(demux->hide_packs_err_mess)) {
       mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_TooManyAudioInBuffer,demux->audio->packs,demux->audio->bytes);
-      mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI);
+        mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI); }
       break;
     }
-    if(demux->video->packs>=MAX_PACKS || demux->video->bytes>=MAX_PACK_BYTES){
+    if(demux->video->packs>=demux->max_video_packs || demux->video->bytes>=demux->max_video_bytes){
+      if (!(demux->hide_packs_err_mess)) {
       mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_TooManyVideoInBuffer,demux->video->packs,demux->video->bytes);
-      mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI);
+        mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI);}
       break;
     }
     if(!demux_fill_buffer(demux,ds)){
@@ -620,7 +638,7 @@
 
 static demuxer_t* demux_open_stream(stream_t *stream, int file_format,
                     int force, int audio_id, int video_id, int dvdsub_id,
-                    char* filename) {
+                    char* filename,int maxvpacks, int maxapacks, int hideerrmess) {
 
 //int file_format=(*file_format_ptr);
 
@@ -637,7 +655,7 @@
 // If somebody requested a demuxer check it
 if (file_format) {
   if ((demuxer_desc = get_demuxer_desc_from_type(file_format))) {
-    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename);
+    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename, maxvpacks, maxapacks, hideerrmess);
     if (demuxer_desc->check_file) {
       fformat = demuxer_desc->check_file(demuxer);
       if (force)
@@ -651,7 +669,7 @@
           // Format changed after check, recurse
           free_demuxer(demuxer);
           return demux_open_stream(stream, fformat, force,
-                   audio_id, video_id, dvdsub_id, filename);
+                   audio_id, video_id, dvdsub_id, filename, maxvpacks, maxapacks, hideerrmess);
         }
       } else {
         // Check failed for forced demuxer, quit
@@ -668,7 +686,7 @@
 // Test demuxers with safe file checks
 for (i = 0; (demuxer_desc = demuxer_list[i]); i++) {
   if (demuxer_desc->safe_check) {
-    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename);
+    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename, maxvpacks, maxapacks, hideerrmess);
     if ((fformat = demuxer_desc->check_file(demuxer)) != 0) {
       if (fformat == demuxer_desc->type) {
         mp_msg(MSGT_DEMUXER, MSGL_INFO, MSGTR_Detected_XXX_FileFormat, demuxer_desc->shortdesc);
@@ -680,7 +698,7 @@
         // Format changed after check, recurse
         free_demuxer(demuxer);
         demuxer=demux_open_stream(stream, fformat, force,
-                  audio_id, video_id, dvdsub_id, filename);
+                  audio_id, video_id, dvdsub_id, filename, maxvpacks, maxapacks, hideerrmess);
         if(demuxer) return demuxer; // done!
         file_format = DEMUXER_TYPE_UNKNOWN;
       }
@@ -703,7 +721,7 @@
   if(file_format!=DEMUXER_TYPE_UNKNOWN){
     // we like recursion :)
     demuxer=demux_open_stream(stream, file_format, force,
-              audio_id, video_id, dvdsub_id, filename);
+              audio_id, video_id, dvdsub_id, filename, maxvpacks, maxapacks, hideerrmess);
     if(demuxer) return demuxer; // done!
     file_format=DEMUXER_TYPE_UNKNOWN; // continue fuzzy guessing...
     mp_msg(MSGT_DEMUXER,MSGL_V,"demuxer: continue fuzzy content-based format guessing...\n");
@@ -713,7 +731,7 @@
 // Try detection for all other demuxers
 for (i = 0; (demuxer_desc = demuxer_list[i]); i++) {
   if (!demuxer_desc->safe_check && demuxer_desc->check_file) {
-    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename);
+    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename, maxvpacks, maxapacks, hideerrmess);
     if ((fformat = demuxer_desc->check_file(demuxer)) != 0) {
       if (fformat == demuxer_desc->type) {
         mp_msg(MSGT_DEMUXER, MSGL_INFO, MSGTR_Detected_XXX_FileFormat, demuxer_desc->shortdesc);
@@ -725,7 +743,7 @@
         // Format changed after check, recurse
         free_demuxer(demuxer);
         demuxer=demux_open_stream(stream, fformat, force,
-                  audio_id, video_id, dvdsub_id, filename);
+                  audio_id, video_id, dvdsub_id, filename, maxvpacks, maxapacks, hideerrmess);
         if(demuxer) return demuxer; // done!
         file_format = DEMUXER_TYPE_UNKNOWN;
       }
@@ -778,7 +796,7 @@
 extern float stream_cache_min_percent;
 extern float stream_cache_seek_min_percent;
 
-demuxer_t* demux_open(stream_t *vs,int file_format,int audio_id,int video_id,int dvdsub_id,char* filename){
+demuxer_t* demux_open(stream_t *vs,int file_format,int audio_id,int video_id,int dvdsub_id,char* filename,int maxvpacks, int maxapacks, int hideerrmess){
   stream_t *as = NULL,*ss = NULL;
   demuxer_t *vd,*ad = NULL,*sd = NULL;
   int afmt =DEMUXER_TYPE_UNKNOWN,sfmt = DEMUXER_TYPE_UNKNOWN ;
@@ -823,7 +841,7 @@
 
   vd = demux_open_stream(vs, demuxer_type ? demuxer_type : file_format,
          demuxer_force, audio_stream ? -2 : audio_id, video_id,
-         sub_stream ? -2 : dvdsub_id, filename);
+         sub_stream ? -2 : dvdsub_id, filename, maxvpacks, maxapacks, hideerrmess);
   if(!vd) {
     if(as) free_stream(as);
     if(ss) free_stream(ss);
@@ -831,7 +849,7 @@
   }
   if(as) {
     ad = demux_open_stream(as, audio_demuxer_type ? audio_demuxer_type : afmt,
-           audio_demuxer_force, audio_id, -2, -2, audio_stream);
+           audio_demuxer_force, audio_id, -2, -2, audio_stream, maxvpacks, maxapacks, hideerrmess);
     if(!ad) {
       mp_msg(MSGT_DEMUXER,MSGL_WARN,MSGTR_OpeningAudioDemuxerFailed,audio_stream);
       free_stream(as);
@@ -841,7 +859,7 @@
   }
   if(ss) {
     sd = demux_open_stream(ss, sub_demuxer_type ? sub_demuxer_type : sfmt,
-           sub_demuxer_force, -2, -2, dvdsub_id, sub_stream);
+           sub_demuxer_force, -2, -2, dvdsub_id, sub_stream, maxvpacks, maxapacks, hideerrmess);
     if(!sd) {
       mp_msg(MSGT_DEMUXER,MSGL_WARN,MSGTR_OpeningSubtitlesDemuxerFailed,sub_stream);
       free_stream(ss);
@@ -960,6 +978,17 @@
 
 int demux_control(demuxer_t *demuxer, int cmd, void *arg) {
 
+    switch (cmd) {
+      case DEMUXER_CTRL_SETMAXAUDIOPACKS:
+        demuxer->max_audio_packs=*((int*)arg);
+        return DEMUXER_CTRL_OK;
+      case DEMUXER_CTRL_SETMAXVIDEOPACKS:
+        demuxer->max_video_packs=*((int*)arg);
+        return DEMUXER_CTRL_OK;
+      case DEMUXER_CTRL_SETHIDEPACKSERR:
+        demuxer->hide_packs_err_mess=*((int*)arg);
+        return DEMUXER_CTRL_OK;
+      }
     if (demuxer->desc->control)
       return demuxer->desc->control(demuxer,cmd,arg);
 
@@ -1005,3 +1034,20 @@
       index = demuxer->audio->id;
     return index;
 }
+
+void demuxer_set_max_packet(demuxer_t *demuxer, int maxvideopacket, int maxaudiopacket, int hideflg)
+{
+    if (maxvideopacket==0) maxvideopacket=MAX_PACKS;	// restore default
+    if (maxaudiopacket==0) maxaudiopacket=MAX_PACKS;	// restore default
+    demux_control(demuxer, DEMUXER_CTRL_SETMAXAUDIOPACKS,(void *)&maxaudiopacket);
+    demux_control(demuxer, DEMUXER_CTRL_SETMAXVIDEOPACKS,(void *)&maxvideopacket);
+    demux_control(demuxer, DEMUXER_CTRL_SETHIDEPACKSERR,(void *)&hideflg);
+    return;
+}
+
+void demuxer_update_time_pts(demuxer_t *demuxer, float final_pts, off_t endpos) {
+demuxer->stream->start_pos=0;
+demuxer->stream->end_pos=endpos;
+demuxer->movi_end=endpos;
+demux_control(demuxer, DEMUXER_CTRL_SET_TIME_PTS,(void *)&final_pts);
+}
--- libmpdemux/demuxer.h	2006-02-17 02:57:41.000000000 +0100
+++ libmpdemux/demuxer.h	2006-04-04 01:27:36.000000000 +0200
@@ -76,6 +76,13 @@
 #define DEMUXER_CTRL_GET_PERCENT_POS 11
 #define DEMUXER_CTRL_SWITCH_AUDIO 12
 
+// DEMUXER ds_fill_buffer packs/bytes command
+#define DEMUXER_CTRL_SETMAXAUDIOPACKS 13
+#define DEMUXER_CTRL_SETMAXVIDEOPACKS 14
+#define DEMUXER_CTRL_SETHIDEPACKSERR 15
+
+#define DEMUXER_CTRL_SET_TIME_PTS 16
+
 // Holds one packet/frame/whatever
 typedef struct demux_packet_st {
   int len;
@@ -171,6 +178,13 @@
   demux_stream_t *audio; // audio buffer/demuxer
   demux_stream_t *video; // video buffer/demuxer
   demux_stream_t *sub;   // dvd subtitle buffer/demuxer
+// --------------
+  int max_video_packs;
+  int max_video_bytes;
+  int max_audio_packs;
+  int max_audio_bytes;
+  int hide_packs_err_mess;
+// --------------
 
   // stream headers:
   void* a_streams[MAX_A_STREAMS]; // audio streams (sh_audio_t)
@@ -242,7 +256,7 @@
 }
 
 demux_stream_t* new_demuxer_stream(struct demuxer_st *demuxer,int id);
-demuxer_t* new_demuxer(stream_t *stream,int type,int a_id,int v_id,int s_id,char *filename);
+demuxer_t* new_demuxer(stream_t *stream,int type,int a_id,int v_id,int s_id,char *filename,int maxvpacks, int maxapacks, int hideerrmess);
 void free_demuxer_stream(demux_stream_t *ds);
 void free_demuxer(demuxer_t *demuxer);
 
@@ -305,7 +319,7 @@
   return a*10+b;
 }
 
-demuxer_t* demux_open(stream_t *stream,int file_format,int aid,int vid,int sid,char* filename);
+demuxer_t* demux_open(stream_t *stream,int file_format,int aid,int vid,int sid,char* filename,int maxvpacks, int maxapacks, int hideerrmess);
 int demux_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags);
 demuxer_t*  new_demuxers_demuxer(demuxer_t* vd, demuxer_t* ad, demuxer_t* sd);
 
@@ -339,3 +353,7 @@
 
 extern void demuxer_help(void);
 extern int get_demuxer_type_from_name(char *demuxer_name, int *force);
+
+void demuxer_set_max_packet(demuxer_t *demuxer, int maxvideopacket, int maxaudiopacket, int hideflg);
+
+void demuxer_update_time_pts(demuxer_t *demuxer, float final_pts, off_t endpos);
--- libmpdemux/stream.c	2006-03-24 09:12:02.000000000 +0100
+++ libmpdemux/stream.c	2006-04-04 01:27:36.000000000 +0200
@@ -115,7 +115,7 @@
   &stream_info_dvd,
 #endif
 #ifdef USE_DVDNAV
-  &stream_info_dvdnav;
+  &stream_info_dvdnav,
 #endif
 
   &stream_info_null,
--- libmpdemux/stream.h	2006-04-02 15:31:03.000000000 +0200
+++ libmpdemux/stream.h	2006-04-04 01:27:36.000000000 +0200
@@ -290,20 +290,26 @@
 extern int dvd_angle;
 //#endif
 
+extern int dvbin_param_on;
+
 extern char * audio_stream;
 
-#ifdef USE_DVDNAV
-#include "dvdnav_stream.h"
-#endif
 
 #ifdef USE_DVDREAD
 
 #ifdef USE_MPDVDKIT
+#if (USE_MPDVDKIT == 2)
 #include "libmpdvdkit2/dvd_reader.h"
 #include "libmpdvdkit2/ifo_types.h"
 #include "libmpdvdkit2/ifo_read.h"
 #include "libmpdvdkit2/nav_read.h"
 #else
+#include "libmpdvdkit/dvd_reader.h"
+#include "libmpdvdkit/ifo_types.h"
+#include "libmpdvdkit/ifo_read.h"
+#include "libmpdvdkit/nav_read.h"
+#endif
+#else
 #include <dvdread/dvd_reader.h>
 #include <dvdread/ifo_types.h>
 #include <dvdread/ifo_read.h>
@@ -349,6 +355,10 @@
 int dvd_sid_from_lang(stream_t *stream, unsigned char* lang);
 int dvd_chapter_from_cell(dvd_priv_t *dvd,int title,int cell);
 
+//#ifdef USE_MPDVDNAV
+//#include "stream_dvdnav.h"
+//#endif
+
 #endif
 							    
 #endif // __STREAM_H
--- libmpdemux/stheader.h	2006-02-18 10:26:39.000000000 +0100
+++ libmpdemux/stheader.h	2006-04-04 01:27:36.000000000 +0200
@@ -82,6 +82,13 @@
   void* ImageDesc; // for quicktime codecs
   // codec-specific:
   void* context;   // codec-specific stuff (usually HANDLE or struct pointer)
+#ifdef USE_MPDVDNAV
+  int config_lock;
+  int config_w;
+  int config_h;
+  unsigned int config_outfmt;
+  int enable_mpeg2_reset;
+#endif
 } sh_video_t;
 
 // demuxer.c:
--- libmpdemux/demux_mpg.c	2006-03-12 13:28:09.000000000 +0100
+++ libmpdemux/demux_mpg.c	2006-04-04 01:27:36.000000000 +0200
@@ -746,6 +746,7 @@
 	  int i;
           if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts){
 	    float a_pts=d_audio->pts;
+	  if((float)sh_audio->i_bps==0.0f) break;
             a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
 	    if(d_video->pts>a_pts){
 	      skip_audio_frame(sh_audio);  // sync audio
@@ -852,6 +853,24 @@
             *((int*)arg) = demuxer->audio->id;
             return DEMUXER_CTRL_OK;
 
+	case DEMUXER_CTRL_SET_TIME_PTS: {
+	      if (demuxer->movi_end==0)
+		{
+    		mpg_d->final_pts = 0.0;
+		mpg_d->has_valid_timestamps = 0;
+            	return DEMUXER_CTRL_OK;
+		}
+              mpg_d->final_pts=*((float *)arg);
+	      if (mpg_d->final_pts==0.0)
+		{
+    		mpg_d->final_pts = 0.0;
+		mpg_d->has_valid_timestamps = 0;
+            	return DEMUXER_CTRL_OK;
+		}
+	      mpg_d->has_valid_timestamps = 1;
+              return DEMUXER_CTRL_OK;
+	      }
+
 	default:
 	    return DEMUXER_CTRL_NOTIMPL;
     }
--- libmpdemux/demux_avi.c	2006-02-18 10:26:38.000000000 +0100
+++ libmpdemux/demux_avi.c	2006-04-04 01:27:36.000000000 +0200
@@ -898,7 +898,7 @@
       stream_t* s;
       demuxer_t  *od;
       s = new_ds_stream(demuxer->audio);
-      od = new_demuxer(s,DEMUXER_TYPE_OGG,-1,-2,-2,NULL);
+      od = new_demuxer(s,DEMUXER_TYPE_OGG,-1,-2,-2,NULL,0,0,0);
       if(!demux_ogg_open(od)) {
         mp_msg( MSGT_DEMUXER,MSGL_ERR,MSGTR_ErrorOpeningOGGDemuxer);
         free_stream(s);
--- libmpdemux/demux_ogg.c	2006-03-27 19:25:41.000000000 +0200
+++ libmpdemux/demux_ogg.c	2006-04-04 01:27:36.000000000 +0200
@@ -1385,7 +1385,7 @@
 
   // Create the ds_stream and the ogg demuxer
   s = new_ds_stream(demuxer->audio);
-  od = new_demuxer(s,DEMUXER_TYPE_OGG,0,-2,-2,NULL);
+  od = new_demuxer(s,DEMUXER_TYPE_OGG,0,-2,-2,NULL,0,0,0);
 
   /// Add the header packets in the ogg demuxer audio stream
   // Initial header
--- libmpdemux/demux_rtp.cpp	2006-02-19 14:27:27.000000000 +0100
+++ libmpdemux/demux_rtp.cpp	2006-04-04 01:27:36.000000000 +0200
@@ -241,7 +241,7 @@
   if (demux_is_multiplexed_rtp_stream(demuxer)) {
     stream_t* s = new_ds_stream(demuxer->video);
     demuxer_t* od = demux_open(s, DEMUXER_TYPE_UNKNOWN,
-			       audio_id, video_id, dvdsub_id, NULL);
+			       audio_id, video_id, dvdsub_id, NULL, 0, 0, 0);
     demuxer = new_demuxers_demuxer(od, od, od);
   }
 
--- libmpdemux/test.c	2005-11-18 15:39:20.000000000 +0100
+++ libmpdemux/test.c	2006-04-04 01:27:36.000000000 +0200
@@ -69,7 +69,7 @@
   if(stream_cache_size)
       stream_enable_cache(stream,stream_cache_size,0,0);
 
-  demuxer=demux_open(stream,file_format,-1,-1,-1,NULL);
+  demuxer=demux_open(stream,file_format,-1,-1,-1,NULL,0,0,0);
   if(!demuxer){
 	printf("Cannot open demuxer\n");
 	exit(1);
--- libvo/sub.h	2006-02-09 15:07:59.000000000 +0100
+++ libvo/sub.h	2006-04-04 01:27:36.000000000 +0200
@@ -10,6 +10,12 @@
 #define OSDTYPE_SUBTITLE 2
 #define OSDTYPE_PROGBAR 3
 #define OSDTYPE_SPU 4
+#ifdef USE_DVDNAV
+#ifdef USE_MPDVDNAV
+#define OSDTYPE_DVDNAV 5
+void dvdnav_box_area(int sx, int sy, int ex, int ey, int show, unsigned char image, unsigned char alpha);
+#endif
+#endif
 
 #define OSDFLAG_VISIBLE 1
 #define OSDFLAG_CHANGED 2
@@ -51,7 +57,7 @@
 #if 0
 
 // disable subtitles:
-static inline void vo_draw_text_osd(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){
+static inline void vo_draw_text_osd(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)){
 }
 
 #else
@@ -110,7 +116,7 @@
 //extern void vo_draw_text_osd(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
 //extern void vo_draw_text_progbar(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
 //extern void vo_draw_text_sub(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
-extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride));
 extern void vo_remove_text(int dxs,int dys,void (*remove)(int x0,int y0, int w,int h));
 
 void vo_init_osd(void);
--- libvo/sub.c	2006-02-09 15:07:58.000000000 +0100
+++ libvo/sub.c	2006-04-04 01:27:36.000000000 +0200
@@ -67,6 +67,16 @@
 int sub_bg_color=0; /* subtitles background color */
 int sub_bg_alpha=0;
 int sub_justify=0;
+#ifdef USE_MPDVDNAV
+uint16_t  dvdnav_sx=0;
+uint16_t  dvdnav_ex=0;
+uint16_t  dvdnav_sy=0;
+uint16_t  dvdnav_ey=0;
+int	  dvdnav_show=0;
+unsigned char dvdnav_image=0x7f;
+unsigned char dvdnav_alpha=0x7f;
+
+#endif
 
 // return the real height of a char:
 static inline int get_height(int c,int h){
@@ -129,11 +139,12 @@
 }
 
 // renders the buffer
-inline static void vo_draw_text_from_buffer(mp_osd_obj_t* obj,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){
+inline static void vo_draw_text_from_buffer(mp_osd_obj_t* obj,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)){
     if (obj->allocated > 0) {
 	draw_alpha(obj->bbox.x1,obj->bbox.y1,
 		   obj->bbox.x2-obj->bbox.x1,
 		   obj->bbox.y2-obj->bbox.y1,
+		   0,
 		   obj->bitmap_buffer,
 		   obj->alpha_buffer,
 		   obj->stride);
@@ -177,6 +188,52 @@
         }
 }
 
+#ifdef USE_DVDNAV
+#ifdef USE_MPDVDNAV
+#undef max
+#define max(x,y) ((x) > (y) ? (x) : (y))
+#undef min
+#define min(x,y) ((x) < (y) ? (x) : (y))
+
+void dvdnav_box_area(int sx, int sy, int ex, int ey, int show, unsigned char image, unsigned char alpha)
+{
+  dvdnav_sx=min(sx,ex);
+  dvdnav_ex=max(sx,ex);
+  dvdnav_sy=min(sy,ey);
+  dvdnav_ey=max(sy,ey);
+  dvdnav_show=show;
+  dvdnav_image=image;
+  dvdnav_alpha=alpha;
+}
+
+
+inline static void vo_update_dvdnav(mp_osd_obj_t* obj,int dxs,int dys){
+
+unsigned char * bitmap_buffer;
+unsigned char * alpha_buffer;
+int len;
+int stride;
+
+if (dvdnav_show)
+    {
+    obj->bbox.x1=obj->x=dvdnav_sx;
+    obj->bbox.y1=obj->y=dvdnav_sy;
+    obj->bbox.x2=dvdnav_ex;
+    obj->bbox.y2=dvdnav_ey;
+    alloc_buf(obj);
+    len = obj->stride*(obj->bbox.y2-obj->bbox.y1);
+//printf("dvdnav box image: %x alpha: %x \n",dvdnav_image,dvdnav_alpha);
+    memset(obj->bitmap_buffer,dvdnav_image,len);
+    memset(obj->alpha_buffer,dvdnav_alpha,len);
+    obj->flags|=OSDFLAG_BBOX|OSDFLAG_VISIBLE|OSDFLAG_CHANGED;
+    }
+    else
+    obj->flags&=~OSDFLAG_VISIBLE;
+}
+
+#endif
+#endif
+
 int vo_osd_progbar_type=-1;
 int vo_osd_progbar_value=100;   // 0..256
 
@@ -721,7 +778,7 @@
   obj->flags |= OSDFLAG_BBOX;
 }
 
-inline static void vo_draw_spudec_sub(mp_osd_obj_t* obj, void (*draw_alpha)(int x0, int y0, int w, int h, unsigned char* src, unsigned char* srca, int stride))
+inline static void vo_draw_spudec_sub(mp_osd_obj_t* obj, void (*draw_alpha)(int x0, int y0, int w, int h, int dp, unsigned char* src, unsigned char* srca, int stride))
 {
   spudec_draw_scaled(vo_spudec, obj->dxs, obj->dys, draw_alpha);
 }
@@ -801,6 +858,14 @@
         int vis=obj->flags&OSDFLAG_VISIBLE;
 	obj->flags&=~OSDFLAG_BBOX;
 	switch(obj->type){
+#ifdef USE_DVDNAV
+#ifdef USE_MPDVDNAV
+	case OSDTYPE_DVDNAV:
+	    vo_update_dvdnav(obj,dxs,dys);
+    	    obj->flags|=OSDFLAG_CHANGED;
+	    break;
+#endif
+#endif
 	case OSDTYPE_SUBTITLE:
 	    vo_update_text_sub(obj,dxs,dys);
 	    break;
@@ -868,6 +933,11 @@
     new_osd_obj(OSDTYPE_SUBTITLE);
     new_osd_obj(OSDTYPE_PROGBAR);
     new_osd_obj(OSDTYPE_SPU);
+#ifdef USE_DVDNAV
+#ifdef USE_MPDVDNAV
+    new_osd_obj(OSDTYPE_DVDNAV);
+#endif
+#endif
 #ifdef HAVE_FREETYPE
     force_load_font = 1;
 #endif
@@ -893,7 +963,7 @@
     }
 }
 
-void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){
+void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)){
     mp_osd_obj_t* obj=vo_osd_list;
     vo_update_osd(dxs,dys);
     while(obj){
@@ -903,6 +973,11 @@
 	case OSDTYPE_SPU:
 	    vo_draw_spudec_sub(obj, draw_alpha); // FIXME
 	    break;
+#ifdef USE_DVDNAV
+#ifdef USE_MPDVDNAV
+	case OSDTYPE_DVDNAV:
+#endif
+#endif
 	case OSDTYPE_OSD:
 	case OSDTYPE_SUBTITLE:
 	case OSDTYPE_PROGBAR:
--- libmpcodecs/Makefile	2006-03-16 22:56:23.000000000 +0100
+++ libmpcodecs/Makefile	2006-04-04 01:27:36.000000000 +0200
@@ -71,6 +71,7 @@
                vd_xvid4.c \
                vd_xvid.c \
                vd_zrmjpeg.c \
+               vd_videostill.c \
 
 ifeq ($(CONFIG_LIBAVCODEC),yes)
 VIDEO_SRCS_OPT+=vd_ffmpeg.c
--- libmpcodecs/vd.h	2004-02-18 16:23:41.000000000 +0100
+++ libmpcodecs/vd.h	2006-04-04 01:27:36.000000000 +0200
@@ -24,6 +24,7 @@
 #define VDCTRL_SET_EQUALIZER 6 /* set color options (brightness,contrast etc) */
 #define VDCTRL_GET_EQUALIZER 7 /* get color options (brightness,contrast etc) */
 #define VDCTRL_RESYNC_STREAM 8 /* seeking */
+#define VDCTRL_RESET	9
 
 // callbacks:
 int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int preferred_outfmt);
--- libmpcodecs/vd.c	2006-03-24 09:12:02.000000000 +0100
+++ libmpcodecs/vd.c	2006-04-04 01:27:36.000000000 +0200
@@ -154,10 +154,15 @@
         mp_msg(MSGT_DECVIDEO,MSGL_WARN, MSGTR_CodecDidNotSet);
     /* XXX: HACK, if sh->disp_* aren't set,
      * but we have w and h, set them :: atmos */
+#ifdef USE_MPDVDNAV
+    if(w) sh->disp_w=w;
+    if(h) sh->disp_h=h;
+#else
     if(!sh->disp_w && w)
         sh->disp_w=w;
     if(!sh->disp_h && h)
         sh->disp_h=h;
+#endif
 
     if(!sh->disp_w || !sh->disp_h)
 	return 0;
--- libmpcodecs/vf.c	2006-03-31 02:15:47.000000000 +0200
+++ libmpcodecs/vf.c	2006-04-04 01:27:36.000000000 +0200
@@ -314,12 +314,18 @@
     if(mpi->width!=w2 || mpi->height!=h){
 //	printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
 	if(mpi->flags&MP_IMGFLAG_ALLOCATED){
+#ifdef USE_MPDVDNAV
+		// need to re-allocate buffer memory:
+		free(mpi->planes[0]);
+		mpi->flags&=~MP_IMGFLAG_ALLOCATED;
+#else
 	    if(mpi->width<w2 || mpi->height<h){
 		// need to re-allocate buffer memory:
 		free(mpi->planes[0]);
 		mpi->flags&=~MP_IMGFLAG_ALLOCATED;
 		mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
 	    }
+#endif
 //	} else {
 	} {
 	    mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
--- libmpcodecs/vd_libmpeg2.c	2005-11-18 15:39:22.000000000 +0100
+++ libmpcodecs/vd_libmpeg2.c	2006-04-04 01:27:36.000000000 +0200
@@ -45,6 +45,9 @@
 	    (*((int*)arg)) == IMGFMT_422P)
 	    return CONTROL_TRUE;
 	return CONTROL_FALSE;
+    case VDCTRL_RESET:
+	mpeg2_reset(mpeg2dec,(*((int*)arg)));
+	return CONTROL_TRUE;
     }
     
     return CONTROL_UNKNOWN;
@@ -122,6 +125,9 @@
     mpeg2dec->decoder.convert_id=NULL;
     
     if(len<=0) return NULL; // skipped null frame
+#ifdef USE_MPDVDNAV
+    sh->enable_mpeg2_reset=0;
+#endif
     
     // append extra 'end of frame' code:
     ((char*)data+len)[0]=0;
@@ -154,16 +160,39 @@
 	    break;
 	case STATE_SEQUENCE:
 	    // video parameters inited/changed, (re)init libvo:
+#ifdef USE_MPDVDNAV
+	    sh->enable_mpeg2_reset=1;
+#endif
 	    if (info->sequence->width >> 1 == info->sequence->chroma_width &&
 		info->sequence->height >> 1 == info->sequence->chroma_height) {
+#ifdef USE_MPDVDNAV
+//printf("lock: %i w:%i (%i) h: %i (%i) fmt: %i (%i) \n",sh->config_lock,sh->config_w,info->sequence->picture_width,
+//    sh->config_h,info->sequence->picture_height,sh->config_outfmt,IMGFMT_YV12);
+		if (sh->config_lock && sh->config_w==info->sequence->picture_width &&
+		    sh->config_h ==info->sequence->picture_height && sh->config_outfmt == IMGFMT_YV12) break;
+#endif
 		if(!mpcodecs_config_vo(sh,
 				       info->sequence->picture_width,
 				       info->sequence->picture_height, IMGFMT_YV12)) return 0;
+#ifdef USE_MPDVDNAV
+		if(sh->config_lock) {sh->config_w=info->sequence->picture_width; 
+		    sh->config_h=info->sequence->picture_height; sh->config_outfmt=IMGFMT_YV12;}
+#endif
 	    } else if (info->sequence->width >> 1 == info->sequence->chroma_width &&
 		info->sequence->height == info->sequence->chroma_height) {
+#ifdef USE_MPDVDNAV
+//printf("lock: %i w:%i (%i) h: %i (%i) fmt: %i (%i) \n",sh->config_lock,sh->config_w,info->sequence->picture_width,
+//    sh->config_h,info->sequence->picture_height,sh->config_outfmt,IMGFMT_422P);
+		if (sh->config_lock && sh->config_w==info->sequence->picture_width &&
+		    sh->config_h ==info->sequence->picture_height && sh->config_outfmt == IMGFMT_422P) break;
+#endif
 		if(!mpcodecs_config_vo(sh,
 				       info->sequence->picture_width,
 				       info->sequence->picture_height, IMGFMT_422P)) return 0;
+#ifdef USE_MPDVDNAV
+		if(sh->config_lock) {sh->config_w=info->sequence->picture_width; 
+		    sh->config_h=info->sequence->picture_height; sh->config_outfmt=IMGFMT_422P;}
+#endif
 	    } else return 0;
 	    break;
 	case STATE_PICTURE:
--- help/help_mp-en.h	2006-03-31 08:22:51.000000000 +0200
+++ help/help_mp-en.h	2006-04-04 01:27:36.000000000 +0200
@@ -24,6 +24,10 @@
 #ifdef USE_DVDREAD
 " dvd://<titleno>   play DVD title from device instead of plain file\n"
 " -alang/-slang    select DVD audio/subtitle language (by 2-char country code)\n"
+#ifdef USE_MPDVDNAV
+" -mlang           select DVD menu language (by 2-char country code)\n"
+" -dvdnav-menutype set DVD menu button type: 0: spu (default), 1: simple box, 2: spu & simple box\n"
+#endif
 #endif
 " -ss <timepos>    seek to given (seconds or hh:mm:ss) position\n"
 " -nosound         do not play sound\n"
@@ -1544,3 +1548,160 @@
 
 // libmpcodecs/vf_test.c, vf_yuy2.c, vf_yvu9.c
 #define MSGTR_MPCODECS_WarnNextFilterDoesntSupport "%s not supported by next filter/vo :(\n"
+
+// mpdvdnav - gui
+#define MSGTR_MENU_DVDNAV "DVDNAV"
+#define MSGTR_MENU_PlayDVDNAV "Play DVDNAV..."
+#define MSGTR_MENU_MenuDVDNAV "Main DVD Menu"
+
+// mpdvdnav
+
+#define MSGTR_MPDVDNAV_StopEvent "DVDNAV Event: STOP!\n"
+#define MSGTR_MPDVDNAV_WaitEvent "DVDNAV Event: Wait\n"
+#define MSGTR_MPDVDNAV_StillFrameEvent "DVDNAV Event: Still frame\n"
+#define MSGTR_MPDVDNAV_VtsChangeEvent "DVDNAV Event: Vts change\n"
+#define MSGTR_MPDVDNAV_CellChangeEvent "DVDNAV Event: Cell change\n"
+#define MSGTR_MPDVDNAV_SpuClutChangeEvent "DVDNAV Event: Spu clut change\n"
+#define MSGTR_MPDVDNAV_HighlightEvent "DVDNAV Event: Highlight\n"
+#define MSGTR_MPDVDNAV_NavPacketEvent "DVDNAV Event: Nav packet\n"
+
+#define MSGTR_MPDVDNAV_StillFrameDecodeError "Still frame decode error\n"
+#define MSGTR_MPDVDNAV_StillSkip "Dvdnav still skip\n"
+#define MSGTR_MPDVDNAV_CellN "cellN      : %i\n"
+#define MSGTR_MPDVDNAV_PgN "pgN        : %d\n"
+#define MSGTR_MPDVDNAV_CellLength "cell_length: %d\n"
+#define MSGTR_MPDVDNAV_PgLength "pg_lenght  : %d\n"
+#define MSGTR_MPDVDNAV_PgcLength "pgc_lenght : %d\n"
+#define MSGTR_MPDVDNAV_CellStart "cell_start : %d\n"
+#define MSGTR_MPDVDNAV_PgStart "pg_start   : %d\n"
+#define MSGTR_MPDVDNAV_Title "DVDNAV new title: %i\n"
+#define MSGTR_MPDVDNAV_Part  "DVDNAV new part: %i\n"
+#define MSGTR_MPDVDNAV_Aspect43 "Aspect 4/3\n"
+#define MSGTR_MPDVDNAV_Aspect169 "Aspect 16/9\n"
+#define MSGTR_MPDVDNAV_AspectOther "Aspect ? (%i)\n"
+#define MSGTR_MPDVDNAV_AudioID "DVDNAV new audio ID: %i\n"
+#define MSGTR_MPDVDNAV_DvdSubID "DVDNAV new dvdsub ID: %i\n"
+#define MSGTR_MPDVDNAV_Len "DVDNAV len: %i\n"
+#define MSGTR_MPDVDNAV_ReadInStillActive "%s: got a stream_read while I should be asleep!\n"
+#define MSGTR_MPDVDNAV_ErrorGetNextBlock "Error getting next block from DVD (%s)\n"
+#define MSGTR_MPDVDNAV_ErrorStreamRead "DVDNAV stream read error: %s\n"
+#define MSGTR_MPDVDNAV_ErrorSeek "DVDNAV stream seek error: %s (%llx)\n"
+#define MSGTR_MPDVDNAV_ErrorNav "DVDNAV navigation error: %s\n"
+#define MSGTR_MPDVDNAV_NoColorSpu "Color SPU does not support this vo!\n"
+
+// ----------------------- libmpdvdnav error -----------------------
+// libmpdvdnav - dvdnav.c
+#define MSGTR_LIBMPDVDNAV_Err_ErrorInitialisingTheDVDVM "Error initialising the DVD VM."
+#define MSGTR_LIBMPDVDNAV_Err_ErrorStartingTheVM "Error starting the VM / opening the DVD device."
+#define MSGTR_LIBMPDVDNAV_Err_PassedANullPointer "Passed a NULL pointer."
+#define MSGTR_LIBMPDVDNAV_Err_VirtualDVDMachineNotStarted "Virtual DVD machine not started."
+#define MSGTR_LIBMPDVDNAV_Err_ErrorRestartingTheVM "Error restarting the VM."
+#define MSGTR_LIBMPDVDNAV_Err_ErrorReadingNAVPacket "Error reading NAV packet."
+#define MSGTR_LIBMPDVDNAV_Err_ExpectedNAVPacketButNoneFound "Expected NAV packet but none found."
+#define MSGTR_LIBMPDVDNAV_Err_UnknownDomainWhenChangingVTS "Unknown domain when changing VTS."
+#define MSGTR_LIBMPDVDNAV_Err_ErrorReadingNAVPacket "Error reading NAV packet."
+#define MSGTR_LIBMPDVDNAV_Err_AttemptingToReadWithoutOpeningFile "Attempting to read without opening file."
+#define MSGTR_LIBMPDVDNAV_Err_ErrorReadingFromDVD "Error reading from DVD."
+#define MSGTR_LIBMPDVDNAV_Err_NoCurrentPGC "No current PGC."
+#define MSGTR_LIBMPDVDNAV_Err_PassedAnInvalidAngleNumber "Passed an invalid angle number."
+// libmpdvdnav - searching.c
+#define MSGTR_LIBMPDVDNAV_Err_CannotSeekInAStillFrame "Cannot seek in a still frame."
+#define MSGTR_LIBMPDVDNAV_Err_RequestToSeekBehindEnd "Request to seek behind end."
+#define MSGTR_LIBMPDVDNAV_Err_RequestToSeekBeforeStart "Request to seek before start."
+#define MSGTR_LIBMPDVDNAV_Err_IllegalSeekMode "Illegal seek mode."
+#define MSGTR_LIBMPDVDNAV_Err_ErrorWhenSeeking "Error when seeking."
+#define MSGTR_LIBMPDVDNAV_Err_SkipToPreviousChapterFailed "Skip to previous chapter failed."
+#define MSGTR_LIBMPDVDNAV_Err_SkipToTopChapterFailed "Skip to top chapter failed."
+#define MSGTR_LIBMPDVDNAV_Err_SkipToNextChapterFailed "Skip to next chapter failed."
+#define MSGTR_LIBMPDVDNAV_Err_NoSuchMenuOrMenuNotReachable "No such menu or menu not reachable."
+#define MSGTR_LIBMPDVDNAV_Err_NewPositionNotYetDetermined "New position not yet determined."
+// libmpdvdnav - highlight.c
+#define MSGTR_LIBMPDVDNAV_Err_BadVMState "Bad VM state."
+// libmpdvdnav - settings.c
+#define MSGTR_LIBMPDVDNAV_Err_PassedIllegalLanguageCode "Passed illegal language code."
+
+// ----------------------- libmpdvdnav -----------------------------
+// libmpdvdnav - dvdnav.c
+#define MSGTR_LIBMPDVDNAV_Using "libdvdnav: Using dvdnav version %s from http://dvd.sf.net\n"
+#define MSGTR_LIBMPDVDNAV_Demux_error "libdvdnav: demux error! %02x %02x %02x (should be 0x000001) \n"
+#define MSGTR_LIBMPDVDNAV_ErrorOpeningVtsDomain "Error opening vtsN=%i, domain=%i.\n"
+// libmpdvdnav - highlight.c
+#define MSGTR_LIBMPDVDNAV_NoCurrentPGC "No current PGC.\n"
+#define MSGTR_LIBMPDVDNAV_NotInAMenu "Not in a menu.\n"
+#define MSGTR_LIBMPDVDNAV_ThisNAVHasAlreadyBeenLeft "This NAV has already been left.\n"
+#define MSGTR_LIBMPDVDNAV_ButtonDoesNotExist "Button does not exist.\n"
+#define MSGTR_LIBMPDVDNAV_TitleOutOfRange "Title out of range.\n"
+#define MSGTR_LIBMPDVDNAV_PartOutOfRange "Part out of range.\n"
+#define MSGTR_LIBMPDVDNAV_NotImplementedYet "Not implemented yet.\n"
+#define MSGTR_LIBMPDVDNAV_NotInATitleOrMenu "Not in a title or menu.\n"
+// libmpdvdnav - navigation.c
+#define MSGTR_LIBMPDVDNAV_PassedANullPointer "Passed a NULL pointer.\n"
+#define MSGTR_LIBMPDVDNAV_VirtualDVDMachineNotStarted "Virtual DVD machine not started.\n"
+#define MSGTR_LIBMPDVDNAV_BadVMState "Bad VM state.\n"
+#define MSGTR_LIBMPDVDNAV_PassedATitleNumberOutOfRange "Passed a title number out of range.\n"
+// libmpdvdnav - read_cache.c
+#define MSGTR_LIBMPDVDNAV_PreCacheDVDReadReallocHappened "pre_cache DVD read realloc happened\n"
+#define MSGTR_LIBMPDVDNAV_PreCacheDVDReadMalloc "pre_cache DVD read malloc %d blocks\n"
+#define MSGTR_LIBMPDVDNAV_PreCachingWasImpossible "pre_caching was impossible, no cache chunk available\n"
+#define MSGTR_LIBMPDVDNAV_ReadCacheSectorInfo "libdvdnav: sector=%d, start_sector=%d, last_sector=%d\n"
+#define MSGTR_LIBMPDVDNAV_ReadCacheReadAheadSize "libdvdnav: read_ahead_size=%d, size=%d\n"
+#define MSGTR_LIBMPDVDNAV_CacheMissOnSector "cache miss on sector %d\n"
+// libmpdvdnav - remap.c
+#define MSGTR_LIBMPDVDNAV_UnableToFindMapFile "libdvdnav: Unable to find map file '%s'\n"
+#define MSGTR_LIBMPDVDNAV_IgnoringMapLine "libdvdnav: Ignoring map line (%d): %s\n"
+#define MSGTR_LIBMPDVDNAV_RemapInfo "libdvdnav: %s: domain %d, title %d, program %d, start %lx, next %lx\n"
+#define MSGTR_LIBMPDVDNAV_RedirectedTo "libdvdnav: Redirected to %lx\n"
+// libmpdvdnav - searching.c
+#define MSGTR_LIBMPDVDNAV_UnknownDomainForSeeking "libdvdnav: Error: Unknown domain for seeking.\n"
+#define MSGTR_LIBMPDVDNAV_CouldNotLocateBlock "libdvdnav: Could not locate block\n"
+#define MSGTR_LIBMPDVDNAV_AdmapNotLocated "libdvdnav: admap not located\n"
+#define MSGTR_LIBMPDVDNAV_ErrorWhenSeeking "libdvdnav: Error when seeking\n"
+#define MSGTR_LIBMPDVDNAV_FIXMEImplementSeekingToLocation "libdvdnav: FIXME: Implement seeking to location %u\n"
+#define MSGTR_LIBMPDVDNAV_PreviousChapterFailed "libdvdnav: previous chapter failed.\n"
+#define MSGTR_LIBMPDVDNAV_TopChapterFailed "libdvdnav: top chapter failed.\n"
+#define MSGTR_LIBMPDVDNAV_NextChapterFailed "libdvdnav: next chapter failed.\n"
+#define MSGTR_LIBMPDVDNAV_SearchChapterFailed "libdvdnav: search chapter failed.\n"
+// libmpdvdnav - decoder.c
+#define MSGTR_LIBMPDVDNAV_BadCallToVMGetbits "libdvdnav: Bad call to vm_getbits. Parameter out of range\n"
+#define MSGTR_LIBMPDVDNAV_SuspectedRCERegionProtection "libdvdnav: Suspected RCE Region Protection!!!\n"
+#define MSGTR_LIBMPDVDNAV_EvalCompareInvalidComparisonCode "libdvdnav: eval_compare: Invalid comparison code\n"
+#define MSGTR_LIBMPDVDNAV_UnknownInstrution "libdvdnav: Unknown Instruction!\n"
+#define MSGTR_LIBMPDVDNAV_WarningUnknownComman "libdvdnav: WARNING: Unknown Command=%x\n"
+#define MSGTR_LIBMPDVDNAV_DecoderCWarningUnknownBits "libdvdnav: decoder.c: [WARNING, unknown bits:"
+#define MSGTR_LIBMPDVDNAV_DecoderCButton "libdvdnav: %s (button %d)\n"
+#define MSGTR_LIBMPDVDNAV_DecoderCButton2 "libdvdnav: %s %d (button %d)\n"
+#define MSGTR_LIBMPDVDNAV_DecoderCVtsTitleMenu "libdvdnav: %s vts %d title %d menu %d\n"
+#define MSGTR_LIBMPDVDNAV_DecoderCResumeCell "libdvdnav: %s resume cell %d\n"
+#define MSGTR_LIBMPDVDNAV_DecoderCResumeCell2 "libdvdnav: %s %d resume cell %d\n"
+// libmpdvdnav - vm.c
+#define MSGTR_LIBMPDVDNAV_VmCDVDTitle "libdvdnav: DVD Title: "
+#define MSGTR_LIBMPDVDNAV_VmCDVDSerialNumber "\nlibdvdnav: DVD Serial Number: "
+#define MSGTR_LIBMPDVDNAV_VmCDVDTitleAlternative "\nlibdvdnav: DVD Title (Alternative): "
+#define MSGTR_LIBMPDVDNAV_VmCCantReadNameBlock "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n"
+#define MSGTR_LIBMPDVDNAV_VmCCantSeekToBlock "libdvdnav: Can't seek to block %u\n"
+#define MSGTR_LIBMPDVDNAV_VmCNameOpenFailed "NAME OPEN FAILED\n"
+#define MSGTR_LIBMPDVDNAV_VmCIfoOpenVTSIFailed "libdvdnav: ifoOpenVTSI failed - CRASHING!!!\n"
+#define MSGTR_LIBMPDVDNAV_VmCIfoReadVTSPTTSRPTFailed "libdvdnav: ifoRead_VTS_PTT_SRPT failed - CRASHING!!!\n"
+#define MSGTR_LIBMPDVDNAV_VmCIfoReadPGCITFailed "libdvdnav: ifoRead_PGCIT failed - CRASHING!!!\n"
+#define MSGTR_LIBMPDVDNAV_VmCIfoReadPGCIUTFailed "libdvdnav: ifoRead_PGCI_UT failed - CRASHING!!!\n"
+#define MSGTR_LIBMPDVDNAV_VmCIfoReadVOBUADMAPVtsiFailed "libdvdnav: ifoRead_VOBU_ADMAP vtsi failed - CRASHING\n"
+#define MSGTR_LIBMPDVDNAV_VmCIfoReadTITLEVOBUADMAPVtsiFailed "libdvdnav: ifoRead_TITLE_VOBU_ADMAP vtsi failed - CRASHING\n"
+#define MSGTR_LIBMPDVDNAV_VmCVmFaildToOpenReadTheDVD "libdvdnav: vm: faild to open/read the DVD\n"
+#define MSGTR_LIBMPDVDNAV_VmCVmFaildToReadVIDEOTSIFO "libdvdnav: vm: faild to read VIDEO_TS.IFO\n"
+#define MSGTR_LIBMPDVDNAV_VmCVmIfoReadFPPGCFailed "libdvdnav: vm: ifoRead_FP_PGC failed\n"
+#define MSGTR_LIBMPDVDNAV_VmCVmIfoReadTTSRPTFailed "libdvdnav: vm: ifoRead_TT_SRPT failed\n"
+#define MSGTR_LIBMPDVDNAV_VmCVmIfoReadPGCIUTFailed "libdvdnav: vm: ifoRead_PGCI_UT failed\n"
+#define MSGTR_LIBMPDVDNAV_VmCVmIfoReadPRLMAITFailed "libdvdnav: vm: ifoRead_PTL_MAIT failed\n"
+#define MSGTR_LIBMPDVDNAV_VmCVmIfoReadVTSATRTFailed "libdvdnav: vm: ifoRead_VTS_ATRT failed\n"
+#define MSGTR_LIBMPDVDNAV_VmCVmIfoReadVOBUADMAPVgmiFailed "libdvdnav: vm: ifoRead_VOBU_ADMAP vgmi failed\n"
+#define MSGTR_LIBMPDVDNAV_VmCDVDDiskReportsItselfWithRegionMask "libdvdnav: DVD disk reports itself with Region mask 0x%08x. Regions:"
+#define MSGTR_LIBMPDVDNAV_VmCChapterNotFound "libdvdnav: chapter NOT FOUND!\n"
+#define MSGTR_LIBMPDVDNAV_VmCInvalidAngleBlock "libdvdnav: Invalid angle block\n"
+#define MSGTR_LIBMPDVDNAV_VmCInvalidBlockMode "libdvdnav: Invalid? Cell block_mode (%d), block_type (%d)\n"
+#define MSGTR_LIBMPDVDNAV_VmCCellIsInBlockButDidNotEnter "libdvdnav: Cell is in block but did not enter at first cell!\n"
+#define MSGTR_LIBMPDVDNAV_VmCTryingToResumeWithoutAnyResume "libdvdnav: trying to resume without any resume info set\n"
+#define MSGTR_LIBMPDVDNAV_VmCRandomOrShuffleTitlesAreNotHandledYet "libdvdnav: RANDOM or SHUFFLE titles are NOT handled yet.\n"
+#define MSGTR_LIBMPDVDNAV_VmCGetPGCNFailed "libdvdnav: get_PGCN failed. Was trying to find pgcN in domain %d\n"
+#define MSGTR_LIBMPDVDNAV_VmCPgciUtHandleIsNULL "libdvdnav: *** pgci_ut handle is NULL ***\n"
+#define MSGTR_LIBMPDVDNAV_VmCLanguageNotFound "libdvdnav: Language '%c%c' not found, using '%c%c' instead\n"
+#define MSGTR_LIBMPDVDNAV_VmCMenuLanguagesAvailable "libdvdnav: Menu Languages available: "
--- libvo/video_out.h	2006-02-09 15:07:59.000000000 +0100
+++ libvo/video_out.h	2006-04-04 01:27:36.000000000 +0200
@@ -74,6 +74,11 @@
   int w,h;
 } mp_win_t;
 
+#define VOCTRL_YUVSPU_SUPPORT 28
+#define VOCTRL_RGBSPU_SUPPORT 29
+#define VOCTRL_BGRSPU_SUPPORT 30
+#define VOCTRL_YUYSPU_SUPPORT 31
+
 #define VO_TRUE		1
 #define VO_FALSE	0
 #define VO_ERROR	-1
--- libvo/vo_fbdev.c	2006-03-20 23:24:14.000000000 +0100
+++ libvo/vo_fbdev.c	2006-04-04 01:27:36.000000000 +0200
@@ -562,7 +562,7 @@
 static int fb_line_len;
 static int fb_xres;
 static int fb_yres;
-static void (*draw_alpha_p)(int w, int h, unsigned char *src,
+static void (*draw_alpha_p)(int w, int h, int dp, unsigned char *src,
 		unsigned char *srca, int stride, unsigned char *dst,
 		int dstride);
 
@@ -1053,14 +1053,14 @@
 	return 0;
 }
 
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src,
 		unsigned char *srca, int stride)
 {
 	unsigned char *dst;
 
 	dst = center + fb_line_len * y0 + fb_pixel_size * x0;
 
-	(*draw_alpha_p)(w, h, src, srca, stride, dst, fb_line_len);
+ 	(*draw_alpha_p)(w, h, dp, src, srca, stride, dst, fb_line_len);
 }
 
 static int draw_frame(uint8_t *src[]) { return 1; }
@@ -1174,6 +1174,13 @@
     return get_image(data);
   case VOCTRL_QUERY_FORMAT:
     return query_format(*((uint32_t*)data));
+  case VOCTRL_YUVSPU_SUPPORT:
+    return VO_FALSE;
+  case VOCTRL_RGBSPU_SUPPORT:
+    return VO_FALSE;
+  case VOCTRL_BGRSPU_SUPPORT:
+    if (fb_bpp == 32 || fb_bpp==24 || fb_bpp==16 || fb_bpp==15) return VO_TRUE;
+    return VO_FALSE;
   }
 
 #ifdef CONFIG_VIDIX
--- libvo/vo_directfb2.c	2006-03-27 09:22:48.000000000 +0200
+++ libvo/vo_directfb2.c	2006-04-04 01:27:36.000000000 +0200
@@ -1445,6 +1445,20 @@
     
 	return(directfb_get_video_eq(data, value));
       }
+    case VOCTRL_YUVSPU_SUPPORT:
+	if (pixel_format==DSPF_I420 || pixel_format==DSPF_YV12) return VO_TRUE;
+	return VO_FALSE;
+    case VOCTRL_RGBSPU_SUPPORT:
+	if (pixel_format==DSPF_RGB32 || pixel_format==DSPF_ARGB || pixel_format==DSPF_RGB24 ||
+		pixel_format==DSPF_RGB16) return VO_TRUE;
+#if DIRECTFBVERSION > 915
+	if (pixel_format==DSPF_ARGB1555) return VO_TRUE;
+#else
+	if (pixel_format==DSPF_RGB15) return VO_TRUE;
+#endif
+	return VO_FALSE;
+    case VOCTRL_BGRSPU_SUPPORT:
+	return VO_FALSE;
   };
   return VO_NOTIMPL;
 }
@@ -1458,7 +1472,7 @@
 
 // hopefully will be removed soon
 
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src,
 		unsigned char *srca, int stride)
 {
         void *dst;
@@ -1477,35 +1491,51 @@
 	switch(pixel_format) {
                 case DSPF_RGB32:
                 case DSPF_ARGB:
-                        vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 4*x0,pitch);
+                        vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 4*x0,pitch);
                         break;
 
                 case DSPF_RGB24:
-                        vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 3*x0,pitch);
+                        vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 3*x0,pitch);
                         break;
 
                 case DSPF_RGB16:
-                        vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch);
+                        vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch);
                         break;
 #if DIRECTFBVERSION > 915
                 case DSPF_ARGB1555:
 #else
                 case DSPF_RGB15:
 #endif
-                        vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch);
+                        vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch);
                         break;
 
 		case DSPF_YUY2:
-    			vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0,pitch);
+    			vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0,pitch);
 		break;
 
         	case DSPF_UYVY:
-    			vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0 + 1,pitch);
+    			vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0 + 1,pitch);
 		break;
 
         	case DSPF_I420:
 		case DSPF_YV12:
-    			vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 1*x0,pitch);
+		  switch (dp) {
+		    case 0:
+    			vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 1*x0,pitch);
+			break;
+		    case 1:
+			if (pixel_format==DSPF_YV12)
+    			    vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*height/4 + pitch*y0 + 1*x0,pitch);
+			    else
+    			    vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*height/2 + pitch*y0 + 1*x0,pitch);
+		        break;
+		    case 2:
+			if (pixel_format==DSPF_YV12)
+    			    vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*height/2 + pitch*y0 + 1*x0,pitch);
+			    else
+    			    vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*height/4 + pitch*y0 + 1*x0,pitch);
+		        break;
+		    }
 		break;
 		}
 
--- libvo/vo_svga.c	2006-03-24 09:12:02.000000000 +0100
+++ libvo/vo_svga.c	2006-04-04 01:27:36.000000000 +0200
@@ -45,6 +45,7 @@
 #include "sub.h"
 
 #include "mp_msg.h"
+#include "help_mp.h"
 //#include "mp_image.h"
 
 #include <assert.h>
@@ -54,7 +55,7 @@
 
 
 static int query_format(uint32_t format);
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src,
                        unsigned char *srca, int stride);
 static uint32_t get_image(mp_image_t *mpi);
 
@@ -383,6 +384,13 @@
 
       return vidix_control(request, data, value);
     }
+    case VOCTRL_YUVSPU_SUPPORT:
+        return VO_FALSE;
+    case VOCTRL_RGBSPU_SUPPORT:
+	if (mode_bpp==32 || mode_bpp==24 || mode_bpp==16 || mode_bpp==15) return VO_TRUE;
+	return VO_FALSE;
+    case VOCTRL_BGRSPU_SUPPORT:
+	return VO_FALSE;
     }
     return vidix_control(request, data);
   }
@@ -683,13 +691,13 @@
   return 0;
 }
 
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src,
                        unsigned char *srca, int stride) {
   char* base;
 
   if( mp_msg_test(MSGT_VO,MSGL_DBG3) )
-    printf("vo_svga: draw_alpha(x0=%d,y0=%d,w=%d,h=%d,src=%p,srca=%p,stride=%d\n",
-           x0,y0,w,h,src,srca,stride);
+    printf("vo_svga: draw_alpha(x0=%d,y0=%d,w=%d,h=%d,dp=%d,src=%p,srca=%p,stride=%d\n",
+           x0,y0,w,h,dp,src,srca,stride);
   if(!blackbar_osd) {
     //drawing in the image, so place the stuff there
     x0+=x_pos;
@@ -701,16 +709,16 @@
   base=PageStore[cpage].vbase + y0*mode_stride + x0*modeinfo->bytesperpixel;
   switch (mode_bpp) {
     case 32: 
-      vo_draw_alpha_rgb32(w, h, src, srca, stride, base, mode_stride);
+      vo_draw_alpha_rgb32(w, h, dp, src, srca, stride, base, mode_stride);
       break;
     case 24: 
-      vo_draw_alpha_rgb24(w, h, src, srca, stride, base, mode_stride);
+      vo_draw_alpha_rgb24(w, h, dp, src, srca, stride, base, mode_stride);
       break;
     case 16:
-      vo_draw_alpha_rgb16(w, h, src, srca, stride, base, mode_stride);
+      vo_draw_alpha_rgb16(w, h, dp, src, srca, stride, base, mode_stride);
       break;
     case 15:
-      vo_draw_alpha_rgb15(w, h, src, srca, stride, base, mode_stride);
+      vo_draw_alpha_rgb15(w, h, dp, src, srca, stride, base, mode_stride);
       break;
   }
 }
--- libvo/vo_vesa.c	2006-03-24 09:12:02.000000000 +0100
+++ libvo/vo_vesa.c	2006-04-04 01:27:36.000000000 +0200
@@ -44,6 +44,7 @@
 #include "vosub_vidix.h"
 #endif
 #include "mp_msg.h"
+#include "help_mp.h"
 
 #include "postproc/swscale.h"
 #include "libmpcodecs/vf_scale.h"
@@ -105,7 +106,7 @@
 static unsigned video_mode; /* selected video mode for playback */
 static struct VesaModeInfoBlock video_mode_info;
 static int flip_trigger = 0;
-static void (*draw_alpha_fnc)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
+static void (*draw_alpha_fnc)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride);
 
 /* multibuffering */
 uint8_t*  video_base; /* should be never changed */
@@ -293,7 +294,7 @@
 /* Please comment it out if you want have OSD within movie */
 /*#define OSD_OUTSIDE_MOVIE 1*/
 
-static void draw_alpha_32(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)
+static void draw_alpha_32(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)
 {
    int dstride=HAS_DGA()?video_mode_info.XResolution:dstW;
 #ifndef OSD_OUTSIDE_MOVIE
@@ -303,10 +304,10 @@
 	y0 += y_offset;
    }
 #endif
-   vo_draw_alpha_rgb32(w,h,src,srca,stride,dga_buffer+4*(y0*dstride+x0),4*dstride);
+   vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,dga_buffer+4*(y0*dstride+x0),4*dstride);
 }
 
-static void draw_alpha_24(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)
+static void draw_alpha_24(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)
 {
    int dstride=HAS_DGA()?video_mode_info.XResolution:dstW;
 #ifndef OSD_OUTSIDE_MOVIE
@@ -316,10 +317,10 @@
 	y0 += y_offset;
    }
 #endif
-   vo_draw_alpha_rgb24(w,h,src,srca,stride,dga_buffer+3*(y0*dstride+x0),3*dstride);
+   vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,dga_buffer+3*(y0*dstride+x0),3*dstride);
 }
 
-static void draw_alpha_16(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)
+static void draw_alpha_16(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)
 {
    int dstride=HAS_DGA()?video_mode_info.XResolution:dstW;
 #ifndef OSD_OUTSIDE_MOVIE
@@ -329,10 +330,10 @@
 	y0 += y_offset;
    }
 #endif
-   vo_draw_alpha_rgb16(w,h,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride);
+   vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride);
 }
 
-static void draw_alpha_15(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)
+static void draw_alpha_15(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)
 {
    int dstride=HAS_DGA()?video_mode_info.XResolution:dstW;
 #ifndef OSD_OUTSIDE_MOVIE
@@ -342,15 +343,16 @@
 	y0 += y_offset;
    }
 #endif
-   vo_draw_alpha_rgb15(w,h,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride);
+   vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride);
 }
 
-static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)
+static void draw_alpha_null(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)
 {
   UNUSED(x0);
   UNUSED(y0);
   UNUSED(w);
   UNUSED(h);
+  UNUSED(dp);
   UNUSED(src);
   UNUSED(srca);
   UNUSED(stride);
@@ -1098,6 +1100,14 @@
   switch (request) {
   case VOCTRL_QUERY_FORMAT:
     return query_format(*((uint32_t*)data));
+  case VOCTRL_YUVSPU_SUPPORT:
+    return VO_FALSE;
+  case VOCTRL_RGBSPU_SUPPORT:
+    return VO_FALSE;
+  case VOCTRL_BGRSPU_SUPPORT:
+    if (dstFourcc == IMGFMT_BGR15 || dstFourcc == IMGFMT_BGR16 || dstFourcc == IMGFMT_BGR24 ||
+	    dstFourcc == IMGFMT_BGR32 || dstFourcc == IMGFMT_BGR16) return VO_TRUE;
+    return VO_FALSE;
   }
 
 #ifdef CONFIG_VIDIX
--- libvo/osd.c	2006-03-27 09:22:48.000000000 +0200
+++ libvo/osd.c	2006-04-04 01:27:36.000000000 +0200
@@ -101,152 +101,152 @@
 
 #endif //CAN_COMPILE_X86_ASM
 
-void vo_draw_alpha_yv12(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+void vo_draw_alpha_yv12(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
 #ifdef RUNTIME_CPUDETECT
 #ifdef CAN_COMPILE_X86_ASM
 	// ordered by speed / fastest first
 	if(gCpuCaps.hasMMX2)
-		vo_draw_alpha_yv12_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.has3DNow)
-		vo_draw_alpha_yv12_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.hasMMX)
-		vo_draw_alpha_yv12_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else
-		vo_draw_alpha_yv12_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_yv12_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #else //RUNTIME_CPUDETECT
 #ifdef HAVE_MMX2
-		vo_draw_alpha_yv12_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_3DNOW)
-		vo_draw_alpha_yv12_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_MMX)
-		vo_draw_alpha_yv12_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined(ARCH_X86) || defined(ARCH_X86_64)
-		vo_draw_alpha_yv12_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_yv12_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yv12_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #endif //!RUNTIME_CPUDETECT
 }
 
-void vo_draw_alpha_yuy2(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+void vo_draw_alpha_yuy2(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
 #ifdef RUNTIME_CPUDETECT
 #ifdef CAN_COMPILE_X86_ASM
 	// ordered by speed / fastest first
 	if(gCpuCaps.hasMMX2)
-		vo_draw_alpha_yuy2_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.has3DNow)
-		vo_draw_alpha_yuy2_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.hasMMX)
-		vo_draw_alpha_yuy2_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else
-		vo_draw_alpha_yuy2_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_yuy2_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #else //RUNTIME_CPUDETECT
 #ifdef HAVE_MMX2
-		vo_draw_alpha_yuy2_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_3DNOW)
-		vo_draw_alpha_yuy2_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_MMX)
-		vo_draw_alpha_yuy2_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined(ARCH_X86) || defined(ARCH_X86_64)
-		vo_draw_alpha_yuy2_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_yuy2_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_yuy2_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #endif //!RUNTIME_CPUDETECT
 }
 
-void vo_draw_alpha_uyvy(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+void vo_draw_alpha_uyvy(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
 #ifdef RUNTIME_CPUDETECT
 #ifdef CAN_COMPILE_X86_ASM
 	// ordered by speed / fastest first
 	if(gCpuCaps.hasMMX2)
-		vo_draw_alpha_uyvy_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.has3DNow)
-		vo_draw_alpha_uyvy_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.hasMMX)
-		vo_draw_alpha_uyvy_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else
-		vo_draw_alpha_uyvy_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_uyvy_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #else //RUNTIME_CPUDETECT
 #ifdef HAVE_MMX2
-		vo_draw_alpha_uyvy_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_3DNOW)
-		vo_draw_alpha_uyvy_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_MMX)
-		vo_draw_alpha_uyvy_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined(ARCH_X86) || defined(ARCH_X86_64)
-		vo_draw_alpha_uyvy_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_uyvy_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_uyvy_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #endif //!RUNTIME_CPUDETECT
 }
 
-void vo_draw_alpha_rgb24(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+void vo_draw_alpha_rgb24(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
 #ifdef RUNTIME_CPUDETECT
 #ifdef CAN_COMPILE_X86_ASM
 	// ordered by speed / fastest first
 	if(gCpuCaps.hasMMX2)
-		vo_draw_alpha_rgb24_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.has3DNow)
-		vo_draw_alpha_rgb24_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.hasMMX)
-		vo_draw_alpha_rgb24_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else
-		vo_draw_alpha_rgb24_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_rgb24_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #else //RUNTIME_CPUDETECT
 #ifdef HAVE_MMX2
-		vo_draw_alpha_rgb24_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_3DNOW)
-		vo_draw_alpha_rgb24_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_MMX)
-		vo_draw_alpha_rgb24_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined(ARCH_X86) || defined(ARCH_X86_64)
-		vo_draw_alpha_rgb24_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_rgb24_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb24_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #endif //!RUNTIME_CPUDETECT
 }
 
-void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+void vo_draw_alpha_rgb32(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
 #ifdef RUNTIME_CPUDETECT
 #ifdef CAN_COMPILE_X86_ASM
 	// ordered by speed / fastest first
 	if(gCpuCaps.hasMMX2)
-		vo_draw_alpha_rgb32_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.has3DNow)
-		vo_draw_alpha_rgb32_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else if(gCpuCaps.hasMMX)
-		vo_draw_alpha_rgb32_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 	else
-		vo_draw_alpha_rgb32_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_rgb32_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #else //RUNTIME_CPUDETECT
 #ifdef HAVE_MMX2
-		vo_draw_alpha_rgb32_MMX2(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_3DNOW)
-		vo_draw_alpha_rgb32_3DNow(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined (HAVE_MMX)
-		vo_draw_alpha_rgb32_MMX(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #elif defined(ARCH_X86) || defined(ARCH_X86_64)
-		vo_draw_alpha_rgb32_X86(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_X86(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #else
-		vo_draw_alpha_rgb32_C(w, h, src, srca, srcstride, dstbase, dststride);
+		vo_draw_alpha_rgb32_C(w, h, dp, src, srca, srcstride, dstbase, dststride);
 #endif
 #endif //!RUNTIME_CPUDETECT
 }
@@ -297,8 +297,10 @@
 	}
 }
 
-void vo_draw_alpha_rgb15(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+void vo_draw_alpha_rgb15(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
     int y;
+switch (dp) {
+  case 0 :
     for(y=0;y<h;y++){
         register unsigned short *dst = (unsigned short*) dstbase;
         register int x;
@@ -327,10 +329,67 @@
         dstbase+=dststride;
     }
     return;
+  case 3:
+    for(y=0;y<h;y++){
+        register unsigned short *dst = (unsigned short*) dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+                unsigned char r=dst[x]&0x1F;
+                unsigned char g=(dst[x]>>5)&0x1F;
+                unsigned char b=(dst[x]>>10)&0x1F;
+                r=(((r*srca[x])>>5)+src[x])>>3;
+                dst[x]=(b<<10)|(g<<5)|r;
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+  case 4:
+    for(y=0;y<h;y++){
+        register unsigned short *dst = (unsigned short*) dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+                unsigned char r=dst[x]&0x1F;
+                unsigned char g=(dst[x]>>5)&0x1F;
+                unsigned char b=(dst[x]>>10)&0x1F;
+                g=(((g*srca[x])>>5)+src[x])>>3;
+                dst[x]=(b<<10)|(g<<5)|r;
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+  case 5:
+    for(y=0;y<h;y++){
+        register unsigned short *dst = (unsigned short*) dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+                unsigned char r=dst[x]&0x1F;
+                unsigned char g=(dst[x]>>5)&0x1F;
+                unsigned char b=(dst[x]>>10)&0x1F;
+                b=(((b*srca[x])>>5)+src[x])>>3;
+                dst[x]=(b<<10)|(g<<5)|r;
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+  }
 }
 
-void vo_draw_alpha_rgb16(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+void vo_draw_alpha_rgb16(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
     int y;
+switch (dp) {
+  case 0 :
     for(y=0;y<h;y++){
         register unsigned short *dst = (unsigned short*) dstbase;
         register int x;
@@ -358,5 +417,60 @@
         dstbase+=dststride;
     }
     return;
+  case 3 :
+    for(y=0;y<h;y++){
+        register unsigned short *dst = (unsigned short*) dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+                unsigned char r=dst[x]&0x1F;
+                unsigned char b=(dst[x]>>11)&0x1F;
+                unsigned char g=(dst[x]>>5)&0x3F;
+                r=(((r*srca[x])>>5)+src[x])>>3;
+                dst[x]=(b<<11)|(g<<5)|r;
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+  case 4 :
+    for(y=0;y<h;y++){
+        register unsigned short *dst = (unsigned short*) dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+                unsigned char r=dst[x]&0x1F;
+                unsigned char g=(dst[x]>>5)&0x3F;
+                unsigned char b=(dst[x]>>11)&0x1F;
+                g=(((g*srca[x])>>6)+src[x])>>2;
+                dst[x]=(b<<11)|(g<<5)|r;
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+  case 5 :
+    for(y=0;y<h;y++){
+        register unsigned short *dst = (unsigned short*) dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+                unsigned char r=dst[x]&0x1F;
+                unsigned char g=(dst[x]>>5)&0x3F;
+                unsigned char b=(dst[x]>>11)&0x1F;
+                b=(((b*srca[x])>>5)+src[x])>>3;
+                dst[x]=(b<<11)|(g<<5)|r;
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+  }
 }
 
--- libvo/osd.h	2006-02-09 15:07:58.000000000 +0100
+++ libvo/osd.h	2006-04-04 01:27:36.000000000 +0200
@@ -7,13 +7,13 @@
 
 extern void vo_draw_alpha_init(void); // build tables
 
-extern void vo_draw_alpha_yv12(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
-extern void vo_draw_alpha_yuy2(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
-extern void vo_draw_alpha_uyvy(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
-extern void vo_draw_alpha_rgb24(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
-extern void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
-extern void vo_draw_alpha_rgb15(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
-extern void vo_draw_alpha_rgb16(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
+extern void vo_draw_alpha_yv12(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
+extern void vo_draw_alpha_yuy2(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
+extern void vo_draw_alpha_uyvy(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
+extern void vo_draw_alpha_rgb24(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
+extern void vo_draw_alpha_rgb32(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
+extern void vo_draw_alpha_rgb15(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
+extern void vo_draw_alpha_rgb16(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
 
 #endif
 
--- libvo/vo_dfbmga.c	2006-03-27 09:31:08.000000000 +0200
+++ libvo/vo_dfbmga.c	2006-04-04 01:27:36.000000000 +0200
@@ -922,7 +922,7 @@
 }
 
 static void
-vo_draw_alpha_alut44( int w, int h,
+vo_draw_alpha_alut44( int w, int h, int dp,
                     unsigned char* src,
                     unsigned char *srca,
                     int srcstride,
@@ -953,6 +953,7 @@
 static void
 draw_alpha( int x0, int y0,
             int w, int h,
+	    int dp,
             unsigned char *src,
 	    unsigned char *srca,
             int stride )
@@ -977,38 +978,47 @@
 
      switch (subframe_format) {
      case DSPF_ALUT44:
-          vo_draw_alpha_alut44( w, h, src, srca, stride,
+          vo_draw_alpha_alut44( w, h, dp, src, srca, stride,
                                 ((uint8_t *) dst) + pitch * y0 + x0,
                               pitch );
           break;
      case DSPF_RGB32:
      case DSPF_ARGB:
-	  vo_draw_alpha_rgb32( w, h, src, srca, stride,
+	  vo_draw_alpha_rgb32( w, h, dp, src, srca, stride,
 			       (( uint8_t *) dst) + pitch * y0 + 4 * x0,
                                pitch );
 	  break;
      case DSPF_RGB24:
-	  vo_draw_alpha_rgb24( w, h, src, srca, stride,
+	  vo_draw_alpha_rgb24( w, h, dp, src, srca, stride,
 			       ((uint8_t *) dst) + pitch * y0 + 3 * x0,
                                pitch );
 	  break;
      case DSPF_RGB16:
-	  vo_draw_alpha_rgb16( w, h, src, srca, stride,
+	  vo_draw_alpha_rgb16( w, h, dp, src, srca, stride,
 			       ((uint8_t *) dst) + pitch * y0 + 2 * x0,
                                pitch );
 	  break;
      case DSPF_ARGB1555:
-	  vo_draw_alpha_rgb15( w, h, src, srca, stride,
+	  vo_draw_alpha_rgb15( w, h, dp, src, srca, stride,
 			       ((uint8_t *) dst) + pitch * y0 + 2 * x0,
                                pitch );
 	  break;
      case DSPF_YUY2:
-	  vo_draw_alpha_yuy2( w, h, src, srca, stride,
+    	switch (dp) {
+	    case 0:
+	    vo_draw_alpha_yuy2( w, h, dp, src, srca, stride,
 			      ((uint8_t *) dst) + pitch * y0 + 2 * x0,
                               pitch );
 	  break;
+	    case 6:
+	    vo_draw_alpha_yv12( w, h, dp, src, srca, stride,
+			      ((uint8_t *) dst) + pitch * y0 + 2 * x0,
+                              pitch );
+	    break;
+	    }
+	  break;
      case DSPF_UYVY:
-	  vo_draw_alpha_yuy2( w, h, src, srca, stride,
+	  vo_draw_alpha_yuy2( w, h, dp, src, srca, stride,
 			      ((uint8_t *) dst) + pitch * y0 + 2 * x0 + 1,
                               pitch );
 	  break;
@@ -1018,10 +1028,34 @@
 #endif
      case DSPF_I420:
      case DSPF_YV12:
-	  vo_draw_alpha_yv12( w, h, src, srca, stride,
+    	switch (dp) {
+	  case 0:
+	    vo_draw_alpha_yv12( w, h, dp, src, srca, stride,
 			      ((uint8_t *) dst) + pitch * y0 + x0,
                               pitch );
 	  break;
+	  case 1:
+	    if (subframe_format==DSPF_YV12)
+		vo_draw_alpha_yv12( w, h, dp, src, srca, stride,
+			      ((uint8_t *) dst) + pitch * y0 + x0 + pitch * in_height,
+                              pitch );
+		else
+		vo_draw_alpha_yv12( w, h, dp, src, srca, stride,
+			      ((uint8_t *) dst) + pitch * y0 + x0 + pitch * (in_height+in_height/2),
+                              pitch );
+	    break;
+	  case 2:
+	    if (subframe_format==DSPF_YV12)
+		vo_draw_alpha_yv12( w, h, dp, src, srca, stride,
+			      ((uint8_t *) dst) + pitch * y0 + x0 + pitch * (in_height+in_height/2),
+                              pitch );
+		else
+		vo_draw_alpha_yv12( w, h, dp, src, srca, stride,
+			      ((uint8_t *) dst) + pitch * y0 + x0 + pitch * in_height,
+                              pitch );
+	    break;
+	  }
+	  break;
      }
 
      subframe->Unlock( subframe );
@@ -1416,6 +1450,18 @@
 
                return get_equalizer( data, value );
           }
+    case VOCTRL_YUVSPU_SUPPORT:
+		if (subframe_format==DSPF_I420 || subframe_format==DSPF_YV12) return VO_TRUE;
+		return VO_FALSE;
+    case VOCTRL_YUYSPU_SUPPORT:
+		if (subframe_format==DSPF_YUY2) return VO_TRUE;
+		return VO_FALSE;
+    case VOCTRL_RGBSPU_SUPPORT:
+		if (subframe_format==DSPF_RGB32 || subframe_format==DSPF_ARGB || subframe_format==DSPF_RGB24 ||
+			subframe_format==DSPF_RGB16 || subframe_format==DSPF_ARGB1555) return VO_TRUE;
+		return VO_FALSE;
+    case VOCTRL_BGRSPU_SUPPORT:
+		return VO_FALSE;
      }
 
      return VO_NOTIMPL;
--- libvo/vo_quartz.c	2006-02-07 02:36:32.000000000 +0100
+++ libvo/vo_quartz.c	2006-04-04 01:27:36.000000000 +0200
@@ -129,7 +129,7 @@
 #include "osdep/keycodes.h"
 
 extern void mplayer_put_key(int code);
-extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride));
 
 //PROTOTYPE/////////////////////////////////////////////////////////////////
 static OSStatus KeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
@@ -194,23 +194,23 @@
     }
 }
 
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride)
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride)
 {
 	switch (image_format)
 	{
 		case IMGFMT_RGB32:
-			vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*imgRect.right+x0),4*imgRect.right);
+			vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,image_data+4*(y0*imgRect.right+x0),4*imgRect.right);
 			break;
 		case IMGFMT_YV12:
 		case IMGFMT_IYUV:
 		case IMGFMT_I420:
-			vo_draw_alpha_yv12(w,h,src,srca,stride, ((char*)P) + P->componentInfoY.offset + x0 + y0 * imgRect.right, imgRect.right);
+			vo_draw_alpha_yv12(w,h,dp,src,srca,stride, ((char*)P) + P->componentInfoY.offset + x0 + y0 * imgRect.right, imgRect.right);
 			break;
 		case IMGFMT_UYVY:
-			vo_draw_alpha_uyvy(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
+			vo_draw_alpha_uyvy(w,h,dp,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
 			break;
 		case IMGFMT_YUY2:
-			vo_draw_alpha_yuy2(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
+			vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
 			break;
 	}
 }
--- libvo/vo_directx.c	2006-03-15 10:04:24.000000000 +0100
+++ libvo/vo_directx.c	2006-04-04 01:27:36.000000000 +0200
@@ -82,7 +82,7 @@
 static RECT last_rect = {0xDEADC0DE, 0xDEADC0DE, 0xDEADC0DE, 0xDEADC0DE};
 
 extern void mplayer_put_key(int code);              //let mplayer handel the keyevents 
-extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride));
 extern int vidmode;
 
 /*****************************************************************************
@@ -140,37 +140,61 @@
 
 LIBVO_EXTERN(directx)
 
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src,
 		unsigned char *srca, int stride)
 {
+    uint8_t *d;
+    uint32_t uvstride=dstride/2;
     switch(image_format) {
     case IMGFMT_YV12 :
     case IMGFMT_I420 :
 	case IMGFMT_IYUV :
 	case IMGFMT_YVU9 :
-    	vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) image) + dstride*y0 + x0,dstride);
+    switch (dp) {
+      case 0:
+    	vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + dstride*y0 + x0,dstride);
+        break;
+      case 1:
+	if(image_format == IMGFMT_YV12)
+    	    vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + image_height*dstride + uvstride*y0 + x0,uvstride);
+	    else
+    	    vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + image_height*dstride + uvstride*(image_height/2) + uvstride*y0 + x0,uvstride);
+        break;
+      case 2:
+	if(image_format == IMGFMT_YV12)
+    	    vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + image_height*dstride + uvstride*(image_height/2) + uvstride*y0 + x0,uvstride);
+	    else
+    	    vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + image_height*dstride + uvstride*y0 + x0,uvstride);
+        break;
+      }
 	break;
 	case IMGFMT_YUY2 :
-	    vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) image)+ dstride*y0 + 2*x0 ,dstride);
+	  switch (dp) {
+    	    case 0:
+	    vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) image)+ dstride*y0 + 2*x0 ,dstride);
+	    break;
+    	    case 6:
+	    vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image)+ dstride*y0 + 2*x0 ,dstride);
+	    }
     break;
     case IMGFMT_UYVY :
-        vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) image) + dstride*y0 + 2*x0 + 1,dstride);
+        vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) image) + dstride*y0 + 2*x0 + 1,dstride);
     break;
 	case IMGFMT_RGB15:	
     case IMGFMT_BGR15:
-		vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride);
+		vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride);
     break;
     case IMGFMT_RGB16:
 	case IMGFMT_BGR16:
-        vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride);
+        vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride);
     break;
     case IMGFMT_RGB24:
 	case IMGFMT_BGR24:
-        vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride);
+        vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride);
     break;
     case IMGFMT_RGB32:
 	case IMGFMT_BGR32:
-        vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride);
+        vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride);
     break;
     }
 }
@@ -1596,6 +1620,25 @@
 		va_end(ap);
 		return color_ctrl_get(data, value);
 	}
+ 	case VOCTRL_YUVSPU_SUPPORT: {
+ 		if (image_format==IMGFMT_YV12 || image_format==IMGFMT_I420 || 
+ 		    image_format==IMGFMT_IYUV || image_format==IMGFMT_YVU9) return VO_TRUE;
+ 		return VO_FALSE;
+	}
+ 	case VOCTRL_YUYSPU_SUPPORT: {
+ 		if (image_format==IMGFMT_YUY2) return VO_TRUE;
+ 		return VO_FALSE;
+	}
+ 	case VOCTRL_RGBSPU_SUPPORT: {
+ 		if (image_format==IMGFMT_RGB15 || image_format==IMGFMT_RGB16 || 
+ 		    image_format==IMGFMT_RGB32) return VO_TRUE;
+ 		return VO_FALSE;
+	}
+ 	case VOCTRL_BGRSPU_SUPPORT: {
+ 		if (image_format==IMGFMT_BGR15 || image_format==IMGFMT_BGR16 || 
+ 		    image_format==IMGFMT_BGR32) return VO_TRUE;
+ 		return VO_FALSE;
+	}
     case VOCTRL_RESET:
         last_rect.left = 0xDEADC0DE;   // reset window position cache
         // fall-through intended
--- libvo/osd_template.c	2005-09-13 23:41:44.000000000 +0200
+++ libvo/osd_template.c	2006-04-04 01:27:36.000000000 +0200
@@ -27,7 +27,7 @@
 #define EMMS     "emms"
 #endif
 
-static inline void RENAME(vo_draw_alpha_yv12)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+static inline void RENAME(vo_draw_alpha_yv12)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
     int y;
 #if defined(FAST_OSD) && !defined(HAVE_MMX)
     w=w>>1;
@@ -93,7 +93,7 @@
     return;
 }
 
-static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
     int y;
 #if defined(FAST_OSD) && !defined(HAVE_MMX)
     w=w>>1;
@@ -160,7 +160,7 @@
     return;
 }
 
-static inline void RENAME(vo_draw_alpha_uyvy)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+static inline void RENAME(vo_draw_alpha_uyvy)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
   int y;
 #if defined(FAST_OSD)
   w=w>>1;
@@ -184,8 +184,11 @@
   }
 }
 
-static inline void RENAME(vo_draw_alpha_rgb24)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+static inline void RENAME(vo_draw_alpha_rgb24)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
     int y;
+
+switch (dp) {
+ case 0:
     for(y=0;y<h;y++){
         register unsigned char *dst = dstbase;
         register int x;
@@ -286,13 +289,61 @@
 	asm volatile(EMMS:::"memory");
 #endif
     return;
+ case 3:
+    for(y=0;y<h;y++){
+        register unsigned char *dst = dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+		dst[0]=((dst[0]*srca[x])>>8)+src[x];
+            }
+            dst+=3; // 24bpp
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+ case 4:
+    for(y=0;y<h;y++){
+        register unsigned char *dst = dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+		dst[1]=((dst[1]*srca[x])>>8)+src[x];
+            }
+            dst+=3; // 24bpp
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+ case 5:
+    for(y=0;y<h;y++){
+        register unsigned char *dst = dstbase;
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+		dst[2]=((dst[2]*srca[x])>>8)+src[x];
+            }
+            dst+=3; // 24bpp
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+ }
 }
 
-static inline void RENAME(vo_draw_alpha_rgb32)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
+static inline void RENAME(vo_draw_alpha_rgb32)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){
     int y;
 #ifdef WORDS_BIGENDIAN
     dstbase++;
 #endif
+switch (dp) {
+ case 0:
     for(y=0;y<h;y++){
         register int x;
 #if defined(ARCH_X86) || defined(ARCH_X86_64)
@@ -442,4 +493,44 @@
 	asm volatile(EMMS:::"memory");
 #endif
     return;
+ case 3:
+    for(y=0;y<h;y++){
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+		dstbase[4*x+0]=(((dstbase[4*x+0]*srca[x])>>8)+src[x])&0xff;
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+ case 4:
+    for(y=0;y<h;y++){
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+		dstbase[4*x+1]=(((dstbase[4*x+1]*srca[x])>>8)+src[x])&0xff;
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+ case 5:
+    for(y=0;y<h;y++){
+        register int x;
+        for(x=0;x<w;x++){
+            if(srca[x]){
+		dstbase[4*x+2]=(((dstbase[4*x+2]*srca[x])>>8)+src[x])&0xff;
+            }
+        }
+        src+=srcstride;
+        srca+=srcstride;
+        dstbase+=dststride;
+    }
+    return;
+ }
 }
--- libvo/vo_yuv4mpeg.c	2005-08-05 03:24:37.000000000 +0200
+++ libvo/vo_yuv4mpeg.c	2006-04-04 01:27:36.000000000 +0200
@@ -179,25 +179,37 @@
 	}
 }
 
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src,
                        unsigned char *srca, int stride) {
 	switch (using_format)
 	{
     	case IMGFMT_YV12:
-	    	vo_draw_alpha_yv12(w, h, src, srca, stride, 
+		switch (dp) {
+		  case 0:
+	    	    vo_draw_alpha_yv12(w, h, dp, src, srca, stride, 
 				       image + y0 * image_width + x0, image_width);
 			break;
+		  case 1:
+		    if (image_u) vo_draw_alpha_yv12(w, h, dp, src, srca, stride, 
+				       image_u + y0 * image_width + x0, image_width);
+		    break;
+		  case 2:
+	    	    if (image_v) vo_draw_alpha_yv12(w, h, dp, src, srca, stride, 
+				       image_v + y0 * image_width + x0, image_width);
+		    break;
+		  }
+		break;
 		
 		case IMGFMT_BGR|24:
 		case IMGFMT_RGB|24:
 			if (config_interlace != Y4M_ILACE_BOTTOM_FIRST)
-				vo_draw_alpha_rgb24(w, h, src, srca, stride,
+				vo_draw_alpha_rgb24(w, h, dp, src, srca, stride,
 						rgb_buffer + (y0 * image_width + x0) * 3, image_width * 3);
 			else
 			{
 				swap_fields (rgb_buffer, image_height, image_width * 3);
 
-				vo_draw_alpha_rgb24(w, h, src, srca, stride,
+				vo_draw_alpha_rgb24(w, h, dp, src, srca, stride,
 						rgb_buffer + (y0 * image_width  + x0) * 3, image_width * 3);
 				
 				swap_fields (rgb_buffer, image_height, image_width * 3);
@@ -543,6 +555,15 @@
     return query_format(*((uint32_t*)data));
   case VOCTRL_DUPLICATE_FRAME:
     return write_last_frame();
+  case VOCTRL_YUVSPU_SUPPORT:
+    if (using_format==IMGFMT_YV12) return VO_TRUE;
+    return VO_FALSE;
+  case VOCTRL_RGBSPU_SUPPORT:
+    if (using_format==IMGFMT_RGB|24) return VO_TRUE;
+    return VO_FALSE;
+  case VOCTRL_BGRSPU_SUPPORT:
+    if (using_format==IMGFMT_BGR|24) return VO_TRUE;
+    return VO_FALSE;
   }
   return VO_NOTIMPL;
 }
--- libvo/vosub_vidix.c	2006-03-29 00:44:16.000000000 +0200
+++ libvo/vosub_vidix.c	2006-04-04 01:27:36.000000000 +0200
@@ -282,7 +282,7 @@
   }	
 }
 
-static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)
+static void draw_alpha(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)
 {
     uint32_t apitch,bespitch;
     void *lvo_mem;
@@ -296,36 +296,55 @@
     case IMGFMT_IF09:
     case IMGFMT_Y8:
     case IMGFMT_Y800:
+	switch (dp) {
+	  case 0:
 	bespitch = (vidix_play.src.w + apitch) & (~apitch);
-        vo_draw_alpha_yv12(w,h,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch);
+           vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch);
+	  break;
+	  case 1:
+	     lvo_mem = vidix_mem + vidix_play.offsets[next_frame] + vidix_play.offset.u;
+	     vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem+dstrides.u*y0/4+x0,dstrides.u/2);
+	  break;
+	  case 2:
+    	     lvo_mem = vidix_mem + vidix_play.offsets[next_frame] + vidix_play.offset.v;
+	     vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem+dstrides.v*y0/4+x0,dstrides.v/2);
+	  break;
+	  }
         break;
     case IMGFMT_YUY2:
 	bespitch = (vidix_play.src.w*2 + apitch) & (~apitch);
-        vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+bespitch*y0+2*x0,bespitch);
+	switch (dp) {
+	case 0:
+          vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+2*x0,bespitch);
+	  break;
+	case 6:
+           vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch);
+	  break;
+	  }
         break;
     case IMGFMT_UYVY:
 	bespitch = (vidix_play.src.w*2 + apitch) & (~apitch);
-        vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+bespitch*y0+2*x0+1,bespitch);
+        vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+2*x0+1,bespitch);
         break;
     case IMGFMT_RGB32:
     case IMGFMT_BGR32:
 	bespitch = (vidix_play.src.w*4 + apitch) & (~apitch);
-	vo_draw_alpha_rgb32(w,h,src,srca,stride,lvo_mem+y0*bespitch+4*x0,bespitch);
+	vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,lvo_mem+y0*bespitch+4*x0,bespitch);
         break;
     case IMGFMT_RGB24:
     case IMGFMT_BGR24:
 	bespitch = (vidix_play.src.w*3 + apitch) & (~apitch);
-	vo_draw_alpha_rgb24(w,h,src,srca,stride,lvo_mem+y0*bespitch+3*x0,bespitch);
+	vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,lvo_mem+y0*bespitch+3*x0,bespitch);
         break;
     case IMGFMT_RGB16:
     case IMGFMT_BGR16:
 	bespitch = (vidix_play.src.w*2 + apitch) & (~apitch);
-	vo_draw_alpha_rgb16(w,h,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch);
+	vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch);
         break;
     case IMGFMT_RGB15:
     case IMGFMT_BGR15:
 	bespitch = (vidix_play.src.w*2 + apitch) & (~apitch);
-	vo_draw_alpha_rgb15(w,h,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch);
+	vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch);
         break;
     default:
 	return;
@@ -511,7 +530,7 @@
 	    next_frame = i;
 	    memset(vidix_mem + vidix_play.offsets[i], 0x80,
 		vidix_play.frame_size);
-	    draw_alpha(0, 0, image_width, image_height, tmp, tmpa, image_width);
+	    draw_alpha(0, 0, image_width, image_height, 0, tmp, tmpa, image_width);
 	}
 	free(tmp);
 	free(tmpa);
@@ -699,6 +718,16 @@
 
     return VO_TRUE;
   }
+  case VOCTRL_YUVSPU_SUPPORT:
+    if((vidix_play.fourcc==IMGFMT_YV12 || vidix_play.fourcc==IMGFMT_YV12 || vidix_play.fourcc==IMGFMT_IYUV ||
+	vidix_play.fourcc==IMGFMT_I420 || vidix_play.fourcc==IMGFMT_YVU9 || vidix_play.fourcc==IMGFMT_IF09 ||
+	vidix_play.fourcc==IMGFMT_Y8 || vidix_play.fourcc==IMGFMT_Y800) &&
+	!(vidix_play.flags & VID_PLAY_INTERLEAVED_UV)) return VO_TRUE;
+    return VO_FALSE;
+  case VOCTRL_YUYSPU_SUPPORT:
+    if((vidix_play.fourcc==IMGFMT_YUY2) &&
+	!(vidix_play.flags & VID_PLAY_INTERLEAVED_UV)) return VO_TRUE;
+    return VO_FALSE;
   }
   return VO_NOTIMPL;
   // WARNING: we drop extra parameters (...) here!
--- libvo/vo_tdfxfb.c	2005-08-05 03:24:36.000000000 +0200
+++ libvo/vo_tdfxfb.c	2006-04-04 01:27:36.000000000 +0200
@@ -38,6 +38,8 @@
 #include <linux/fb.h>
 
 #include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
 #include "fastmemcpy.h"
 #include "video_out.h"
 #include "video_out_internal.h"
@@ -80,6 +82,9 @@
 static voodoo_yuv_reg *reg_YUV;
 static struct YUV_plane *YUV;
 static void (*alpha_func)(), (*alpha_func_double)();
+static int support_yuv = VO_FALSE;
+static int support_rgb = VO_FALSE;
+static int support_bgr = VO_FALSE;
 
 static int preinit(const char *arg)
 {
@@ -232,18 +237,21 @@
 		screendepth = 2;
 		vid_voodoo_format = VOODOO_BLT_FORMAT_16;
 		alpha_func_double = vo_draw_alpha_rgb16;
+		support_rgb = VO_TRUE;
 		break;
 
 	case 24:
 		screendepth = 3;
 		vid_voodoo_format = VOODOO_BLT_FORMAT_24;
 		alpha_func_double = vo_draw_alpha_rgb24;
+		support_rgb = VO_TRUE;
 		break;
 
 	case 32:
 		screendepth = 4;
 		vid_voodoo_format = VOODOO_BLT_FORMAT_32;
 		alpha_func_double = vo_draw_alpha_rgb32;
+		support_rgb = VO_TRUE;
 		break;
 
 	default:
@@ -261,6 +269,7 @@
 	switch(in_format) {
 	case IMGFMT_YV12:
 	case IMGFMT_I420:
+//		support_yuv = VO_TRUE;
 	case IMGFMT_IYUV:
 	case IMGFMT_YUY2:
 		break;
@@ -270,18 +279,21 @@
 	case IMGFMT_BGR16:
 		in_voodoo_format = VOODOO_BLT_FORMAT_16;
 		alpha_func = vo_draw_alpha_rgb16;
+		support_rgb = VO_TRUE;
 		break;
 
 	case IMGFMT_BGR24:
 		in_depth = 3;
 		in_voodoo_format = VOODOO_BLT_FORMAT_24;
 		alpha_func = vo_draw_alpha_rgb24;
+		support_rgb = VO_TRUE;
 		break;
 
 	case IMGFMT_BGR32:
 		in_depth = 4;
 		in_voodoo_format = VOODOO_BLT_FORMAT_32;
 		alpha_func = vo_draw_alpha_rgb32;
+		support_rgb = VO_TRUE;
 		break;
 
 	default:
@@ -323,19 +335,19 @@
 }
 
 /* Double-buffering draw_alpha */
-static void draw_alpha_double(int x, int y, int w, int h, unsigned char *src,
+static void draw_alpha_double(int x, int y, int w, int h, int dp, unsigned char *src,
 		unsigned char *srca, int stride)
 {
 	char *dst = (char *)vidpage + ((y + vidy) * screenwidth + x + vidx) * screendepth;
-	alpha_func_double(w, h, src, srca, stride, dst, screenwidth * screendepth);
+	alpha_func_double(w, h, dp, src, srca, stride, dst, screenwidth * screendepth);
 }
 
 /* Single-buffering draw_alpha */
-static void draw_alpha(int x, int y, int w, int h, unsigned char *src,
+static void draw_alpha(int x, int y, int w, int h, int dp, unsigned char *src,
 		unsigned char *srca, int stride)
 {
 	char *dst = (char *)inpage + (y * in_width + x) * in_depth;
-	alpha_func(w, h, src, srca, stride, dst, in_width * in_depth);
+	alpha_func(w, h, dp, src, srca, stride, dst, in_width * in_depth);
 }
 
 static void draw_osd(void)
@@ -502,6 +514,12 @@
 	case VOCTRL_FULLSCREEN:
 		setup_screen(!vo_fs);
 		return 0;
+        case VOCTRL_YUVSPU_SUPPORT:
+            return support_yuv;
+        case VOCTRL_RGBSPU_SUPPORT:
+	    return support_rgb;
+        case VOCTRL_BGRSPU_SUPPORT:
+	    return support_bgr;
 	}
 
 	return VO_NOTIMPL;
--- libvo/mga_common.c	2005-08-05 03:24:36.000000000 +0200
+++ libvo/mga_common.c	2006-04-04 01:27:36.000000000 +0200
@@ -5,6 +5,7 @@
 #include "postproc/rgb2rgb.h"
 #include "libmpcodecs/vf_scale.h"
 #include "mp_msg.h"
+#include "help_mp.h"
 
 // mga_vid drawing functions
 static void set_window( void );		/* forward declaration to kill warnings */
@@ -27,20 +28,20 @@
 #endif
 static uint32_t               drwcX,drwcY,dwidth,dheight;
 
-static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
+static void draw_alpha(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
     uint32_t bespitch = (mga_vid_config.src_width + 31) & ~31;
     x0+=mga_vid_config.src_width*(vo_panscan_x>>1)/(vo_dwidth+vo_panscan_x);
     switch(mga_vid_config.format){
     case MGA_VID_FORMAT_YV12:
     case MGA_VID_FORMAT_IYUV:
     case MGA_VID_FORMAT_I420:
-        vo_draw_alpha_yv12(w,h,src,srca,stride,vid_data+bespitch*y0+x0,bespitch);
+        vo_draw_alpha_yv12(w,h,dp,src,srca,stride,vid_data+bespitch*y0+x0,bespitch);
         break;
     case MGA_VID_FORMAT_YUY2:
-        vo_draw_alpha_yuy2(w,h,src,srca,stride,vid_data+2*(bespitch*y0+x0),2*bespitch);
+        vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,vid_data+2*(bespitch*y0+x0),2*bespitch);
         break;
     case MGA_VID_FORMAT_UYVY:
-        vo_draw_alpha_yuy2(w,h,src,srca,stride,vid_data+2*(bespitch*y0+x0)+1,2*bespitch);
+        vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,vid_data+2*(bespitch*y0+x0)+1,2*bespitch);
         break;
     }
 }
--- libvo/vo_dga.c	2006-01-12 21:04:35.000000000 +0100
+++ libvo/vo_dga.c	2006-04-04 01:27:37.000000000 +0200
@@ -227,7 +227,7 @@
 
 //---------------------------------------------------------
 
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src,
                        unsigned char *srca, int stride)
 {
 
@@ -243,19 +243,19 @@
     {
 
         case 32:
-            vo_draw_alpha_rgb32(w, h, src, srca, stride, d + 4 * offset,
+            vo_draw_alpha_rgb32(w, h, dp, src, srca, stride, d + 4 * offset,
                                 4 * buffer_stride);
             break;
         case 24:
-            vo_draw_alpha_rgb24(w, h, src, srca, stride, d + 3 * offset,
+            vo_draw_alpha_rgb24(w, h, dp, src, srca, stride, d + 3 * offset,
                                 3 * buffer_stride);
             break;
         case 15:
-            vo_draw_alpha_rgb15(w, h, src, srca, stride, d + 2 * offset,
+            vo_draw_alpha_rgb15(w, h, dp, src, srca, stride, d + 2 * offset,
                                 2 * buffer_stride);
             break;
         case 16:
-            vo_draw_alpha_rgb16(w, h, src, srca, stride, d + 2 * offset,
+            vo_draw_alpha_rgb16(w, h, dp, src, srca, stride, d + 2 * offset,
                                 2 * buffer_stride);
             break;
     }
@@ -982,6 +982,14 @@
             return get_image(data);
         case VOCTRL_QUERY_FORMAT:
             return query_format(*((uint32_t *) data));
+	case VOCTRL_YUVSPU_SUPPORT:
+	    return VO_FALSE;
+	case VOCTRL_RGBSPU_SUPPORT:
+	    return VO_FALSE;
+	case VOCTRL_BGRSPU_SUPPORT:
+	    if(HW_MODE.vdm_mplayer_depth==32 || HW_MODE.vdm_mplayer_depth==24 || 
+		HW_MODE.vdm_mplayer_depth==15 || HW_MODE.vdm_mplayer_depth==16) return VO_TRUE;
+	    return VO_FALSE;
     }
     return VO_NOTIMPL;
 }
--- libvo/vo_gl2.c	2006-02-09 15:07:59.000000000 +0100
+++ libvo/vo_gl2.c	2006-04-04 01:27:37.000000000 +0200
@@ -84,7 +84,7 @@
 static int      use_glFinish;
 
 static void (*draw_alpha_fnc)
-                 (int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
+                 (int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride);
 
 
 /* The squares that are tiled to make up the game screen polygon */
@@ -573,23 +573,23 @@
   glLoadIdentity();
 }
 
-static void draw_alpha_32(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
-   vo_draw_alpha_rgb32(w,h,src,srca,stride,ImageData+4*(y0*image_width+x0),4*image_width);
+static void draw_alpha_32(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
+   vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,ImageData+4*(y0*image_width+x0),4*image_width);
 }
 
-static void draw_alpha_24(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
-   vo_draw_alpha_rgb24(w,h,src,srca,stride,ImageData+3*(y0*image_width+x0),3*image_width);
+static void draw_alpha_24(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
+   vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,ImageData+3*(y0*image_width+x0),3*image_width);
 }
 
-static void draw_alpha_16(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
-   vo_draw_alpha_rgb16(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width);
+static void draw_alpha_16(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
+   vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width);
 }
 
-static void draw_alpha_15(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
-   vo_draw_alpha_rgb15(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width);
+static void draw_alpha_15(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
+   vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width);
 }
 
-static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
+static void draw_alpha_null(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
 }
 
 #ifdef GL_WIN32
@@ -1142,6 +1142,13 @@
       return vo_x11_get_equalizer(data, value);
     }
 #endif
+  case VOCTRL_YUVSPU_SUPPORT:
+    return VO_FALSE;
+  case VOCTRL_RGBSPU_SUPPORT:
+    return VO_FALSE;
+  case VOCTRL_BGRSPU_SUPPORT:
+    if (image_bpp==15 || image_bpp==16 || image_bpp==24 || image_bpp==32) return VO_TRUE;
+    return VO_FALSE;
   }
   return VO_NOTIMPL;
 }
--- libvo/vo_x11.c	2006-03-09 19:05:38.000000000 +0100
+++ libvo/vo_x11.c	2006-04-04 01:27:37.000000000 +0200
@@ -42,6 +42,7 @@
 #include "postproc/swscale_internal.h"       //FIXME
 #include "postproc/rgb2rgb.h"
 #include "libmpcodecs/vf_scale.h"
+#include "help_mp.h"
 
 #include "mp_msg.h"
 
@@ -60,7 +61,7 @@
 LIBVO_EXTERN(x11)
 /* private prototypes */
 static void Display_Image(XImage * myximage, unsigned char *ImageData);
-static void (*draw_alpha_fnc) (int x0, int y0, int w, int h,
+static void (*draw_alpha_fnc) (int x0, int y0, int w, int h, int dp,
                                unsigned char *src, unsigned char *srca,
                                int stride);
 
@@ -105,39 +106,39 @@
 
 }
 
-static void draw_alpha_32(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha_32(int x0, int y0, int w, int h, int dp, unsigned char *src,
                           unsigned char *srca, int stride)
 {
-    vo_draw_alpha_rgb32(w, h, src, srca, stride,
+    vo_draw_alpha_rgb32(w, h, dp, src, srca, stride,
                         ImageData + 4 * (y0 * image_width + x0),
                         4 * image_width);
 }
 
-static void draw_alpha_24(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha_24(int x0, int y0, int w, int h, int dp, unsigned char *src,
                           unsigned char *srca, int stride)
 {
-    vo_draw_alpha_rgb24(w, h, src, srca, stride,
+    vo_draw_alpha_rgb24(w, h, dp, src, srca, stride,
                         ImageData + 3 * (y0 * image_width + x0),
                         3 * image_width);
 }
 
-static void draw_alpha_16(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha_16(int x0, int y0, int w, int h, int dp, unsigned char *src,
                           unsigned char *srca, int stride)
 {
-    vo_draw_alpha_rgb16(w, h, src, srca, stride,
+    vo_draw_alpha_rgb16(w, h, dp, src, srca, stride,
                         ImageData + 2 * (y0 * image_width + x0),
                         2 * image_width);
 }
 
-static void draw_alpha_15(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha_15(int x0, int y0, int w, int h, int dp, unsigned char *src,
                           unsigned char *srca, int stride)
 {
-    vo_draw_alpha_rgb15(w, h, src, srca, stride,
+    vo_draw_alpha_rgb15(w, h, dp, src, srca, stride,
                         ImageData + 2 * (y0 * image_width + x0),
                         2 * image_width);
 }
 
-static void draw_alpha_null(int x0, int y0, int w, int h,
+static void draw_alpha_null(int x0, int y0, int w, int h, int dp,
                             unsigned char *src, unsigned char *srca,
                             int stride)
 {
@@ -795,6 +796,14 @@
                 vo_x11_clearwindow(mDisplay, vo_window);
             }
             return VO_TRUE;
+        case VOCTRL_YUVSPU_SUPPORT:
+            return VO_FALSE;
+        case VOCTRL_RGBSPU_SUPPORT:
+	    return VO_FALSE;
+        case VOCTRL_BGRSPU_SUPPORT:
+	    if (out_format == IMGFMT_BGR15 || out_format == IMGFMT_BGR16 || 
+		out_format == IMGFMT_BGR24 || out_format == IMGFMT_BGR32) return VO_TRUE;
+	    return VO_FALSE;
     }
     return VO_NOTIMPL;
 }
--- libvo/vo_sdl.c	2006-03-24 09:12:02.000000000 +0100
+++ libvo/vo_sdl.c	2006-04-04 01:27:37.000000000 +0200
@@ -284,7 +284,7 @@
  *
  **/
 
-static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
+static void draw_alpha(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
 	struct sdl_priv_s *priv = &sdl_priv;
 	
     if(priv->osd_has_changed) {
@@ -325,16 +325,43 @@
 		case IMGFMT_YV12:  
 		case IMGFMT_I420:
         	case IMGFMT_IYUV:
-            vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]);
+		    switch (dp) {
+		      case 0 :
+        		vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]);
+			break;
+		      case 1 :
+		        SDL_OVR_LOCK(-1)
+		        if (priv->format==IMGFMT_YV12)
+        		  vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) (priv->overlay->pixels[1]))+priv->overlay->pitches[1]*y0+x0,priv->overlay->pitches[1]);
+			  else
+        		  vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) (priv->overlay->pixels[2]))+priv->overlay->pitches[2]*y0+x0,priv->overlay->pitches[2]);
+			SDL_OVR_UNLOCK
+		        break;
+		      case 2 :
+		        SDL_OVR_LOCK(-1)
+		        if (priv->format==IMGFMT_YV12) 
+        		  vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) (priv->overlay->pixels[2]))+priv->overlay->pitches[2]*y0+x0,priv->overlay->pitches[2]);
+			  else 
+        		  vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) (priv->overlay->pixels[1]))+priv->overlay->pitches[1]*y0+x0,priv->overlay->pitches[1]);
+			SDL_OVR_UNLOCK
+		        break;
+		      }
 		break;
 		case IMGFMT_YUY2:
         	case IMGFMT_YVYU:
                 x0 *= 2;
-    			vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]);
+		    switch (dp) {
+		      case 0 :
+    			vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]);
+			break;
+		      case 6 :
+    			vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]);
+			break;
+		      }
 		break;	
         	case IMGFMT_UYVY:
                 x0 *= 2;
-    			vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]);
+    			vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]);
 		break;
 
 		default:
@@ -343,19 +370,19 @@
 		switch(priv->format) {
 		case IMGFMT_RGB15:
 		case IMGFMT_BGR15:
-    			vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
+    			vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
 		break;
 		case IMGFMT_RGB16:
 		case IMGFMT_BGR16:
-    			vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
+    			vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
 		break;
 		case IMGFMT_RGB24:
 		case IMGFMT_BGR24:
-    			vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
+    			vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
 		break;
 		case IMGFMT_RGB32:
 		case IMGFMT_BGR32:
-    			vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
+    			vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch);
 		break;
 		}
         }
@@ -364,19 +391,19 @@
 		switch(priv->format) {
 		case IMGFMT_RGB15:
 		case IMGFMT_BGR15:
-    			vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
+    			vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
 		break;
 		case IMGFMT_RGB16:
 		case IMGFMT_BGR16:
-    			vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
+    			vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
 		break;
 		case IMGFMT_RGB24:
 		case IMGFMT_BGR24:
-    			vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
+    			vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
 		break;
 		case IMGFMT_RGB32:
 		case IMGFMT_BGR32:
-    			vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
+    			vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch);
 		break;
 		}
         }
@@ -1727,6 +1754,18 @@
         printf("SDL: Set fullscreen mode\n"); }
     }
     return VO_TRUE;
+  case VOCTRL_YUVSPU_SUPPORT:
+    if (priv->format == IMGFMT_YV12 || priv->format == IMGFMT_I420 || priv->format==IMGFMT_IYUV) return VO_TRUE;
+    return VO_FALSE;
+  case VOCTRL_YUYSPU_SUPPORT:
+    if (priv->format==IMGFMT_YUY2) return VO_TRUE;
+    return VO_FALSE;
+  case VOCTRL_RGBSPU_SUPPORT:
+    if (priv->mode == RGB) return VO_TRUE;
+    return VO_FALSE;
+  case VOCTRL_BGRSPU_SUPPORT:
+    if (priv->mode == BGR) return VO_TRUE;
+    return VO_FALSE;
   }
 
   return VO_NOTIMPL;
--- libvo/vesa_lvo.c	2006-03-24 09:12:02.000000000 +0100
+++ libvo/vesa_lvo.c	2006-04-04 01:27:37.000000000 +0200
@@ -234,50 +234,51 @@
   }	
 }
 
-static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)
+static void draw_alpha_null(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)
 {
   UNUSED(x0);
   UNUSED(y0);
   UNUSED(w);
   UNUSED(h);
+  UNUSED(dp);
   UNUSED(src);
   UNUSED(srca);
   UNUSED(stride);
 }
 
-static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)
+static void draw_alpha(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)
 {
     uint32_t bespitch = /*(*/mga_vid_config.src_width;// + 15) & ~15;
     switch(mga_vid_config.format){
     case IMGFMT_BGR15:
     case IMGFMT_RGB15:
-	vo_draw_alpha_rgb15(w,h,src,srca,stride,lvo_mem+2*(y0*bespitch+x0),2*bespitch);
+	vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,lvo_mem+2*(y0*bespitch+x0),2*bespitch);
 	break;
     case IMGFMT_BGR16:
     case IMGFMT_RGB16:
-	vo_draw_alpha_rgb16(w,h,src,srca,stride,lvo_mem+2*(y0*bespitch+x0),2*bespitch);
+	vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,lvo_mem+2*(y0*bespitch+x0),2*bespitch);
 	break;
     case IMGFMT_BGR24:
     case IMGFMT_RGB24:
-	vo_draw_alpha_rgb24(w,h,src,srca,stride,lvo_mem+3*(y0*bespitch+x0),3*bespitch);
+	vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,lvo_mem+3*(y0*bespitch+x0),3*bespitch);
 	break;
     case IMGFMT_BGR32:
     case IMGFMT_RGB32:
-	vo_draw_alpha_rgb32(w,h,src,srca,stride,lvo_mem+4*(y0*bespitch+x0),4*bespitch);
+	vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,lvo_mem+4*(y0*bespitch+x0),4*bespitch);
 	break;
     case IMGFMT_YV12:
     case IMGFMT_IYUV:
     case IMGFMT_I420:
-        vo_draw_alpha_yv12(w,h,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch);
+        vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch);
         break;
     case IMGFMT_YUY2:
-        vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+2*(bespitch*y0+x0),bespitch);
+        vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,lvo_mem+2*(bespitch*y0+x0),bespitch);
         break;
     case IMGFMT_UYVY:
-        vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+2*(bespitch*y0+x0)+1,bespitch);
+        vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,lvo_mem+2*(bespitch*y0+x0)+1,bespitch);
         break;
     default:
-        draw_alpha_null(x0,y0,w,h,src,srca,stride);
+        draw_alpha_null(x0,y0,w,h,dp,src,srca,stride);
     }
 }
 
--- libvo/vo_aa.c	2006-02-09 15:07:59.000000000 +0100
+++ libvo/vo_aa.c	2006-04-04 01:27:37.000000000 +0200
@@ -531,7 +531,7 @@
 }
 
 #ifdef USE_OSD
-static void draw_alpha(int x,int y, int w,int h, unsigned char* src, unsigned char *srca, int stride){
+static void draw_alpha(int x,int y, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
     int i,j;
     for (i = 0; i < h; i++) {
 	for (j = 0; j < w; j++) {
--- libvo/vo_xv.c	2005-11-10 03:39:31.000000000 +0100
+++ libvo/vo_xv.c	2006-04-04 01:27:37.000000000 +0200
@@ -92,47 +92,83 @@
 static uint32_t dwidth, dheight;
 static uint32_t max_width = 0, max_height = 0; // zero means: not set
 
-static void (*draw_alpha_fnc) (int x0, int y0, int w, int h,
+static int support_yuvspu = VO_FALSE;
+static int support_yuyspu = VO_FALSE;
+
+static void (*draw_alpha_fnc) (int x0, int y0, int w, int h, int dp,
                                unsigned char *src, unsigned char *srca,
                                int stride);
 
-static void draw_alpha_yv12(int x0, int y0, int w, int h,
+static void draw_alpha_yv12(int x0, int y0, int w, int h, int dp,
                             unsigned char *src, unsigned char *srca,
                             int stride)
 {
+    switch (dp)  { 
+	case 1:  {
+    x0 += image_width/2 * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x);
+    vo_draw_alpha_yv12(w, h, dp, src, srca, stride,
+                       xvimage[current_buf]->data +
+                       xvimage[current_buf]->offsets[1] +
+                       xvimage[current_buf]->pitches[1] * y0 + x0,
+                       xvimage[current_buf]->pitches[1]);
+	  break; }
+	case 2:  {
+    x0 += image_width/2 * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x);
+    vo_draw_alpha_yv12(w, h, dp, src, srca, stride,
+                       xvimage[current_buf]->data +
+                       xvimage[current_buf]->offsets[2] +
+                       xvimage[current_buf]->pitches[2] * y0 + x0,
+                       xvimage[current_buf]->pitches[2]);
+	  break; }
+	case 0: {
     x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x);
-    vo_draw_alpha_yv12(w, h, src, srca, stride,
+    vo_draw_alpha_yv12(w, h, dp, src, srca, stride,
                        xvimage[current_buf]->data +
                        xvimage[current_buf]->offsets[0] +
                        xvimage[current_buf]->pitches[0] * y0 + x0,
                        xvimage[current_buf]->pitches[0]);
 }
+	}
 
-static void draw_alpha_yuy2(int x0, int y0, int w, int h,
+}
+
+static void draw_alpha_yuy2(int x0, int y0, int w, int h, int dp,
                             unsigned char *src, unsigned char *srca,
                             int stride)
 {
+  switch (dp) {
+    case 0:
+    x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x);
+    vo_draw_alpha_yuy2(w, h, dp, src, srca, stride,
+                       xvimage[current_buf]->data +
+                       xvimage[current_buf]->offsets[0] +
+                       xvimage[current_buf]->pitches[0] * y0 + 2 * x0,
+                       xvimage[current_buf]->pitches[0]);
+    break;
+    case 6:
     x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x);
-    vo_draw_alpha_yuy2(w, h, src, srca, stride,
+    vo_draw_alpha_yv12(w, h, dp, src, srca, stride,
                        xvimage[current_buf]->data +
                        xvimage[current_buf]->offsets[0] +
                        xvimage[current_buf]->pitches[0] * y0 + 2 * x0,
                        xvimage[current_buf]->pitches[0]);
+    break;
+    }
 }
 
-static void draw_alpha_uyvy(int x0, int y0, int w, int h,
+static void draw_alpha_uyvy(int x0, int y0, int w, int h, int dp,
                             unsigned char *src, unsigned char *srca,
                             int stride)
 {
     x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x);
-    vo_draw_alpha_yuy2(w, h, src, srca, stride,
+    vo_draw_alpha_yuy2(w, h, dp, src, srca, stride,
                        xvimage[current_buf]->data +
                        xvimage[current_buf]->offsets[0] +
                        xvimage[current_buf]->pitches[0] * y0 + 2 * x0 + 1,
                        xvimage[current_buf]->pitches[0]);
 }
 
-static void draw_alpha_null(int x0, int y0, int w, int h,
+static void draw_alpha_null(int x0, int y0, int w, int h, int dp,
                             unsigned char *src, unsigned char *srca,
                             int stride)
 {
@@ -391,11 +427,13 @@
     {
         case IMGFMT_YV12:
         case IMGFMT_I420:
+	    support_yuvspu = VO_TRUE;
         case IMGFMT_IYUV:
             draw_alpha_fnc = draw_alpha_yv12;
             break;
         case IMGFMT_YUY2:
         case IMGFMT_YVYU:
+	    support_yuyspu = VO_TRUE;
             draw_alpha_fnc = draw_alpha_yuy2;
             break;
         case IMGFMT_UYVY:
@@ -1007,6 +1045,14 @@
         case VOCTRL_ONTOP:
             vo_x11_ontop();
             return VO_TRUE;
+        case VOCTRL_YUVSPU_SUPPORT:
+            return support_yuvspu;
+        case VOCTRL_RGBSPU_SUPPORT:
+	    return VO_FALSE;
+        case VOCTRL_BGRSPU_SUPPORT:
+	    return VO_FALSE;
+        case VOCTRL_YUYSPU_SUPPORT:
+            return support_yuyspu;
     }
     return VO_NOTIMPL;
 }
--- libvo/vo_fbdev2.c	2006-03-04 21:00:06.000000000 +0100
+++ libvo/vo_fbdev2.c	2006-04-04 01:27:37.000000000 +0200
@@ -79,7 +79,7 @@
 static int fb_bpp;		// 32: 32  24: 24  16: 16  15: 15
 static size_t fb_size; // size of frame_buffer
 static int fb_line_len; // length of one line in bytes
-static void (*draw_alpha_p)(int w, int h, unsigned char *src,
+static void (*draw_alpha_p)(int w, int h, int dp, unsigned char *src,
 		unsigned char *srca, int stride, unsigned char *dst,
 		int dstride);
 
@@ -317,7 +317,7 @@
 	return 0;
 }
 
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src,
 		unsigned char *srca, int stride)
 {
 	unsigned char *dst;
@@ -330,7 +330,7 @@
 	dst = next_frame + (in_width * y0 + x0) * fb_pixel_size;
 	dstride = in_width * fb_pixel_size;
 #endif
-	(*draw_alpha_p)(w, h, src, srca, stride, dst, dstride);
+	(*draw_alpha_p)(w, h, dp, src, srca, stride, dst, dstride);
 }
 
 static void draw_osd(void)
@@ -403,6 +403,13 @@
   switch (request) {
   case VOCTRL_QUERY_FORMAT:
     return query_format(*((uint32_t*)data));
+  case VOCTRL_YUVSPU_SUPPORT:
+    return VO_FALSE;
+  case VOCTRL_RGBSPU_SUPPORT:
+    return VO_FALSE;
+  case VOCTRL_BGRSPU_SUPPORT:
+    if (fb_bpp == 32 || fb_bpp==24 || fb_bpp==16 || fb_bpp==15) return VO_TRUE;
+    return VO_FALSE;
   }
   return VO_NOTIMPL;
 }
--- libvo/vo_macosx.m	2006-03-04 13:37:44.000000000 +0100
+++ libvo/vo_macosx.m	2006-04-04 01:27:37.000000000 +0200
@@ -78,17 +78,17 @@
 LIBVO_EXTERN(macosx)
 
 extern void mplayer_put_key(int code);
-extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride));
 
-static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride)
+static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride)
 {
 	switch (image_format)
 	{
 		case IMGFMT_RGB32:
-			vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*image_width+x0),4*image_width);
+			vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,image_data+4*(y0*image_width+x0),4*image_width);
 			break;
 		case IMGFMT_YUY2:
-			vo_draw_alpha_yuy2(w,h,src,srca,stride,image_data + (x0 + y0 * image_width) * 2,image_width*2);
+			vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,image_data + (x0 + y0 * image_width) * 2,image_width*2);
 			break;
 	}
 }
--- libvo/vo_dxr3.c	2006-01-12 21:04:35.000000000 +0100
+++ libvo/vo_dxr3.c	2006-04-04 01:27:37.000000000 +0200
@@ -675,7 +675,7 @@
 	return 0;
 }
 
-static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride)
+static void draw_alpha(int x, int y, int w, int h, int dp, unsigned char* src, unsigned char *srca, int srcstride)
 {
 #ifdef SPU_SUPPORT
 	unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x];
--- libvo/vo_xvmc.c	2006-03-24 09:12:02.000000000 +0100
+++ libvo/vo_xvmc.c	2006-04-04 01:27:37.000000000 +0200
@@ -84,12 +84,12 @@
 static int free_element;
 
 
-static void (*draw_osd_fnc)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
+static void (*draw_osd_fnc)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride);
 static void (*clear_osd_fnc)(int x0,int y0, int w,int h);
 static void (*init_osd_fnc)(void);
 
-static void   draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
-static void   draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
+static void   draw_osd_AI44(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride);
+static void   draw_osd_IA44(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride);
 static void   clear_osd_subpic(int x0,int y0, int w,int h);
 static void   init_osd_yuv_pal(void);
 
@@ -877,7 +877,7 @@
    subpicture_alloc = 1;
 }
 
-static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
+static void draw_osd_IA44(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
 int ox,oy;
 int rez;
 
@@ -897,7 +897,7 @@
    }
 }
 
-static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
+static void draw_osd_AI44(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){
 int ox,oy;
 int rez;
    if(  mp_msg_test(MSGT_VO,MSGL_DBG4) )
--- libmpcodecs/vf_expand.c	2006-03-31 02:15:47.000000000 +0200
+++ libmpcodecs/vf_expand.c	2006-04-04 01:27:37.000000000 +0200
@@ -80,7 +80,7 @@
     // TODO  clear left and right side of the image if needed
 }
 
-static void draw_func(int x0,int y0, int w,int h,unsigned char* src, unsigned char *srca, int stride){
+static void draw_func(int x0,int y0, int w,int h,int dp,unsigned char* src, unsigned char *srca, int stride){
     unsigned char* dst;
     if(!vo_osd_changed_flag && vf->dmpi->planes[0]==vf->priv->fb_ptr){
 	// ok, enough to update the area inside the video, leave the black bands
@@ -108,19 +108,19 @@
     switch(vf->dmpi->imgfmt){
     case IMGFMT_BGR15:
     case IMGFMT_RGB15:
-	vo_draw_alpha_rgb15(w,h,src,srca,stride,dst,vf->dmpi->stride[0]);
+	vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]);
 	break;
     case IMGFMT_BGR16:
     case IMGFMT_RGB16:
-	vo_draw_alpha_rgb16(w,h,src,srca,stride,dst,vf->dmpi->stride[0]);
+	vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]);
 	break;
     case IMGFMT_BGR24:
     case IMGFMT_RGB24:
-	vo_draw_alpha_rgb24(w,h,src,srca,stride,dst,vf->dmpi->stride[0]);
+	vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]);
 	break;
     case IMGFMT_BGR32:
     case IMGFMT_RGB32:
-	vo_draw_alpha_rgb32(w,h,src,srca,stride,dst,vf->dmpi->stride[0]);
+	vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]);
 	break;
     case IMGFMT_YV12:
     case IMGFMT_I420:
@@ -129,13 +129,13 @@
     case IMGFMT_IF09:
     case IMGFMT_Y800:
     case IMGFMT_Y8:
-	vo_draw_alpha_yv12(w,h,src,srca,stride,dst,vf->dmpi->stride[0]);
+	vo_draw_alpha_yv12(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]);
 	break;
     case IMGFMT_YUY2:
-	vo_draw_alpha_yuy2(w,h,src,srca,stride,dst,vf->dmpi->stride[0]);
+	vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]);
 	break;
     case IMGFMT_UYVY:
-	vo_draw_alpha_yuy2(w,h,src,srca,stride,dst+1,vf->dmpi->stride[0]);
+	vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,dst+1,vf->dmpi->stride[0]);
 	break;
     }
 }
--- libmenu/menu.c	2006-03-30 08:40:58.000000000 +0200
+++ libmenu/menu.c	2006-04-04 01:27:37.000000000 +0200
@@ -252,7 +252,7 @@
 
 ///////////////////////////// Helpers ////////////////////////////////////
 
-typedef void (*draw_alpha_f)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
+typedef void (*draw_alpha_f)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride);
 
 inline static draw_alpha_f get_draw_alpha(uint32_t fmt) {
   switch(fmt) {
@@ -312,7 +312,7 @@
   while (*txt) {
     unsigned char c=*txt++;
     if ((font=vo_font->font[c])>=0 && (x + vo_font->width[c] <= mpi->w) && (y + vo_font->pic_a[font]->h <= mpi->h))
-      draw_alpha(vo_font->width[c], vo_font->pic_a[font]->h,
+      draw_alpha(vo_font->width[c], vo_font->pic_a[font]->h,0,
 		 vo_font->pic_b[font]->bmp+vo_font->start[c],
 		 vo_font->pic_a[font]->bmp+vo_font->start[c],
 		 vo_font->pic_a[font]->w,
@@ -479,7 +479,7 @@
       if(font >= 0) {
  	int cs = (vo_font->pic_a[font]->h - vo_font->height) / 2;
 	if ((sx + vo_font->width[c] < xmax)  &&  (sy + vo_font->height < ymax) )
-	  draw_alpha(vo_font->width[c], vo_font->height,
+	  draw_alpha(vo_font->width[c], vo_font->height, 0,
 		     vo_font->pic_b[font]->bmp+vo_font->start[c] +
 		     cs * vo_font->pic_a[font]->w,
 		     vo_font->pic_a[font]->bmp+vo_font->start[c] +
