summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-05-12 23:10:14 +0200
committerwm4 <wm4@nowhere>2020-05-12 23:10:14 +0200
commit0ff839d46742a0927752f6899688228b30df6a5f (patch)
tree3d17976ef6e17c1603e0cb907704c00e1f64416a /sub
parent1e75f442b1454a1a4c16fc556e892150fd6ceec5 (diff)
downloadmpv-0ff839d46742a0927752f6899688228b30df6a5f.tar.bz2
mpv-0ff839d46742a0927752f6899688228b30df6a5f.tar.xz
draw_bmp: add integer blending for 8 bit formats
Whatever it's worth. Instead of doing a pretty stupid conversion to float, just blend it directly. This works for most RGB formats that are 8 bits per component or below (the latter because we expand packed fringe RGB formats for simplicity). For higher bit depth RGB this would need extra code.
Diffstat (limited to 'sub')
-rw-r--r--sub/draw_bmp.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c
index 7ef0a9f3ff..ba6ea7e646 100644
--- a/sub/draw_bmp.c
+++ b/sub/draw_bmp.c
@@ -114,6 +114,16 @@ static void blend_line_f32(void *dst, void *src, void *src_a, int w)
dst_f[x] = src_f[x] + dst_f[x] * (1.0f - src_a_f[x]);
}
+static void blend_line_u8(void *dst, void *src, void *src_a, int w)
+{
+ uint8_t *dst_i = dst;
+ uint8_t *src_i = src;
+ uint8_t *src_a_i = src_a;
+
+ for (int x = 0; x < w; x++)
+ dst_i[x] = src_i[x] + dst_i[x] * (255u - src_a_i[x]) / 255u;
+}
+
static void blend_slice(struct mp_draw_sub_cache *p)
{
struct mp_image *ov = p->overlay_tmp;
@@ -500,13 +510,48 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p)
bool need_premul = params->alpha != MP_ALPHA_PREMUL &&
(mp_imgfmt_get_desc(params->imgfmt).flags & MP_IMGFLAG_ALPHA);
- int rflags = REPACK_CREATE_EXPAND_8BIT | REPACK_CREATE_PLANAR_F32;
- p->blend_line = blend_line_f32;
+ // Intermediate format for video_overlay. Requirements:
+ // - same subsampling as video
+ // - uses video colorspace
+ // - has alpha
+ // - repacker support (to the format used in p->blend_line)
+ // - probably 8 bit per component rather than something wasteful or strange
+ struct mp_regular_imgfmt vfdesc = {0};
+
+ int rflags = REPACK_CREATE_EXPAND_8BIT;
+ bool use_shortcut = false;
p->video_to_f32 = mp_repack_create_planar(params->imgfmt, false, rflags);
talloc_steal(p, p->video_to_f32);
if (!p->video_to_f32)
return false;
+ mp_get_regular_imgfmt(&vfdesc, mp_repack_get_format_dst(p->video_to_f32));
+ assert(vfdesc.num_planes); // must have succeeded
+
+ if (params->color.space == MP_CSP_RGB && vfdesc.num_planes >= 3) {
+ use_shortcut = true;
+
+ if (vfdesc.component_type == MP_COMPONENT_TYPE_UINT &&
+ vfdesc.component_size == 1 && vfdesc.component_pad == 0)
+ p->blend_line = blend_line_u8;
+ }
+
+ // If no special blender is available, blend in float.
+ if (!p->blend_line) {
+ TA_FREEP(&p->video_to_f32);
+
+ rflags |= REPACK_CREATE_PLANAR_F32;
+
+ p->video_to_f32 = mp_repack_create_planar(params->imgfmt, false, rflags);
+ talloc_steal(p, p->video_to_f32);
+ if (!p->video_to_f32)
+ return false;
+
+ mp_get_regular_imgfmt(&vfdesc, mp_repack_get_format_dst(p->video_to_f32));
+ assert(vfdesc.component_type == MP_COMPONENT_TYPE_FLOAT);
+
+ p->blend_line = blend_line_f32;
+ }
p->scale_in_tiles = SCALE_IN_TILES;
@@ -520,18 +565,8 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p)
assert(mp_repack_get_format_dst(p->video_to_f32) ==
mp_repack_get_format_src(p->video_from_f32));
- // Find a reasonable intermediate format for video_overlay. Requirements:
- // - same subsampling
- // - has alpha
- // - uses video colorspace
- // - REPACK_CREATE_PLANAR_F32 support
- // - probably not using float (vaguely wastes memory)
- struct mp_regular_imgfmt vfdesc = {0};
- mp_get_regular_imgfmt(&vfdesc, mp_repack_get_format_dst(p->video_to_f32));
- assert(vfdesc.component_type == MP_COMPONENT_TYPE_FLOAT);
-
int overlay_fmt = 0;
- if (params->color.space == MP_CSP_RGB && vfdesc.num_planes >= 3) {
+ if (use_shortcut) {
// No point in doing anything fancy.
overlay_fmt = IMGFMT_BGRA;
p->scale_in_tiles = false;
@@ -643,6 +678,9 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p)
int xs = p->video_overlay->fmt.chroma_xs;
int ys = p->video_overlay->fmt.chroma_ys;
if (xs || ys) {
+ // Require float so format selection becomes simpler (maybe).
+ assert(rflags & REPACK_CREATE_PLANAR_F32);
+
// For extracting the alpha plane, construct a gray format that is
// compatible with the alpha one.
struct mp_regular_imgfmt odesc = {0};