RGB/BGR fix for subtitles

Scott Smith <[email protected]> Sun, 05 Oct 2003 15:05:03 -0700
Newsgroups gmane.comp.video.ogle.devel
Message-ID <[email protected]>
I was using Ogle 0.9.1 and was getting incorrect colors for subtitles.
I tracked it down to the fact that my computer uses RGB for 16-bit
color mode instead of BGR.  I fixed the code without any performance
impact by adjusting yuv2rgb() in spu_mixer.c.  Also in the process I
found a masking bug for 16-bit color mode -- the mask 0x0770 was used
instead of 0x07e0 for the middle 6 contiguous bits.  Here is the patch:

diff -aur ogle-0.9.1/mpeg2_video/spu_mixer.c rgb-ogle-0.9.1/mpeg2_video/spu_mixer.c
--- ogle-0.9.1/mpeg2_video/spu_mixer.c	2003-01-20 14:17:05.000000000 -0800
+++ rgb-ogle-0.9.1/mpeg2_video/spu_mixer.c	2003-10-05 14:57:51.000000000 -0700
@@ -36,6 +36,7 @@
 #include "queue.h"
 #include "timemath.h"
 #include "sync.h"
+#include "spu_mixer.h"
 
 #ifndef SHM_SHARE_MMU
 #define SHM_SHARE_MMU 0
@@ -119,9 +120,13 @@
 extern MsgEventQ_t *msgq;
 
 static int flush_to_scrid = -1;
+static int rgbmode,pixelstride;
 
 #define MAX_BUF_SIZE 65536
 
+#define MODE_RGB  0x1
+#define MODE_BGR  0x2
+
 
 extern void redraw_request(void);
 extern int register_event_handler(int(*eh)(MsgEventQ_t *, MsgEvent_t *));
@@ -165,8 +170,11 @@
     Er = 255;
   if(Er < 0)
     Er = 0;
-  
-  result = (Eb << 16) | (Eg << 8) | Er;
+
+  if( rgbmode == MODE_BGR )
+    result = (Eb << 16) | (Eg << 8) | Er;
+  else
+    result = (Er << 16) | (Eg << 8) | Eb;
   
   return result;
 }
@@ -742,7 +750,7 @@
     
     /* if no transparancy just overwrite */
     if(contrast == (0xf<<4)) {
-      uint16_t color2 = ((b << 8) & 0xf800) | ((g << 3) & 0x0770) | (r >> 3);
+      uint16_t color2 = ((b << 8) & 0xf800) | ((g << 3) & 0x07e0) | (r >> 3);
       for(n = 0; n < length; n++, pixel++) {
 	*pixel = color2;
       }
@@ -751,14 +759,14 @@
 	unsigned int pr, pg, pb;
 	uint16_t source = *pixel;
 	pr = (source & 0x001f) << 3;
-	pg = (source & 0x0770) >> 3; // or 0x037 >> 2, 0x076 >> 3 ???
+	pg = (source & 0x07e0) >> 3; // or 0x037 >> 2, 0x076 >> 3 ???
 	pb = (source & 0xf800) >> 8; // (source >> 8) & 0xf8;
 	
 	pr = (pr * invcontrast + r * contrast) >> 8;
 	pg = (pg * invcontrast + g * contrast) >> 8;
 	pb = (pb * invcontrast + b * contrast) >> 8;
 	
-	*pixel = ((pb << 8) & 0xf800) | ((pg << 3) & 0x0770) | (pr >> 3);
+	*pixel = ((pb << 8) & 0xf800) | ((pg << 3) & 0x07e0) | (pr >> 3);
       }
     }
   }
@@ -1185,7 +1193,27 @@
   return 0;
 }
 
-void mix_subpicture_rgb(char *data, int width, int height, int pixel_stride)
+void mix_subpicture_init(int ps,int mode)
+{
+    rgbmode=mode;
+
+    pixelstride=ps/8;
+
+    switch(pixelstride) {
+    case 1:
+    case 2: 
+      mix_function = display_mix_function_bgr16;
+      break;
+    case 3: 
+      mix_function = display_mix_function_bgr24;
+      break;
+    case 4: 
+      mix_function = display_mix_function_bgr32;
+      break;
+    }
+}
+
+void mix_subpicture_rgb(char *data, int width, int height)
 {
   /*
    * Check for, and execute all pending spu command sequences.
@@ -1222,21 +1250,9 @@
   if(spu_info.display_start /* || spu_info.menu */) {
     
     palette = palette_rgb;
-    switch(pixel_stride) {
-    case 1:
-    case 2: 
-      mix_function = display_mix_function_bgr16;
-      break;
-    case 3: 
-      mix_function = display_mix_function_bgr24;
-      break;
-    case 4: 
-      mix_function = display_mix_function_bgr32;
-      break;
-    }
     
-    decode_display_data(&spu_info, data, pixel_stride, pixel_stride*width, 
-                        pixel_stride*width*height);
+    decode_display_data(&spu_info, data, pixelstride, pixelstride*width, 
+                        pixelstride*width*height);
   }
 }
 
diff -aur ogle-0.9.1/mpeg2_video/spu_mixer.h rgb-ogle-0.9.1/mpeg2_video/spu_mixer.h
--- ogle-0.9.1/mpeg2_video/spu_mixer.h	2001-08-02 12:34:00.000000000 -0700
+++ rgb-ogle-0.9.1/mpeg2_video/spu_mixer.h	2003-10-05 14:51:00.000000000 -0700
@@ -21,7 +21,8 @@
 
 
 //ugly hack
-void mix_subpicture_rgb(char *data, int width, int height, int pixel_stride);
+void mix_subpicture_init(int pixel_stride,int mode);
+void mix_subpicture_rgb(char *data, int width, int height);
 int mix_subpicture_yuv(yuv_image_t *img, yuv_image_t *reserv);
 
 int init_spu(void);
diff -aur ogle-0.9.1/mpeg2_video/video_output_x11.c rgb-ogle-0.9.1/mpeg2_video/video_output_x11.c
--- ogle-0.9.1/mpeg2_video/video_output_x11.c	2003-03-03 08:58:01.000000000 -0800
+++ rgb-ogle-0.9.1/mpeg2_video/video_output_x11.c	2003-10-05 14:52:07.000000000 -0700
@@ -503,6 +503,7 @@
     }
   */
   yuv2rgb_init(pixel_stride, mode);
+  mix_subpicture_init(pixel_stride, mode);
 }
 
 
@@ -1874,9 +1875,7 @@
 #ifdef SPU
     if(msgqid != -1) {
       mix_subpicture_rgb((char *)&rgb_fb[fb_area.y*2048+fb_area.x], 2048,
-			 fb_area.height, 
-			 4); 
-      // Should have mode to or use a mix_subpicture_init(pixel_s,mode);
+			 fb_area.height); 
     }
 #endif
     }
@@ -1897,9 +1896,7 @@
 #ifdef SPU
   if(msgqid != -1) {
     mix_subpicture_rgb(address, dwin->image->info->picture.padded_width,
-		       dwin->image->info->picture.padded_height, 
-		       (pixel_stride/8)); 
-    // Should have mode to or use a mix_subpicture_init(pixel_s,mode);
+		       dwin->image->info->picture.padded_height);
   }
 #endif