[MPlayer-dev-eng] Patch: Display OSD in the black stripes area with vo SDL

Fredrik Kuivinen freku045 at student.liu.se
Sat Feb 9 14:25:24 CET 2002


Hi

With this patch OSD contents will be displayed above and/or below the movie
frames instead of in them when using -vo sdl. It also changes a few things
in the osd handling code in mplayer.c. Those changes are done to let the 
vo drivers know if the osd contents has changed or not.

/ Fredrik Kuivinen

-------------- next part --------------
Index: find_sub.c
===================================================================
RCS file: /cvsroot/mplayer/main/find_sub.c,v
retrieving revision 1.5
diff -u -3 -p -b -r1.5 find_sub.c
--- find_sub.c	17 Dec 2001 00:07:20 -0000	1.5
+++ find_sub.c	9 Feb 2002 13:01:00 -0000
@@ -34,6 +34,10 @@ void find_sub(subtitle* subtitles,int ke
       if(key>nosub_range_start && key<nosub_range_end) return; // OK!
     }
     // sub changed!
+
+    /* Tell the OSD subsystem that the osd contents will change soon */
+    vo_osd_changed(1);
+    
 
     if(key<=0){
       vo_sub=NULL; // no sub here
Index: mplayer.c
===================================================================
RCS file: /cvsroot/mplayer/main/mplayer.c,v
retrieving revision 1.389
diff -u -3 -p -b -r1.389 mplayer.c
--- mplayer.c	9 Feb 2002 01:29:11 -0000	1.389
+++ mplayer.c	9 Feb 2002 13:01:02 -0000
@@ -188,7 +188,17 @@ static int output_quality=0;
 
 int use_gui=0;
 
-int osd_level=2;
+/* Use osd_set_level and osd_get_level to get and set osd_level! */ 
+static int osd_level=2;
+
+static int osd_get_level(void);
+static void osd_set_level(int new_level);
+
+/* Use osd_set_function and osd_get_function to get and set osd_function! */ 
+static int osd_function = OSD_PLAY;
+
+static int osd_get_function(void);
+static void osd_set_function(int new_func);
 
 // seek:
 char *seek_to_sec=NULL;
@@ -450,7 +460,6 @@ int out_fmt=0;
 int eof=0;
 
 int osd_visible=100;
-int osd_function=OSD_PLAY;
 int osd_last_pts=-303;
 int osd_show_av_delay = 0;
 int osd_show_sub_delay = 0;
@@ -1802,7 +1811,7 @@ if(!(vo_flags&256)){ // flag 256 means: 
     if(eof) break;
     if(force_redraw){
       --force_redraw;
-      if(!force_redraw) osd_function=OSD_PLAY;
+      if(!force_redraw) osd_set_function(OSD_PLAY);
       continue;
     }
 
@@ -1934,13 +1943,13 @@ read_input:
 #ifdef USE_OSD
   if(osd_visible){
     if (!--osd_visible){ vo_osd_progbar_type=-1; // disable
-       if (osd_function != OSD_PAUSE)
-	   osd_function = OSD_PLAY;
+       if (osd_get_function() != OSD_PAUSE)
+           osd_set_function(OSD_PLAY);
     }
   }
 #endif
 
-  if(osd_function==OSD_PAUSE){
+  if(osd_get_function() == OSD_PAUSE){
 #ifdef HAVE_NEW_INPUT    
     mp_cmd_t* cmd;
 #endif
@@ -1999,7 +2008,7 @@ read_input:
          }
       }
 #endif /* HAVE_NEW_INPUT */ 
-         osd_function=OSD_PLAY;
+         osd_set_function(OSD_PLAY);
       if (audio_out && sh_audio)
         audio_out->resume();	// resume audio
       (void)GetRelativeTime();	// keep TF around FT in next cycle
@@ -2015,7 +2024,7 @@ read_input:
 // skip some seconds... added by fly
 
 if(step_sec>0) {
-	osd_function=OSD_FFW;
+	osd_set_function(OSD_FFW);
 	rel_seek_secs+=step_sec;
 }
 
@@ -2037,9 +2046,9 @@ if(step_sec>0) {
    if(1 == select (FD_SETSIZE, &set, NULL, NULL, &timeout)) {
      fgets(buffer, 1024, stdin);
      if(!strcmp("play\n", buffer)) {
-       osd_function=OSD_PLAY;
+       osd_set_function(OSD_PLAY);
      } else if(!strcmp("stop\n", buffer)) {
-       osd_function=OSD_PAUSE;
+       osd_set_function(OSD_PAUSE);
      } else if(!strncmp("seek ", buffer, 5)) {
        sscanf(buffer+5, "%d", &arg);
        rel_seek_secs = arg-d_video->pts;
@@ -2050,7 +2059,7 @@ if(step_sec>0) {
        exit_player(MSGTR_Exit_quit);
      } 
    } else {
-     osd_function=OSD_PLAY;
+     osd_set_function(OSD_PLAY);
    }
  } else
  
@@ -2063,17 +2072,17 @@ if(step_sec>0) {
       (!use_stdin && (c=getch2(0))>0) || (c=mplayer_get_key())>0) switch(c){
     // seek 10 sec
     case KEY_RIGHT:
-      osd_function=OSD_FFW;
+      osd_set_function(OSD_FFW);
       rel_seek_secs+=10;break;
     case KEY_LEFT:
-      osd_function=OSD_REW;
+      osd_set_function(OSD_REW);
       rel_seek_secs-=10;break;
     // seek 1 min
     case KEY_UP:
-      osd_function=OSD_FFW;
+      osd_set_function(OSD_FFW);
       rel_seek_secs+=60;break;
     case KEY_DOWN:
-      osd_function=OSD_REW;
+      osd_set_function(OSD_REW);
       rel_seek_secs-=60;break;
     // seek 10 min
     case KEY_PAGE_UP:
@@ -2102,7 +2111,7 @@ if(step_sec>0) {
     // pause
     case 'p':
     case ' ':
-      osd_function=OSD_PAUSE;
+      osd_set_function(OSD_PAUSE);
       break;
     case KEY_HOME:
       {
@@ -2146,7 +2155,7 @@ if(step_sec>0) {
       break;
     case 'o':  // toggle OSD
       if(sh_video)
-	osd_level=(osd_level+1)%3;
+            osd_set_level((osd_level+1)%3);
       break;
     case 'z':
       sub_delay -= 0.1;
@@ -2167,7 +2176,7 @@ if(step_sec>0) {
         }
 
 #ifdef USE_OSD
-        if(osd_level){
+        if(osd_get_level()){
           osd_visible=sh_video->fps; // 1 sec
           vo_osd_progbar_type=OSD_VOLUME;
           vo_osd_progbar_value=(mixer_getbothvolume()*256.0)/100.0;
@@ -2212,7 +2221,7 @@ if(step_sec>0) {
         }
 	if(set_video_colors(sh_video,"Contrast",v_cont)){
 #ifdef USE_OSD
-    		if(osd_level){
+    		if(osd_get_level()){
             	    osd_visible=sh_video->fps; // 1 sec
 	    	    vo_osd_progbar_type=OSD_CONTRAST;
             	    vo_osd_progbar_value=((v_cont)<<8)/100;
@@ -2240,7 +2249,7 @@ if(step_sec>0) {
         }
 	if(set_video_colors(sh_video,"Brightness",v_bright)){
 #ifdef USE_OSD
-    		if(osd_level){
+    		if(osd_get_level()){
             	    osd_visible=sh_video->fps; // 1 sec
 	    	    vo_osd_progbar_type=OSD_BRIGHTNESS;
             	    vo_osd_progbar_value=((v_bright)<<8)/100;
@@ -2268,7 +2277,7 @@ if(step_sec>0) {
         }
 	if(set_video_colors(sh_video,"Hue",v_hue)){
 #ifdef USE_OSD
-    		if(osd_level){
+    		if(osd_get_level()){
             	    osd_visible=sh_video->fps; // 1 sec
 	    	    vo_osd_progbar_type=OSD_HUE;
             	    vo_osd_progbar_value=((v_hue)<<8)/100;
@@ -2296,7 +2305,7 @@ if(step_sec>0) {
         }
 	if(set_video_colors(sh_video,"Saturation",v_saturation)){
 #ifdef USE_OSD
-    		if(osd_level){
+    		if(osd_get_level()){
             	    osd_visible=sh_video->fps; // 1 sec
 	    	    vo_osd_progbar_type=OSD_SATURATION;
             	    vo_osd_progbar_value=((v_saturation)<<8)/100;
@@ -2344,12 +2353,12 @@ if(step_sec>0) {
       abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0;
       if(abs) {
 	abs_seek_pos = 3;
-	osd_function= (v > sh_video->timer) ? OSD_FFW : OSD_REW;
+	osd_set_function((v > sh_video->timer) ? OSD_FFW : OSD_REW);
 	rel_seek_secs = v;
       }
       else {
 	rel_seek_secs+= v;
-	osd_function= (v > 0) ? OSD_FFW : OSD_REW;
+	osd_set_function((v > 0) ? OSD_FFW : OSD_REW);
       }
     } break;
     case MP_CMD_AUDIO_DELAY : {
@@ -2359,7 +2368,7 @@ if(step_sec>0) {
       if(sh_audio) sh_audio->timer+= v;
     } break;
     case MP_CMD_PAUSE : {
-      osd_function=OSD_PAUSE;
+      osd_set_function(OSD_PAUSE);
     } break;
     case MP_CMD_QUIT : {
       exit_player(MSGTR_Exit_quit);
@@ -2404,9 +2413,9 @@ if(step_sec>0) {
       if(sh_video) {
 	int v = cmd->args[0].v.i;
 	if(v < 0)
-	  osd_level=(osd_level+1)%3;
+	  osd_set_level((osd_level+1)%3);
 	else
-	  osd_level= v > 2 ? 2 : v;
+	  osd_set_level(v > 2 ? 2 : v);
       } break;
     case MP_CMD_VOLUME :  {
       int v = cmd->args[0].v.i;
@@ -2415,7 +2424,7 @@ if(step_sec>0) {
       else
 	mixer_decvolume();
 #ifdef USE_OSD
-      if(osd_level){
+      if(osd_get_level()){
 	osd_visible=sh_video->fps; // 1 sec
 	vo_osd_progbar_type=OSD_VOLUME;
 	vo_osd_progbar_value=(mixer_getbothvolume()*256.0)/100.0;
@@ -2436,7 +2445,7 @@ if(step_sec>0) {
 
       if(set_video_colors(sh_video,"Contrast",v_cont)){
 #ifdef USE_OSD
-	if(osd_level){
+	if(osd_get_level()){
 	  osd_visible=sh_video->fps; // 1 sec
 	  vo_osd_progbar_type=OSD_CONTRAST;
 	  vo_osd_progbar_value=((v_cont)<<8)/100;
@@ -2458,7 +2467,7 @@ if(step_sec>0) {
       }
       if(set_video_colors(sh_video,"Brightness",v_bright)){
 #ifdef USE_OSD
-	if(osd_level){
+	if(osd_get_level()){
 	  osd_visible=sh_video->fps; // 1 sec
 	  vo_osd_progbar_type=OSD_BRIGHTNESS;
 	  vo_osd_progbar_value=((v_bright)<<8)/100;
@@ -2480,7 +2489,7 @@ if(step_sec>0) {
       }
       if(set_video_colors(sh_video,"Hue",v_hue)){
 #ifdef USE_OSD
-	if(osd_level){
+	if(osd_get_level()){
 	  osd_visible=sh_video->fps; // 1 sec
 	  vo_osd_progbar_type=OSD_HUE;
 	  vo_osd_progbar_value=((v_hue)<<8)/100;
@@ -2502,7 +2511,7 @@ if(step_sec>0) {
       }
       if(set_video_colors(sh_video,"Saturation",v_saturation)){
 #ifdef USE_OSD
-	if(osd_level){
+	if(osd_get_level()){
 	  osd_visible=sh_video->fps; // 1 sec
 	  vo_osd_progbar_type=OSD_SATURATION;
 	  vo_osd_progbar_value=((v_saturation)<<8)/100;
@@ -2600,7 +2609,7 @@ if(rel_seek_secs || abs_seek_pos){
       }
 #ifdef USE_OSD
         // Set OSD:
-      if(osd_level){
+      if(osd_get_level()){
         int len=((demuxer->movi_end-demuxer->movi_start)>>8);
         if (len>0){
 	   osd_visible=sh_video->fps; // 1 sec
@@ -2641,13 +2650,13 @@ if(rel_seek_secs || abs_seek_pos){
 	}
 	mplShMem->TimeSec=d_video->pts; 
 	if(mplShMem->Playing==0) break; // STOP
-	if(mplShMem->Playing==2) osd_function=OSD_PAUSE;
+	if(mplShMem->Playing==2) osd_set_function(OSD_PAUSE);
 	if ( mplShMem->VolumeChanged ) 
 	 {
 	  mixer_setvolume( mplShMem->Volume,mplShMem->Volume );
 	  mplShMem->VolumeChanged=0;
 #ifdef USE_OSD
-          if ( osd_level )
+          if (osd_get_level())
 	   {
             osd_visible=sh_video->fps; // 1 sec
             vo_osd_progbar_type=OSD_VOLUME;
@@ -2670,19 +2679,28 @@ if(rel_seek_secs || abs_seek_pos){
 
 //================= Update OSD ====================
 #ifdef USE_OSD
-  if(osd_level>=2){
-      int pts=d_video->pts;
-      if(pts==osd_last_pts-1) ++pts; else osd_last_pts=pts;
+  if(osd_get_level()>=2){
       vo_osd_text=osd_text_buffer;
       if (osd_show_sub_delay) {
 	  sprintf(vo_osd_text, "Sub delay: %d ms",(int)(sub_delay*1000));
 	  osd_show_sub_delay--;
-      } else
-      if (osd_show_av_delay) {
+          vo_osd_changed(1);
+      } else if (osd_show_av_delay) {
 	  sprintf(vo_osd_text, "A-V delay: %d ms",(int)(audio_delay*1000));
 	  osd_show_av_delay--;
-      } else
-          sprintf(vo_osd_text,"%c %02d:%02d:%02d",osd_function,pts/3600,(pts/60)%60,pts%60);
+          vo_osd_changed(1);
+      } else {
+          int pts=d_video->pts;              
+          if(pts%60 != osd_last_pts%60)
+              vo_osd_changed(1);
+          
+          if(pts==osd_last_pts-1)
+              ++pts;
+          else
+              osd_last_pts=pts;
+
+          sprintf(vo_osd_text,"%c %02d:%02d:%02d",osd_get_function(),pts/3600,(pts/60)%60,pts%60);
+      }
   } else {
       vo_osd_text=NULL;
   }
@@ -2709,6 +2727,9 @@ if(rel_seek_secs || abs_seek_pos){
   if(vo_vobsub){
     current_module="vobsub";
     vobsub_process(vo_vobsub,d_video->pts);
+
+    /* Don't know how to detect wether the sub has changed or not */
+    vo_osd_changed(1);
     current_module=NULL;
   }
 
@@ -2732,6 +2753,8 @@ if(rel_seek_secs || abs_seek_pos){
       spudec_assemble(vo_spudec,packet,len,100*d_dvdsub->pts);
     }
     spudec_heartbeat(vo_spudec,100*d_video->pts);
+    /* Don't know how to detect wether the sub has changed or not */
+    vo_osd_changed(1);
     current_module=NULL;
   }
 #endif
@@ -2842,4 +2865,32 @@ if(use_gui || playtree_iter != NULL
 exit_player(MSGTR_Exit_eof);
 
 return 1;
+}
+
+static int osd_get_function(void)
+{
+    return osd_function;
+}
+
+static void osd_set_function(int new_func) 
+{
+    if(osd_function != new_func)
+    {
+        osd_function = new_func;
+        vo_osd_changed(1);
+    }
+}
+
+static int osd_get_level(void)
+{
+    return osd_level;
+}
+
+static void osd_set_level(int new_level)
+{
+    if(osd_level != new_level)
+    {
+        osd_level = new_level;
+        vo_osd_changed(1);
+    }
 }

Index: libvo/sub.c
Index: sub.c
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/sub.c,v
retrieving revision 1.41
diff -u -3 -p -b -r1.41 sub.c
--- sub.c       11 Jan 2002 16:06:45 -0000      1.41
+++ sub.c       9 Feb 2002 13:35:33 -0000
@@ -319,3 +319,11 @@ void vo_draw_text(int dxs,int dys,void (
 
 }
          
+static int vo_osd_changed_status = 0;
+
+int vo_osd_changed(int new_value)
+{
+    int ret = vo_osd_changed_status;
+    vo_osd_changed_status = new_value;
+    return ret;
+}
Index: libvo/sub.h
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/sub.h,v
retrieving revision 1.10
diff -u -3 -p -b -r1.10 sub.h
--- libvo/sub.h	10 Jan 2002 17:20:27 -0000	1.10
+++ libvo/sub.h	9 Feb 2002 13:01:03 -0000
@@ -50,5 +50,7 @@ extern char * __sub_osd_names_short[];
 //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));
 
+int vo_osd_changed(int new_value);
+
 #endif
 #endif
Index: libvo/vo_sdl.c
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/vo_sdl.c,v
retrieving revision 1.67
diff -u -3 -p -b -r1.67 vo_sdl.c
--- libvo/vo_sdl.c	9 Feb 2002 01:21:48 -0000	1.67
+++ libvo/vo_sdl.c	9 Feb 2002 13:01:03 -0000
@@ -164,6 +164,29 @@ static void setenv(const char *name, con
 #define ZOOM 0x04
 #define FLIP 0x08  
 
+#ifdef SDL_ENABLE_LOCKS
+#define	SDL_OVR_LOCK(x)        if (SDL_LockYUVOverlay (priv->overlay)) { \
+				if(verbose) printf("SDL: Couldn't lock YUV overlay\n"); \
+				return x; \
+	    		    }
+#define SDL_OVR_UNLOCK      SDL_UnlockYUVOverlay (priv->overlay);
+
+#define SDL_SRF_LOCK(srf, x)   if(SDL_MUSTLOCK(srf)) { \
+				if(SDL_LockSurface (srf)) { \
+					if(verbose) printf("SDL: Couldn't lock RGB surface\n"); \
+					return x; \
+				} \
+			    }
+
+#define SDL_SRF_UNLOCK(srf) if(SDL_MUSTLOCK(srf)) \
+				SDL_UnlockSurface (srf);
+#else
+#define SDL_OVR_LOCK(x)
+#define SDL_OVR_UNLOCK
+#define SDL_SRF_LOCK(srf, x)
+#define SDL_SRF_UNLOCK(srf)
+#endif
+
 /** Private SDL Data structure **/
 
 static struct sdl_priv_s {
@@ -232,10 +255,50 @@ static struct sdl_priv_s {
 	/* destination dimensions */
 	int dstwidth, dstheight;
 
+    /* Draw image at coordinate y on the SDL surfaces */
+    int y;
+
+    /* The picture is displayed between those y coordinates in priv->surface */
+    int y_screen_top, y_screen_bottom;
+
+    /* 1 if the OSD has changed otherwise 0 */
+    int osd_has_changed;
+    
 	/* source image format (YUV/RGB/...) */
         int format;
+
+    /* dirty_off_frame[0] contains a bounding box around the osd contents drawn above the frame
+       dirty_off_frame[1] is the corresponding thing for OSD contents drawn below the frame
+    */
+    SDL_Rect dirty_off_frame[2];
 } sdl_priv;
 
+static void erase_area_4(int x_start, int width, int height, int pitch, uint32_t color, uint8_t* pixels);
+static void erase_area_1(int x_start, int width, int height, int pitch, uint8_t color, uint8_t* pixels);
+
+/* Expand 'rect' to contain the rectangle specified by x, y, w and h */
+static void expand_rect(SDL_Rect* rect, int x, int y, int w, int h)
+{
+    if(rect->x < 0 || rect->y < 0) {
+        rect->x = x;
+        rect->y = y;
+        rect->w = w;
+        rect->h = h;
+        return;
+    }
+    
+    if(rect->x > x)
+        rect->x = x;
+
+    if(rect->y > y)
+        rect->y = y;
+
+    if(rect->x + rect->w < x + w)
+        rect->w = x + w - rect->x;
+
+    if(rect->y + rect->h < y + h)
+        rect->h = y + h - rect->y;
+}
 
 /** libvo Plugin functions **/
 
@@ -247,11 +310,45 @@ static struct sdl_priv_s {
 static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
 	struct sdl_priv_s *priv = &sdl_priv;
 	
+    if(priv->osd_has_changed) {
+        /* OSD did change. Store a bounding box of everything drawn into the OSD */
+        if(priv->y >= y0) {
+            /* Make sure we don't mark part of the frame area dirty */
+            if(h + y0 > priv->y) 
+                expand_rect(&priv->dirty_off_frame[0], x0, y0, w, priv->y - y0);
+            else
+                expand_rect(&priv->dirty_off_frame[0], x0, y0, w, h);
+        }
+        else if(priv->y + priv->height <= y0 + h) {
+            /* Make sure we don't mark part of the frame area dirty */
+            if(y0 < priv->y + priv->height) 
+                expand_rect(&priv->dirty_off_frame[1], x0,
+                            priv->y + priv->height,
+                            w, h - ((priv->y + priv->height) - y0));
+            else
+                expand_rect(&priv->dirty_off_frame[1], x0, y0, w, h);
+        }
+    }
+    else { /* OSD contents didn't change only draw parts that was erased by the frame */
+        if(priv->y >= y0) {
+           src = src + (priv->y - y0) * stride;
+           srca = srca + (priv->y - y0) * stride;
+           h -= priv->y - y0;
+           y0 = priv->y;
+        }
+
+        if(priv->y + priv->height <= y0 + h)
+            h = priv->y + priv->height - y0;
+
+        if(h <= 0)
+            return;
+    }
+
 	switch(priv->format) {
 		case IMGFMT_YV12:  
 		case IMGFMT_I420:
         	case IMGFMT_IYUV:
-    			vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->width*y0+x0,priv->width);
+            vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->width);
 		break;
 		case IMGFMT_YUY2:
         	case IMGFMT_YVYU:		
@@ -260,6 +357,7 @@ static void draw_alpha(int x0,int y0, in
         	case IMGFMT_UYVY:
     			vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+2*(priv->width*y0+x0)+1,2*priv->width);
 		break;
+
 		default:
 		if(priv->dblit)		
 		switch(priv->format) {
@@ -419,7 +517,7 @@ static int sdl_open (void *plugin, void 
     * we'll force the BPP to 16, and pray that SDL can emulate for us.
     */
 	priv->bpp = vidInfo->vfmt->BitsPerPixel;
-	if (!priv->mode && priv->bpp < 16) {
+	if (priv->mode == YUV && priv->bpp < 16) {
 
 		if(verbose) printf("SDL: Your SDL display target wants to be at a color depth of (%d), but we need it to be at\
 least 16 bits, so we need to emulate 16-bit color. This is going to slow things down; you might want to\
@@ -559,37 +657,52 @@ static void set_fullmode (int mode)
 static void set_fullmode (int mode) {
 	struct sdl_priv_s *priv = &sdl_priv;
 	SDL_Surface *newsurface = NULL;
+ 	int screen_surface_w, screen_surface_h;
 	
 	/* if we haven't set a fullmode yet, default to the lowest res fullmode first */
 	/* But select a mode where the full video enter */
+#ifdef HAVE_X11
+	if(priv->fulltype & FS) {
+		screen_surface_w = priv->XWidth;
+		screen_surface_h = priv->XHeight;
+	}
+	else if (mode < 0) {
+#else
 	if (mode < 0) {
-	        int i = 0;
+#endif
+        int i;
 		mode = 0; // Default to the biggest mode avaible
 		for(i = findArrayEnd(priv->fullmodes) - 1; i >=0; i--) {
-		  if( (priv->fullmodes[i]->w >= priv->width) && 
-		      (priv->fullmodes[i]->h >= priv->height) ) {
+		  if( (priv->fullmodes[i]->w >= priv->dstwidth) && 
+		      (priv->fullmodes[i]->h >= priv->dstheight) ) {
 		    mode = i;
 		    break;
 		  }
 		}
 		priv->fullmode = mode;
+        screen_surface_h = priv->fullmodes[mode]->h;
+        screen_surface_w = priv->fullmodes[mode]->w;
+	}
+    else {
+       screen_surface_h = priv->fullmodes[mode]->h;
+       screen_surface_w = priv->fullmodes[mode]->w;
 	}
 	
-	aspect_save_screenres(priv->fullmodes[mode]->w, priv->fullmodes[mode]->h);
+	aspect_save_screenres(screen_surface_w, screen_surface_h);
 
 	/* calculate new video size/aspect */
-	if(!priv->mode) {
+	if(priv->mode == YUV) {
 	if(priv->fulltype&FS) {
 #ifdef HAVE_X11		
 		aspect_save_screenres(priv->XWidth, priv->XHeight);
 #endif		
 	}
 	aspect(&priv->dstwidth, &priv->dstheight, A_ZOOM);
-
 	}
 
 	/* try to change to given fullscreenmode */
-	newsurface = SDL_SetVideoMode(priv->dstwidth, priv->dstheight, priv->bpp, priv->sdlfullflags);
+	newsurface = SDL_SetVideoMode(priv->dstwidth, screen_surface_h, priv->bpp,
+                                  priv->sdlfullflags);
 	
 	/* if creation of new surface was successfull, save it and hide mouse cursor */
 	if(newsurface) {
@@ -617,12 +730,15 @@ config(uint32_t width, uint32_t height, 
 {
 	struct sdl_priv_s *priv = &sdl_priv;
         unsigned int sdl_format;
+    int surfwidth, surfheight;
+    
 #ifdef HAVE_X11	
 	static Display *XDisplay;
 	static int XScreen;
 #endif
+
 	aspect_save_orig(width,height);
-	aspect_save_prescale(d_width,d_height);
+	aspect_save_prescale(d_width ? d_width : width, d_height ? d_height : height);
 
 	sdl_format = format;
         switch(format){
@@ -640,6 +756,7 @@ config(uint32_t width, uint32_t height, 
 			if(verbose) printf("SDL: Using 0x%X (I420) image format\n", format);
 			printf("SDL: Mapping I420 to IYUV\n");
 			sdl_format = SDL_IYUV_OVERLAY;
+            priv->mode = YUV;
 		break;
 		case IMGFMT_BGR15:	
 			if(verbose) printf("SDL: Using 0x%X (BGR15) image format\n", format);
@@ -767,6 +884,19 @@ config(uint32_t width, uint32_t height, 
 		return -1;
 	}	
 
+    {
+        float h_scale = ((float) priv->dstwidth) / width;
+        float v_scale = ((float) priv->dstheight) / height;
+
+        surfwidth = width + (priv->surface->w - priv->dstwidth) / h_scale;
+        surfheight = height + (priv->surface->h - priv->dstheight) / v_scale;
+
+        /* Place the image in the middle of the screen */
+        priv->y = (surfheight - height) / 2;
+        priv->y_screen_top = priv->y * v_scale;
+        priv->y_screen_bottom = (priv->y + priv->dstheight) * v_scale;        
+    }
+
 	switch(format) {
 	    	/* Initialize and create the RGB Surface used for video out in BGR/RGB mode */
 //SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);	
@@ -777,56 +907,56 @@ config(uint32_t width, uint32_t height, 
 		// 15 bit: r:111110000000000b g:000001111100000b b:000000000011111b
 		// FIXME: colorkey detect based on bpp, FIXME static bpp value, FIXME alpha value correct?
 	    case IMGFMT_RGB15:
-		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, width, height, 15, 31, 992, 31744, 0))) {
+		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 15, 31, 992, 31744, 0))) {
 			printf ("SDL: Couldn't create a RGB surface: %s\n", SDL_GetError());
 			return -1;
 		}
 	    break;	
 	    case IMGFMT_BGR15:
-		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, width, height, 15, 31744, 992, 31, 0))) {
+		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 15, 31744, 992, 31, 0))) {
 			printf ("SDL: Couldn't create a RGB surface: %s\n", SDL_GetError());
 			return -1;
 		}
 	    break;	
 	    case IMGFMT_RGB16:
-		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, width, height, 16, 31, 2016, 63488, 0))) {
+		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 16, 31, 2016, 63488, 0))) {
 			printf ("SDL: Couldn't create a RGB surface: %s\n", SDL_GetError());
 			return -1;
 		}
 	    break;	
 	    case IMGFMT_BGR16:
-		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, width, height, 16, 63488, 2016, 31, 0))) {
+		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 16, 63488, 2016, 31, 0))) {
 			printf ("SDL: Couldn't create a RGB surface: %s\n", SDL_GetError());
 			return -1;
 		}
 	    break;	
 	    case IMGFMT_RGB24:
-		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, width, height, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0))) {
+		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0))) {
 			printf ("SDL: Couldn't create a RGB surface: %s\n", SDL_GetError());
 			return -1;
 		}
 	    break;	
 	    case IMGFMT_BGR24:
-		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, width, height, 24, 0xFF0000, 0x00FF00, 0x0000FF, 0))) {
+		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 24, 0xFF0000, 0x00FF00, 0x0000FF, 0))) {
 			printf ("SDL: Couldn't create a RGB surface: %s\n", SDL_GetError());
 			return -1;
 		}
 	    break;	
 	    case IMGFMT_RGB32:
-		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, width, height, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0/*0xFF000000*/))) {
+		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0/*0xFF000000*/))) {
 			printf ("SDL: Couldn't create a RGB surface: %s\n", SDL_GetError());
 			return -1;
 		}
 	    break;	
 	    case IMGFMT_BGR32:
-		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, width, height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0/*0xFF000000*/))) {
+		if (!(priv->rgbsurface = SDL_CreateRGBSurface (SDL_SRCCOLORKEY, surfwidth, surfheight, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0/*0xFF000000*/))) {
 			printf ("SDL: Couldn't create a RGB surface: %s\n", SDL_GetError());
 			return -1;
 		}
 	    break;	
 	    default:
 		/* Initialize and create the YUV Overlay used for video out */
-		if (!(priv->overlay = SDL_CreateYUVOverlay (width, height, sdl_format, priv->surface))) {
+		if (!(priv->overlay = SDL_CreateYUVOverlay (surfwidth, surfheight, sdl_format, priv->surface))) {
 			printf ("SDL: Couldn't create a YUV overlay: %s\n", SDL_GetError());
 			return -1;
 		}
@@ -838,37 +968,29 @@ config(uint32_t width, uint32_t height, 
 		priv->stridePlaneYUY = width * 2;
 	}
 	
-	if(priv->mode) {
+	if(priv->mode != YUV) {
 		if((priv->format&0xFF) != priv->bpp) { priv->dblit = 0; printf("SDL: using depth/colorspace conversion, this will slow things down (%ibpp -> %ibpp).\n", priv->format&0xFF, priv->bpp); }
 		else if(strcmp(priv->driver, "x11") == 0) priv->dblit = 1;
+
 		priv->framePlaneRGB = width * height * priv->rgbsurface->format->BytesPerPixel;
 		priv->stridePlaneRGB = width * priv->rgbsurface->format->BytesPerPixel;
 	}	
-	return 0;
-}
 
-#ifdef SDL_ENABLE_LOCKS
-#define	SDL_OVR_LOCK        if (SDL_LockYUVOverlay (priv->overlay)) { \
-				if(verbose) printf("SDL: Couldn't lock YUV overlay\n"); \
-				return -1; \
-	    		    }
-#define SDL_OVR_UNLOCK      SDL_UnlockYUVOverlay (priv->overlay);
+    SDL_SRF_LOCK(priv->surface, -1)
+    SDL_FillRect(priv->surface, NULL, 0);
+    SDL_SRF_UNLOCK(priv->surface)
 
-#define SDL_SRF_LOCK(srf)   if(SDL_MUSTLOCK(srf)) { \
-				if(SDL_LockSurface (srf)) { \
-					if(verbose) printf("SDL: Couldn't lock RGB surface\n"); \
-					return -1; \
-				} \
-			    }
+    priv->dirty_off_frame[0].x = 0;
+    priv->dirty_off_frame[0].y = 0;
+    priv->dirty_off_frame[0].w = surfwidth;
+    priv->dirty_off_frame[0].h = surfheight;
+        
+    priv->dirty_off_frame[1].x = -1;
+    priv->dirty_off_frame[1].y = -1;
+    vo_osd_changed(1);
 
-#define SDL_SRF_UNLOCK(srf) if(SDL_MUSTLOCK(srf)) \
-				SDL_UnlockSurface (srf);
-#else
-#define SDL_OVR_LOCK
-#define SDL_OVR_UNLOCK
-#define SDL_SRF_LOCK(srf)
-#define SDL_SRF_UNLOCK(srf)
-#endif
+	return 0;
+}
 
 /**
  * Draw a frame to the SDL YUV overlay.
@@ -889,27 +1011,29 @@ static uint32_t draw_frame(uint8_t *src[
         case IMGFMT_YV12:
         case IMGFMT_I420:
         case IMGFMT_IYUV:
-	    SDL_OVR_LOCK
-	    dst = (uint8_t *) *(priv->overlay->pixels);
-	    memcpy (dst, src[0], priv->framePlaneY);
-	    dst += priv->framePlaneY;
-	    memcpy (dst, src[2], priv->framePlaneUV);
-	    dst += priv->framePlaneUV;
-	    memcpy (dst, src[1], priv->framePlaneUV);
+        SDL_OVR_LOCK(-1)
+            
+        dst = priv->overlay->pixels[0] + priv->y*priv->overlay->pitches[0];
+        memcpy(dst, src[0], priv->overlay->pitches[0]*priv->overlay->h);
+        dst = priv->overlay->pixels[1] + priv->y*priv->overlay->pitches[1]/2;
+        memcpy(dst, src[1], priv->overlay->pitches[1]*priv->overlay->h/2);
+        dst = priv->overlay->pixels[2] + priv->y*priv->overlay->pitches[2]/2;
+        memcpy(dst, src[2], priv->overlay->pitches[2]*priv->overlay->h/2);
+        
 	    SDL_OVR_UNLOCK
             break;
 
         case IMGFMT_YUY2:
         case IMGFMT_UYVY:
         case IMGFMT_YVYU:
-	    SDL_OVR_LOCK
-	    dst = (uint8_t *) *(priv->overlay->pixels);
+        SDL_OVR_LOCK(-1)
+        dst = (uint8_t *) *(priv->overlay->pixels) + priv->overlay->pitches[0]*priv->y;
 	    if(priv->flip) {
 	    	mysrc+=priv->framePlaneYUY;
 		for(i = 0; i < priv->height; i++) {
 			mysrc-=priv->stridePlaneYUY;
 			memcpy (dst, mysrc, priv->stridePlaneYUY);
-			dst+=priv->stridePlaneYUY;
+                dst+=priv->overlay->pitches[0];
 		}
 	    }
 	    else memcpy (dst, src[0], priv->framePlaneYUY);
@@ -925,27 +1049,28 @@ static uint32_t draw_frame(uint8_t *src[
 	case IMGFMT_RGB32:
 	case IMGFMT_BGR32:
 		if(priv->dblit) {
-			SDL_SRF_LOCK(priv->surface)
-			dst = (uint8_t *) priv->surface->pixels;
+			SDL_SRF_LOCK(priv->surface, -1)
+            dst = (uint8_t *) priv->surface->pixels + priv->y*priv->surface->pitch;
+            
 			if(priv->flip) {
 				mysrc+=priv->framePlaneRGB;
 				for(i = 0; i < priv->height; i++) {
 					mysrc-=priv->stridePlaneRGB;
 					memcpy (dst, mysrc, priv->stridePlaneRGB);
-					dst+=priv->stridePlaneRGB;
+					dst += priv->surface->pitch;
 				}
 			}
 			else memcpy (dst, src[0], priv->framePlaneRGB);
 			SDL_SRF_UNLOCK(priv->surface)
 		} else {
-			SDL_SRF_LOCK(priv->rgbsurface)
-			dst = (uint8_t *) priv->rgbsurface->pixels;
+			SDL_SRF_LOCK(priv->rgbsurface, -1)
+			dst = (uint8_t *) priv->rgbsurface->pixels + priv->y*priv->rgbsurface->pitch;
 			if(priv->flip) {
 				mysrc+=priv->framePlaneRGB;
 				for(i = 0; i < priv->height; i++) {
 					mysrc-=priv->stridePlaneRGB;
 					memcpy (dst, mysrc, priv->stridePlaneRGB);
-					dst+=priv->stridePlaneRGB;
+					dst += priv->rgbsurface->pitch;
 				}
 			}
 			else memcpy (dst, src[0], priv->framePlaneRGB);
@@ -974,35 +1099,35 @@ static uint32_t draw_slice(uint8_t *imag
 	uint8_t *src;
         int i;
 
-	SDL_OVR_LOCK
+    SDL_OVR_LOCK(-1)
+
+    y += priv->y;
+    
+    dst = priv->overlay->pixels[0] + priv->overlay->pitches[0]*y + x;
 
-	dst = (uint8_t *) *(priv->overlay->pixels) 
-            + (priv->stridePlaneY * y + x);
         src = image[0];
         for(i=0;i<h;i++){
             memcpy(dst,src,w);
             src+=stride[0];
-            dst+=priv->stridePlaneY;
+        dst += priv->overlay->pitches[0];
         }
         
         x/=2;y/=2;w/=2;h/=2;
 
-	dst = (uint8_t *) *(priv->overlay->pixels) + priv->framePlaneY
-            + (priv->stridePlaneUV * y + x);
-        src = image[2];
+    dst = priv->overlay->pixels[2] + priv->overlay->pitches[2]*y + x;
+    src = image[1];
         for(i=0;i<h;i++){
             memcpy(dst,src,w);
             src+=stride[2];
-            dst+=priv->stridePlaneUV;
+        dst += priv->overlay->pitches[2];
         }
         
-	dst = (uint8_t *) *(priv->overlay->pixels) + priv->framePlaneY
-            + priv->framePlaneUV + (priv->stridePlaneUV * y + x);
-        src = image[1];
+    dst = priv->overlay->pixels[1] + priv->overlay->pitches[1]*y + x;
+    src = image[2];
         for(i=0;i<h;i++){
             memcpy(dst,src,w);
             src+=stride[1];
-            dst+=priv->stridePlaneUV;
+        dst += priv->overlay->pitches[1];
         }
 
 	SDL_OVR_UNLOCK
@@ -1224,8 +1349,150 @@ static void check_events (void)
 static void draw_osd(void)
 {	struct sdl_priv_s *priv = &sdl_priv;
 
+    priv->osd_has_changed = vo_osd_changed(0);
+
+    if(priv->osd_has_changed)
+    {
+        SDL_Rect dirty_area;
+        int i;
+        
+        for(i = 0; i < 2; i++) {
+            dirty_area = priv->dirty_off_frame[i];
+
+            if(priv->dirty_off_frame[i].x < 0 || priv->dirty_off_frame[i].y < 0)
+                continue;
+            
+            switch(priv->format) {
+                case IMGFMT_YV12:  
+                case IMGFMT_I420:
+                case IMGFMT_IYUV:
+                {
+                    SDL_OVR_LOCK((void) 0)
+                        
+                        /* Erase Y plane */
+                    erase_area_1(dirty_area.x, dirty_area.w, dirty_area.h,
+                                 priv->overlay->pitches[0], 0,
+                                 priv->overlay->pixels[0] +
+                                 priv->overlay->pitches[0]*dirty_area.y);
+                    
+                        
+                        /* Erase U and V planes */
+                    dirty_area.w /= 2;
+                    dirty_area.x /= 2;
+                    dirty_area.h /= 2;
+                    dirty_area.y /= 2;
+                        
+                    erase_area_1(dirty_area.x, dirty_area.w, dirty_area.h,
+                                 priv->overlay->pitches[1], 128,
+                                 priv->overlay->pixels[1] +
+                                 priv->overlay->pitches[1]*dirty_area.y);
+                        
+                    erase_area_1(dirty_area.x, dirty_area.w, dirty_area.h,
+                                 priv->overlay->pitches[2], 128,
+                                 priv->overlay->pixels[2] +
+                                 priv->overlay->pitches[2]*dirty_area.y);
+                    SDL_OVR_UNLOCK
+                    break;
+                }
+
+                case IMGFMT_YUY2:
+                case IMGFMT_YVYU:
+                {
+                        /* yuy2 and yvyu represent black the same way */
+                    uint8_t yuy2_black[] = {0, 128, 0, 128};
+
+                    SDL_OVR_LOCK((void) 0)
+                    erase_area_4(dirty_area.x*2, dirty_area.w*2, dirty_area.h,
+                                 priv->overlay->pitches[0],
+                                 *((uint32_t*) yuy2_black),
+                                 priv->overlay->pixels[0] +
+                                 priv->overlay->pitches[0]*dirty_area.y);
+                    SDL_OVR_UNLOCK
+                    break;
+                }
+            
+                case IMGFMT_UYVY:
+                {
+                    uint8_t uyvy_black[] = {128, 0, 128, 0};
+
+                    SDL_OVR_LOCK((void) 0)
+                    erase_area_4(dirty_area.x*2, dirty_area.w*2, dirty_area.h,
+                                 priv->overlay->pitches[0],
+                                 *((uint32_t*) uyvy_black),
+                                 priv->overlay->pixels[0] +
+                                 priv->overlay->pitches[0]*dirty_area.y);
+                    SDL_OVR_UNLOCK
+                    break;
+                }
+            
+                case IMGFMT_RGB15:
+                case IMGFMT_BGR15:
+                case IMGFMT_RGB16:
+                case IMGFMT_BGR16:
+                case IMGFMT_RGB24:
+                case IMGFMT_BGR24:
+                case IMGFMT_RGB32:
+                case IMGFMT_BGR32:
+                    if(priv->dblit) {
+                        SDL_SRF_LOCK(priv->surface, (void) 0)
+                        SDL_FillRect(priv->surface, &dirty_area, 0);
+                        SDL_SRF_UNLOCK(priv->surface)
+                    }
+                    else {
+                        SDL_SRF_LOCK(priv->rgbsurface, (void) 0)
+                        SDL_FillRect(priv->rgbsurface, &dirty_area, 0);
+                        SDL_SRF_UNLOCK(priv->rgbsurface)
+                    }
+                    break;
+            }
+            priv->dirty_off_frame[i].x = -1;
+            priv->dirty_off_frame[i].y = -1;
+        }
+    }
+ 
 	/* update osd/subtitles */
-	vo_draw_text(priv->width,priv->height,draw_alpha);
+    if(priv->mode == YUV)
+        vo_draw_text(priv->overlay->w, priv->overlay->h, draw_alpha);
+    else {
+        if(priv->dblit)
+            vo_draw_text(priv->surface->w, priv->surface->h, draw_alpha);
+        else
+            vo_draw_text(priv->rgbsurface->w, priv->rgbsurface->h, draw_alpha);    
+    }
+
+    /* Change this in flip_page instead. */
+//  priv->osd_has_changed = 0;
+}
+
+
+/* Fill area beginning at 'pixels' with 'color'. 'x_start', 'width' and 'pitch'
+ * are given in bytes. 4 bytes at a time.
+ */
+static void erase_area_4(int x_start, int width, int height, int pitch, uint32_t color, uint8_t* pixels)
+{
+    int x_end = x_start/4 + width/4;
+    int x, y;
+    uint32_t* data = (uint32_t*) pixels;
+    
+    x_start /= 4;
+    pitch /= 4;
+
+    for(y = 0; y < height; y++) {
+        for(x = x_start; x < x_end; x++)
+            data[y*pitch + x] = color;
+    }
+}
+
+/* Fill area beginning at 'pixels' with 'color'. 'x_start', 'width' and 'pitch'
+ * are given in bytes. 1 byte at a time.
+ */
+static void erase_area_1(int x_start, int width, int height, int pitch, uint8_t color, uint8_t* pixels)
+{
+    int y;
+    
+    for(y = 0; y < height; y++) {
+        memset(&pixels[y*pitch + x_start], color, width);
+    }
 }
 
 /**
@@ -1256,7 +1523,13 @@ static void flip_page (void)
 
 		/* update screen */
 		//SDL_UpdateRect(priv->surface, 0, 0, priv->surface->clip_rect.w, priv->surface->clip_rect.h);
+        if(priv->osd_has_changed) {
+            priv->osd_has_changed = 0;
 		SDL_UpdateRects(priv->surface, 1, &priv->surface->clip_rect);
+        }
+        else
+            SDL_UpdateRect(priv->surface, 0, priv->y_screen_top,
+                           priv->surface->clip_rect.w, priv->y_screen_bottom);
 		
 		/* check if we have a double buffered surface and flip() if we do. */
 		if ( priv->surface->flags & SDL_DOUBLEBUF )


More information about the MPlayer-dev-eng mailing list