summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libvo/gl_osd.c4
-rw-r--r--libvo/vo_gl3.c1
-rw-r--r--libvo/vo_gl3_shaders.glsl11
-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
12 files changed, 191 insertions, 185 deletions
diff --git a/libvo/gl_osd.c b/libvo/gl_osd.c
index ce4bee5c03..74053afd4a 100644
--- a/libvo/gl_osd.c
+++ b/libvo/gl_osd.c
@@ -33,20 +33,16 @@ struct osd_fmt_entry {
static const int blend_factors[SUBBITMAP_COUNT][2] = {
[SUBBITMAP_LIBASS] = {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
[SUBBITMAP_RGBA] = {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
- [SUBBITMAP_OLD] = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
};
static const struct osd_fmt_entry osd_to_gl3_formats[SUBBITMAP_COUNT] = {
[SUBBITMAP_LIBASS] = {GL_RED, GL_RED, GL_UNSIGNED_BYTE},
[SUBBITMAP_RGBA] = {GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE},
- [SUBBITMAP_OLD] = {GL_RG, GL_RG, GL_UNSIGNED_BYTE},
};
static const struct osd_fmt_entry osd_to_gl_legacy_formats[SUBBITMAP_COUNT] = {
[SUBBITMAP_LIBASS] = {GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE},
[SUBBITMAP_RGBA] = {GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE},
- [SUBBITMAP_OLD] =
- {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
};
struct mpgl_osd *mpgl_osd_init(GL *gl, bool legacy)
diff --git a/libvo/vo_gl3.c b/libvo/vo_gl3.c
index f3c1767b78..f5df6a1ae4 100644
--- a/libvo/vo_gl3.c
+++ b/libvo/vo_gl3.c
@@ -252,7 +252,6 @@ static const struct fmt_entry mp_to_gl_formats[] = {
static const char *osd_shaders[SUBBITMAP_COUNT] = {
[SUBBITMAP_LIBASS] = "frag_osd_libass",
[SUBBITMAP_RGBA] = "frag_osd_rgba",
- [SUBBITMAP_OLD] = "frag_osd_old",
};
diff --git a/libvo/vo_gl3_shaders.glsl b/libvo/vo_gl3_shaders.glsl
index 20f8c597ad..04d886f9c0 100644
--- a/libvo/vo_gl3_shaders.glsl
+++ b/libvo/vo_gl3_shaders.glsl
@@ -66,17 +66,6 @@ void main() {
out_color = texture(texture1, texcoord);
}
-#!section frag_osd_old
-uniform sampler2D texture1;
-uniform vec4 osd_color;
-
-in vec2 texcoord;
-out vec4 out_color;
-
-void main() {
- out_color = texture(texture1, texcoord).rrrg * osd_color;
-}
-
#!section frag_video
uniform sampler2D texture1;
uniform sampler2D texture2;
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;