diff options
-rw-r--r-- | libmpcodecs/vfcap.h | 1 | ||||
-rw-r--r-- | libvo/bitmap_packer.c | 47 | ||||
-rw-r--r-- | libvo/bitmap_packer.h | 9 | ||||
-rw-r--r-- | libvo/vo_corevideo.m | 7 | ||||
-rw-r--r-- | libvo/vo_gl.c | 3 | ||||
-rw-r--r-- | libvo/vo_gl3.c | 3 | ||||
-rw-r--r-- | libvo/vo_vdpau.c | 84 | ||||
-rw-r--r-- | mplayer.c | 2 | ||||
-rw-r--r-- | sub/dec_sub.c | 3 | ||||
-rw-r--r-- | sub/dec_sub.h | 49 | ||||
-rw-r--r-- | sub/sd_ass.c | 28 | ||||
-rw-r--r-- | sub/sd_lavc.c | 5 |
12 files changed, 130 insertions, 111 deletions
diff --git a/libmpcodecs/vfcap.h b/libmpcodecs/vfcap.h index aef75840ae..0bb255b3cd 100644 --- a/libmpcodecs/vfcap.h +++ b/libmpcodecs/vfcap.h @@ -46,7 +46,6 @@ #define VFCAP_EOSD_UNSCALED 0x4000 // used by libvo and vf_vo, indicates the VO does not support draw_slice for this format #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 diff --git a/libvo/bitmap_packer.c b/libvo/bitmap_packer.c index eedc2e2242..5e5bafea0c 100644 --- a/libvo/bitmap_packer.c +++ b/libvo/bitmap_packer.c @@ -30,6 +30,24 @@ #include "sub/ass_mp.h" #include "sub/dec_sub.h" +void packer_reset(struct bitmap_packer *packer) +{ + struct bitmap_packer old = *packer; + *packer = (struct bitmap_packer) { + .w_max = old.w_max, + .h_max = old.h_max, + }; + talloc_free_children(packer); +} + +void packer_get_bb(struct bitmap_packer *packer, struct pos out_bb[2]) +{ + out_bb[0] = (struct pos) {0}; + out_bb[1] = (struct pos) { + FFMIN(packer->used_width + packer->padding, packer->w), + FFMIN(packer->used_height + packer->padding, packer->h), + }; +} #define HEIGHT_SORT_BITS 4 static int size_index(int s) @@ -171,36 +189,15 @@ void packer_set_size(struct bitmap_packer *packer, int size) packer->asize + 16); } -static int packer_pack_from_assimg(struct bitmap_packer *packer, - struct ass_image *imglist) -{ - int count = 0; - struct ass_image *img = imglist; - while (img) { - if (count >= packer->asize) - packer_set_size(packer, FFMAX(packer->asize * 2, 32)); - packer->in[count].x = img->w; - packer->in[count].y = img->h; - img = img->next; - count++; - } - packer->count = count; - return packer_pack(packer); -} - int packer_pack_from_subbitmaps(struct bitmap_packer *packer, - struct sub_bitmaps *b, int padding_pixels) + struct sub_bitmaps *b) { - packer->padding = 0; packer->count = 0; - if (b->type == SUBBITMAP_EMPTY) + if (b->format == 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); + packer_set_size(packer, b->num_parts); int a = packer->padding; - for (int i = 0; i < b->part_count; i++) + for (int i = 0; i < b->num_parts; 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 c7c377cbd0..99c7b514b4 100644 --- a/libvo/bitmap_packer.h +++ b/libvo/bitmap_packer.h @@ -26,6 +26,13 @@ struct bitmap_packer { struct ass_image; struct sub_bitmaps; +// Clear all internal state. Leave the following fields: w_max, h_max +void packer_reset(struct bitmap_packer *packer); + +// Get the bounding box used for bitmap data (including padding). +// The bounding box doesn't exceed (0,0)-(packer->w,packer->h). +void packer_get_bb(struct bitmap_packer *packer, struct pos out_bb[2]); + /* Reallocate packer->in for at least to desired number of items. * Also sets packer->count to the same value. */ @@ -46,6 +53,6 @@ int packer_pack(struct bitmap_packer *packer); * given image list. */ int packer_pack_from_subbitmaps(struct bitmap_packer *packer, - struct sub_bitmaps *b, int padding_pixels); + struct sub_bitmaps *b); #endif diff --git a/libvo/vo_corevideo.m b/libvo/vo_corevideo.m index 1d10330bcb..fd667acb61 100644 --- a/libvo/vo_corevideo.m +++ b/libvo/vo_corevideo.m @@ -45,11 +45,10 @@ struct quad { }; #define CV_VERTICES_PER_QUAD 6 -#define CV_MAX_OSD_PARTS 20 struct osd_p { - GLuint tex[CV_MAX_OSD_PARTS]; - NSRect tex_rect[CV_MAX_OSD_PARTS]; + GLuint tex[MAX_OSD_PARTS]; + NSRect tex_rect[MAX_OSD_PARTS]; int tex_cnt; }; @@ -185,7 +184,7 @@ static void create_osd_texture(void *ctx, int x0, int y0, int w, int h, return; } - if (osd->tex_cnt >= CV_MAX_OSD_PARTS) { + if (osd->tex_cnt >= MAX_OSD_PARTS) { mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the" " developers!\n"); return; diff --git a/libvo/vo_gl.c b/libvo/vo_gl.c index 5453943fe9..236471d537 100644 --- a/libvo/vo_gl.c +++ b/libvo/vo_gl.c @@ -44,9 +44,6 @@ #include "fastmemcpy.h" #include "sub/ass_mp.h" -//! How many parts the OSD may consist of at most -#define MAX_OSD_PARTS 20 - //for gl_priv.use_yuv #define MASK_ALL_YUV (~(1 << YUV_CONVERSION_NONE)) #define MASK_NOT_COMBINERS (~((1 << YUV_CONVERSION_NONE) | (1 << YUV_CONVERSION_COMBINERS))) diff --git a/libvo/vo_gl3.c b/libvo/vo_gl3.c index dea0c6637a..ebce32677b 100644 --- a/libvo/vo_gl3.c +++ b/libvo/vo_gl3.c @@ -59,9 +59,6 @@ static const char vo_gl3_shaders[] = #include "libvo/vo_gl3_shaders.h" ; -// How many parts the OSD may consist of at most. -#define MAX_OSD_PARTS 20 - // Pixel width of 1D lookup textures. #define LOOKUP_TEXTURE_SIZE 256 diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index 594829b394..d5856e2dfa 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -92,8 +92,6 @@ struct vdp_functions { #undef VDP_FUNCTION }; -#define MAX_OLD_OSD_BITMAPS 6 - struct vdpctx { struct vdp_functions *vdp; @@ -165,7 +163,7 @@ struct vdpctx { int x0, y0, w, h; unsigned char *src, *srca; int stride; - } old_osd_elements[MAX_OLD_OSD_BITMAPS]; + } old_osd_elements[MAX_OSD_PARTS]; int old_osd_count; unsigned char *osd_data_temp; int osd_data_size; @@ -184,7 +182,7 @@ struct vdpctx { VdpRect source; VdpRect dest; VdpColor color; - } *eosd_targets, osd_targets[MAX_OLD_OSD_BITMAPS][2]; + } *eosd_targets, osd_targets[MAX_OSD_PARTS][2]; int eosd_targets_size; int eosd_render_count; int bitmap_id; @@ -1008,7 +1006,7 @@ static void generate_eosd(struct vo *vo, mp_eosd_images_t *imgs) vc->eosd_render_count = 0; - if (imgs->type == SUBBITMAP_EMPTY) + if (imgs->format == SUBBITMAP_EMPTY) return; if (imgs->bitmap_id == vc->bitmap_id) @@ -1017,7 +1015,7 @@ static void generate_eosd(struct vo *vo, mp_eosd_images_t *imgs) need_upload = true; VdpRGBAFormat format; int format_size; - switch (imgs->type) { + switch (imgs->format) { case SUBBITMAP_LIBASS: format = VDP_RGBA_FORMAT_A8; format_size = 1; @@ -1036,7 +1034,8 @@ static void generate_eosd(struct vo *vo, mp_eosd_images_t *imgs) sfc->format = format; if (!sfc->packer) sfc->packer = make_packer(vo, format); - int r = packer_pack_from_subbitmaps(sfc->packer, imgs, imgs->scaled); + sfc->packer->padding = imgs->scaled; // assume 2x2 filter on scaling + int r = packer_pack_from_subbitmaps(sfc->packer, imgs); if (r < 0) { mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] EOSD bitmaps do not fit on " "a surface with the maximum supported size\n"); @@ -1072,57 +1071,34 @@ eosd_skip_upload: vc->eosd_targets_size = sfc->packer->count; vc->eosd_targets = talloc_size(vc, vc->eosd_targets_size * sizeof(*vc->eosd_targets)); - } + } - 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++; + 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}; + target->dest = (VdpRect){b->x, b->y, b->x + b->dw, b->y + b->dh}; + target->color = (VdpColor){1, 1, 1, 1}; + if (imgs->format == SUBBITMAP_LIBASS) { + uint32_t color = b->libass.color; + target->color.alpha = 1.0 - ((color >> 0) & 0xff) / 255.0; + target->color.blue = ((color >> 8) & 0xff) / 255.0; + target->color.green = ((color >> 16) & 0xff) / 255.0; + target->color.red = ((color >> 24) & 0xff) / 255.0; } - } 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); + if (need_upload) { + vdp_st = vdp-> + bitmap_surface_put_bits_native(sfc->surface, + &(const void *){b->bitmap}, + &(uint32_t){b->stride}, + &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++; } + vc->eosd_render_count++; } + vc->bitmap_id = imgs->bitmap_id; vc->bitmap_pos_id = imgs->bitmap_pos_id; } @@ -1133,7 +1109,7 @@ static void record_osd(void *ctx, int x0, int y0, int w, int h, struct vo *vo = ctx; struct vdpctx *vc = vo->priv; - assert(vc->old_osd_count < MAX_OLD_OSD_BITMAPS); + assert(vc->old_osd_count < MAX_OSD_PARTS); if (!w || !h) return; vc->old_osd_elements[vc->old_osd_count++] = (struct old_osd){ @@ -2638,8 +2638,6 @@ static int redraw_osd(struct MPContext *mpctx) { struct sh_video *sh_video = mpctx->sh_video; struct vf_instance *vf = sh_video->vfilter; - if (sh_video->output_flags & VFCAP_OSD_FILTER) - return -1; if (vo_redraw_frame(mpctx->video_out) < 0) return -1; mpctx->osd->sub_pts = mpctx->video_pts; diff --git a/sub/dec_sub.c b/sub/dec_sub.c index 4a048b27a6..31b06b9b80 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){ .type = SUBBITMAP_EMPTY, + *res = (struct sub_bitmaps){ .render_index = 0, + .format = 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) { diff --git a/sub/dec_sub.h b/sub/dec_sub.h index c71a2348aa..df6aaf9b91 100644 --- a/sub/dec_sub.h +++ b/sub/dec_sub.h @@ -1,14 +1,22 @@ #ifndef MPLAYER_DEC_SUB_H #define MPLAYER_DEC_SUB_H +#include <stdbool.h> +#include <stdint.h> + +#define MAX_OSD_PARTS 8 + struct sh_sub; struct osd_state; struct ass_track; -enum sub_bitmap_type { +enum sub_bitmap_format { SUBBITMAP_EMPTY, - SUBBITMAP_LIBASS, - SUBBITMAP_RGBA, + SUBBITMAP_LIBASS, // A8, with a per-surface blend color (libass.color) + SUBBITMAP_RGBA, // B8G8R8A8 + SUBBITMAP_OLD, // I8A8 (monochrome), premultiplied alpha + + SUBBITMAP_COUNT }; typedef struct mp_eosd_res { @@ -16,21 +24,34 @@ typedef struct mp_eosd_res { int mt, mb, ml, mr; // borders (top, bottom, left, right) } mp_eosd_res_t; +struct sub_bitmap { + void *bitmap; + int stride; + int w, h; + int x, y; + // Note: not clipped, going outside the screen area is allowed + int dw, dh; + + union { + struct { + uint32_t color; + } libass; + }; +}; + typedef struct sub_bitmaps { - enum sub_bitmap_type type; + int render_index; // for VO cache state (limited by MAX_OSD_PARTS) - struct ass_image *imgs; + enum sub_bitmap_format format; + bool scaled; // if false, dw==w && dh==h - 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; + struct sub_bitmap *parts; + int num_parts; + + // Provided for VOs with old code + struct ass_image *imgs; - bool scaled; + // Incremented on each change int bitmap_id, bitmap_pos_id; } mp_eosd_images_t; diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 9295cab07d..aa190ee4ac 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -36,6 +36,7 @@ struct sd_ass_priv { struct ass_track *ass_track; bool vsfilter_aspect; bool incomplete_event; + struct sub_bitmap *parts; }; static void free_last_event(ASS_Track *track) @@ -147,7 +148,32 @@ 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; + res->format = SUBBITMAP_LIBASS; + + int num_parts = 0; + int num_parts_alloc = MP_TALLOC_ELEMS(ctx->parts); + struct ass_image *img = res->imgs; + while (img) { + if (img->w == 0 || img->h == 0) + continue; + if (num_parts >= num_parts_alloc) { + num_parts_alloc = FFMAX(num_parts_alloc * 2, 32); + ctx->parts = talloc_realloc(ctx, ctx->parts, struct sub_bitmap, + num_parts_alloc); + } + struct sub_bitmap *p = &ctx->parts[num_parts]; + p->bitmap = img->bitmap; + p->stride = img->stride; + p->libass.color = img->color; + p->dw = p->w = img->w; + p->dh = p->h = img->h; + p->x = img->dst_x; + p->y = img->dst_y; + img = img->next; + num_parts++; + } + res->parts = ctx->parts; + res->num_parts = num_parts; } static void reset(struct sh_sub *sh, struct osd_state *osd) diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index 1da33ffca1..39e4891fb1 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -175,6 +175,7 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, uint32_t *outbmp = talloc_size(priv->inbitmaps, r->w * r->h * 4); b->bitmap = outbmp; + b->stride = r->w * 4; b->w = r->w; b->h = r->h; b->x = r->x; @@ -233,13 +234,13 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, SET(bo->dh, bi->h * yscale); } res->parts = priv->outbitmaps; - res->part_count = priv->count; + res->num_parts = 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->format = SUBBITMAP_RGBA; res->scaled = xscale != 1 || yscale != 1; } |