draw_bmp: don't copy Y plane on up/down-sampling

Image areas with subtitles are upsampled to 4:4:4 in order to render
the subtitles (makes blending easier). Try not to copy the Y plane on
upsampling. The libswscale API requires this, but this commit works it
around by scaling the chroma planes separately as AV_PIX_FMT_GRAY8. The
Y plane is not touched at all. This is done for 420p8 only, which is the
most commonly needed case. For other formats, the old way is used.

Seems to make ASS rendering faster about 15% in the setup I tested.
This commit is contained in:
wm4 2012-12-25 16:27:20 +01:00
parent 7d15bd1488
commit fb23c3a8ee
1 changed files with 46 additions and 5 deletions

View File

@ -464,23 +464,64 @@ static struct mp_image *chroma_up(struct mp_draw_sub_cache *cache, int imgfmt,
cache->upsample_temp = *cache->upsample_img;
struct mp_image *temp = &cache->upsample_temp;
mp_image_set_size(temp, src->w, src->h);
// temp is always YUV, but src not necessarily
// reduce amount of conversions in YUV case (upsampling/shifting only)
// The temp image is always YUV, but src not necessarily.
// Reduce amount of conversions in YUV case (upsampling/shifting only)
if (src->flags & MP_IMGFLAG_YUV) {
temp->colorspace = src->colorspace;
temp->levels = src->levels;
}
mp_image_swscale(temp, src, SWS_POINT); // chroma up
if (src->imgfmt == IMGFMT_420P) {
assert(imgfmt == IMGFMT_444P);
// Faster upsampling: keep Y plane, upsample chroma planes only
// The whole point is not having swscale copy the Y plane
struct mp_image t_dst = *temp;
mp_image_setfmt(&t_dst, IMGFMT_Y8);
mp_image_set_size(&t_dst, temp->chroma_width, temp->chroma_height);
struct mp_image t_src = t_dst;
mp_image_set_size(&t_src, src->chroma_width, src->chroma_height);
for (int c = 0; c < 2; c++) {
t_dst.planes[0] = temp->planes[1 + c];
t_dst.stride[0] = temp->stride[1 + c];
t_src.planes[0] = src->planes[1 + c];
t_src.stride[0] = src->stride[1 + c];
mp_image_swscale(&t_dst, &t_src, SWS_POINT);
}
temp->planes[0] = src->planes[0];
temp->stride[0] = src->stride[0];
} else {
mp_image_swscale(temp, src, SWS_POINT);
}
return temp;
}
// Undo chroma_up()
// Undo chroma_up() (copy temp to old_src if needed)
static void chroma_down(struct mp_image *old_src, struct mp_image *temp)
{
assert(old_src->w == temp->w && old_src->h == temp->h);
if (temp != old_src) {
mp_image_swscale(old_src, temp, SWS_AREA); // chroma down
if (old_src->imgfmt == IMGFMT_420P) {
// Downsampling, skipping the Y plane (see chroma_up())
assert(temp->imgfmt == IMGFMT_444P);
assert(temp->planes[0] == old_src->planes[0]);
struct mp_image t_dst = *temp;
mp_image_setfmt(&t_dst, IMGFMT_Y8);
mp_image_set_size(&t_dst, old_src->chroma_width,
old_src->chroma_height);
struct mp_image t_src = t_dst;
mp_image_set_size(&t_src, temp->chroma_width, temp->chroma_height);
for (int c = 0; c < 2; c++) {
t_dst.planes[0] = old_src->planes[1 + c];
t_dst.stride[0] = old_src->stride[1 + c];
t_src.planes[0] = temp->planes[1 + c];
t_src.stride[0] = temp->stride[1 + c];
mp_image_swscale(&t_dst, &t_src, SWS_AREA);
}
} else {
mp_image_swscale(old_src, temp, SWS_AREA); // chroma down
}
}
}