Web lists-archives.org

[MPlayer-dev-eng] [PATCH] color SPU - Part 5/3




Hi All!

modify spudec.c to UV and RGB planes (scale more plane)

04-colorspu-spudec.patch:
- add need variables to spudec_handle_t
- move split function scaler code from spudec_draw_scaled() to 
spudec_scaled_approx(), spudec_scaled_none(), ...

05-colorspu-spudec.patch:
- add scaler more planes to spudec_scaled_none()

06-colorspu-spudec.patch:
- add scaler more planes to spudec_scaled_approx()

07-colorspu-spudec.patch:
- add scaler more planes to spudec_scaled_bilinear()

08-colorspu-spudec.patch:
- add scaler more planes to spudec_scaled_sws()

09-colorspu-spudec.patch:
- add scaler more planes to spudec_scaled_full()

10-colorspu-spudec.patch:
- draw code to U,V or R,G.B planes

11-colorspu-spudec.patch:
- add create code to UV and RGB planes

12-colorspu-spudec.patch:
- add spudec_set_spu_format() function

Best regards!
Attila
--- spudec.c	2008-05-27 20:19:32.000000000 +0200
+++ spudec.c	2008-05-27 20:22:24.000000000 +0200
@@ -794,20 +794,30 @@
 	sws_freeContext(ctx);
 }
 
-void spu_scaled_none(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
-                     unsigned int scalex, unsigned int scaley)
+void spu_scaled_none(unsigned int dxs, unsigned int dys,
+                     int src_stride,
+                     int dst_width, int dst_height, int dst_stride,
+                     unsigned int scalex, unsigned int scaley,
+                     unsigned char *src_y, unsigned char *src_a,
+                     unsigned char *src_u, unsigned char *src_v,
+                     unsigned char *dst_y, unsigned char *dst_a,
+                     unsigned char *dst_u, unsigned char *dst_v)
 {
 	  unsigned int x, y;
 
 	  /* no antialiasing */
-	  for (y = 0; y < spu->scaled_height; ++y) {
+  for (y = 0; y < dst_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 strides = src_stride * unscaled_y;
+    int scaled_strides = dst_stride * y;
+    for (x = 0; x < dst_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];
+      dst_y[scaled_strides + x] = src_y[strides + unscaled_x];
+      dst_a[scaled_strides + x] = src_a[strides + unscaled_x];
+      if(src_u)
+        dst_u[scaled_strides + x] = src_u[strides + unscaled_x];
+      if(src_v)
+        dst_v[scaled_strides + x] = src_v[strides + unscaled_x];
 	    }
 	  }
 }
@@ -1055,6 +1065,40 @@
                 spu->stride);
 }
 
+void aa_scaler(int aamode, int width, int height, int dxs, int dys,
+               int src_width, int src_height, int src_stride,
+               int dst_width, int dst_height, int dst_stride,
+               unsigned int scalex, unsigned int scaley,
+               unsigned char *src_y, unsigned char *src_a,
+               unsigned char *src_u, unsigned char *src_v,
+               unsigned char *dst_y, unsigned char *dst_a,
+               unsigned char *dst_u, unsigned char *dst_v,
+               spudec_handle_t *spu)
+{
+switch(aamode&15) {
+  case 4:
+    spu_scaled_sws(spu,dxs,dys,scalex,scaley);
+    break;
+  case 3:
+    spu_scaled_bilinear(spu,dxs,dys,scalex,scaley);
+    break;
+  case 0:
+    spu_scaled_none(dxs, dys,
+                    src_stride,
+                    dst_width, dst_height, dst_stride,
+                    scalex,scaley,
+                    src_y, src_a, src_u, src_v,
+                    dst_y, dst_a, dst_u, dst_v);
+    break;
+  case 1:
+    spu_scaled_approx(spu,dxs,dys,scalex,scaley);
+    break;
+  case 2:
+    spu_scaled_full(spu,dxs,dys,scalex,scaley);
+    break;
+  }
+}
+
 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;
@@ -1102,23 +1146,13 @@
 	if (spu->scaled_image) {
 	  unsigned int y;
 	  if (spu->scaled_width > 1 && spu->scaled_height > 1)
-	    switch(spu_aamode&15) {
-	    case 4:
-	      spu_scaled_sws(spu,dxs,dys,scalex,scaley);
-	      break;
-	    case 3:
-	      spu_scaled_bilinear(spu,dxs,dys,scalex,scaley);
-	      break;
-	    case 0:
-	      spu_scaled_none(spu,dxs,dys,scalex,scaley);
-	      break;
-	    case 1:
-	      spu_scaled_approx(spu,dxs,dys,scalex,scaley);
-	      break;
-	    case 2:
-	      spu_scaled_full(spu,dxs,dys,scalex,scaley);
-	      break;
-	  }
+            aa_scaler(spu_aamode&15, spu->width, spu->height, dxs, dys,
+                      spu->orig_frame_width, spu->orig_frame_height,spu->stride,
+                      spu->scaled_width, spu->scaled_height, spu->scaled_stride,
+                      scalex, scaley,
+                      spu->image, spu->aimage, NULL, NULL,
+                      spu->scaled_image, spu->scaled_aimage, NULL, NULL,
+                      spu);
 	  /* Kludge: draw_alpha needs width multiple of 8. */
 	  if (spu->scaled_width < spu->scaled_stride)
 	    for (y = 0; y < spu->scaled_height; ++y) {
--- spudec.c	2008-05-27 20:12:13.000000000 +0200
+++ spudec.c	2008-05-27 20:19:32.000000000 +0200
@@ -39,6 +39,15 @@
 float spu_gaussvar = 1.0;
 extern int sub_pos;
 
+/* color mode flags */
+typedef enum {
+  COLORSPU_Y   = 0, /* Grayscale */
+  COLORSPU_YUV = 1,
+  COLORSPU_YUY = 2,
+  COLORSPU_RGB = 3,
+  COLORSPU_BGR = 4,
+} colorspu_t;
+
 typedef struct packet_t packet_t;
 struct packet_t {
   unsigned char *packet;
@@ -74,22 +83,40 @@
   unsigned int start_pts, end_pts;
   unsigned int start_col, end_col;
   unsigned int start_row, end_row;
+  unsigned int start_coluv, end_coluv;
+  unsigned int start_rowuv, end_rowuv;
   unsigned int width, height, stride;
+  unsigned int widthuv, heightuv, strideuv, strideyuy;
   size_t image_size;		/* Size of the image buffer */
-  unsigned char *image;		/* Grayscale value */
+  size_t image_sizeuv;          /* Size of the imageuv buffer */
+  size_t image_sizeyuy;         /* Size of the imageyuy buffer */
+  unsigned char *image;		/* Grayscale value or Y value or RB value */
+  unsigned char *imageu;        /* U value or G value */
+  unsigned char *imagev;        /* V value or BR value */
+  unsigned char *imageyuy;      /* image yuy */
   unsigned char *aimage;	/* Alpha value */
+  unsigned char *aimageuv;      /* Alpha value to uv planes */
+  unsigned char *aimageyuy;     /* Alpha valur to yuy planes */
   unsigned int scaled_frame_width, scaled_frame_height;
   unsigned int scaled_start_col, scaled_start_row;
   unsigned int scaled_width, scaled_height, scaled_stride;
+  unsigned int scaled_frame_widthuv, scaled_frame_heightuv;
+  unsigned int scaled_start_coluv, scaled_start_rowuv;
+  unsigned int scaled_widthuv, scaled_heightuv, scaled_strideuv;
   size_t scaled_image_size;
+  size_t scaled_image_sizeuv;
   unsigned char *scaled_image;
   unsigned char *scaled_aimage;
+  unsigned char *scaled_imageu;
+  unsigned char *scaled_imagev;
+  unsigned char *scaled_aimageuv;
   int auto_palette; /* 1 if we lack a palette and must use an heuristic. */
   int font_start_level;  /* Darkest value used for the computed font */
   const vo_functions_t *hw_spu;
   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 */
+  colorspu_t colorspu;          /* spu color mode */
 } spudec_handle_t;
 
 static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet)
@@ -767,78 +794,11 @@
 	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, int dp, unsigned char* src, unsigned char *srca, int stride))
+void spu_scaled_none(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
+                     unsigned int scalex, unsigned int scaley)
 {
-  spudec_handle_t *spu = (spudec_handle_t *)me;
-  scale_pixel *table_x;
-  scale_pixel *table_y;
-
-  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,
-		   DEST_PLANES_Y, spu->image, 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. */
-	unsigned int scalex = 0x100 * dxs / spu->orig_frame_width;
-	unsigned int 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);
-	    spu->scaled_image_size = 0;
-	  }
-	  spu->scaled_image = malloc(2 * 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_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(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);
-	  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);
-	  break;
-	  case 0:
+
 	  /* no antialiasing */
 	  for (y = 0; y < spu->scaled_height; ++y) {
 	    int unscaled_y = y * 0x100 / scaley;
@@ -850,9 +810,13 @@
 	      spu->scaled_aimage[scaled_strides + x] = spu->aimage[strides + unscaled_x];
 	    }
 	  }
-	  break;
-	  case 1:
+}
+
+void spu_scaled_approx(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
+                       unsigned int scalex, unsigned int scaley)
 	  {
+  unsigned int x, y;
+
 	    /* Intermediate antialiasing. */
 	    for (y = 0; y < spu->scaled_height; ++y) {
 	      const unsigned int unscaled_top = y * spu->orig_frame_height / dys;
@@ -889,9 +853,12 @@
 	      }
 	    }
 	  }
-	  break;
-	  case 2:
+
+void spu_scaled_full(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
+                     unsigned int scalex, unsigned int scaley)
 	  {
+  unsigned int x, y;
+
 	    /* Best antialiasing.  Very slow. */
 	    /* Any pixel (x, y) represents pixels from the original
 	       rectangular region comprised between the columns
@@ -1057,8 +1024,101 @@
 	      }
 	    }
 	  }
+
+void spu_scaled_bilinear(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
+                         unsigned int scalex, unsigned int scaley)
+{
+  unsigned int x, y;
+  scale_pixel *table_x;
+  scale_pixel *table_y;
+
+  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);
+}
+
+void spu_scaled_sws(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
+                    unsigned int scalex, unsigned int scaley)
+{
+  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);
+}
+
+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;
+
+  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,
+		   DEST_PLANES_Y, spu->image, 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. */
+	unsigned int scalex = 0x100 * dxs / spu->orig_frame_width;
+	unsigned int 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);
+	    spu->scaled_image_size = 0;
+	  }
+	  spu->scaled_image = malloc(2 * 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_image) {
+	  unsigned int y;
+	  if (spu->scaled_width > 1 && spu->scaled_height > 1)
+	    switch(spu_aamode&15) {
+	    case 4:
+	      spu_scaled_sws(spu,dxs,dys,scalex,scaley);
+	      break;
+	    case 3:
+	      spu_scaled_bilinear(spu,dxs,dys,scalex,scaley);
+	      break;
+	    case 0:
+	      spu_scaled_none(spu,dxs,dys,scalex,scaley);
+	      break;
+	    case 1:
+	      spu_scaled_approx(spu,dxs,dys,scalex,scaley);
+	      break;
+	    case 2:
+	      spu_scaled_full(spu,dxs,dys,scalex,scaley);
+	      break;
 	  }
-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) {
@@ -1170,6 +1230,13 @@
 	free(spu->scaled_image);
     if (spu->image)
       free(spu->image);
+    if (spu->imageu)		// Free dvdnav SPU uv or GB image
+      free(spu->imageu);
+    if (spu->imageyuy)		// Free dvdnav SPU YUY image
+      free(spu->imageyuy);
+    spu->imageyuy=NULL;
+    if (spu->scaled_imageu)	// Free dvdnav SPU uv or GB alpha
+	free(spu->scaled_imageu);
     free(spu);
   }
 }
--- spudec.c	2008-05-27 20:22:24.000000000 +0200
+++ spudec.c	2008-05-27 20:30:34.000000000 +0200
@@ -822,43 +822,63 @@
 	  }
 }
 
-void spu_scaled_approx(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
-                       unsigned int scalex, unsigned int scaley)
+void spu_scaled_approx(int width, int height, unsigned int dxs, unsigned int dys,
+                       int src_width, int src_height, int src_stride,
+                       int dst_width, int dst_height, int dst_stride,
+                       unsigned int scalex, unsigned int scaley,
+                       unsigned char *src_y, unsigned char *src_a,
+                       unsigned char *src_u, unsigned char *src_v,
+                       unsigned char *dst_y, unsigned char *dst_a,
+                       unsigned char *dst_u, unsigned char *dst_v)
 	  {
   unsigned int x, y;
 
 	    /* 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;
+	    for (y = 0; y < dst_height; ++y) {
+	      const unsigned int unscaled_top = y * src_height / dys;
+	      unsigned int unscaled_bottom = (y + 1) * src_height / dys;
+	      if (unscaled_bottom >= height)
+		unscaled_bottom = height - 1;
+	      for (x = 0; x < dst_width; ++x) {
+		const unsigned int unscaled_left = x * src_width / dxs;
+		unsigned int unscaled_right = (x + 1) * src_width / dxs;
 		unsigned int color = 0;
+		unsigned int coloru = 0;
+		unsigned int colorv = 0;
 		unsigned int alpha = 0;
 		unsigned int walkx, walky;
 		unsigned int base, tmp;
-		if (unscaled_right >= spu->width)
-		  unscaled_right = spu->width - 1;
+		if (unscaled_right >= width)
+		  unscaled_right = 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]);
+		    base = walky * src_stride + walkx;
+		    tmp = canon_alpha(src_a[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] =
+		    color += tmp * src_y[base];
+	            if(src_u)
+		      coloru += tmp * src_u[base];
+	            if(src_v)
+		      colorv += tmp * src_v[base];
+		  }
+		base = y * dst_stride + x;
+		dst_y[base] = alpha ? color / alpha : 0;
+	        if(src_u)
+		  dst_u[base] = alpha ? coloru / alpha : 0;
+	        if(src_v)
+		  dst_v[base] = alpha ? colorv / alpha : 0;
+		dst_a[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 (dst_a[base]) {
+		  dst_a[base] = 256 - dst_a[base];
+		  if (dst_a[base] + dst_y[base] > 255)
+		    dst_y[base] = 256 - dst_a[base];
+		  if (src_u && dst_a[base] + dst_u[base] > 255)
+		    dst_u[base] = 256 - dst_a[base];
+		  if (src_v && dst_a[base] + dst_v[base] > 255)
+		    dst_v[base] = 256 - dst_a[base];
 		}
 	      }
 	    }
@@ -1091,7 +1111,12 @@
                     dst_y, dst_a, dst_u, dst_v);
     break;
   case 1:
-    spu_scaled_approx(spu,dxs,dys,scalex,scaley);
+    spu_scaled_approx(width, height, dxs, dys,
+                      src_width, src_height, src_stride,
+                      dst_width, dst_height, dst_stride,
+                      scalex,scaley,
+                      src_y, src_a, src_u, src_v,
+                      dst_y, dst_a, dst_u, dst_v);
     break;
   case 2:
     spu_scaled_full(spu,dxs,dys,scalex,scaley);
--- spudec.c	2008-05-27 20:35:59.000000000 +0200
+++ spudec.c	2008-05-27 20:44:16.000000000 +0200
@@ -917,8 +917,13 @@
 	    }
 	  }
 
-void spu_scaled_full(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
-                     unsigned int scalex, unsigned int scaley)
+void spu_scaled_full(int src_stride,
+                     int dst_width, int dst_height, int dst_stride,
+                     unsigned int scalex, unsigned int scaley,
+                     unsigned char *src_y, unsigned char *src_a,
+                     unsigned char *src_u, unsigned char *src_v,
+                     unsigned char *dst_y, unsigned char *dst_a,
+                     unsigned char *dst_u, unsigned char *dst_v)
 	  {
   unsigned int x, y;
 
@@ -963,7 +968,7 @@
 	       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) {
+	    for (y = 0; y < dst_height; ++y) {
 	      const double unscaled_y = y * inv_scaley;
 	      const double unscaled_y_bottom = unscaled_y + inv_scaley;
 	      const unsigned int top_low_row = FFMIN(unscaled_y_bottom, unscaled_y + 1.0);
@@ -974,7 +979,7 @@
 	      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) {
+	      for (x = 0; x < dst_width; ++x) {
 		const double unscaled_x = x * inv_scalex;
 		const double unscaled_x_right = unscaled_x + inv_scalex;
 		const unsigned int left_right_column = FFMIN(unscaled_x_right, unscaled_x + 1.0);
@@ -986,6 +991,8 @@
 		  ? unscaled_x_right - floor(unscaled_x_right)
 		  : 0.0;
 		double color = 0.0;
+		double coloru = 0.0;
+		double colorv = 0.0;
 		double alpha = 0.0;
 		double tmp;
 		unsigned int base;
@@ -997,35 +1004,51 @@
 		  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]);
+		base = src_stride * (unsigned int) unscaled_y;
+		tmp = left * top * canon_alpha(src_a[base + (unsigned int) unscaled_x]);
 		alpha += tmp;
-		color += tmp * spu->image[base + (unsigned int) unscaled_x];
+		color += tmp * src_y[base + (unsigned int) unscaled_x];
+	        if(src_u)
+		  coloru += tmp * src_u[base + (unsigned int) unscaled_x];
+	        if(src_v)
+		  colorv += tmp * src_v[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]);
+		    base = src_stride * (unsigned int) unscaled_y + walkx;
+		    tmp = /* 1.0 * */ top * canon_alpha(src_a[base]);
 		    alpha += tmp;
-		    color += tmp * spu->image[base];
+		    color += tmp * src_y[base];
+        	    if(src_u)
+		      coloru += tmp * src_u[base];
+        	    if(src_v)
+		      colorv += tmp * src_v[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]);
+		  base = src_stride * (unsigned int) unscaled_y + (unsigned int) unscaled_x_right;
+		  tmp = right * top * canon_alpha(src_a[base]);
 		  alpha += tmp;
-		  color += tmp * spu->image[base];
+		  color += tmp * src_y[base];
+        	  if(src_u)
+		    coloru += tmp * src_u[base];
+        	  if(src_u)
+		    colorv += tmp * src_v[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]);
+		    base = src_stride * walky + (unsigned int) unscaled_x;
+		    tmp = left /* * 1.0 */ * canon_alpha(src_a[base]);
 		    alpha += tmp;
-		    color += tmp * spu->image[base];
+		    color += tmp * src_y[base];
+        	    if(src_u)
+		      coloru += tmp * src_u[base];
+        	    if(src_u)
+		      colorv += tmp * src_v[base];
 		  }
 		}
 		/* 5: center part */
@@ -1033,11 +1056,15 @@
 		  unsigned int walky;
 		  for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) {
 		    unsigned int walkx;
-		    base = spu->stride * walky;
+		    base = src_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]);
+		      tmp = /* 1.0 * 1.0 * */ canon_alpha(src_a[base + walkx]);
 		      alpha += tmp;
-		      color += tmp * spu->image[base + walkx];
+		      color += tmp * src_y[base + walkx];
+        	      if(src_u)
+	        	coloru += tmp * src_u[base];
+	              if(src_u)
+		        colorv += tmp * src_v[base];
 		    }
 		  }		    
 		}
@@ -1045,44 +1072,68 @@
 		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]);
+		    base = src_stride * walky + (unsigned int) unscaled_x_right;
+		    tmp = right /* * 1.0 */ * canon_alpha(src_a[base]);
 		    alpha += tmp;
-		    color += tmp * spu->image[base];
+		    color += tmp * src_y[base];
+        	    if(src_u)
+		      coloru += tmp * src_u[base];
+        	    if(src_u)
+		      colorv += tmp * src_v[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]);
+		  base = src_stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x;
+		  tmp = left * bottom * canon_alpha(src_a[base]);
 		  alpha += tmp;
-		  color += tmp * spu->image[base];
+		  color += tmp * src_y[base];
+        	  if(src_u)
+		    coloru += tmp * src_u[base];
+        	  if(src_u)
+		    colorv += tmp * src_v[base];
 		}
 		/* 8: bottom center part */
 		if (width > 0 && bottom > 0.0) {
 		  unsigned int walkx;
-		  base = spu->stride * (unsigned int) unscaled_y_bottom;
+		  base = src_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]);
+		    tmp = /* 1.0 * */ bottom * canon_alpha(src_a[base + walkx]);
 		    alpha += tmp;
-		    color += tmp * spu->image[base + walkx];
+		    color += tmp * src_y[base + walkx];
+        	    if(src_u)
+		      coloru += tmp * src_u[base];
+        	    if(src_u)
+		      colorv += tmp * src_v[base];
 		  }
 		}
 		/* 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]);
+		  base = src_stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x_right;
+		  tmp = right * bottom * canon_alpha(src_a[base]);
 		  alpha += tmp;
-		  color += tmp * spu->image[base];
+		  color += tmp * src_y[base];
+        	  if(src_u)
+		    coloru += tmp * src_u[base];
+        	  if(src_u)
+		    colorv += tmp * src_v[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];
+		base = dst_stride * y + x;
+		dst_y[base] = alpha > 0 ? color / alpha : 0;
+	        if(src_u)
+		  dst_u[base] = alpha > 0 ? coloru / alpha : 0;
+	        if(src_v)
+		  dst_v[base] = alpha > 0 ? colorv / alpha : 0;
+		dst_a[base] = alpha * scalex * scaley / 0x10000;
+		if (dst_a[base]) {
+		  dst_a[base] = 256 - dst_a[base];
+		  if (dst_a[base] + dst_y[base] > 255)
+		    dst_y[base] = 256 - dst_a[base];
+		  if (src_u && dst_a[base] + dst_u[base] > 255)
+		    dst_u[base] = 256 - dst_a[base];
+		  if (src_v && dst_a[base] + dst_v[base] > 255)
+		    dst_v[base] = 256 - dst_a[base];
 		}
 	      }
 	    }
@@ -1140,8 +1191,7 @@
                unsigned char *src_y, unsigned char *src_a,
                unsigned char *src_u, unsigned char *src_v,
                unsigned char *dst_y, unsigned char *dst_a,
-               unsigned char *dst_u, unsigned char *dst_v,
-               spudec_handle_t *spu)
+               unsigned char *dst_u, unsigned char *dst_v)
 {
 switch(aamode&15) {
   case 4:
@@ -1177,7 +1227,11 @@
                       dst_y, dst_a, dst_u, dst_v);
     break;
   case 2:
-    spu_scaled_full(spu,dxs,dys,scalex,scaley);
+    spu_scaled_full(src_stride,
+                    dst_width, dst_height, dst_stride,
+                    scalex,scaley,
+                    src_y, src_a, src_u, src_v,
+                    dst_y, dst_a, dst_u, dst_v);
     break;
   }
 }
@@ -1234,8 +1288,7 @@
                       spu->scaled_width, spu->scaled_height, spu->scaled_stride,
                       scalex, scaley,
                       spu->image, spu->aimage, NULL, NULL,
-                      spu->scaled_image, spu->scaled_aimage, NULL, NULL,
-                      spu);
+                      spu->scaled_image, spu->scaled_aimage, NULL, NULL);
 	  /* Kludge: draw_alpha needs width multiple of 8. */
 	  if (spu->scaled_width < spu->scaled_stride)
 	    for (y = 0; y < spu->scaled_height; ++y) {
--- spudec.c	2008-05-27 20:31:18.000000000 +0200
+++ spudec.c	2008-05-27 20:35:59.000000000 +0200
@@ -795,8 +795,10 @@
   }
 }
 
-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)
+void sws_spu_image(unsigned char *d1, unsigned char *d2, unsigned char *d3, unsigned char *d4,
+                   int dw, int dh, int ds,
+                   unsigned char *s1, unsigned char *s2, unsigned char *s3, unsigned char *s4,
+                   int sw, int sh, int ss)
 {
 	struct SwsContext *ctx;
 	static SwsFilter filter;
@@ -815,6 +817,10 @@
 	
 	ctx=sws_getContext(sw, sh, PIX_FMT_GRAY8, dw, dh, PIX_FMT_GRAY8, SWS_GAUSS, &filter, NULL, NULL);
 	sws_scale(ctx,&s1,&ss,0,sh,&d1,&ds);
+        if(s3)
+	  sws_scale(ctx,&s3,&ss,0,sh,&d3,&ds);
+        if(s4)
+	  sws_scale(ctx,&s4,&ss,0,sh,&d4,&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;
@@ -1112,13 +1118,19 @@
   free(table_y);
 }
 
-void spu_scaled_sws(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
-                    unsigned int scalex, unsigned int scaley)
+
+void spu_scaled_sws(int width, int height, unsigned int dxs, unsigned int dys,
+                    int src_width, int src_height, int src_stride,
+                    int dst_width, int dst_height, int dst_stride,
+                    unsigned int scalex, unsigned int scaley,
+                    unsigned char *src_y, unsigned char *src_a,
+                    unsigned char *src_u, unsigned char *src_v,
+                    unsigned char *dst_y, unsigned char *dst_a,
+                    unsigned char *dst_u, unsigned char *dst_v)
 {
-  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(dst_y, dst_a, dst_u, dst_y,
+                dst_width, dst_height, dst_stride,
+                src_y, src_a, src_u, src_y, width, height, src_stride);
 }
 
 void aa_scaler(int aamode, int width, int height, int dxs, int dys,
@@ -1133,7 +1145,12 @@
 {
 switch(aamode&15) {
   case 4:
-    spu_scaled_sws(spu,dxs,dys,scalex,scaley);
+    spu_scaled_sws(width, height, dxs, dys,
+                   src_width, src_height, src_stride,
+                   dst_width, dst_height, dst_stride,
+                   scalex,scaley,
+                   src_y, src_a, src_u, src_v,
+                   dst_y, dst_a, dst_u, dst_v);
     break;
   case 3:
     spu_scaled_bilinear(width, height,
--- spudec.c	2008-05-27 20:44:16.000000000 +0200
+++ spudec.c	2008-05-27 20:59:50.000000000 +0200
@@ -651,13 +651,106 @@
   }
 }
 
+//
+// Convert Yuv image to YuY image
+//
+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->scaled_image+y*spu->scaled_stride;
+      sptru=spu->scaled_imageu+y/2*spu->scaled_strideuv;
+      sptrv=spu->scaled_imagev+y/2*spu->scaled_strideuv;
+      saptr=spu->scaled_aimage+y*spu->scaled_stride;
+      saptruv=spu->scaled_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 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)
     {
+	switch(spu->colorspu) {
+	case COLORSPU_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,
+		   DEST_PLANES_YUYV, spu->imageyuy, spu->aimageyuy, spu->strideyuy);
+	  break;
+	case COLORSPU_YUV:
+	  draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+		   DEST_PLANES_Y, spu->image, spu->aimage, spu->stride);
+	  draw_alpha(spu->start_coluv, spu->start_rowuv, spu->widthuv, spu->heightuv,
+		   DEST_PLANES_U, spu->imageu, spu->aimageuv, spu->strideuv);
+	  draw_alpha(spu->start_coluv, spu->start_rowuv, spu->widthuv, spu->heightuv,
+		   DEST_PLANES_V, spu->imagev, spu->aimageuv, spu->strideuv);
+	  break;
+	case COLORSPU_RGB:
+	case COLORSPU_BGR:
+	  draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+		   DEST_PLANES_BR, spu->imagev, spu->aimage, spu->stride);
+	  draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+		   DEST_PLANES_G, spu->imageu, spu->aimage, spu->stride);
+	  draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+		   DEST_PLANES_RB, spu->image, spu->aimage, spu->stride);
+	  break;
+	default:
 	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
 		   DEST_PLANES_Y, spu->image, spu->aimage, spu->stride);
+	}
 	spu->spu_changed = 0;
     }
 }
@@ -1251,8 +1344,34 @@
 	|| (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) {
       if (spu->image)
       {
+	switch(spu->colorspu) {
+	case COLORSPU_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,
+		   DEST_PLANES_YUYV, spu->imageyuy, spu->aimageyuy, spu->strideyuy);
+	  break;
+	case COLORSPU_YUV:
+	  draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+		   DEST_PLANES_Y, spu->image, spu->aimage, spu->stride);
+	  draw_alpha(spu->start_coluv, spu->start_rowuv, spu->widthuv, spu->heightuv,
+		   DEST_PLANES_U, spu->imageu, spu->aimageuv, spu->strideuv);
+	  draw_alpha(spu->start_coluv, spu->start_rowuv, spu->widthuv, spu->heightuv,
+		   DEST_PLANES_V, spu->imagev, spu->aimageuv, spu->strideuv);
+	  break;
+	case COLORSPU_RGB:
+	case COLORSPU_BGR:
+	  draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+		   DEST_PLANES_BR, spu->imagev, spu->aimage, spu->stride);
+	  draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+		   DEST_PLANES_G, spu->imageu, spu->aimage, spu->stride);
+	  draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
+		   DEST_PLANES_RB, spu->image, spu->aimage, spu->stride);
+	  break;
+	default:
 	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
 		   DEST_PLANES_Y, spu->image, spu->aimage, spu->stride);
+	}
 	spu->spu_changed = 0;
       }
     }
@@ -1267,11 +1386,23 @@
 	spu->scaled_start_row = spu->start_row * scaley / 0x100;
 	spu->scaled_width = spu->width * scalex / 0x100;
 	spu->scaled_height = spu->height * scaley / 0x100;
+        switch(spu->colorspu) {
+          case COLORSPU_YUV:
+          case COLORSPU_YUY:
+            spu->scaled_widthuv = spu->widthuv * scalex / 0x100;
+            spu->scaled_heightuv = spu->heightuv * scaley / 0x100;
+            spu->scaled_strideuv = (spu->scaled_widthuv + 7) & ~7;
+	    spu->scaled_start_coluv = spu->start_coluv * scalex / 0x100;
+	    spu->scaled_start_rowuv = spu->start_rowuv * scaley / 0x100;
+            break;
+	}
 	/* 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);
@@ -1280,15 +1411,67 @@
 	    spu->scaled_aimage = spu->scaled_image + spu->scaled_image_size;
 	  }
 	}
+        switch(spu->colorspu) {
+        case COLORSPU_YUV:
+        case COLORSPU_YUY:
+           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;
+            }
+ 	    break;
+ 	case COLORSPU_RGB:
+ 	case COLORSPU_BGR:
+ 	  spu->scaled_imageu = malloc(3 * spu->scaled_stride * spu->scaled_height);
+ 	  if (spu->scaled_imageu)
+ 	    spu->scaled_imagev = spu->scaled_imageu + spu->scaled_image_size;
+ 	  break;
+        }
 	if (spu->scaled_image) {
 	  unsigned int y;
 	  if (spu->scaled_width > 1 && spu->scaled_height > 1)
+            switch(spu->colorspu) {
+            case COLORSPU_YUV:
+            case COLORSPU_YUY:
+              if (spu->scaled_widthuv <= 1 || spu->scaled_heightuv <= 1) {
             aa_scaler(spu_aamode&15, spu->width, spu->height, dxs, dys,
                       spu->orig_frame_width, spu->orig_frame_height,spu->stride,
                       spu->scaled_width, spu->scaled_height, spu->scaled_stride,
                       scalex, scaley,
                       spu->image, spu->aimage, NULL, NULL,
                       spu->scaled_image, spu->scaled_aimage, NULL, NULL);
+              aa_scaler(spu_aamode&15, spu->widthuv, spu->heightuv, dxs/2, dys/2,
+                        spu->orig_frame_width/2, spu->orig_frame_height/2, spu->strideuv,
+                        spu->scaled_widthuv, spu->scaled_heightuv, spu->scaled_strideuv,
+                        scalex, scaley,
+                        spu->imageu, spu->aimage, spu->imagev, NULL,
+                        spu->scaled_imageu, spu->scaled_aimage, spu->scaled_imagev, NULL);
+              }
+ 	      break;
+ 	    case COLORSPU_RGB:
+ 	    case COLORSPU_BGR:
+              aa_scaler(spu_aamode&15, spu->width, spu->height, dxs, dys,
+                        spu->orig_frame_width, spu->orig_frame_height, spu->stride,
+                        spu->scaled_width, spu->scaled_height, spu->scaled_stride,
+                        scalex, scaley,
+                        spu->image, spu->aimage, spu->imageu, spu->imagev,
+                        spu->scaled_image, spu->scaled_aimage, spu->scaled_imageu, spu->scaled_imagev);
+ 	      break;
+ 	    default:
+               aa_scaler(spu_aamode&15, spu->width, spu->height, dxs, dys,
+                         spu->orig_frame_width, spu->orig_frame_height, spu->stride,
+                         spu->scaled_width, spu->scaled_height, spu->scaled_stride,
+                         scalex, scaley,
+                         spu->image, spu->aimage, NULL, NULL,
+                         spu->scaled_image, spu->scaled_aimage, NULL, NULL);
+            }
 	  /* Kludge: draw_alpha needs width multiple of 8. */
 	  if (spu->scaled_width < spu->scaled_stride)
 	    for (y = 0; y < spu->scaled_height; ++y) {
@@ -1297,6 +1480,16 @@
 	    }
 	  spu->scaled_frame_width = dxs;
 	  spu->scaled_frame_height = dys;
+	  if (spu->colorspu==COLORSPU_YUY || spu->colorspu==COLORSPU_YUV) {
+	    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){
@@ -1305,18 +1498,60 @@
           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;
+	  if (spu->colorspu==COLORSPU_YUY || spu->colorspu==COLORSPU_YUV) {
+            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 && spu->scaled_start_row + spu->scaled_height > dys)
 	      spu->scaled_start_row = dys - spu->scaled_height;
+	  if (spu->colorspu==COLORSPU_YUY || spu->colorspu==COLORSPU_YUV) {
+            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->colorspu==COLORSPU_YUY || spu->colorspu==COLORSPU_YUV)
+            spu->scaled_start_rowuv = (dys/2)*sub_pos/100 - spu->scaled_heightuv;
 	  break;
 	}
+	switch(spu->colorspu) {
+	  case COLORSPU_YUY:
+	    if (!spu->imageyuy) spudec_create_yuy(spu,1);
+	    if (spu->imageyuy)
+	      draw_alpha(spu->start_col, spu->start_row, spu->width*2, spu->height/2,
+		         DEST_PLANES_YUYV, spu->imageyuy, spu->aimageyuy, spu->strideyuy);
+	    break;
+	  case COLORSPU_YUV:
 	draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,
 		   DEST_PLANES_Y, 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,
+		       DEST_PLANES_U, 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,
+		       DEST_PLANES_V, spu->scaled_imagev, spu->scaled_aimageuv, spu->scaled_strideuv);
+	    break;
+	  case COLORSPU_RGB:
+	  case COLORSPU_BGR:
+	    draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,
+		       DEST_PLANES_BR, spu->scaled_imagev, spu->scaled_aimage, spu->scaled_stride);
+	    draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,
+		       DEST_PLANES_G, 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,
+		       DEST_PLANES_RB, spu->scaled_image, spu->scaled_aimage, spu->scaled_stride);
+	    break;
+	  default:
+	    draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height,
+		     DEST_PLANES_Y, spu->scaled_image, spu->scaled_aimage, spu->scaled_stride);
+        }
 	spu->spu_changed = 0;
       }
     }
--- spudec.c	2008-05-27 22:04:11.000000000 +0200
+++ spudec.c	2008-05-27 21:02:42.000000000 +0200
@@ -2032,3 +2032,39 @@
   spu->hw_spu = hw_spu;
   hw_spu->control(VOCTRL_SET_SPU_PALETTE,spu->global_palette);
 }
+
+void spudec_set_spu_format(void *this, uint32_t fmt)
+{
+  spudec_handle_t *spu = (spudec_handle_t*)this;
+  if (!spu)
+    return;
+  switch(fmt) {
+  case IMGFMT_YV12:
+  case IMGFMT_I420:
+  case IMGFMT_IYUV:
+  case IMGFMT_YVU9:   
+  case IMGFMT_IF09:
+  case IMGFMT_Y800:
+  case IMGFMT_Y8:
+    spu->colorspu=COLORSPU_YUV;
+    break;
+  case IMGFMT_YUY2:
+    spu->colorspu=COLORSPU_YUY;
+    break;
+  case IMGFMT_RGB15:
+  case IMGFMT_RGB16:
+  case IMGFMT_RGB24:
+  case IMGFMT_RGB32:
+    spu->colorspu=COLORSPU_RGB;
+    break;
+  case IMGFMT_BGR15:
+  case IMGFMT_BGR16:
+  case IMGFMT_BGR24:
+  case IMGFMT_BGR32:
+    spu->colorspu=COLORSPU_BGR;
+    break;
+  case 0:
+  default:
+    spu->colorspu=COLORSPU_Y;
+  }
+}
--- spudec.h	2008-05-27 22:05:52.000000000 +0200
+++ spudec.h	2008-05-27 21:02:42.000000000 +0200
@@ -19,5 +19,6 @@
 int spudec_changed(void *this);
 void spudec_calc_bbox(void *me, unsigned int dxs, unsigned int dys, unsigned int* bbox);
 void spudec_set_forced_subs_only(void * const this, const unsigned int flag);
+void spudec_set_spu_format(void *this, uint32_t fmt);
 
 #endif /* MPLAYER_SPUDEC_H */
--- spudec.c	2008-05-27 20:59:50.000000000 +0200
+++ spudec.c	2008-05-27 22:04:11.000000000 +0200
@@ -117,6 +117,11 @@
   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 */
   colorspu_t colorspu;          /* spu color mode */
+  uint32_t     dvdnav_palette;	/* dvdnav menu button palette */
+  unsigned int spu_sx;	/* dvdnav menu item box */
+  unsigned int spu_ex;
+  unsigned int spu_sy;
+  unsigned int spu_ey;
 } spudec_handle_t;
 
 static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet)
@@ -236,11 +241,145 @@
   } else {
     mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: update_spu: malloc requested %d bytes\n", 2 * this->stride * this->height);
   }
+//
+// Cut the sub to visible part UV planes
+//
+  unsigned char *imageu;
+  unsigned char *imagev;
+  switch (this->colorspu) {
+  case COLORSPU_YUV:
+  case COLORSPU_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 COLORSPU_RGB:
+  case COLORSPU_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;
+  }
+}
+
+//
+// Fill to spu image buffer
+//	y : image col
+//	x : start pos in image row
+//	len : fill length in image row
+//	color : Y: (YUV,YUY,Y), Red: (RGB) or Blue: (BGR)
+//	coloru: U: (YUV,YUY), Green: (RGB,BGR)
+//	colorv: V: (YUV,YUY), Blue: (RGB) or Red (BGR)
+//	alpha: alpha channel
+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;
+
+  if (this->stride-x-len<0) return;
+  if (len<0) return;
+  switch (this->colorspu) {
+  case COLORSPU_YUV:
+  case COLORSPU_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 COLORSPU_RGB:
+  case COLORSPU_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;
+  }
+}
+
+//
+// Convert yuv color to rgb color
+//
+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;
+return;
 }
 
 static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
 {
   unsigned int cmap[4], alpha[4];
+  unsigned int thpalette[4], thalpha[4];	/* dvdnav highlight menu palette */
+  unsigned int hcmap[4], halpha[4];		/* dvdnav highlight map */
+  unsigned int cmapu[4], cmapv[4];
+  unsigned int hcmapu[4], hcmapv[4];
+  unsigned int ty, tu, tv, tr, tg, tb;
   unsigned int i, x, y;
 
   this->scaled_frame_width = 0;
@@ -252,7 +391,136 @@
   this->height = packet->height;
   this->width = packet->width;
   this->stride = packet->stride;
+  this->strideuv = packet->stride;
+
+  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;
+
   for (i = 0; i < 4; ++i) {
+    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);
+    alpha[i] = mkalpha(packet->alpha[i]);
+    if (this->custom && (this->cuspal[i] >> 31) != 0)
+      alpha[i] = 0;
+
+    switch(this->colorspu) {
+    case COLORSPU_YUV:
+    case COLORSPU_YUY:
+      if (alpha[i] == 0)
+        cmap[i] = cmapu[i] = cmapv[i] = 0;
+      else if (this->custom){
+        cmap[i] = ((this->cuspal[i] >> 16) & 0xff);
+        cmapu[i] = ((this->cuspal[i] >> 8) & 0xff);
+        cmapv[i] = ((this->cuspal[i] >> 0) & 0xff);
+        if (cmap[i] + alpha[i] > 255)
+	  cmap[i] = 256 - alpha[i];
+      } else {
+        cmap[i] = ((this->global_palette[packet->palette[i]] >> 16) & 0xff);
+        cmapu[i] = ((this->global_palette[packet->palette[i]] >> 8) & 0xff);
+        cmapv[i] = ((this->global_palette[packet->palette[i]] >> 0) & 0xff);
+        if (cmap[i] + alpha[i] > 255)
+	  cmap[i] = 256 - alpha[i];
+      }
+      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];
+        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 COLORSPU_RGB:
+      if (alpha[i] == 0)
+        cmap[i] = cmapu[i] = cmapv[i] = 0;
+      else if (this->custom){
+        ty = ((this->cuspal[i] >> 16) & 0xff);
+        tu = ((this->cuspal[i] >> 8) & 0xff);
+        tv = ((this->cuspal[i] >> 0) & 0xff);
+        spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb);
+        cmap[i] = tr;							// Red
+        cmapu[i] = tg;							// Green
+        cmapv[i] = tb;							// Blue
+        cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8;
+        cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8;
+        cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8;
+      } else {
+        ty = ((this->global_palette[packet->palette[i]] >> 16) & 0xff);
+        tu = ((this->global_palette[packet->palette[i]] >> 8) & 0xff);
+        tv = ((this->global_palette[packet->palette[i]] >> 0) & 0xff);
+	spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb);
+	cmap[i] = tr;							// Red
+	cmapu[i] = tg;							// Green
+	cmapv[i] = tb;							// Blue
+	cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8;
+	cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8;
+	cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8;
+      }
+      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];
+        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 COLORSPU_BGR:
+      if (alpha[i] == 0)
+        cmap[i] = cmapu[i] = cmapv[i] = 0;
+      else if (this->custom){
+        ty = ((this->cuspal[i] >> 16) & 0xff);
+        tu = ((this->cuspal[i] >> 8) & 0xff);
+        tv = ((this->cuspal[i] >> 0) & 0xff);
+	spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb);
+        cmap[i] = tb;							// Red
+	cmapu[i] = tg;							// Green
+        cmapv[i] = tr;							// Blue
+        cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8;
+        cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8;
+        cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8;
+      } else {
+        ty = ((this->global_palette[packet->palette[i]] >> 16) & 0xff);
+        tu = ((this->global_palette[packet->palette[i]] >> 8) & 0xff);
+        tv = ((this->global_palette[packet->palette[i]] >> 0) & 0xff);
+        spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb);
+        cmap[i] = tb;							// Red
+        cmapu[i] = tg;							// Green
+        cmapv[i] = tr;							// Blue
+	cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8;
+	cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8;
+	cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8;
+      }
+      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];
+        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;
+    default:
     alpha[i] = mkalpha(packet->alpha[i]);
     if (this->custom && (this->cuspal[i] >> 31) != 0)
       alpha[i] = 0;
@@ -269,6 +537,7 @@
 	cmap[i] = 256 - alpha[i];
     }
   }
+  }
 
   if (this->image_size < this->stride * this->height) {
     if (this->image != NULL) {
@@ -292,6 +561,52 @@
       memset(this->image + y * this->stride + this->width, 0, this->stride - this->width);
     }
 
+  if (this->imageyuy) {
+    free(this->imageyuy);
+    this->imageyuy=NULL;
+    this->aimageyuy=NULL;
+  }
+  switch(this->colorspu) {
+  case COLORSPU_YUY:
+  case COLORSPU_YUV:
+    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;
+      }
+    }
+    if (this->imageu == NULL) return;
+    memset(this->imageu,0,3 * this->strideuv * this->heightuv);
+    break;
+  case COLORSPU_RGB:
+  case COLORSPU_BGR:
+    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;
+      }
+    }
+    if (this->imageu == NULL) return;
+    memset(this->imageu,0,2 * this->stride * this->height);
+    break;
+  default:
+    if (this->imageu) free(this->imageu);
+    this->imageu=NULL;
+    this->image_sizeuv=0;
+  }
+
   i = packet->current_nibble[1];
   x = 0;
   y = 0;
@@ -317,8 +632,71 @@
     if (len > this->width - x || len == 0)
       len = this->width - x;
     /* FIXME have to use palette and alpha map*/
+    switch(this->colorspu) {
+    case COLORSPU_YUV:
+    case COLORSPU_YUY:
+    case COLORSPU_RGB:
+    case COLORSPU_BGR:
+      if (!this->spu_sx && !this->spu_sy &&!this->spu_ex && !this->spu_ey) {
+	spudec_process_fill(this, x, y, len,
+                            cmap[color], cmapu[color],
+                            cmapv[color], alpha[color]);
+      } else {
+        if (this->start_row+y>=this->spu_sy &&
+	    this->start_row+y<=this->spu_ey) {
+          if (this->start_col+x>=this->spu_sx &&
+              this->start_col+x+len<=this->spu_ex)
+            spudec_process_fill(this, x, y, len,
+		                hcmap[color], hcmapu[color],
+                                hcmapv[color], halpha[color]);
+	  else if(this->start_col+x<this->spu_sx &&
+		this->start_col+x+len>this->spu_sx &&
+		this->start_col+x+len<=this->spu_ex) {
+            spudec_process_fill(this, x, y, this->spu_sx-this->start_col-x,
+                                cmap[color], cmapu[color],
+                                cmapv[color], alpha[color]);
+            spudec_process_fill(this, this->spu_sx-this->start_col, y,
+                                len+this->start_col+x-this->spu_sx,
+                                hcmap[color], hcmapu[color],
+                                hcmapv[color], halpha[color]);
+	  } else if(this->start_col+x<this->spu_sx &&
+		this->start_col+x+len>this->spu_sx &&
+		this->start_col+x+len>this->spu_ex) {
+	    spudec_process_fill(this, x, y, this->spu_sx-this->start_col-x,
+                                cmap[color], cmapu[color],
+                                cmapv[color], alpha[color]);
+            spudec_process_fill(this, this->spu_sx-this->start_col, y,
+                                this->spu_ex-this->spu_sx,
+                                hcmap[color], hcmapu[color],
+                                hcmapv[color], halpha[color]);
+            spudec_process_fill(this, this->spu_ex-this->start_col, y,
+                                x+len+this->start_col-this->spu_ex,
+                                cmap[color], cmapu[color], 
+                                cmapv[color], alpha[color]);
+	  } else if(this->start_col+x>=this->spu_sx &&
+		this->start_col+x<this->spu_ex &&
+		this->start_col+x+len>this->spu_ex) {
+            spudec_process_fill(this, x, y, this->spu_ex-this->start_col-x,
+                                hcmap[color], hcmapu[color],
+                                hcmapv[color], halpha[color]);
+            spudec_process_fill(this, this->spu_ex-this->start_col, y,
+                                len+this->start_col+x-this->spu_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]);
+      }
+      break;
+    default:
     memset(this->image + y * this->stride + x, cmap[color], len);
     memset(this->aimage + y * this->stride + x, alpha[color], len);
+    }
     x += len;
     if (x >= this->width) {
       next_line(packet);
@@ -626,7 +1004,7 @@
     packet_t *packet = spudec_dequeue_packet(spu);
     spu->start_pts = packet->start_pts;
     spu->end_pts = packet->end_pts;
-    if (spu->auto_palette)
+    if (spu->auto_palette && spu->colorspu==COLORSPU_Y)
       compute_palette(spu, packet);
     spudec_process_data(spu, packet);
     spudec_free_packet(packet);
--- spudec.c	2008-05-27 20:30:34.000000000 +0200
+++ spudec.c	2008-05-27 20:31:18.000000000 +0200
@@ -738,33 +738,60 @@
 }
 
 /* bilinear scale, similar to vobsub's code */
-static void scale_image(int x, int y, scale_pixel* table_x, scale_pixel* table_y, spudec_handle_t * spu)
+static void scale_image(int x, int y, scale_pixel* table_x, scale_pixel* table_y,
+                        int src_stride, int dst_stride,
+                        unsigned char *src_y, unsigned char *src_a,
+                        unsigned char *src_u, unsigned char *src_v,
+                        unsigned char *dst_y, unsigned char *dst_a,
+                        unsigned char *dst_u, unsigned char *dst_v)
 {
   int alpha[4];
   int color[4];
+  int coloru[4];
+  int colorv[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]);
-  color[0] = spu->image[base];
-  color[1] = spu->image[base + 1];
-  color[2] = spu->image[base + spu->stride];
-  color[3] = spu->image[base + spu->stride + 1];
+  int base = table_y[y].position * src_stride + table_x[x].position;
+  int scaled = y * dst_stride + x;
+  alpha[0] = canon_alpha(src_a[base]);
+  alpha[1] = canon_alpha(src_a[base + 1]);
+  alpha[2] = canon_alpha(src_a[base + src_stride]);
+  alpha[3] = canon_alpha(src_a[base + src_stride + 1]);
+  color[0] = src_y[base];
+  color[1] = src_y[base + 1];
+  color[2] = src_y[base + src_stride];
+  color[3] = src_y[base + src_stride + 1];
+  if(src_u) {
+    coloru[0] = src_u[base];
+    coloru[1] = src_u[base + 1];
+    coloru[2] = src_u[base + src_stride];
+    coloru[3] = src_u[base + src_stride + 1];
+  }
+  if(src_v) {
+    colorv[0] = src_v[base];
+    colorv[1] = src_v[base + 1];
+    colorv[2] = src_v[base + src_stride];
+    colorv[3] = src_v[base + src_stride + 1];
+  }
   scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0];
   if (table_y[y].left_up == 0x10000) // necessary to avoid overflow-case
     scale[0] = table_x[x].left_up * 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] = (color[0] * scale[0] + color[1] * scale[1] + color[2] * scale[2] + color[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];
+  dst_y[scaled] = (color[0] * scale[0] + color[1] * scale[1] + color[2] * scale[2] + color[3] * scale[3])>>24;
+  if(src_u)
+    dst_u[scaled] = (coloru[0] * scale[0] + coloru[1] * scale[1] + coloru[2] * scale[2] + coloru[3] * scale[3])>>24;
+  if(src_v)
+    dst_v[scaled] = (colorv[0] * scale[0] + colorv[1] * scale[1] + colorv[2] * scale[2] + colorv[3] * scale[3])>>24;
+  dst_a[scaled] = (scale[0] + scale[1] + scale[2] + scale[3]) >> 16;
+  if (dst_a[scaled]){
+    dst_a[scaled] = 256 - dst_a[scaled];
+    if(dst_a[scaled] + dst_y[scaled] > 255)
+      dst_y[scaled] = 256 - dst_a[scaled];
+    if(src_u && dst_a[scaled] + dst_u[scaled] > 255)
+      dst_u[scaled] = 256 - dst_a[scaled];
+    if(src_v && dst_a[scaled] + dst_v[scaled] > 255)
+      dst_v[scaled] = 256 - dst_a[scaled];
   }
 }
 
@@ -1055,23 +1082,32 @@
 	    }
 	  }
 
-void spu_scaled_bilinear(spudec_handle_t *spu, unsigned int dxs, unsigned int dys,
-                         unsigned int scalex, unsigned int scaley)
+void spu_scaled_bilinear(int width, int height,
+                         int src_stride,
+                         int dst_width, int dst_height, int dst_stride,
+                         unsigned int scalex, unsigned int scaley,
+                         unsigned char *src_y, unsigned char *src_a,
+                         unsigned char *src_u, unsigned char *src_v,
+                         unsigned char *dst_y, unsigned char *dst_a,
+                         unsigned char *dst_u, unsigned char *dst_v)
 {
   unsigned int x, y;
   scale_pixel *table_x;
   scale_pixel *table_y;
 
-  table_x = calloc(spu->scaled_width, sizeof(scale_pixel));
-  table_y = calloc(spu->scaled_height, sizeof(scale_pixel));
+  table_x = calloc(dst_width, sizeof(scale_pixel));
+  table_y = calloc(dst_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);
+  scale_table(0, 0, width - 1, dst_width - 1, table_x);
+  scale_table(0, 0, height - 1, dst_height - 1, table_y);
+  for (y = 0; y < dst_height; y++)
+    for (x = 0; x < dst_width; x++)
+      scale_image(x, y, table_x, table_y,
+                  src_stride, dst_stride,
+                  src_y, src_a, src_u, src_v,
+                  dst_y, dst_a, dst_u, dst_v);
   free(table_x);
   free(table_y);
 }
@@ -1100,7 +1136,12 @@
     spu_scaled_sws(spu,dxs,dys,scalex,scaley);
     break;
   case 3:
-    spu_scaled_bilinear(spu,dxs,dys,scalex,scaley);
+    spu_scaled_bilinear(width, height,
+                        src_stride,
+                        dst_width, dst_height, dst_stride,
+                        scalex,scaley,
+                        src_y, src_a, src_u, src_v,
+                        dst_y, dst_a, dst_u, dst_v);
     break;
   case 0:
     spu_scaled_none(dxs, dys,
_______________________________________________
MPlayer-dev-eng mailing list
MPlayer-dev-eng@xxxxxxxxxxxx
https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng