From be5994a7818a63e16d78ed4817eb1ac490869bfe Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 6 Feb 2015 23:20:41 +0100 Subject: video: work around libswscale for PNG pixel formats The intention is that we can test vo_opengl with high bit depth PNGs better. This throws libswscale completely out of the loop, which before was needed in order to convert from big endian to little endian. Also apply a minimal cleanup to fmt-conversion.c (unrelated). --- video/sws_utils.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'video/sws_utils.c') diff --git a/video/sws_utils.c b/video/sws_utils.c index 8937799f09..7f3cd089ac 100644 --- a/video/sws_utils.c +++ b/video/sws_utils.c @@ -20,6 +20,7 @@ #include #include +#include #include #include "config.h" @@ -34,6 +35,7 @@ #include "csputils.h" #include "common/msg.h" #include "video/filter/vf.h" +#include "osdep/endian.h" //global sws_flags from the command line struct sws_opts { @@ -317,4 +319,38 @@ int mp_sws_set_vf_equalizer(struct mp_sws_context *sws, struct vf_seteq *eq) return mp_sws_reinit(sws) >= 0 ? 1 : -1; } +static const int endian_swaps[][2] = { +#if BYTE_ORDER == LITTLE_ENDIAN +#if defined(AV_PIX_FMT_YA16) && defined(AV_PIX_FMT_RGBA64) + {AV_PIX_FMT_YA16BE, AV_PIX_FMT_YA16LE}, + {AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_RGBA64LE}, + {AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_GRAY16LE}, + {AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGB48LE}, +#endif +#endif + {AV_PIX_FMT_NONE, AV_PIX_FMT_NONE} +}; + +// Swap _some_ non-native endian formats to native. We do this specifically +// for pixel formats used by PNG, to avoid going through libswscale, which +// might reduce the effective bit depth in some cases. +struct mp_image *mp_img_swap_to_native(struct mp_image *img) +{ + int to = AV_PIX_FMT_NONE; + for (int n = 0; endian_swaps[n][0] != AV_PIX_FMT_NONE; n++) { + if (endian_swaps[n][0] == img->fmt.avformat) + to = endian_swaps[n][1]; + } + if (to == AV_PIX_FMT_NONE || !mp_image_make_writeable(img)) + return img; + int elems = img->fmt.bytes[0] / 2 * img->w; + for (int y = 0; y < img->h; y++) { + uint16_t *p = (uint16_t *)(img->planes[0] + y * img->stride[0]); + for (int i = 0; i < elems; i++) + p[i] = av_be2ne16(p[i]); + } + mp_image_setfmt(img, pixfmt2imgfmt(to)); + return img; +} + // vim: ts=4 sw=4 et tw=80 -- cgit v1.2.3