summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2001-09-27 02:11:16 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2001-09-27 02:11:16 +0000
commit5bb8e3e9446a5212dcc0010d57c46e87e88598e0 (patch)
tree2d0cd3d419b5abee7386709889b91028db64c30d
parentb0b0b35a2ffb59f2d4c62daee08a84fffd0e278f (diff)
downloadxine-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.c109
-rw-r--r--src/libspudec/spu.h11
-rw-r--r--src/libspudec/xine_decoder.c18
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;
}