changeset 3402:5d3cbbf63d18

Patch by Kim Minh Kaplan <kmkaplan@selfoffice.com>: - removes garbage on the right hand side of DVD subtitles - improves the handling of unknown SPU control codes
author pl
date Sun, 09 Dec 2001 16:56:23 +0000
parents 85feae032869
children c4ca766a2d05
files spudec.c
diffstat 1 files changed, 27 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/spudec.c	Sun Dec 09 16:21:32 2001 +0000
+++ b/spudec.c	Sun Dec 09 16:56:23 2001 +0000
@@ -8,6 +8,7 @@
    read brightness from the IFO.
 
    For information on SPU format see <URL:http://sam.zoy.org/doc/dvd/subtitles/>
+   and <URL:http://members.aol.com/mpucoder/DVD/spu.html>
 
  */
 #include "config.h"
@@ -33,7 +34,7 @@
   int start_pts, end_pts;
   int start_col, end_col;
   int start_row, end_row;
-  int width, height;
+  int width, height, stride;
   int current_nibble[2];	/* next data nibble (4 bits) to be
                                    processed (for RLE decoding) for
                                    even and odd lines */
@@ -94,32 +95,41 @@
 static void spudec_process_data(spudec_handle_t *this)
 {
   int cmap[4], alpha[4];
-  int i;
-  int y = 0, x = 0;
+  int i, x, y;
 
   for (i = 0; i < 4; ++i) {
     alpha[i] = mkalpha(this->alpha[i]);
     if (alpha[i] == 0)
       cmap[i] = 0;
     else {
-      cmap[i] = ((this->dvd_info->vts_file->vts_pgcit->pgci_srp[0].pgc->palette[this->palette[i]] >> 16) & 0xff) - alpha[i];
+      cmap[i] = ((this->dvd_info->cur_pgc->palette[this->palette[i]] >> 16) & 0xff) - alpha[i];
       if (cmap[i] < 0)
 	cmap[i] = 0;
     }
   }
 
-  if (this->image_size < this->width * this->height) {
-    if (this->image != NULL)
+  if (this->image_size < this->stride * this->height) {
+    if (this->image != NULL) {
       free(this->image);
-    this->image = malloc(2 * this->width * this->height);
+      this->image_size = 0;
+    }
+    this->image = malloc(2 * this->stride * this->height);
     if (this->image) {
-      this->image_size = this->width * this->height;
+      this->image_size = this->stride * this->height;
       this->aimage = this->image + this->image_size;
     }
   }
   if (this->image == NULL)
     return;
+
+  /* Kludge: draw_alpha needs width multiple of 8. */
+  if (this->width < this->stride)
+    for (y = 0; y < this->height; ++y)
+      memset(this->aimage + y * this->stride + this->width, 0, this->stride - this->width);
+
   i = this->current_nibble[1];
+  x = 0;
+  y = 0;
   while (this->current_nibble[0] < i
 	 && this->current_nibble[1] / 2 < this->control_start
 	 && y < this->height) {
@@ -139,11 +149,11 @@
     }
     color = 3 - (rle & 0x3);
     len = rle >> 2;
-    if (len > this->width - x)
+    if (len > this->width - x || len == 0)
       len = this->width - x;
     /* FIXME have to use palette and alpha map*/
-    memset(this->image + y * this->width + x, cmap[color], len);
-    memset(this->aimage + y * this->width + x, alpha[color], len);
+    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(this);
@@ -213,6 +223,7 @@
 	this->start_col = a >> 12;
 	this->end_col = a & 0xfff;
 	this->width = this->end_col - this->start_col + 1;
+	this->stride = (this->width + 7) & ~7; /* Kludge: draw_alpha needs width multiple of 8 */
 	this->start_row = b >> 12;
 	this->end_row = b & 0xfff;
 	this->height = this->end_row - this->start_row /* + 1 */;
@@ -235,13 +246,12 @@
 	return;
 	break;
       default:
-	printf("spudec: Error determining control type 0x%02x.\n",type);
-	return;
-	break;
+	printf("spudec: Error determining control type 0x%02x.  Skipping %d bytes.\n",
+	       type, next_off - off);
+	goto next_control;
       }
-
-      /* printf("spudec: Processsed control type 0x%02x.\n",type); */
     }
+  next_control:
   }
 }
 
@@ -296,7 +306,7 @@
     spudec_handle_t *spu = (spudec_handle_t *)this;
     if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts && spu->image)
 	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,
-		   spu->image, spu->aimage, spu->width);
+		   spu->image, spu->aimage, spu->stride);
 }
 
 void *spudec_new(dvd_priv_t *dvd_info)