summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmpcodecs/vfcap.h1
-rw-r--r--libvo/bitmap_packer.c47
-rw-r--r--libvo/bitmap_packer.h9
-rw-r--r--libvo/vo_corevideo.m7
-rw-r--r--libvo/vo_gl.c3
-rw-r--r--libvo/vo_gl3.c3
-rw-r--r--libvo/vo_vdpau.c84
-rw-r--r--mplayer.c2
-rw-r--r--sub/dec_sub.c3
-rw-r--r--sub/dec_sub.h49
-rw-r--r--sub/sd_ass.c28
-rw-r--r--sub/sd_lavc.c5
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){
diff --git a/mplayer.c b/mplayer.c
index d17be7c357..5c08cdf330 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -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;
}