changeset 31762:da0bfd02286c

Support for image highlights for dvdnav menus. Does not work 100% reliably and needs -sid 0.
author reimar
date Mon, 26 Jul 2010 19:41:04 +0000
parents 54f1eb233db9
children 550ffba86d9c
files mplayer.c spudec.c spudec.h
diffstat 3 files changed, 96 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/mplayer.c	Mon Jul 26 17:15:56 2010 +0000
+++ b/mplayer.c	Mon Jul 26 19:41:04 2010 +0000
@@ -3920,8 +3920,14 @@
  if (mpctx->stream->type == STREAMTYPE_DVDNAV) {
    nav_highlight_t hl;
    mp_dvdnav_get_highlight (mpctx->stream, &hl);
+   if (!vo_spudec || !spudec_apply_palette_crop(vo_spudec, hl.palette, hl.sx, hl.sy, hl.ex, hl.ey)) {
    osd_set_nav_box (hl.sx, hl.sy, hl.ex, hl.ey);
    vo_osd_changed (OSDTYPE_DVDNAV);
+   } else {
+     osd_set_nav_box(0, 0, 0, 0);
+     vo_osd_changed(OSDTYPE_DVDNAV);
+     vo_osd_changed(OSDTYPE_SPU);
+   }
 
    if (mp_dvdnav_stream_has_changed(mpctx->stream)) {
      double ar = -1.0;
--- a/spudec.c	Mon Jul 26 17:15:56 2010 +0000
+++ b/spudec.c	Mon Jul 26 19:41:04 2010 +0000
@@ -76,6 +76,13 @@
   packet_t *next;
 };
 
+struct palette_crop_cache {
+  int valid;
+  uint32_t palette;
+  int sx, sy, ex, ey;
+  int result;
+};
+
 typedef struct {
   packet_t *queue_head;
   packet_t *queue_tail;
@@ -98,6 +105,8 @@
   size_t image_size;		/* Size of the image buffer */
   unsigned char *image;		/* Grayscale value */
   unsigned char *aimage;	/* Alpha value */
+  unsigned int pal_start_col, pal_start_row;
+  unsigned int pal_width, pal_height;
   unsigned char *pal_image;	/* palette entry value */
   unsigned int scaled_frame_width, scaled_frame_height;
   unsigned int scaled_start_col, scaled_start_row;
@@ -111,6 +120,8 @@
   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 */
+
+  struct palette_crop_cache palette_crop_cache;
 } spudec_handle_t;
 
 static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet)
@@ -219,6 +230,7 @@
       free(this->image);
       free(this->pal_image);
       this->image_size = 0;
+      this->pal_width = this->pal_height  = 0;
     }
     this->image = malloc(2 * this->stride * this->height);
     if (this->image) {
@@ -254,44 +266,102 @@
   }
 }
 
-static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
+static int apply_palette_crop(spudec_handle_t *this,
+                              unsigned crop_x, unsigned crop_y,
+                              unsigned crop_w, unsigned crop_h)
 {
+  int i;
+  uint8_t *src;
   uint16_t pal[4];
-  unsigned int i, x, y;
-  uint8_t *dst;
-
-  this->scaled_frame_width = 0;
-  this->scaled_frame_height = 0;
-  this->start_col = packet->start_col;
-  this->start_row = packet->start_row;
-  this->height = packet->height;
-  this->width = packet->width;
-  this->stride = packet->stride;
+  unsigned stride = (crop_w + 7) & ~7;
+  if (crop_x > this->pal_width || crop_y > this->pal_height ||
+      crop_w > this->pal_width - crop_x || crop_h > this->pal_width - crop_y ||
+      crop_w > 0x8000 || crop_h > 0x8000 ||
+      stride * crop_h  > this->image_size) {
+    return 0;
+  }
   for (i = 0; i < 4; ++i) {
     int color;
-    int alpha = packet->alpha[i];
+    int alpha = this->alpha[i];
     // extend 4 -> 8 bit
     alpha |= alpha << 4;
     if (this->custom && (this->cuspal[i] >> 31) != 0)
       alpha = 0;
     color = this->custom ? this->cuspal[i] :
-            this->global_palette[packet->palette[i]];
+            this->global_palette[this->palette[i]];
     color = (color >> 16) & 0xff;
     // convert to MPlayer-style gray/alpha palette
     color = FFMIN(color, alpha);
     pal[i] = (-alpha << 8) | color;
   }
+  src = this->pal_image + crop_y * this->pal_width + crop_x;
+  pal2gray_alpha(pal, src, this->pal_width,
+                 this->image, this->aimage, stride,
+                 crop_w, crop_h);
+  this->width  = crop_w;
+  this->height = crop_h;
+  this->stride = stride;
+  this->start_col = this->pal_start_col + crop_x;
+  this->start_row = this->pal_start_row + crop_y;
+  spudec_cut_image(this);
 
-  if (!spudec_alloc_image(this, this->stride, this->height))
+  // reset scaled image
+  this->scaled_frame_width = 0;
+  this->scaled_frame_height = 0;
+  this->palette_crop_cache.valid = 0;
+  return 1;
+}
+
+int spudec_apply_palette_crop(void *this, uint32_t palette,
+                              int sx, int sy, int ex, int ey)
+{
+  spudec_handle_t *spu = this;
+  struct palette_crop_cache *c = &spu->palette_crop_cache;
+  if (c->valid && c->palette == palette &&
+      c->sx == sx && c->sy == sy && c->ex == ex && c->ey == ey)
+    return c->result;
+  spu->palette[0] = (palette >> 28) & 0xf;
+  spu->palette[1] = (palette >> 24) & 0xf;
+  spu->palette[2] = (palette >> 20) & 0xf;
+  spu->palette[3] = (palette >> 16) & 0xf;
+  spu->alpha[0]   = (palette >> 12) & 0xf;
+  spu->alpha[1]   = (palette >>  8) & 0xf;
+  spu->alpha[2]   = (palette >>  4) & 0xf;
+  spu->alpha[3]   =  palette        & 0xf;
+  spu->spu_changed = 1;
+  c->result = apply_palette_crop(spu,
+                                 sx - spu->pal_start_col, sy - spu->pal_start_row,
+                                 ex - sx, ey - sy);
+  c->palette = palette;
+  c->sx = sx; c->sy = sy;
+  c->ex = ex; c->ey = ey;
+  c->valid = 1;
+  return c->result;
+}
+
+static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
+{
+  unsigned int i, x, y;
+  uint8_t *dst;
+
+  if (!spudec_alloc_image(this, packet->stride, packet->height))
     return;
 
+  this->pal_start_col = packet->start_col;
+  this->pal_start_row = packet->start_row;
+  this->pal_height = packet->height;
+  this->pal_width  = packet->width;
+  this->stride = packet->stride;
+  memcpy(this->palette, packet->palette, sizeof(this->palette));
+  memcpy(this->alpha,   packet->alpha,   sizeof(this->alpha));
+
   i = packet->current_nibble[1];
   x = 0;
   y = 0;
   dst = this->pal_image;
   while (packet->current_nibble[0] < i
 	 && packet->current_nibble[1] / 2 < packet->control_start
-	 && y < this->height) {
+	 && y < this->pal_height) {
     unsigned int len, color;
     unsigned int rle = 0;
     rle = get_nibble(packet);
@@ -306,8 +376,8 @@
     color = 3 - (rle & 0x3);
     len = rle >> 2;
     x += len;
-    if (len == 0 || x >= this->width) {
-      len += this->width - x;
+    if (len == 0 || x >= this->pal_width) {
+      len += this->pal_width - x;
       next_line(packet);
       x = 0;
       ++y;
@@ -315,10 +385,7 @@
     memset(dst, color, len);
     dst += len;
   }
-  pal2gray_alpha(pal, this->pal_image, this->width,
-                 this->image, this->aimage, this->stride,
-                 this->width, this->height);
-  spudec_cut_image(this);
+  apply_palette_crop(this, 0, 0, this->pal_width, this->pal_height);
 }
 
 
@@ -1257,6 +1324,7 @@
     free(spu->pal_image);
     spu->pal_image = NULL;
     spu->image_size = 0;
+    spu->pal_width = spu->pal_height  = 0;
     free(spu);
   }
 }
--- a/spudec.h	Mon Jul 26 17:15:56 2010 +0000
+++ b/spudec.h	Mon Jul 26 19:41:04 2010 +0000
@@ -25,6 +25,7 @@
 void spudec_assemble(void *this, unsigned char *packet, unsigned int len, int pts100);
 void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
 void spudec_draw_scaled(void *this, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
+int spudec_apply_palette_crop(void *this, uint32_t palette, int sx, int ex, int sy, int ey);
 void spudec_update_palette(void *this, unsigned int *palette);
 void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height, uint8_t *extradata, int extradata_len);
 void *spudec_new(unsigned int *palette);