diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2001-09-27 02:11:16 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2001-09-27 02:11:16 +0000 |
commit | 5bb8e3e9446a5212dcc0010d57c46e87e88598e0 (patch) | |
tree | 2d0cd3d419b5abee7386709889b91028db64c30d | |
parent | b0b0b35a2ffb59f2d4c62daee08a84fffd0e278f (diff) | |
download | xine-lib-5bb8e3e9446a5212dcc0010d57c46e87e88598e0.tar.gz xine-lib-5bb8e3e9446a5212dcc0010d57c46e87e88598e0.tar.bz2 |
discover the colors used by the subtitles
and assign a "readable" pallete to them
CVS patchset: 701
CVS date: 2001/09/27 02:11:16
-rw-r--r-- | src/libspudec/spu.c | 109 | ||||
-rw-r--r-- | src/libspudec/spu.h | 11 | ||||
-rw-r--r-- | src/libspudec/xine_decoder.c | 18 |
3 files changed, 117 insertions, 21 deletions
diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c index 4892233b5..3b52ac161 100644 --- a/src/libspudec/spu.c +++ b/src/libspudec/spu.c @@ -19,7 +19,7 @@ * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * -* $Id: spu.c,v 1.12 2001/09/18 19:01:27 jcdutton Exp $ +* $Id: spu.c,v 1.13 2001/09/27 02:11:16 miguelfreitas Exp $ * *****/ @@ -68,6 +68,7 @@ #include <fcntl.h> #include "spu.h" +#include "video_out/alphablend.h" #define LOG_DEBUG 1 @@ -180,6 +181,10 @@ void spuDoCommands(spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl) case CMD_SPU_SET_PALETTE: { /* CLUT */ spu_clut_t *clut = (spu_clut_t *) (buf+1); + state->cur_colors[3] = clut->entry0; + state->cur_colors[2] = clut->entry1; + state->cur_colors[1] = clut->entry2; + state->cur_colors[0] = clut->entry3; ovl->color[3] = state->clut[clut->entry0]; ovl->color[2] = state->clut[clut->entry1]; ovl->color[1] = state->clut[clut->entry2]; @@ -207,10 +212,10 @@ void spuDoCommands(spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl) case CMD_SPU_SET_SIZE: /* image coordinates */ state->o_left = (buf[1] << 4) | (buf[2] >> 4); state->o_right = (((buf[2] & 0x0f) << 8) | buf[3]); - + state->o_top = (buf[4] << 4) | (buf[5] >> 4); state->o_bottom = (((buf[5] & 0x0f) << 8) | buf[6]); - + LOG (LOG_DEBUG, "\ttop = %d bottom = %d left = %d right = %d", state->o_left, state->o_right, state->o_top, state->o_bottom); state->modified = 1; @@ -230,7 +235,7 @@ void spuDoCommands(spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl) state->menu = 1; buf++; break; - + default: fprintf(stderr, "libspudec: unknown seqence command (%02x)\n", buf[0]); buf++; @@ -271,7 +276,7 @@ static u_int get_bits (u_int bits) } } - return ret; + return ret; } static int spu_next_line (vo_overlay_t *spu) @@ -326,7 +331,7 @@ void spuDrawPicture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl) while (bit_ptr[1] < seq->buf + seq->cmd_offs) { u_int len; u_int vlc; - + vlc = get_bits (4); if (vlc < 0x0004) { vlc = (vlc << 4) | get_bits (4); @@ -337,27 +342,109 @@ void spuDrawPicture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl) } } } - + len = vlc >> 2; - + /* if len == 0 -> end sequence - fill to end of line */ if (len == 0) len = ovl->width - put_x; - + rle->len = len; rle->color = vlc & 0x03; rle++; put_x += len; - + if (put_x >= ovl->width) { if (spu_next_line (ovl) < 0) break; } } - + ovl->num_rle = rle - ovl->rle; } +/* Heuristic to discover the colors used by the subtitles + and assign a "readable" pallete to them. + Currently looks for sequence of border-fg-border or + border1-border2-fg-border2-border1. + MINFOUND is the number of ocurrences threshold. +*/ +#define MINFOUND 25 +void spuDiscoverClut(spu_state_t *state, vo_overlay_t *ovl) +{ + int bg,c; + int seqcolor[10]; + int n,i; + rle_elem_t *rle; + + int found[2][16]; + + static clut_t text_clut[] = { + CLUT_Y_CR_CB_INIT(0x80, 0x90, 0x80), + CLUT_Y_CR_CB_INIT(0x00, 0x90, 0x00), + CLUT_Y_CR_CB_INIT(0xff, 0x90, 0x00) + }; + + memset(found,0,sizeof(found)); + rle = ovl->rle; + + /* suppose the first and last pixels are bg */ + if( rle[0].color != rle[ovl->num_rle-1].color ) + return; + + bg = rle[0].color; + + i = 0; + for( n = 0; n < ovl->num_rle; n++ ) + { + c = rle[n].color; + + if( c == bg ) + { + if( i == 3 && seqcolor[1] == seqcolor[3] ) + { + found[0][seqcolor[2]]++; + if( found[0][seqcolor[2]] > MINFOUND ) + { + memcpy(&state->clut[state->cur_colors[seqcolor[1]]], &text_clut[1], + sizeof(clut_t)); + memcpy(&state->clut[state->cur_colors[seqcolor[2]]], &text_clut[2], + sizeof(clut_t)); + ovl->color[seqcolor[1]] = state->clut[state->cur_colors[seqcolor[1]]]; + ovl->color[seqcolor[2]] = state->clut[state->cur_colors[seqcolor[2]]]; + state->need_clut = 0; + } + } + if( i == 5 && seqcolor[1] == seqcolor[5] + && seqcolor[2] == seqcolor[4] ) + { + found[1][seqcolor[3]]++; + if( found[1][seqcolor[3]] > MINFOUND ) + { + memcpy(&state->clut[state->cur_colors[seqcolor[1]]], &text_clut[0], + sizeof(clut_t)); + memcpy(&state->clut[state->cur_colors[seqcolor[2]]], &text_clut[1], + sizeof(clut_t)); + memcpy(&state->clut[state->cur_colors[seqcolor[3]]], &text_clut[2], + sizeof(clut_t)); + ovl->color[seqcolor[1]] = state->clut[state->cur_colors[seqcolor[1]]]; + ovl->color[seqcolor[2]] = state->clut[state->cur_colors[seqcolor[2]]]; + ovl->color[seqcolor[3]] = state->clut[state->cur_colors[seqcolor[3]]]; + state->need_clut = 0; + } + } + i = 0; + seqcolor[i] = c; + } + else if ( i < 6 ) + { + i++; + seqcolor[i] = c; + } + } +} + + void spuUpdateMenu (spu_state_t *state, vo_overlay_t *ovl) { if (!state->menu) diff --git a/src/libspudec/spu.h b/src/libspudec/spu.h index 42de3a9ea..95145d1b3 100644 --- a/src/libspudec/spu.h +++ b/src/libspudec/spu.h @@ -19,7 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: spu.h,v 1.4 2001/08/16 12:33:00 ehasenle Exp $ + * $Id: spu.h,v 1.5 2001/09/27 02:11:16 miguelfreitas Exp $ * * This file was originally part of the OMS program. * @@ -35,6 +35,12 @@ #include <inttypes.h> #include "video_out.h" +#ifdef __GNUC__ +#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) {y: (_y), cr: (_cr), cb: (_cb)} +#else +#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) { (_cb), (_cr), (_y) } +#endif + typedef struct spu_clut_struct { #ifdef WORDS_BIGENDIAN uint8_t entry0 : 4; @@ -75,6 +81,8 @@ typedef struct { int visible; /* Must the sub-picture be shown? */ int menu; /* This overlay is a menu */ int b_show; /* is a button shown? */ + int need_clut; /* doesn't have the right clut yet */ + int cur_colors[4];/* current 4 colors been used */ uint32_t clut[16]; } spu_state_t; @@ -83,6 +91,7 @@ int spuReassembly (spu_seq_t *seq, int start, uint8_t *pkt_data, u_int pkt_len); int spuNextEvent (spu_state_t *state, spu_seq_t* seq, int pts); void spuDoCommands (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl); void spuDrawPicture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl); +void spuDiscoverClut (spu_state_t *state, vo_overlay_t *ovl); void spuUpdateMenu (spu_state_t *state, vo_overlay_t *ovl); #endif diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c index e5f6f9232..bdd19d9fe 100644 --- a/src/libspudec/xine_decoder.c +++ b/src/libspudec/xine_decoder.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000-2001 the xine project * * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 @@ -19,7 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine_decoder.c,v 1.12 2001/09/06 18:38:12 jkeil Exp $ + * $Id: xine_decoder.c,v 1.13 2001/09/27 02:11:16 miguelfreitas Exp $ * * stuff needed to turn libspu into a xine decoder plugin */ @@ -43,12 +43,6 @@ #include "video_out/alphablend.h" #include "xine-engine/bswap.h" -#ifdef __GNUC__ -#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) {y: (_y), cr: (_cr), cb: (_cb)} -#else -#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) { (_cb), (_cr), (_y) } -#endif - static clut_t __default_clut[] = { CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), CLUT_Y_CR_CB_INIT(0xbf, 0x80, 0x80), @@ -123,6 +117,7 @@ void spudec_init (spu_decoder_t *this_gen, vo_instance_t *vo_out) { spudec_reset(this); memcpy(this->state.clut, __default_clut, sizeof(this->state.clut)); + this->state.need_clut = 1; vo_out->register_ovl_src(vo_out, &this->ovl_src); } @@ -139,6 +134,7 @@ void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { for (i = 0; i < 16; i++) this->state.clut[i] = bswap_32(clut[i]); } + this->state.need_clut = 0; return; } @@ -218,6 +214,9 @@ static vo_overlay_t* spudec_get_overlay(ovl_src_t *ovl_src, int pts) { spuDrawPicture(&this->state, this->cur_seq, &this->ovl); } + if (this->state.need_clut) + spuDiscoverClut(&this->state, &this->ovl); + return &this->ovl; } @@ -232,7 +231,7 @@ static void spudec_event(spu_decoder_t *this_gen, spu_event_t *event) { { spu_button_t *but = event->data; if (!this->state.menu) return; - + if (but->show) { int i; for (i = 0; i < 4; i++) { @@ -254,6 +253,7 @@ static void spudec_event(spu_decoder_t *this_gen, spu_event_t *event) { { spu_cltbl_t *clut = event->data; memcpy(this->state.clut, clut->clut, sizeof(int32_t)*16); + this->state.need_clut = 0; } break; } |