diff --git a/doc/decoders.texi b/doc/decoders.texi index ae20cea9d3..2c920e7d05 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -191,6 +191,10 @@ numbers (without 0x prefix) separated by comas, for example @code{0d00ee, ee450d, 101010, eaeaea, 0ce60b, ec14ed, ebff0b, 0d617a, 7b7b7b, d1d1d1, 7b2a0e, 0d950c, 0f007b, cf0dec, cfa80c, 7c127b}. +@item ifo_palette +Specify the the IFO file from which the global palette is obtained. +(experimental) + @item forced_subs_only Only decode subtitle entries marked as forced. Some titles have forced and non-forced subtitles in the same track. Setting this flag to @code{1} diff --git a/libavcodec/dvdsubdec.c b/libavcodec/dvdsubdec.c index bb28d9e3b7..d165934cc3 100644 --- a/libavcodec/dvdsubdec.c +++ b/libavcodec/dvdsubdec.c @@ -28,12 +28,14 @@ #include "libavutil/opt.h" #include "libavutil/imgutils.h" #include "libavutil/avstring.h" +#include "libavutil/bswap.h" typedef struct DVDSubContext { AVClass *class; uint32_t palette[16]; char *palette_str; + char *ifo_str; int has_palette; uint8_t colormap[4]; uint8_t alpha[256]; @@ -583,6 +585,57 @@ static void parse_palette(DVDSubContext *ctx, char *p) } } +static int parse_ifo_palette(DVDSubContext *ctx, char *p) +{ + FILE *ifo; + char ifostr[12]; + uint32_t sp_pgci, pgci, off_pgc, pgc; + uint8_t r, g, b, yuv[65], *buf; + int i, y, cb, cr, r_add, g_add, b_add; + int ret = 0; + const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; + + ctx->has_palette = 0; + if ((ifo = fopen(p, "r")) == NULL) { + av_log(ctx, AV_LOG_WARNING, "Unable to open IFO file \"%s\": %s\n", p, strerror(errno)); + return AVERROR_EOF; + } + if (fread(ifostr, 12, 1, ifo) != 1 || memcmp(ifostr, "DVDVIDEO-VTS", 12)) { + av_log(ctx, AV_LOG_WARNING, "\"%s\" is not a proper IFO file\n", p); + ret = AVERROR_INVALIDDATA; + goto end; + } + fseek(ifo, 0xCC, SEEK_SET); + if (fread(&sp_pgci, 4, 1, ifo) == 1) { + pgci = av_be2ne32(sp_pgci) * 2048; + fseek(ifo, pgci + 0x0C, SEEK_SET); + if (fread(&off_pgc, 4, 1, ifo) == 1) { + pgc = pgci + av_be2ne32(off_pgc); + fseek(ifo, pgc + 0xA4, SEEK_SET); + if (fread(yuv, 64, 1, ifo) == 1) { + buf = yuv; + for(i=0; i<16; i++) { + y = *++buf; + cr = *++buf; + cb = *++buf; + YUV_TO_RGB1_CCIR(cb, cr); + YUV_TO_RGB2_CCIR(r, g, b, y); + ctx->palette[i] = (r << 16) + (g << 8) + b; + buf++; + } + ctx->has_palette = 1; + } + } + } + if (ctx->has_palette == 0) { + av_log(ctx, AV_LOG_WARNING, "Failed to read palette from IFO file \"%s\"\n", p); + ret = AVERROR_INVALIDDATA; + } +end: + fclose(ifo); + return ret; +} + static int dvdsub_parse_extradata(AVCodecContext *avctx) { DVDSubContext *ctx = (DVDSubContext*) avctx->priv_data; @@ -631,6 +684,8 @@ static av_cold int dvdsub_init(AVCodecContext *avctx) if ((ret = dvdsub_parse_extradata(avctx)) < 0) return ret; + if (ctx->ifo_str) + parse_ifo_palette(ctx, ctx->ifo_str); if (ctx->palette_str) parse_palette(ctx, ctx->palette_str); if (ctx->has_palette) { @@ -656,6 +711,7 @@ static av_cold int dvdsub_close(AVCodecContext *avctx) #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { { "palette", "set the global palette", OFFSET(palette_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD }, + { "ifo_palette", "obtain the global palette from .IFO file", OFFSET(ifo_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD }, { "forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, SD}, { NULL } }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 5d2c9a2ad3..ce4af6cc89 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #define LIBAVCODEC_VERSION_MAJOR 56 #define LIBAVCODEC_VERSION_MINOR 12 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \