diff options
-rw-r--r-- | libmpcodecs/vf_ass.c | 1 | ||||
-rw-r--r-- | libmpcodecs/vf_vo.c | 1 | ||||
-rw-r--r-- | libmpcodecs/vfcap.h | 1 | ||||
-rw-r--r-- | libvo/bitmap_packer.c | 48 | ||||
-rw-r--r-- | libvo/bitmap_packer.h | 8 | ||||
-rw-r--r-- | libvo/vo_vdpau.c | 111 | ||||
-rw-r--r-- | sub/dec_sub.c | 3 | ||||
-rw-r--r-- | sub/dec_sub.h | 19 | ||||
-rw-r--r-- | sub/sd_ass.c | 1 | ||||
-rw-r--r-- | sub/sd_lavc.c | 131 | ||||
-rw-r--r-- | sub/sub.h | 1 |
11 files changed, 273 insertions, 52 deletions
diff --git a/libmpcodecs/vf_ass.c b/libmpcodecs/vf_ass.c index ad4671fe57..f0b2e6ab77 100644 --- a/libmpcodecs/vf_ass.c +++ b/libmpcodecs/vf_ass.c @@ -364,6 +364,7 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) osd->normal_scale = vf->priv->aspect_correction; osd->vsfilter_scale = 1; osd->sub_pts = pts - osd->sub_offset; + osd->support_rgba = false; struct sub_bitmaps b; sub_get_bitmaps(osd, &b); images = b.imgs; diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c index 3aec40cd15..862cd63492 100644 --- a/libmpcodecs/vf_vo.c +++ b/libmpcodecs/vf_vo.c @@ -119,6 +119,7 @@ static int control(struct vf_instance *vf, int request, void *data) } case VFCTRL_DRAW_EOSD: { struct osd_state *osd = data; + osd->support_rgba = vf->default_caps & VFCAP_EOSD_RGBA; osd->dim = (struct mp_eosd_res){0}; if (!video_out->config_ok || vo_control(video_out, VOCTRL_GET_EOSD_RES, &osd->dim) != true) diff --git a/libmpcodecs/vfcap.h b/libmpcodecs/vfcap.h index 86c6f6e477..aef75840ae 100644 --- a/libmpcodecs/vfcap.h +++ b/libmpcodecs/vfcap.h @@ -48,5 +48,6 @@ #define VOCAP_NOSLICES 0x8000 #define VFCAP_OSD_FILTER 0x10000 // OSD is drawn in filter chain #define VFCAP_EOSD_FILTER 0x20000 // EOSD is drawn in filter chain +#define VFCAP_EOSD_RGBA 0x40000 #endif /* MPLAYER_VFCAP_H */ diff --git a/libvo/bitmap_packer.c b/libvo/bitmap_packer.c index 2ae8a1eee0..eedc2e2242 100644 --- a/libvo/bitmap_packer.c +++ b/libvo/bitmap_packer.c @@ -28,6 +28,7 @@ #include "mp_msg.h" #include "mpcommon.h" #include "sub/ass_mp.h" +#include "sub/dec_sub.h" #define HEIGHT_SORT_BITS 4 @@ -55,7 +56,7 @@ static int size_index(int s) * free rectangle with corners (13, 20)-(w, 50) is filled recursively. */ static int pack_rectangles(struct pos *in, struct pos *out, int num_rects, - int w, int h, int *scratch) + int w, int h, int *scratch, int *used_width) { int bins[16 << HEIGHT_SORT_BITS]; int sizes[16 << HEIGHT_SORT_BITS] = { 0 }; @@ -100,11 +101,12 @@ static int pack_rectangles(struct pos *in, struct pos *out, int num_rects, s.x = right; maxy = FFMAX(maxy, bottom); } + *used_width = FFMAX(*used_width, s.x); if (maxy > 0) s.bottom = maxy; } } - return num_rects ? -1 : 0; + return num_rects ? -1 : y; } int packer_pack(struct bitmap_packer *packer) @@ -115,7 +117,7 @@ int packer_pack(struct bitmap_packer *packer) struct pos *in = packer->in; int xmax = 0, ymax = 0; for (int i = 0; i < packer->count; i++) { - if (in[i].x == 0 || in[i].y == 0) + if (in[i].x <= packer->padding || in[i].y <= packer->padding) in[i] = (struct pos){0, 0}; if (in[i].x < 0 || in [i].x > 65535 || in[i].y < 0 || in[i].y > 65535) { mp_msg(MSGT_VO, MSGL_FATAL, "Invalid OSD / subtitle bitmap size\n"); @@ -124,20 +126,33 @@ int packer_pack(struct bitmap_packer *packer) xmax = FFMAX(xmax, in[i].x); ymax = FFMAX(ymax, in[i].y); } + xmax = FFMAX(0, xmax - packer->padding); + ymax = FFMAX(0, ymax - packer->padding); if (xmax > packer->w) packer->w = 1 << av_log2(xmax - 1) + 1; if (ymax > packer->h) packer->h = 1 << av_log2(ymax - 1) + 1; while (1) { - if (pack_rectangles(in, packer->result, packer->count, packer->w, - packer->h, packer->scratch) >= 0) + int used_width = 0; + int y = pack_rectangles(in, packer->result, packer->count, + packer->w + packer->padding, + packer->h + packer->padding, + packer->scratch, &used_width); + if (y >= 0) { + // No padding at edges + packer->used_width = FFMIN(used_width, packer->w); + packer->used_height = FFMIN(y, packer->h); return packer->w != w_orig || packer->h != h_orig; + } if (packer->w <= packer->h && packer->w != packer->w_max) packer->w = FFMIN(packer->w * 2, packer->w_max); else if (packer->h != packer->h_max) packer->h = FFMIN(packer->h * 2, packer->h_max); - else + else { + packer->w = w_orig; + packer->h = h_orig; return -1; + } } } @@ -156,8 +171,8 @@ void packer_set_size(struct bitmap_packer *packer, int size) packer->asize + 16); } -int packer_pack_from_assimg(struct bitmap_packer *packer, - struct ass_image *imglist) +static int packer_pack_from_assimg(struct bitmap_packer *packer, + struct ass_image *imglist) { int count = 0; struct ass_image *img = imglist; @@ -172,3 +187,20 @@ int packer_pack_from_assimg(struct bitmap_packer *packer, packer->count = count; return packer_pack(packer); } + +int packer_pack_from_subbitmaps(struct bitmap_packer *packer, + struct sub_bitmaps *b, int padding_pixels) +{ + packer->padding = 0; + packer->count = 0; + if (b->type == SUBBITMAP_EMPTY) + return 0; + if (b->type == SUBBITMAP_LIBASS) + return packer_pack_from_assimg(packer, b->imgs); + packer->padding = padding_pixels; + packer_set_size(packer, b->part_count); + int a = packer->padding; + for (int i = 0; i < b->part_count; i++) + packer->in[i] = (struct pos){b->parts[i].w + a, b->parts[i].h + a}; + return packer_pack(packer); +} diff --git a/libvo/bitmap_packer.h b/libvo/bitmap_packer.h index 45b6fbc4ae..c7c377cbd0 100644 --- a/libvo/bitmap_packer.h +++ b/libvo/bitmap_packer.h @@ -11,9 +11,12 @@ struct bitmap_packer { int h; int w_max; int h_max; + int padding; int count; struct pos *in; struct pos *result; + int used_width; + int used_height; // internal int *scratch; @@ -21,6 +24,7 @@ struct bitmap_packer { }; struct ass_image; +struct sub_bitmaps; /* Reallocate packer->in for at least to desired number of items. * Also sets packer->count to the same value. @@ -41,7 +45,7 @@ int packer_pack(struct bitmap_packer *packer); * packer->in will be reallocated if needed and filled from the * given image list. */ -int packer_pack_from_assimg(struct bitmap_packer *packer, - struct ass_image *imglist); +int packer_pack_from_subbitmaps(struct bitmap_packer *packer, + struct sub_bitmaps *b, int padding_pixels); #endif diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index 922ec24201..594829b394 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -172,6 +172,7 @@ struct vdpctx { // EOSD struct eosd_bitmap_surface { + VdpRGBAFormat format; VdpBitmapSurface surface; uint32_t max_width; uint32_t max_height; @@ -1007,16 +1008,35 @@ static void generate_eosd(struct vo *vo, mp_eosd_images_t *imgs) vc->eosd_render_count = 0; - if (!imgs->imgs) - return; // There's nothing to render! + if (imgs->type == SUBBITMAP_EMPTY) + return; if (imgs->bitmap_id == vc->bitmap_id) goto eosd_skip_upload; need_upload = true; + VdpRGBAFormat format; + int format_size; + switch (imgs->type) { + case SUBBITMAP_LIBASS: + format = VDP_RGBA_FORMAT_A8; + format_size = 1; + break; + case SUBBITMAP_RGBA: + format = VDP_RGBA_FORMAT_B8G8R8A8; + format_size = 4; + break; + default: + abort(); + }; + if (sfc->format != format) { + talloc_free(sfc->packer); + sfc->packer = NULL; + }; + sfc->format = format; if (!sfc->packer) - sfc->packer = make_packer(vo, VDP_RGBA_FORMAT_A8); - int r = packer_pack_from_assimg(sfc->packer, imgs->imgs); + sfc->packer = make_packer(vo, format); + int r = packer_pack_from_subbitmaps(sfc->packer, imgs, imgs->scaled); if (r < 0) { mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] EOSD bitmaps do not fit on " "a surface with the maximum supported size\n"); @@ -1028,13 +1048,21 @@ static void generate_eosd(struct vo *vo, mp_eosd_images_t *imgs) } mp_msg(MSGT_VO, MSGL_V, "[vdpau] Allocating a %dx%d surface for " "EOSD bitmaps.\n", sfc->packer->w, sfc->packer->h); - vdp_st = vdp->bitmap_surface_create(vc->vdp_device, VDP_RGBA_FORMAT_A8, + vdp_st = vdp->bitmap_surface_create(vc->vdp_device, format, sfc->packer->w, sfc->packer->h, true, &sfc->surface); if (vdp_st != VDP_STATUS_OK) sfc->surface = VDP_INVALID_HANDLE; CHECK_ST_WARNING("EOSD: error when creating surface"); } + if (imgs->scaled) { + char zeros[sfc->packer->used_width * format_size]; + memset(zeros, 0, sizeof(zeros)); + vdp_st = vdp->bitmap_surface_put_bits_native(sfc->surface, + &(const void *){zeros}, &(uint32_t){0}, + &(VdpRect){0, 0, sfc->packer->used_width, + sfc->packer->used_height}); + } eosd_skip_upload: if (sfc->surface == VDP_INVALID_HANDLE) @@ -1046,31 +1074,54 @@ eosd_skip_upload: * sizeof(*vc->eosd_targets)); } - int i = 0; - for (ASS_Image *p = imgs->imgs; p; p = p->next, i++) { - if (p->w == 0 || p->h == 0) - continue; - struct eosd_target *target = &vc->eosd_targets[vc->eosd_render_count]; - int x = sfc->packer->result[i].x; - int y = sfc->packer->result[i].y; - target->source = (VdpRect){x, y, x + p->w, y + p->h}; - if (need_upload) { - vdp_st = vdp-> - bitmap_surface_put_bits_native(sfc->surface, - (const void *) &p->bitmap, - &p->stride, &target->source); - CHECK_ST_WARNING("EOSD: putbits failed"); + if (imgs->type == SUBBITMAP_LIBASS) { + int i = 0; + for (ASS_Image *p = imgs->imgs; p; p = p->next, i++) { + if (p->w == 0 || p->h == 0) + continue; + struct eosd_target *target = vc->eosd_targets + + vc->eosd_render_count; + int x = sfc->packer->result[i].x; + int y = sfc->packer->result[i].y; + target->source = (VdpRect){x, y, x + p->w, y + p->h}; + if (need_upload) { + vdp_st = vdp-> + bitmap_surface_put_bits_native(sfc->surface, + (const void *) &p->bitmap, + &p->stride, &target->source); + CHECK_ST_WARNING("EOSD: putbits failed"); + } + // Render dest, color, etc. + target->color.alpha = 1.0 - ((p->color >> 0) & 0xff) / 255.0; + target->color.blue = ((p->color >> 8) & 0xff) / 255.0; + target->color.green = ((p->color >> 16) & 0xff) / 255.0; + target->color.red = ((p->color >> 24) & 0xff) / 255.0; + target->dest.x0 = p->dst_x; + target->dest.y0 = p->dst_y; + target->dest.x1 = p->w + p->dst_x; + target->dest.y1 = p->h + p->dst_y; + vc->eosd_render_count++; + } + } else { + for (int i = 0 ;i < sfc->packer->count; i++) { + struct sub_bitmap *b = &imgs->parts[i]; + struct eosd_target *target = vc->eosd_targets + + vc->eosd_render_count; + int x = sfc->packer->result[i].x; + int y = sfc->packer->result[i].y; + target->source = (VdpRect){x, y, x + b->w, y + b->h}; + if (need_upload) { + vdp_st = vdp-> + bitmap_surface_put_bits_native(sfc->surface, + &(const void *){b->bitmap}, + &(uint32_t){b->w * 4}, + &target->source); + CHECK_ST_WARNING("EOSD: putbits failed"); + } + target->color = (VdpColor){1, 1, 1, 1}; + target->dest = (VdpRect){b->x, b->y, b->x + b->dw, b->y + b->dh}; + vc->eosd_render_count++; } - // Render dest, color, etc. - target->color.alpha = 1.0 - ((p->color >> 0) & 0xff) / 255.0; - target->color.blue = ((p->color >> 8) & 0xff) / 255.0; - target->color.green = ((p->color >> 16) & 0xff) / 255.0; - target->color.red = ((p->color >> 24) & 0xff) / 255.0; - target->dest.x0 = p->dst_x; - target->dest.y0 = p->dst_y; - target->dest.x1 = p->w + p->dst_x; - target->dest.y1 = p->h + p->dst_y; - vc->eosd_render_count++; } vc->bitmap_id = imgs->bitmap_id; vc->bitmap_pos_id = imgs->bitmap_pos_id; @@ -1529,7 +1580,7 @@ static int query_format(uint32_t format) { int default_flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_EOSD - | VFCAP_EOSD_UNSCALED | VFCAP_FLIP; + | VFCAP_EOSD_UNSCALED | VFCAP_EOSD_RGBA | VFCAP_FLIP; switch (format) { case IMGFMT_YV12: case IMGFMT_I420: diff --git a/sub/dec_sub.c b/sub/dec_sub.c index 3278c10d85..4a048b27a6 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -62,7 +62,8 @@ void sub_get_bitmaps(struct osd_state *osd, struct sub_bitmaps *res) { struct MPOpts *opts = osd->opts; - *res = (struct sub_bitmaps){ .bitmap_id = osd->bitmap_id, + *res = (struct sub_bitmaps){ .type = SUBBITMAP_EMPTY, + .bitmap_id = osd->bitmap_id, .bitmap_pos_id = osd->bitmap_pos_id }; 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 efbfdc9ce7..c71a2348aa 100644 --- a/sub/dec_sub.h +++ b/sub/dec_sub.h @@ -5,13 +5,32 @@ struct sh_sub; struct osd_state; struct ass_track; +enum sub_bitmap_type { + SUBBITMAP_EMPTY, + SUBBITMAP_LIBASS, + SUBBITMAP_RGBA, +}; + typedef struct mp_eosd_res { int w, h; // screen dimensions, including black borders int mt, mb, ml, mr; // borders (top, bottom, left, right) } mp_eosd_res_t; typedef struct sub_bitmaps { + enum sub_bitmap_type type; + struct ass_image *imgs; + + struct sub_bitmap { + int w, h; + int x, y; + // Note: not clipped, going outside the screen area is allowed + int dw, dh; + void *bitmap; + } *parts; + int part_count; + + bool scaled; int bitmap_id, bitmap_pos_id; } mp_eosd_images_t; diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 37c220a4b5..9295cab07d 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -147,6 +147,7 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, res->bitmap_id = ++res->bitmap_pos_id; else if (changed) res->bitmap_pos_id++; + res->type = SUBBITMAP_LIBASS; } static void reset(struct sh_sub *sh, struct osd_state *osd) diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index a4eafff429..1da33ffca1 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -19,6 +19,7 @@ #include <libavcodec/avcodec.h> +#include "talloc.h" #include "mp_msg.h" #include "libmpdemux/stheader.h" #include "sd.h" @@ -26,8 +27,17 @@ // Current code still pushes subs directly to global spudec #include "sub.h" -static void avsub_to_spudec(AVSubtitleRect **rects, int num_rects, - double pts, double endpts) +struct sd_lavc_priv { + AVCodecContext *avctx; + int count; + struct sub_bitmap *inbitmaps; + struct sub_bitmap *outbitmaps; + 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; @@ -69,6 +79,9 @@ static void avsub_to_spudec(AVSubtitleRect **rects, int num_rects, static int init(struct sh_sub *sh, struct osd_state *osd) { + if (sh->initialized) + return 0; + struct sd_lavc_priv *priv = talloc_zero(NULL, struct sd_lavc_priv); enum CodecID cid = CODEC_ID_NONE; switch (sh->type) { case 'b': @@ -77,6 +90,8 @@ static int init(struct sh_sub *sh, struct osd_state *osd) cid = CODEC_ID_HDMV_PGS_SUBTITLE; break; case 'x': cid = CODEC_ID_XSUB; break; + case 'v': + cid = CODEC_ID_DVD_SUBTITLE; break; } AVCodecContext *ctx = NULL; AVCodec *sub_codec = avcodec_find_decoder(cid); @@ -85,25 +100,41 @@ static int init(struct sh_sub *sh, struct osd_state *osd) ctx = avcodec_alloc_context3(sub_codec); if (!ctx) goto error; + ctx->extradata_size = sh->extradata_len; + ctx->extradata = sh->extradata; if (avcodec_open2(ctx, sub_codec, NULL) < 0) goto error; - sh->context = ctx; + priv->avctx = ctx; + sh->context = priv; return 0; error: mp_msg(MSGT_SUBREADER, MSGL_ERR, "Could not open libavcodec subtitle decoder\n"); av_free(ctx); + talloc_free(priv); return -1; } +static void clear(struct sd_lavc_priv *priv) +{ + priv->count = 0; + talloc_free(priv->inbitmaps); + talloc_free(priv->outbitmaps); + priv->inbitmaps = priv->outbitmaps = NULL; + priv->bitmaps_changed = true; + priv->endpts = MP_NOPTS_VALUE; +} + static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, int data_len, double pts, double duration) { - AVCodecContext *ctx = sh->context; + struct sd_lavc_priv *priv = sh->context; + AVCodecContext *ctx = priv->avctx; AVSubtitle sub; AVPacket pkt; + clear(priv); av_init_packet(&pkt); pkt.data = data; pkt.size = data_len; @@ -127,10 +158,37 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, if (sub.num_rects > 0) { switch (sub.rects[0]->type) { case SUBTITLE_BITMAP: - if (!vo_spudec) - vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height, NULL, 0); - avsub_to_spudec(sub.rects, sub.num_rects, pts, endpts); - vo_osd_changed(OSDTYPE_SPU); + // Assume resolution heuristics only work for PGS and DVB + if (!osd->support_rgba || sh->type != 'p' && sh->type != 'b') { + 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); + 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->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; break; default: mp_msg(MSGT_SUBREADER, MSGL_ERR, "sd_lavc: unsupported subtitle " @@ -141,21 +199,72 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, avsubtitle_free(&sub); } +static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, + struct sub_bitmaps *res) +{ + struct sd_lavc_priv *priv = sh->context; + + if (priv->endpts != MP_NOPTS_VALUE && (osd->sub_pts >= priv->endpts || + osd->sub_pts < priv->endpts - 300)) + clear(priv); + if (!osd->support_rgba) + return; + if (priv->bitmaps_changed && priv->count > 0) + priv->outbitmaps = talloc_memdup(priv, priv->inbitmaps, + talloc_get_size(priv->inbitmaps)); + bool pos_changed = false; + // Hope that PGS subs set these and 720/576 works for dvb subs + int inw = priv->avctx->width; + if (!inw) + inw = 720; + int inh = priv->avctx->height; + if (!inh) + inh = 576; + struct mp_eosd_res *d = &osd->dim; + double xscale = (double) (d->w - d->ml - d->mr) / inw; + double yscale = (double) (d->h - d->mt - d->mb) / inh; + for (int i = 0; i < priv->count; i++) { + struct sub_bitmap *bi = &priv->inbitmaps[i]; + struct sub_bitmap *bo = &priv->outbitmaps[i]; +#define SET(var, val) pos_changed |= var != (int)(val); var = (val) + SET(bo->x, bi->x * xscale + d->ml); + SET(bo->y, bi->y * yscale + d->mt); + SET(bo->dw, bi->w * xscale); + SET(bo->dh, bi->h * yscale); + } + res->parts = priv->outbitmaps; + res->part_count = priv->count; + if (priv->bitmaps_changed) + res->bitmap_id = ++res->bitmap_pos_id; + else if (pos_changed) + res->bitmap_pos_id++; + priv->bitmaps_changed = false; + res->type = SUBBITMAP_RGBA; + res->scaled = xscale != 1 || yscale != 1; +} + static void reset(struct sh_sub *sh, struct osd_state *osd) { + struct sd_lavc_priv *priv = sh->context; + + clear(priv); // lavc might not do this right for all codecs; may need close+reopen - avcodec_flush_buffers(sh->context); + avcodec_flush_buffers(priv->avctx); } static void uninit(struct sh_sub *sh) { - avcodec_close(sh->context); - av_free(sh->context); + struct sd_lavc_priv *priv = sh->context; + + avcodec_close(priv->avctx); + av_free(priv->avctx); + talloc_free(priv); } const struct sd_functions sd_lavc = { .init = init, .decode = decode, + .get_bitmaps = get_bitmaps, .reset = reset, .switch_off = reset, .uninit = uninit, @@ -71,6 +71,7 @@ struct osd_state { double normal_scale; double vsfilter_scale; bool unscaled; + bool support_rgba; struct ass_renderer *osd_render; struct ass_library *osd_ass_library; |