diff options
Diffstat (limited to 'sub/draw_bmp.c')
-rw-r--r-- | sub/draw_bmp.c | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index f7f8982051..78e29f491b 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -32,7 +32,7 @@ const bool mp_draw_sub_formats[SUBBITMAP_COUNT] = { [SUBBITMAP_LIBASS] = true, - [SUBBITMAP_RGBA] = true, + [SUBBITMAP_BGRA] = true, }; struct part { @@ -84,7 +84,7 @@ struct mp_draw_sub_cache struct mp_sws_context *alpha_to_calpha; // scaler for overlay -> calpha bool scale_in_tiles; - struct mp_sws_context *sub_scale; // scaler for SUBBITMAP_RGBA + struct mp_sws_context *sub_scale; // scaler for SUBBITMAP_BGRA struct mp_repack *overlay_to_f32; // convert video_overlay to float struct mp_image *overlay_tmp; // slice in float32 @@ -260,8 +260,8 @@ static void mark_rect(struct mp_draw_sub_cache *p, int x0, int y0, int x1, int y assert(x0 >= 0 && x0 <= x1 && x1 <= p->w); assert(y0 >= 0 && y0 <= y1 && y1 <= p->h); - int sx0 = x0 / SLICE_W; - int sx1 = x1 / SLICE_W; + const int sx0 = x0 / SLICE_W; + const int sx1 = MPMIN(x1 / SLICE_W, p->s_w - 1); for (int y = y0; y < y1; y++) { struct slice *line = &p->slices[y * p->s_w]; @@ -270,7 +270,7 @@ static void mark_rect(struct mp_draw_sub_cache *p, int x0, int y0, int x1, int y struct slice *s1 = &line[sx1]; s0->x0 = MPMIN(s0->x0, x0 % SLICE_W); - s1->x1 = MPMAX(s1->x1, x1 % SLICE_W); + s1->x1 = MPMAX(s1->x1, ((x1 - 1) % SLICE_W) + 1); if (s0 != s1) { s0->x1 = SLICE_W; @@ -283,6 +283,11 @@ static void mark_rect(struct mp_draw_sub_cache *p, int x0, int y0, int x1, int y } } + // Ensure the very last slice does not extend + // beyond the total width. + struct slice *last_s = &line[p->s_w - 1]; + last_s->x1 = MPMIN(p->w - ((p->s_w - 1) * SLICE_W), last_s->x1); + p->any_osd = true; } } @@ -363,7 +368,7 @@ static void draw_rgba(uint8_t *dst, ptrdiff_t dst_stride, static bool render_rgba(struct mp_draw_sub_cache *p, struct part *part, struct sub_bitmaps *sb) { - assert(sb->format == SUBBITMAP_RGBA); + assert(sb->format == SUBBITMAP_BGRA); if (part->change_id != sb->change_id) { for (int n = 0; n < part->num_imgs; n++) @@ -426,7 +431,7 @@ static bool render_rgba(struct mp_draw_sub_cache *p, struct part *part, mp_image_set_size(&src_img, sw, sh); src_img.planes[0] = s_ptr; src_img.stride[0] = s_stride; - src_img.params.alpha = MP_ALPHA_PREMUL; + src_img.params.repr.alpha = PL_ALPHA_PREMULTIPLIED; scaled = mp_image_alloc(IMGFMT_BGRA, dw, dh); if (!scaled) @@ -462,7 +467,7 @@ static bool render_sb(struct mp_draw_sub_cache *p, struct sub_bitmaps *sb) case SUBBITMAP_LIBASS: render_ass(p, sb); return true; - case SUBBITMAP_RGBA: + case SUBBITMAP_BGRA: return render_rgba(p, part, sb); } @@ -480,6 +485,10 @@ static void clear_rgba_overlay(struct mp_draw_sub_cache *p) for (int sx = 0; sx < p->s_w; sx++) { struct slice *s = &line[sx]; + // Ensure this final slice doesn't extend beyond the width of p->s_w + if (s->x1 == SLICE_W && sx == p->s_w - 1 && y == p->rgba_overlay->h - 1) + s->x1 = MPMIN(p->w - ((p->s_w - 1) * SLICE_W), s->x1); + if (s->x0 <= s->x1) { memset(px + s->x0, 0, (s->x1 - s->x0) * 4); *s = (struct slice){SLICE_W, 0}; @@ -516,7 +525,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) struct mp_image_params *params = &p->params; mp_image_params_guess_csp(params); - bool need_premul = params->alpha != MP_ALPHA_PREMUL && + bool need_premul = params->repr.alpha != PL_ALPHA_PREMULTIPLIED && (mp_imgfmt_get_desc(params->imgfmt).flags & MP_IMGFLAG_ALPHA); // Intermediate format for video_overlay. Requirements: @@ -537,7 +546,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) 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) { + if (params->repr.sys == PL_COLOR_SYSTEM_RGB && vfdesc.num_planes >= 3) { use_shortcut = true; if (vfdesc.component_type == MP_COMPONENT_TYPE_UINT && @@ -651,9 +660,11 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) return false; mp_image_params_guess_csp(&p->rgba_overlay->params); - p->rgba_overlay->params.alpha = MP_ALPHA_PREMUL; + p->rgba_overlay->params.repr.alpha = PL_ALPHA_PREMULTIPLIED; + p->overlay_tmp->params.repr = params->repr; p->overlay_tmp->params.color = params->color; + p->video_tmp->params.repr = params->repr; p->video_tmp->params.color = params->color; if (p->rgba_overlay->imgfmt == overlay_fmt) { @@ -666,12 +677,13 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) if (!p->video_overlay) return false; + p->video_overlay->params.repr = params->repr; p->video_overlay->params.color = params->color; p->video_overlay->params.chroma_location = params->chroma_location; - p->video_overlay->params.alpha = MP_ALPHA_PREMUL; + p->video_overlay->params.repr.alpha = PL_ALPHA_PREMULTIPLIED; if (p->scale_in_tiles) - p->video_overlay->params.chroma_location = MP_CHROMA_CENTER; + p->video_overlay->params.chroma_location = PL_CHROMA_CENTER; p->rgba_to_overlay = alloc_scaler(p); p->rgba_to_overlay->allow_zimg = true; @@ -715,13 +727,14 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) p->alpha_overlay->stride[0] = p->video_overlay->stride[aplane]; // Full range gray always has the same range as alpha. - p->alpha_overlay->params.color.levels = MP_CSP_LEVELS_PC; + p->alpha_overlay->params.repr.levels = PL_COLOR_LEVELS_FULL; mp_image_params_guess_csp(&p->alpha_overlay->params); p->calpha_overlay = talloc_steal(p, mp_image_alloc(calpha_fmt, w >> xs, h >> ys)); if (!p->calpha_overlay) return false; + p->calpha_overlay->params.repr = p->alpha_overlay->params.repr; p->calpha_overlay->params.color = p->alpha_overlay->params.color; p->calpha_to_f32 = mp_repack_create_planar(calpha_fmt, false, rflags); @@ -753,7 +766,7 @@ static bool reinit_to_video(struct mp_draw_sub_cache *p) if (!p->premul_tmp) return false; mp_image_set_params(p->premul_tmp, params); - p->premul_tmp->params.alpha = MP_ALPHA_PREMUL; + p->premul_tmp->params.repr.alpha = PL_ALPHA_PREMULTIPLIED; // Only zimg supports this. p->premul->force_scaler = MP_SWS_ZIMG; @@ -778,7 +791,7 @@ static bool reinit_to_overlay(struct mp_draw_sub_cache *p) return false; mp_image_params_guess_csp(&p->rgba_overlay->params); - p->rgba_overlay->params.alpha = MP_ALPHA_PREMUL; + p->rgba_overlay->params.repr.alpha = PL_ALPHA_PREMULTIPLIED; // Some non-sense with the intention to somewhat isolate the returned image. mp_image_setfmt(&p->res_overlay, p->rgba_overlay->imgfmt); @@ -835,6 +848,14 @@ struct mp_draw_sub_cache *mp_draw_sub_alloc(void *ta_parent, struct mpv_global * return c; } +// For tests. +struct mp_draw_sub_cache *mp_draw_sub_alloc_test(struct mp_image *dst) +{ + struct mp_draw_sub_cache *c = talloc_zero(NULL, struct mp_draw_sub_cache); + reinit_to_video(c); + return c; +} + bool mp_draw_sub_bitmaps(struct mp_draw_sub_cache *p, struct mp_image *dst, struct sub_bitmap_list *sbs_list) { @@ -951,7 +972,8 @@ static void mark_rcs(struct mp_draw_sub_cache *p, struct rc_grid *gr) rc->y0 = MPMIN(rc->y0, y); rc->y1 = MPMAX(rc->y1, y + 1); rc->x0 = MPMIN(rc->x0, xpos + s->x0); - rc->x1 = MPMAX(rc->x1, xpos + s->x1); + // Ensure this does not extend beyond the total width + rc->x1 = MPCLAMP(xpos + s->x1, rc->x1, p->w); } } } |