[vlc-commits] codec: spudec: handle palette updates (fix #23137)
Francois Cartegnie
git at videolan.org
Sat Jan 4 21:02:58 CET 2020
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Dec 19 19:31:42 2019 +0100| [7f316163a656e49ec175ce7baaa426dc46573cf0] | committer: Francois Cartegnie
codec: spudec: handle palette updates (fix #23137)
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7f316163a656e49ec175ce7baaa426dc46573cf0
---
modules/codec/spudec/parse.c | 99 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 1 deletion(-)
diff --git a/modules/codec/spudec/parse.c b/modules/codec/spudec/parse.c
index 3e04088478..ca9a5ed7bb 100644
--- a/modules/codec/spudec/parse.c
+++ b/modules/codec/spudec/parse.c
@@ -57,6 +57,9 @@ typedef struct
bool b_palette;
uint8_t pi_alpha[4];
uint8_t pi_yuv[4][3];
+ /* PXCTLI commands storage */
+ const uint8_t *p_pxctli;
+ size_t i_pxclti;
/* Auto crop fullscreen subtitles */
bool b_auto_crop;
@@ -101,6 +104,88 @@ static void CLUTIdxToYUV(const struct subs_format_t *subs,
}
}
+static void ParsePXCTLI( decoder_t *p_dec, const subpicture_data_t *p_spu_data,
+ subpicture_t *p_spu )
+{
+ plane_t *p_plane = &p_spu->p_region->p_picture->p[0];
+ video_palette_t *p_palette = p_spu->p_region->fmt.p_palette;
+
+ for( size_t i=0;i<p_spu_data->i_pxclti; i++ )
+ {
+ uint16_t i_col = GetWBE(&p_spu_data->p_pxctli[i*6 + 0]);
+ uint16_t i_color = GetWBE(&p_spu_data->p_pxctli[i*6 + 2]);
+ uint16_t i_contrast = GetWBE(&p_spu_data->p_pxctli[i*6 + 4]);
+
+ if(p_palette->i_entries +4 >= VIDEO_PALETTE_COLORS_MAX)
+ break;
+
+ if( p_dec->fmt_in.subs.spu.palette[0] == SPU_PALETTE_DEFINED )
+ {
+ /* Lookup the CLUT palette for the YUV values */
+ uint8_t idx[4];
+ uint8_t yuv[4][3];
+ uint8_t alpha[4];
+ idx[0] = (i_color >> 12)&0x0f;
+ idx[1] = (i_color >> 8)&0x0f;
+ idx[2] = (i_color >> 4)&0x0f;
+ idx[3] = i_color&0x0f;
+ CLUTIdxToYUV( &p_dec->fmt_in.subs, idx, yuv );
+
+ /* Process the contrast */
+ alpha[3] = (i_contrast >> 12)&0x0f;
+ alpha[2] = (i_contrast >> 8)&0x0f;
+ alpha[1] = (i_contrast >> 4)&0x0f;
+ alpha[0] = i_contrast&0x0f;
+
+ /* Create a new YUVA palette entries for the picture */
+ int index_map[4];
+ for( int j=0; j<4; j++ )
+ {
+ uint8_t yuvaentry[4];
+ yuvaentry[0] = yuv[j][0];
+ yuvaentry[1] = yuv[j][1];
+ yuvaentry[2] = yuv[j][2];
+ yuvaentry[3] = alpha[j] * 0x11;
+ int i_index = VIDEO_PALETTE_COLORS_MAX;
+ for( int k = p_palette->i_entries; k > 0; k-- )
+ {
+ if( !memcmp( &p_palette->palette[k], yuvaentry, sizeof(uint8_t [4]) ) )
+ {
+ i_index = VIDEO_PALETTE_COLORS_MAX;
+ break;
+ }
+ }
+
+ /* Add an entry in out palette */
+ if( i_index == VIDEO_PALETTE_COLORS_MAX )
+ {
+ if(p_palette->i_entries == VIDEO_PALETTE_COLORS_MAX)
+ {
+ msg_Warn( p_dec, "Cannot create new color, skipping PXCTLI" );
+ return;
+ }
+ i_index = p_palette->i_entries++;
+ memcpy( p_palette->palette[ i_index ], yuvaentry, sizeof(uint8_t [4]) );
+ }
+ index_map[j] = i_index;
+ }
+
+ if( p_spu->p_region->i_x >= i_col )
+ i_col -= p_spu->p_region->i_x;
+
+ for( int j=0; j<p_plane->i_visible_lines; j++ )
+ {
+ uint8_t *p_line = &p_plane->p_pixels[j * p_plane->i_pitch];
+ /* Extends to end of the line */
+ for( int k=i_col; k<p_plane->i_visible_pitch; k++ )
+ {
+ if( p_line[k] < 4 ) /* can forge write-again */
+ p_line[k] = index_map[ p_line[k] ];
+ }
+ }
+ }
+ }
+}
/*****************************************************************************
* OutputPicture:
@@ -164,6 +249,9 @@ static void OutputPicture( decoder_t *p_dec,
Render( p_dec, p_spu, p_pixeldata, &render_spu_data, p_spu_properties );
free( p_pixeldata );
+ if( p_spu_data->p_pxctli && p_spu )
+ ParsePXCTLI( p_dec, p_spu_data, p_spu );
+
pf_queue( p_dec, p_spu );
}
@@ -421,12 +509,21 @@ static int ParseControlSeq( decoder_t *p_dec, vlc_tick_t i_pts,
break;
case SPU_CMD_SET_COLCON:
- if( i_index + 3 > p_sys->i_spu_size )
+ if( i_index + 7 > p_sys->i_spu_size )
{
msg_Err( p_dec, "overflow in SPU command" );
return VLC_EGENERIC;
}
+ spu_properties.i_start = i_pts + date;
+
+ if( p_sys->i_spu_size >
+ i_index + 3 + 4 + (p_sys->buffer[i_index+5] >> 4) )
+ {
+ spu_data.p_pxctli = &p_sys->buffer[i_index+3 + 4];
+ spu_data.i_pxclti = p_sys->buffer[i_index+5] >> 4;
+ }
+
i_index += 1 + GetWBE(&p_sys->buffer[i_index+1]);
break;
More information about the vlc-commits
mailing list