|
|
|
@ -25,6 +25,12 @@ |
|
|
|
|
|
|
|
|
|
//#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; |
|
|
|
@ -116,6 +122,7 @@ static int decode_rle(uint8_t *bitmap, int linesize, int w, int h, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void guess_palette(uint32_t *rgba_palette, |
|
|
|
|
DVDSubContext* ctx, |
|
|
|
|
uint8_t *colormap, |
|
|
|
|
uint8_t *alpha, |
|
|
|
|
uint32_t subtitle_color) |
|
|
|
@ -131,6 +138,13 @@ static void guess_palette(uint32_t *rgba_palette, |
|
|
|
|
uint8_t color_used[16]; |
|
|
|
|
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; |
|
|
|
|
|
|
|
|
@ -168,7 +182,7 @@ 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; |
|
|
|
@ -333,7 +347,7 @@ 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((uint32_t*)sub_header->rects[0]->pict.data[1], ctx, |
|
|
|
|
colormap, alpha, 0xffff00); |
|
|
|
|
} |
|
|
|
|
sub_header->rects[0]->x = x1; |
|
|
|
@ -469,12 +483,13 @@ static int dvdsub_decode(AVCodecContext *avctx, |
|
|
|
|
void *data, int *data_size, |
|
|
|
|
AVPacket *avpkt) |
|
|
|
|
{ |
|
|
|
|
DVDSubContext *ctx = (DVDSubContext*) 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: |
|
|
|
@ -497,10 +512,58 @@ static int dvdsub_decode(AVCodecContext *avctx, |
|
|
|
|
return buf_size; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int dvdsub_init(AVCodecContext *avctx) |
|
|
|
|
{ |
|
|
|
|
DVDSubContext *ctx = (DVDSubContext*) avctx->priv_data; |
|
|
|
|
char *data; |
|
|
|
|
|
|
|
|
|
if (!avctx->extradata || !avctx->extradata_size) |
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
data = av_malloc(avctx->extradata_size+1); |
|
|
|
|
if (!data) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
memcpy(data, avctx->extradata, avctx->extradata_size); |
|
|
|
|
data[avctx->extradata_size] = '\0'; |
|
|
|
|
|
|
|
|
|
for(;;) { |
|
|
|
|
int pos = strcspn(data, "\n\r"); |
|
|
|
|
if (pos==0 && *data==0) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
if (strncmp("palette:", data, 8) == 0) { |
|
|
|
|
int i; |
|
|
|
|
char *p = data+8; |
|
|
|
|
ctx->has_palette = 1; |
|
|
|
|
for(i=0;i<16;i++) { |
|
|
|
|
ctx->palette[i] = strtoul(p, &p, 16); |
|
|
|
|
while(*p == ',' || isspace(*p)) |
|
|
|
|
p++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
data += pos; |
|
|
|
|
data += strspn(data, "\n\r"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ctx->has_palette) { |
|
|
|
|
int i; |
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, "palette:"); |
|
|
|
|
for(i=0;i<16;i++) |
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, " 0x%06x", ctx->palette[i]); |
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, "\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av_free(data); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
AVCodec ff_dvdsub_decoder = { |
|
|
|
|
.name = "dvdsub", |
|
|
|
|
.type = AVMEDIA_TYPE_SUBTITLE, |
|
|
|
|
.id = CODEC_ID_DVD_SUBTITLE, |
|
|
|
|
.priv_data_size = sizeof(DVDSubContext), |
|
|
|
|
.init = dvdsub_init, |
|
|
|
|
.decode = dvdsub_decode, |
|
|
|
|
.long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), |
|
|
|
|
}; |
|
|
|
|