draw_bmp: better way to find 444 format

Even though #ifdef ACCURATE is removed, the result should be about the
same. The fallback is only used by packed YUV formats (YUYV, NV12), and
doing 16 bit for them instead of 8 bit is not useful.

A side effect is that Y8 (gray) is not converted drawing subs, and for
alpha formats, the alpha plane is not removed. This means the number of
planes after upsampling can be 1-4 (1: gray, 2: gray+alpha, 3: planar,
4: planar+alpha). The code has to be adjusted accordingly to work on the
color planes only. Also remove the workaround for the chroma shift 31
hack.
This commit is contained in:
wm4 2012-12-25 14:54:42 +01:00
parent 8751a0e261
commit 3791c226b7
3 changed files with 30 additions and 43 deletions

View File

@ -264,7 +264,7 @@ static void draw_rgba(struct mp_draw_sub_cache **cache, struct mp_rect bb,
int bytes = (bits + 7) / 8; int bytes = (bits + 7) / 8;
uint8_t *alpha_p = sba->planes[0] + src_y * sba->stride[0] + src_x; uint8_t *alpha_p = sba->planes[0] + src_y * sba->stride[0] + src_x;
for (int p = 0; p < 3; p++) { for (int p = 0; p < (temp->num_planes > 2 ? 3 : 1); p++) {
void *src = sbi->planes[p] + src_y * sbi->stride[p] + src_x * bytes; void *src = sbi->planes[p] + src_y * sbi->stride[p] + src_x * bytes;
blend_src_alpha(dst.planes[p], dst.stride[p], src, sbi->stride[p], blend_src_alpha(dst.planes[p], dst.stride[p], src, sbi->stride[p],
alpha_p, sba->stride[0], dst.w, dst.h, bytes); alpha_p, sba->stride[0], dst.w, dst.h, bytes);
@ -318,7 +318,7 @@ static void draw_ass(struct mp_draw_sub_cache **cache, struct mp_rect bb,
int bytes = (bits + 7) / 8; int bytes = (bits + 7) / 8;
uint8_t *alpha_p = (uint8_t *)sb->bitmap + src_y * sb->stride + src_x; uint8_t *alpha_p = (uint8_t *)sb->bitmap + src_y * sb->stride + src_x;
for (int p = 0; p < 3; p++) { for (int p = 0; p < (temp->num_planes > 2 ? 3 : 1); p++) {
blend_const_alpha(dst.planes[p], dst.stride[p], color_yuv[p], blend_const_alpha(dst.planes[p], dst.stride[p], color_yuv[p],
alpha_p, sb->stride, a, dst.w, dst.h, bytes); alpha_p, sb->stride, a, dst.w, dst.h, bytes);
} }
@ -351,12 +351,6 @@ static void get_swscale_alignment(const struct mp_image *img, int *out_xstep,
int sx = (1 << img->chroma_x_shift); int sx = (1 << img->chroma_x_shift);
int sy = (1 << img->chroma_y_shift); int sy = (1 << img->chroma_y_shift);
// Hack for IMGFMT_Y8
if (img->chroma_x_shift == 31 && img->chroma_y_shift == 31) {
sx = 1;
sy = 1;
}
for (int p = 0; p < img->num_planes; ++p) { for (int p = 0; p < img->num_planes; ++p) {
int bits = img->fmt.bpp[p]; int bits = img->fmt.bpp[p];
// the * 2 fixes problems with writing past the destination width // the * 2 fixes problems with writing past the destination width
@ -389,49 +383,25 @@ static bool align_bbox_for_swscale(struct mp_image *img, struct mp_rect *rc)
return clip_to_bb(img_rect, rc); return clip_to_bb(img_rect, rc);
} }
// Try to find best/closest YUV 444 format for imgfmt // Try to find best/closest YUV 444 format (or similar) for imgfmt
static void get_closest_y444_format(int imgfmt, int *out_format, int *out_bits) static void get_closest_y444_format(int imgfmt, int *out_format, int *out_bits)
{ {
#ifdef ACCURATE struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(imgfmt);
struct mp_image tmp = {0}; if (desc.flags & MP_IMGFLAG_RGB) {
mp_image_setfmt(&tmp, imgfmt);
if (tmp.flags & MP_IMGFLAG_YUV) {
int bits;
if (mp_get_chroma_shift(imgfmt, NULL, NULL, &bits)) {
switch (bits) {
case 8:
*out_format = IMGFMT_444P;
*out_bits = 8;
return;
case 9:
*out_format = IMGFMT_444P9;
*out_bits = 9;
return;
case 10:
*out_format = IMGFMT_444P10;
*out_bits = 10;
return;
case 12:
*out_format = IMGFMT_444P12;
*out_bits = 12;
return;
case 14:
*out_format = IMGFMT_444P14;
*out_bits = 14;
return;
}
}
} else {
*out_format = IMGFMT_GBRP; *out_format = IMGFMT_GBRP;
*out_bits = 8; *out_bits = 8;
return; return;
} else if (desc.flags & MP_IMGFLAG_YUV_P) {
*out_format = mp_imgfmt_find_yuv_planar(0, 0, desc.num_planes,
desc.plane_bits);
if (*out_format && mp_sws_supported_format(*out_format)) {
*out_bits = mp_imgfmt_get_desc(*out_format).plane_bits;
return;
}
} }
*out_format = IMGFMT_444P16; // fallback
*out_bits = 16;
#else
*out_format = IMGFMT_444P; *out_format = IMGFMT_444P;
*out_bits = 8; *out_bits = 8;
#endif
} }
static struct part *get_cache(struct mp_draw_sub_cache **cache, static struct part *get_cache(struct mp_draw_sub_cache **cache,

View File

@ -310,3 +310,18 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(unsigned int out_fmt)
} }
return fmt; return fmt;
} }
// Find a format that is MP_IMGFLAG_YUV_P with the following configuration.
int mp_imgfmt_find_yuv_planar(int xs, int ys, int planes, int component_bits)
{
for (int n = IMGFMT_START + 1; n < IMGFMT_END; n++) {
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(n);
if (desc.id && (desc.flags & MP_IMGFLAG_YUV_P)) {
if (desc.num_planes == planes && desc.chroma_xs == xs &&
desc.chroma_ys == ys && desc.plane_bits == component_bits &&
(desc.flags & MP_IMGFLAG_NE))
return desc.id;
}
}
return 0;
}

View File

@ -298,4 +298,6 @@ const char *mp_imgfmt_to_name(unsigned int fmt);
#define vo_format_name mp_imgfmt_to_name #define vo_format_name mp_imgfmt_to_name
int mp_imgfmt_find_yuv_planar(int xs, int ys, int planes, int component_bits);
#endif /* MPLAYER_IMG_FORMAT_H */ #endif /* MPLAYER_IMG_FORMAT_H */