diff options
author | reimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2010-07-26 19:41:04 +0000 |
---|---|---|
committer | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2010-11-02 04:14:46 +0200 |
commit | 269d3df12cb1db7a8a75585db7fb5bd814f8a554 (patch) | |
tree | d20cd12dd7982e06dc15bcb94996b68c4406101b /spudec.c | |
parent | 1ee113088f7093e6e7d2b27a29270de1ef35f799 (diff) | |
download | mpv-269d3df12cb1db7a8a75585db7fb5bd814f8a554.tar.bz2 mpv-269d3df12cb1db7a8a75585db7fb5bd814f8a554.tar.xz |
dvdnav: Support for image highlights for dvdnav menus.
Does not work 100% reliably and needs -sid 0.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@31828 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'spudec.c')
-rw-r--r-- | spudec.c | 110 |
1 files changed, 89 insertions, 21 deletions
@@ -76,6 +76,13 @@ struct packet_t { 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 @@ typedef struct { 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 @@ typedef struct { 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 @@ static int spudec_alloc_image(spudec_handle_t *this, int stride, int height) 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 pal2gray_alpha(const uint16_t *pal, } } -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 @@ static void spudec_process_data(spudec_handle_t *this, packet_t *packet) 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 @@ static void spudec_process_data(spudec_handle_t *this, packet_t *packet) 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 @@ void spudec_free(void *this) free(spu->pal_image); spu->pal_image = NULL; spu->image_size = 0; + spu->pal_width = spu->pal_height = 0; free(spu); } } |