summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-10-04 17:16:47 +0200
committerwm4 <wm4@nowhere>2012-10-16 07:26:32 +0200
commit3ad918bbc62449759bbf97f6a809ebdde27ad59e (patch)
tree24c3668687c5ebff37d6d1aaa0354d01310a0d8d /sub
parentcc05910f16a5ccd8e3dca26a89e9c3835cbdb645 (diff)
downloadmpv-3ad918bbc62449759bbf97f6a809ebdde27ad59e.tar.bz2
mpv-3ad918bbc62449759bbf97f6a809ebdde27ad59e.tar.xz
sub: never decode subs to old OSD format
Instead, sd_lavc.c and spudec.c (the two image sub decoders) always output indexed/paletted images. For this purpose, add SUBBITMAP_INDEXED, and convert the subs to RGBA in img_convert.c instead. If a VO is used that supports the old OSD format only, the indexed bitmaps are converted to the old OSD format by abusing spudec.c in a similar way sd_lavc.c used to do. The main reason why spudec.c is used is because the images must not only be converted to the old format, but also properly scaled, cropped, and aligned (the asm code in libvo/osd.c requires this alignment). Remove support for the old format (packed variant) from the OpenGL VOs. (The packed formats were how the actual OSD format was handled in some GPU-driven VOs for a while.) Remove all conversions from old to new formats. Now all subtitle decoders and OSD renderers produce the new formats only. Add an evil hack to convert the new format (scaled+indexed bitmaps) to the old format. It creates a new spudec instance to convert images to grayscale and to scale them. This is temporary for VOs which don't support new OSD formats yet (vo_xv, vo_x11, vo_lavc).
Diffstat (limited to 'sub')
-rw-r--r--sub/dec_sub.c3
-rw-r--r--sub/dec_sub.h2
-rw-r--r--sub/img_convert.c148
-rw-r--r--sub/img_convert.h5
-rw-r--r--sub/sd_lavc.c90
-rw-r--r--sub/spudec.c53
-rw-r--r--sub/spudec.h3
-rw-r--r--sub/sub.c32
-rw-r--r--sub/sub.h24
9 files changed, 191 insertions, 169 deletions
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index 87cb9870cb..09d9989494 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -63,9 +63,6 @@ void sub_get_bitmaps(struct osd_state *osd, struct sub_render_params *params,
{
struct MPOpts *opts = osd->opts;
- // temporary hack
- osd->support_rgba = params->support_rgba;
-
*res = (struct sub_bitmaps) {0};
if (!opts->sub_visibility || !osd->sh_sub || !osd->sh_sub->active) {
/* Change ID in case we just switched from visible subtitles
diff --git a/sub/dec_sub.h b/sub/dec_sub.h
index 9cfe8d964c..0c5c1ab7ee 100644
--- a/sub/dec_sub.h
+++ b/sub/dec_sub.h
@@ -15,8 +15,6 @@ struct sub_render_params {
struct mp_eosd_res dim;
double normal_scale;
double vsfilter_scale;
-
- bool support_rgba;
};
static inline bool is_text_sub(int type)
diff --git a/sub/img_convert.c b/sub/img_convert.c
index 6eef4a01a3..b8a769f052 100644
--- a/sub/img_convert.c
+++ b/sub/img_convert.c
@@ -25,14 +25,16 @@
#include "img_convert.h"
#include "sub.h"
+#include "spudec.h"
struct osd_conv_cache {
struct sub_bitmap part;
+ struct sub_bitmap *parts;
// for osd_conv_cache_alloc_old_p() (SUBBITMAP_PLANAR)
int allocated, stride;
struct old_osd_planar bmp;
- // for osd_conv_cache_alloc_bmp() (various other formats)
- unsigned char *packed;
+ // for osd_conv_idx_to_old_p(), a spudec.c handle
+ void *spudec;
};
static int osd_conv_cache_destroy(void *p)
@@ -40,6 +42,8 @@ static int osd_conv_cache_destroy(void *p)
struct osd_conv_cache *c = p;
av_free(c->bmp.bitmap);
av_free(c->bmp.alpha);
+ if (c->spudec)
+ spudec_free(c->spudec);
return 0;
}
@@ -73,21 +77,6 @@ static void osd_conv_cache_alloc_old_p(struct osd_conv_cache *c, int w, int h)
};
}
-static void osd_conv_cache_alloc_bmp(struct osd_conv_cache *c, int w, int h,
- int bpp)
-{
- size_t size = talloc_get_size(c->packed);
- size_t new_size = w * bpp * h;
- if (new_size > size)
- c->packed = talloc_realloc(c, c->packed, unsigned char, new_size);
- c->part = (struct sub_bitmap) {
- .bitmap = c->packed,
- .stride = w * bpp,
- .w = w, .h = h,
- .dw = w, .dh = h,
- };
-}
-
static void draw_alpha_ass_to_old(unsigned char *src, int src_w, int src_h,
int src_stride, unsigned char *dst_a,
unsigned char *dst_i, size_t dst_stride,
@@ -177,80 +166,99 @@ bool osd_conv_ass_to_old_p(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
return true;
}
-// SUBBITMAP_OLD_PLANAR -> SUBBITMAP_RGBA
-bool osd_conv_old_p_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
{
struct sub_bitmaps src = *imgs;
- if (src.format != SUBBITMAP_OLD_PLANAR || src.num_parts > 1)
+ if (src.format != SUBBITMAP_INDEXED)
return false;
imgs->format = SUBBITMAP_RGBA;
- imgs->num_parts = 0;
- imgs->parts = NULL;
-
- if (src.num_parts == 0)
- return true;
-
- struct sub_bitmap *s = &src.parts[0];
- struct old_osd_planar *p = s->bitmap;
-
- osd_conv_cache_alloc_bmp(c, s->w, s->h, 4);
-
- for (int y = 0; y < s->h; y++) {
- unsigned char *y_src = p->bitmap + s->stride * y;
- unsigned char *y_srca = p->alpha + s->stride * y;
- unsigned char *cur = c->packed + y * s->w * 4;
- for (int x = 0; x < s->w; x++) {
- // This is incorrect, as input is premultiplied alpha, but output
- // has to be non-premultiplied. However, this code is for
- // compatibility with spudec.c only, and DVD subtitles have
- // binary transparency only - the rendered result will be the same.
- cur[x*4+0] = cur[x*4+1] = cur[x*4+2] = y_src[x];
- cur[x*4+3] = -y_srca[x];
+ talloc_free(c->parts);
+ imgs->parts = c->parts = talloc_array(c, struct sub_bitmap, src.num_parts);
+
+ for (int n = 0; n < src.num_parts; n++) {
+ struct sub_bitmap *d = &imgs->parts[n];
+ struct sub_bitmap *s = &src.parts[n];
+ struct osd_bmp_indexed *sb = s->bitmap;
+
+ *d = *s;
+ d->stride = s->w * 4;
+ d->bitmap = talloc_size(c->parts, s->h * d->stride);
+
+ uint32_t *palette = sb->palette;
+ uint32_t *outbmp = d->bitmap;
+ for (int y = 0; y < s->h; y++) {
+ uint8_t *inbmp = sb->bitmap + y * s->stride;
+ for (int x = 0; x < s->w; x++)
+ *outbmp++ = palette[*inbmp++];
}
}
-
- c->part.x = s->x;
- c->part.y = s->y;
-
- imgs->parts = &c->part;
- imgs->num_parts = 1;
return true;
}
-// SUBBITMAP_OLD_PLANAR -> SUBBITMAP_OLD
-bool osd_conv_old_p_to_old(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
+bool osd_conv_idx_to_old_p(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
+ int screen_w, int screen_h)
{
struct sub_bitmaps src = *imgs;
- if (src.format != SUBBITMAP_OLD_PLANAR || src.num_parts > 1)
+ if (src.format != SUBBITMAP_INDEXED)
return false;
- imgs->format = SUBBITMAP_OLD;
+ imgs->format = SUBBITMAP_OLD_PLANAR;
imgs->num_parts = 0;
imgs->parts = NULL;
-
if (src.num_parts == 0)
return true;
- struct sub_bitmap *s = &src.parts[0];
- struct old_osd_planar *p = s->bitmap;
-
- osd_conv_cache_alloc_bmp(c, s->w, s->h, 2);
-
- for (int y = 0; y < s->h; y++) {
- unsigned char *y_src = p->bitmap + s->stride * y;
- unsigned char *y_srca = p->alpha + s->stride * y;
- unsigned char *cur = c->packed + y * s->w * 2;
- for (int x = 0; x < s->w; x++) {
- cur[x*2+0] = y_src[x];
- cur[x*2+1] = -y_srca[x];
- }
+ // assume they are all evenly scaled (and size 0 is not possible)
+ // could put more effort into it to reduce rounding errors, but it doesn't
+ // make much sense anyway
+ struct sub_bitmap *s0 = &src.parts[0];
+ double scale_x = (double)s0->w / s0->dw;
+ double scale_y = (double)s0->h / s0->dh;
+ double scale = FFMIN(scale_x, scale_y);
+
+ int xmin, ymin, xmax, ymax;
+
+ xmin = ymin = INT_MAX;
+ xmax = ymax = INT_MIN;
+ for (int n = 0; n < src.num_parts; n++) {
+ struct sub_bitmap *s = &src.parts[n];
+ int sx = s->x * scale;
+ int sy = s->y * scale;
+ xmin = FFMIN(xmin, sx);
+ ymin = FFMIN(ymin, sy);
+ xmax = FFMAX(xmax, sx + s->w);
+ ymax = FFMAX(ymax, sy + s->h);
}
- c->part.x = s->x;
- c->part.y = s->y;
+ int w = xmax - xmin;
+ int h = ymax - ymin;
- imgs->parts = &c->part;
- imgs->num_parts = 1;
+ struct spu_packet_t *packet = spudec_packet_create(xmin, ymin, w, h);
+ if (!packet)
+ return false;
+ spudec_packet_clear(packet);
+ for (int n = 0; n < src.num_parts; n++) {
+ struct sub_bitmap *s = &src.parts[n];
+ struct osd_bmp_indexed *sb = s->bitmap;
+ int sx = s->x * scale;
+ int sy = s->y * scale;
+ assert(sx >= xmin);
+ assert(sy >= ymin);
+ assert(sx - xmin + s->w <= w);
+ assert(sy - ymin + s->h <= h);
+ // assumes sub-images are not overlapping
+ spudec_packet_fill(packet, sb->bitmap, s->stride, sb->palette,
+ sx - xmin, sy - ymin, s->w, s->h);
+ }
+ if (!c->spudec)
+ c->spudec = spudec_new_scaled(NULL, 0, 0, NULL, 0);
+ spudec_packet_send(c->spudec, packet, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
+ spudec_set_res(c->spudec, screen_w * scale, screen_h * scale);
+ spudec_heartbeat(c->spudec, 0);
+ spudec_get_bitmap(c->spudec, screen_w, screen_h, imgs);
+ imgs->render_index = src.render_index;
+ imgs->bitmap_id = src.bitmap_id;
+ imgs->bitmap_pos_id = src.bitmap_pos_id;
return true;
}
diff --git a/sub/img_convert.h b/sub/img_convert.h
index b4201f606c..ac766fb0ed 100644
--- a/sub/img_convert.h
+++ b/sub/img_convert.h
@@ -10,8 +10,9 @@ struct osd_conv_cache *osd_conv_cache_new(void);
// These functions convert from one OSD format to another. On success, they copy
// the converted image data into c, and change imgs to point to the data.
-bool osd_conv_old_p_to_old(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
-bool osd_conv_old_p_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
bool osd_conv_ass_to_old_p(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
+bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
+bool osd_conv_idx_to_old_p(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
+ int screen_w, int screen_h);
#endif
diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c
index a10ac5e18e..a5fe23721a 100644
--- a/sub/sd_lavc.c
+++ b/sub/sd_lavc.c
@@ -16,6 +16,7 @@
*/
#include <stdlib.h>
+#include <assert.h>
#include <libavcodec/avcodec.h>
@@ -23,61 +24,21 @@
#include "mp_msg.h"
#include "libmpdemux/stheader.h"
#include "sd.h"
-#include "spudec.h"
-// Current code still pushes subs directly to global spudec
#include "dec_sub.h"
#include "sub.h"
struct sd_lavc_priv {
AVCodecContext *avctx;
+ AVSubtitle sub;
+ bool have_sub;
int count;
struct sub_bitmap *inbitmaps;
struct sub_bitmap *outbitmaps;
+ struct osd_bmp_indexed *imgs;
bool bitmaps_changed;
double endpts;
};
-static void old_avsub_to_spudec(AVSubtitleRect **rects, int num_rects,
- double pts, double endpts)
-{
- int i, xmin = INT_MAX, ymin = INT_MAX, xmax = INT_MIN, ymax = INT_MIN;
- struct spu_packet_t *packet;
-
- if (num_rects == 1) {
- spudec_set_paletted(vo_spudec,
- rects[0]->pict.data[0],
- rects[0]->pict.linesize[0],
- rects[0]->pict.data[1],
- rects[0]->x,
- rects[0]->y,
- rects[0]->w,
- rects[0]->h,
- pts,
- endpts);
- return;
- }
- for (i = 0; i < num_rects; i++) {
- xmin = FFMIN(xmin, rects[i]->x);
- ymin = FFMIN(ymin, rects[i]->y);
- xmax = FFMAX(xmax, rects[i]->x + rects[i]->w);
- ymax = FFMAX(ymax, rects[i]->y + rects[i]->h);
- }
- packet = spudec_packet_create(xmin, ymin, xmax - xmin, ymax - ymin);
- if (!packet)
- return;
- spudec_packet_clear(packet);
- for (i = 0; i < num_rects; i++)
- spudec_packet_fill(packet,
- rects[i]->pict.data[0],
- rects[i]->pict.linesize[0],
- rects[i]->pict.data[1],
- rects[i]->x - xmin,
- rects[i]->y - ymin,
- rects[i]->w,
- rects[i]->h);
- spudec_packet_send(vo_spudec, packet, pts, endpts);
-}
-
static void guess_resolution(char type, int *w, int *h)
{
if (type == 'v') {
@@ -143,8 +104,13 @@ static void clear(struct sd_lavc_priv *priv)
talloc_free(priv->inbitmaps);
talloc_free(priv->outbitmaps);
priv->inbitmaps = priv->outbitmaps = NULL;
+ talloc_free(priv->imgs);
+ priv->imgs = NULL;
priv->bitmaps_changed = true;
priv->endpts = MP_NOPTS_VALUE;
+ if (priv->have_sub)
+ avsubtitle_free(&priv->sub);
+ priv->have_sub = false;
}
static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
@@ -166,6 +132,8 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
int res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt);
if (res < 0 || !got_sub)
return;
+ priv->sub = sub;
+ priv->have_sub = true;
if (pts != MP_NOPTS_VALUE) {
if (sub.end_display_time > sub.start_display_time)
duration = (sub.end_display_time - sub.start_display_time) / 1000.0;
@@ -174,39 +142,27 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
double endpts = MP_NOPTS_VALUE;
if (pts != MP_NOPTS_VALUE && duration >= 0)
endpts = pts + duration;
- if (vo_spudec && sub.num_rects == 0)
- spudec_set_paletted(vo_spudec, NULL, 0, NULL, 0, 0, 0, 0, pts, endpts);
if (sub.num_rects > 0) {
switch (sub.rects[0]->type) {
case SUBTITLE_BITMAP:
- if (!osd->support_rgba) {
- if (!vo_spudec)
- vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height,
- NULL, 0);
- old_avsub_to_spudec(sub.rects, sub.num_rects, pts, endpts);
- vo_osd_changed(OSDTYPE_SPU);
- break;
- }
priv->inbitmaps = talloc_array(priv, struct sub_bitmap,
sub.num_rects);
+ priv->imgs = talloc_array(priv, struct osd_bmp_indexed,
+ sub.num_rects);
for (int i = 0; i < sub.num_rects; i++) {
struct AVSubtitleRect *r = sub.rects[i];
struct sub_bitmap *b = &priv->inbitmaps[i];
- uint32_t *outbmp = talloc_size(priv->inbitmaps,
- r->w * r->h * 4);
- b->bitmap = outbmp;
- b->stride = r->w * 4;
+ struct osd_bmp_indexed *img = &priv->imgs[i];
+ img->bitmap = r->pict.data[0];
+ assert(r->nb_colors > 0);
+ assert(r->nb_colors * 4 <= sizeof(img->palette));
+ memcpy(img->palette, r->pict.data[1], r->nb_colors * 4);
+ b->bitmap = img;
+ b->stride = r->pict.linesize[0];
b->w = r->w;
b->h = r->h;
b->x = r->x;
b->y = r->y;
- uint8_t *inbmp = r->pict.data[0];
- uint32_t *palette = (uint32_t *) r->pict.data[1];
- for (int y = 0; y < r->h; y++) {
- for (int x = 0; x < r->w; x++)
- *outbmp++ = palette[*inbmp++];
- inbmp += r->pict.linesize[0] - r->w;
- };
}
priv->count = sub.num_rects;
priv->endpts = endpts;
@@ -217,7 +173,6 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
break;
}
}
- avsubtitle_free(&sub);
}
static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
@@ -229,8 +184,6 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
if (priv->endpts != MP_NOPTS_VALUE && (params->pts >= priv->endpts ||
params->pts < priv->endpts - 300))
clear(priv);
- if (!params->support_rgba)
- return;
if (priv->bitmaps_changed && priv->count > 0)
priv->outbitmaps = talloc_memdup(priv, priv->inbitmaps,
talloc_get_size(priv->inbitmaps));
@@ -257,7 +210,7 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
else if (pos_changed)
res->bitmap_pos_id++;
priv->bitmaps_changed = false;
- res->format = SUBBITMAP_RGBA;
+ res->format = SUBBITMAP_INDEXED;
res->scaled = xscale != 1 || yscale != 1;
}
@@ -274,6 +227,7 @@ static void uninit(struct sh_sub *sh)
{
struct sd_lavc_priv *priv = sh->context;
+ clear(priv);
avcodec_close(priv->avctx);
av_free(priv->avctx);
talloc_free(priv);
diff --git a/sub/spudec.c b/sub/spudec.c
index a58df60b17..8ee22a5267 100644
--- a/sub/spudec.c
+++ b/sub/spudec.c
@@ -127,6 +127,7 @@ typedef struct {
struct sub_bitmap borrowed_sub_part;
struct old_osd_planar borrowed_sub_image;
+ struct osd_bmp_indexed borrowed_bmp;
} spudec_handle_t;
static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet)
@@ -760,6 +761,50 @@ void spudec_get_bitmap(void *this, int w, int h, struct sub_bitmaps *res)
}
}
+void spudec_get_indexed(void *this, struct mp_eosd_res *dim,
+ struct sub_bitmaps *res)
+{
+ spudec_handle_t *spu = this;
+ *res = (struct sub_bitmaps) { .format = SUBBITMAP_INDEXED };
+ struct sub_bitmap *part = &spu->borrowed_sub_part;
+ res->parts = part;
+ if (spudec_visible(spu)) {
+ struct osd_bmp_indexed *bmp = &spu->borrowed_bmp;
+ part->bitmap = bmp;
+ bmp->bitmap = spu->pal_image;
+ part->stride = spu->pal_width;
+ part->w = spu->pal_width;
+ part->h = spu->pal_height;
+ double xscale = (double) (dim->w - dim->ml - dim->mr) / spu->orig_frame_width;
+ double yscale = (double) (dim->h - dim->mt - dim->mb) / spu->orig_frame_height;
+ part->x = spu->pal_start_col * xscale + dim->ml;
+ part->y = spu->pal_start_row * yscale + dim->mt;
+ part->dw = part->w * xscale;
+ part->dh = part->h * yscale;
+ res->num_parts = 1;
+ memset(bmp->palette, 0, sizeof(bmp->palette));
+ for (int i = 0; i < 4; ++i) {
+ int alpha = spu->alpha[i];
+ // extend 4 -> 8 bit
+ alpha |= alpha << 4;
+ if (spu->custom && (spu->cuspal[i] >> 31) != 0)
+ alpha = 0;
+ int color = spu->custom ? spu->cuspal[i] :
+ spu->global_palette[spu->palette[i]];
+ int y = (color >> 16) & 0xff;
+ int u = (color >> 8) & 0xff;
+ int v = color & 0xff;
+ // stolen from some site, likely incorrect
+ int b = 1.164 * (y - 16) + 2.018 * (u - 128);
+ int g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128);
+ int r = 1.164 * (y - 16) + 1.596 * (v - 128);
+#define CL(x) FFMAX(FFMIN((x), 255), 0)
+ bmp->palette[i] = (alpha << 24) | CL(r) | (CL(g) << 8) | (CL(b) << 16);
+#undef CL
+ }
+ }
+}
+
void spudec_draw(void *this, void (*draw_alpha)(void *ctx, int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride), void *ctx)
{
spudec_handle_t *spu = this;
@@ -1325,6 +1370,14 @@ void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigne
return this;
}
+void spudec_set_res(void *this, unsigned int frame_width, unsigned int frame_height)
+{
+ spudec_handle_t *spu = this;
+ // intentionally do not apply resolution heuristics
+ spu->orig_frame_width = frame_width;
+ spu->orig_frame_height = frame_height;
+}
+
void *spudec_new(unsigned int *palette)
{
return spudec_new_scaled(palette, 0, 0, NULL, 0);
diff --git a/sub/spudec.h b/sub/spudec.h
index 2e2542128a..411aafeb19 100644
--- a/sub/spudec.h
+++ b/sub/spudec.h
@@ -22,14 +22,17 @@
#include <stdint.h>
struct sub_bitmaps;
+struct mp_eosd_res;
void spudec_heartbeat(void *this, unsigned int pts100);
void spudec_assemble(void *this, unsigned char *packet, unsigned int len, int pts100);
void spudec_draw(void *this, void (*draw_alpha)(void *ctx, int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride), void *ctx);
void spudec_draw_scaled(void *this, unsigned int dxs, unsigned int dys, void (*draw_alpha)(void *ctx, int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride), void *ctx);
void spudec_get_bitmap(void *this, int w, int h, struct sub_bitmaps *res);
+void spudec_get_indexed(void *this, struct mp_eosd_res *dim, struct sub_bitmaps *res);
int spudec_apply_palette_crop(void *this, uint32_t palette, int sx, int ex, int sy, int ey);
void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height, uint8_t *extradata, int extradata_len);
+void spudec_set_res(void *this, unsigned int frame_width, unsigned int frame_height);
void *spudec_new(unsigned int *palette);
void spudec_free(void *this);
void spudec_reset(void *this); // called after seek
diff --git a/sub/sub.c b/sub/sub.c
index b2d9eb82fc..39cb32e488 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -172,8 +172,10 @@ static bool render_object(struct osd_state *osd, struct osd_object *obj,
if (obj->type == OSDTYPE_SPU) {
*out_imgs = (struct sub_bitmaps) {0};
- if (spu_visible(osd, obj))
- spudec_get_bitmap(vo_spudec, osd->res.w, osd->res.h, out_imgs);
+ if (spu_visible(osd, obj)) {
+ //spudec_get_bitmap(vo_spudec, osd->res.w, osd->res.h, out_imgs);
+ spudec_get_indexed(vo_spudec, &osd->res, out_imgs);
+ }
// Normal change-detection (sub. dec. calls vo_osd_changed(OSDTYPE_SPU))
if (obj->force_redraw) {
out_imgs->bitmap_id++;
@@ -183,9 +185,6 @@ static bool render_object(struct osd_state *osd, struct osd_object *obj,
struct sub_render_params p = *sub_params;
if (p.pts != MP_NOPTS_VALUE)
p.pts += sub_delay - osd->sub_offset;
-
- p.support_rgba = formats[SUBBITMAP_RGBA];
-
sub_get_bitmaps(osd, &p, out_imgs);
} else {
osd_object_get_bitmaps(osd, obj, out_imgs);
@@ -204,7 +203,7 @@ static bool render_object(struct osd_state *osd, struct osd_object *obj,
&& formats[obj->cached.format])
{
*out_imgs = obj->cached;
- return true;
+ return out_imgs->num_parts > 0;
}
out_imgs->render_index = obj->type;
@@ -212,22 +211,22 @@ static bool render_object(struct osd_state *osd, struct osd_object *obj,
out_imgs->bitmap_pos_id = obj->vo_bitmap_pos_id;
if (formats[out_imgs->format])
- return true;
+ return out_imgs->num_parts > 0;
bool cached = false; // do we have a copy of all the image data?
- if ((formats[SUBBITMAP_OLD_PLANAR] || formats[SUBBITMAP_OLD])
- && out_imgs->format == SUBBITMAP_LIBASS)
- {
- cached |= osd_conv_ass_to_old_p(obj->cache[0], out_imgs);
+ if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_INDEXED) {
+ cached |= osd_conv_idx_to_rgba(obj->cache[0], out_imgs);
}
- if (formats[SUBBITMAP_OLD] && out_imgs->format == SUBBITMAP_OLD_PLANAR) {
- cached |= osd_conv_old_p_to_old(obj->cache[1], out_imgs);
+ if (formats[SUBBITMAP_OLD_PLANAR] && out_imgs->format == SUBBITMAP_INDEXED)
+ {
+ cached |= osd_conv_idx_to_old_p(obj->cache[1], out_imgs,
+ osd->res.w, osd->res.h);
}
- if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_OLD_PLANAR) {
- cached |= osd_conv_old_p_to_rgba(obj->cache[2], out_imgs);
+ if (formats[SUBBITMAP_OLD_PLANAR] && out_imgs->format == SUBBITMAP_LIBASS) {
+ cached |= osd_conv_ass_to_old_p(obj->cache[2], out_imgs);
}
if (cached)
@@ -238,7 +237,7 @@ static bool render_object(struct osd_state *osd, struct osd_object *obj,
obj->type, out_imgs->format);
return false;
}
- return true;
+ return out_imgs->num_parts > 0;
}
// This is a hack to render the first subtitle OSD object, which is not empty.
@@ -290,7 +289,6 @@ void draw_osd_with_eosd(struct vo *vo, struct osd_state *osd)
.dim = dim,
.normal_scale = 1,
.vsfilter_scale = (double) asp.prew / asp.preh * asp.orgh / asp.orgw,
- .support_rgba = formats[SUBBITMAP_RGBA],
};
for (int n = 0; n < MAX_OSD_PARTS; n++) {
diff --git a/sub/sub.h b/sub/sub.h
index 6a83036460..8649018029 100644
--- a/sub/sub.h
+++ b/sub/sub.h
@@ -30,13 +30,20 @@ struct sub_render_params;
enum sub_bitmap_format {
SUBBITMAP_EMPTY = 0,// no bitmaps; always has num_parts==0
SUBBITMAP_LIBASS, // A8, with a per-surface blend color (libass.color)
- SUBBITMAP_RGBA, // B8G8R8A8, can be scaled
- SUBBITMAP_OLD, // I8A8 (monochrome), premultiplied alpha
+ SUBBITMAP_RGBA, // B8G8R8A8 (MSB=A, LSB=B), can be scaled
+ SUBBITMAP_INDEXED, // scaled, bitmap points to osd_bmp_indexed
SUBBITMAP_OLD_PLANAR, // like previous, but bitmap points to old_osd_planar
SUBBITMAP_COUNT
};
+// For SUBBITMAP_INDEXED
+struct osd_bmp_indexed {
+ uint8_t *bitmap;
+ // Each entry is like a pixel in SUBBITMAP_RGBA format
+ uint32_t palette[256];
+};
+
// For SUBBITMAP_OLD_PANAR
struct old_osd_planar {
unsigned char *bitmap;
@@ -46,9 +53,10 @@ struct old_osd_planar {
struct sub_bitmap {
void *bitmap;
int stride;
+ // Note: not clipped, going outside the screen area is allowed
+ // (except for SUBBITMAP_LIBASS, which is always clipped)
int w, h;
int x, y;
- // Note: not clipped, going outside the screen area is allowed
int dw, dh;
union {
@@ -59,10 +67,14 @@ struct sub_bitmap {
};
struct sub_bitmaps {
- int render_index; // for VO cache state (limited by MAX_OSD_PARTS)
+ // For VO cache state (limited by MAX_OSD_PARTS)
+ int render_index;
enum sub_bitmap_format format;
- bool scaled; // if false, dw==w && dh==h
+
+ // If false, dw==w && dh==h.
+ // SUBBITMAP_LIBASS is never scaled.
+ bool scaled;
struct sub_bitmap *parts;
int num_parts;
@@ -120,8 +132,6 @@ struct osd_state {
double sub_offset;
double vo_sub_pts;
- bool support_rgba;
-
bool render_subs_in_filter;
struct mp_eosd_res res;