diff options
Diffstat (limited to 'sub')
-rw-r--r-- | sub/dec_sub.c | 3 | ||||
-rw-r--r-- | sub/dec_sub.h | 2 | ||||
-rw-r--r-- | sub/img_convert.c | 148 | ||||
-rw-r--r-- | sub/img_convert.h | 5 | ||||
-rw-r--r-- | sub/sd_lavc.c | 90 | ||||
-rw-r--r-- | sub/spudec.c | 53 | ||||
-rw-r--r-- | sub/spudec.h | 3 | ||||
-rw-r--r-- | sub/sub.c | 32 | ||||
-rw-r--r-- | sub/sub.h | 24 |
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 @@ -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++) { @@ -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; |