From 3973a953df7516afbb21f4b95dde2161a67e5d84 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 24 Dec 2015 16:42:21 +0100 Subject: [PATCH] sub: find GBRP format automatically when rendering to RGB This removes the need to define IMGFMT_GBRAP, which fixes compilation with the current Libav release. This also makes it automatically pick up a GBRP format with the same bit width. (Unfortunately, it seems libswscale does not support conversion to AV_PIX_FMT_GBRAP16, so our code falls back to 8 bit, removing precision for video covered by subtitles in cases this code is used.) Also, when the source video is e.g. 10 bit YUV, upsample to 16 bit. Whether this is good or bad, it fixes behavior with alpha. Although I'm not sure if the alpha range is really correct ([0,2^16-1] vs. [0,255*256]). Keep in mind that libswscale doesn't even agree with the way we do it. --- sub/draw_bmp.c | 23 +++++++++++------------ video/fmt-conversion.c | 2 -- video/img_format.c | 6 +++--- video/img_format.h | 9 +++------ 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index ba5c6271e4..8ea426a768 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -407,21 +407,20 @@ static bool align_bbox_for_swscale(struct mp_image *img, struct mp_rect *rc) static void get_closest_y444_format(int imgfmt, int *out_format, int *out_bits) { struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(imgfmt); + int planes = desc.flags & MP_IMGFLAG_ALPHA ? 4 : 3; + int bits = desc.component_bits > 8 ? 16 : 8; if (desc.flags & MP_IMGFLAG_RGB) { - *out_format = desc.flags & MP_IMGFLAG_ALPHA ? IMGFMT_GBRAP : IMGFMT_GBRP; - *out_bits = 8; - return; + *out_format = mp_imgfmt_find(0, 0, planes, bits, MP_IMGFLAG_RGB_P); + if (!mp_sws_supported_format(*out_format)) + *out_format = mp_imgfmt_find(0, 0, planes, 8, MP_IMGFLAG_RGB_P); } 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 = mp_imgfmt_find(0, 0, planes, bits, MP_IMGFLAG_YUV_P); + } else { + *out_format = 0; } - // fallback - *out_format = IMGFMT_444P; - *out_bits = 8; + if (!mp_sws_supported_format(*out_format)) + *out_format = IMGFMT_444P; // generic fallback + *out_bits = mp_imgfmt_get_desc(*out_format).component_bits; } static struct part *get_cache(struct mp_draw_sub_cache *cache, diff --git a/video/fmt-conversion.c b/video/fmt-conversion.c index 71cd044169..d5dad6f244 100644 --- a/video/fmt-conversion.c +++ b/video/fmt-conversion.c @@ -48,8 +48,6 @@ static const struct { {IMGFMT_BGR8, AV_PIX_FMT_BGR8}, {IMGFMT_BGR4, AV_PIX_FMT_BGR4}, {IMGFMT_PAL8, AV_PIX_FMT_PAL8}, - {IMGFMT_GBRP, AV_PIX_FMT_GBRP}, - {IMGFMT_GBRAP, AV_PIX_FMT_GBRAP}, {IMGFMT_YUYV, AV_PIX_FMT_YUYV422}, {IMGFMT_UYVY, AV_PIX_FMT_UYVY422}, {IMGFMT_NV12, AV_PIX_FMT_NV12}, diff --git a/video/img_format.c b/video/img_format.c index 42b4df45ab..3535807993 100644 --- a/video/img_format.c +++ b/video/img_format.c @@ -275,12 +275,12 @@ struct mp_imgfmt_desc mp_imgfmt_get_desc(int mpfmt) return desc; } -// 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) +// Find a format that has the given flags set with the following configuration. +int mp_imgfmt_find(int xs, int ys, int planes, int component_bits, int flags) { 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.id && ((desc.flags & flags) == flags)) { if (desc.num_planes == planes && desc.chroma_xs == xs && desc.chroma_ys == ys && desc.plane_bits == component_bits && (desc.flags & MP_IMGFLAG_NE)) diff --git a/video/img_format.h b/video/img_format.h index 8788f86c35..9dbc2eedf2 100644 --- a/video/img_format.h +++ b/video/img_format.h @@ -67,7 +67,8 @@ #define MP_IMGFLAG_HWACCEL 0x10000 // Set if the chroma resolution is lower than luma resolution. Unset for non-YUV. #define MP_IMGFLAG_SUBSAMPLED 0x20000 -// Like MP_IMGFLAG_YUV_P, but RGB. The planes are organized as in IMGFMT_GBRP. +// Like MP_IMGFLAG_YUV_P, but RGB. This can be e.g. AV_PIX_FMT_GBRP. The planes +// are always shuffled (G - B - R [- A]). #define MP_IMGFLAG_RGB_P 0x40000 // Exactly one of these bits is set in mp_imgfmt_desc.flags @@ -195,10 +196,6 @@ enum mp_imgfmt { // 256 entries, with each entry encoded like in IMGFMT_BGR32. IMGFMT_PAL8, - // Planar RGB (planes are shuffled: plane 0 is G, etc.) - IMGFMT_GBRP, - IMGFMT_GBRAP, - // XYZ colorspace, similar organization to RGB48. Even though it says "12", // the components are stored as 16 bit, with lower 4 bits set to 0. IMGFMT_XYZ12, @@ -246,7 +243,7 @@ char **mp_imgfmt_name_list(void); #define vo_format_name mp_imgfmt_to_name -int mp_imgfmt_find_yuv_planar(int xs, int ys, int planes, int component_bits); +int mp_imgfmt_find(int xs, int ys, int planes, int component_bits, int flags); int mp_imgfmt_select_best(int dst1, int dst2, int src);