@ -25,6 +25,11 @@
//#define DEBUG
typedef struct DVDSubContext {
uint32_t palette [ 16 ] ;
int has_palette ;
} DVDSubContext ;
static void yuv_a_to_rgba ( const uint8_t * ycbcr , const uint8_t * alpha , uint32_t * rgba , int num_values )
{
uint8_t * cm = ff_cropTbl + MAX_NEG_CROP ;
@ -115,7 +120,8 @@ static int decode_rle(uint8_t *bitmap, int linesize, int w, int h,
return 0 ;
}
static void guess_palette ( uint32_t * rgba_palette ,
static void guess_palette ( DVDSubContext * ctx ,
uint32_t * rgba_palette ,
uint8_t * colormap ,
uint8_t * alpha ,
uint32_t subtitle_color )
@ -123,6 +129,13 @@ static void guess_palette(uint32_t *rgba_palette,
uint8_t color_used [ 16 ] = { 0 } ;
int nb_opaque_colors , i , level , j , r , g , b ;
if ( ctx - > has_palette ) {
for ( i = 0 ; i < 4 ; i + + )
rgba_palette [ i ] = ( ctx - > palette [ colormap [ i ] ] & 0x00ffffff )
| ( ( alpha [ i ] * 17 ) < < 24 ) ;
return ;
}
for ( i = 0 ; i < 4 ; i + + )
rgba_palette [ i ] = 0 ;
@ -159,13 +172,13 @@ static void guess_palette(uint32_t *rgba_palette,
# define READ_OFFSET(a) (big_offsets ? AV_RB32(a) : AV_RB16(a))
static int decode_dvd_subtitles ( AVSubtitle * sub_header ,
static int decode_dvd_subtitles ( DVDSubContext * ctx , AVSubtitle * sub_header ,
const uint8_t * buf , int buf_size )
{
int cmd_pos , pos , cmd , x1 , y1 , x2 , y2 , offset1 , offset2 , next_cmd_pos ;
int big_offsets , offset_size , is_8bit = 0 ;
const uint8_t * yuv_palette = 0 ;
uint8_t colormap [ 4 ] , alpha [ 256 ] ;
uint8_t colormap [ 4 ] = { 0 } , alpha [ 256 ] = { 0 } ;
int date ;
int i ;
int is_menu = 0 ;
@ -325,7 +338,8 @@ static int decode_dvd_subtitles(AVSubtitle *sub_header,
yuv_a_to_rgba ( yuv_palette , alpha , ( uint32_t * ) sub_header - > rects [ 0 ] - > pict . data [ 1 ] , 256 ) ;
} else {
sub_header - > rects [ 0 ] - > nb_colors = 4 ;
guess_palette ( ( uint32_t * ) sub_header - > rects [ 0 ] - > pict . data [ 1 ] ,
guess_palette ( ctx ,
( uint32_t * ) sub_header - > rects [ 0 ] - > pict . data [ 1 ] ,
colormap , alpha , 0xffff00 ) ;
}
sub_header - > rects [ 0 ] - > x = x1 ;
@ -456,12 +470,13 @@ static int dvdsub_decode(AVCodecContext *avctx,
void * data , int * data_size ,
AVPacket * avpkt )
{
DVDSubContext * ctx = avctx - > priv_data ;
const uint8_t * buf = avpkt - > data ;
int buf_size = avpkt - > size ;
AVSubtitle * sub = data ;
int is_menu ;
is_menu = decode_dvd_subtitles ( sub , buf , buf_size ) ;
is_menu = decode_dvd_subtitles ( ctx , sub , buf , buf_size ) ;
if ( is_menu < 0 ) {
no_subtitle :
@ -484,10 +499,45 @@ static int dvdsub_decode(AVCodecContext *avctx,
return buf_size ;
}
static int dvdsub_init ( AVCodecContext * avctx )
{
DVDSubContext * ctx = avctx - > priv_data ;
char * data , * cur ;
if ( ! avctx - > extradata | | ! avctx - > extradata_size )
return 0 ;
data = av_malloc ( avctx - > extradata_size + 1 ) ;
if ( ! data )
return AVERROR ( ENOMEM ) ;
memcpy ( data , avctx - > extradata , avctx - > extradata_size ) ;
data [ avctx - > extradata_size ] = ' \0 ' ;
cur = data ;
while ( * cur ) {
if ( strncmp ( " palette: " , cur , 8 ) = = 0 ) {
int i ;
char * p = cur + 8 ;
ctx - > has_palette = 1 ;
for ( i = 0 ; i < 16 ; i + + ) {
ctx - > palette [ i ] = strtoul ( p , & p , 16 ) ;
while ( * p = = ' , ' | | isspace ( * p ) )
p + + ;
}
}
cur + = strcspn ( cur , " \n \r " ) ;
cur + = strspn ( cur , " \n \r " ) ;
}
av_free ( data ) ;
return 0 ;
}
AVCodec ff_dvdsub_decoder = {
. name = " dvdsub " ,
. type = AVMEDIA_TYPE_SUBTITLE ,
. id = AV_CODEC_ID_DVD_SUBTITLE ,
. priv_data_size = sizeof ( DVDSubContext ) ,
. init = dvdsub_init ,
. decode = dvdsub_decode ,
. long_name = NULL_IF_CONFIG_SMALL ( " DVD subtitles " ) ,
} ;