From 1e0e193240a8e47a980ac76b8b5af831b17b7928 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 14 Aug 2013 17:19:32 +0200 Subject: [PATCH] sws: add dither enum This allows specifying more dither algorithms without using up flags and without ambiguities. Also initialize the new field based on the flags and use it. Note, improving the logic of the checks is left to subsequent commits, this here only switches from flags to enum. Signed-off-by: Michael Niedermayer --- doc/APIchanges | 3 +++ libswscale/options.c | 5 +++++ libswscale/output.c | 6 +++--- libswscale/swscale.c | 2 +- libswscale/swscale_internal.h | 10 ++++++++++ libswscale/swscale_unscaled.c | 2 +- libswscale/utils.c | 12 ++++++++---- libswscale/version.h | 2 +- 8 files changed, 32 insertions(+), 10 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 049d142760..1ea2bd6ab3 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2012-10-22 API changes, most recent first: +2013-08-xx - xxxxxxx - lsws 2.5.100 - + Add a sws_dither AVOption, allowing to set the dither algorithm used + 2013-08-xx - xxxxxxx - lavc 55.27.100 - vdpau.h Add a render2 alternative to the render callback function. diff --git a/libswscale/options.c b/libswscale/options.c index 81d8c28b08..8985e6b5d6 100644 --- a/libswscale/options.c +++ b/libswscale/options.c @@ -69,6 +69,11 @@ static const AVOption swscale_options[] = { { "dst_v_chr_pos", "destination vertical chroma position in luma grid/256" , OFFSET(dst_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 512, VE }, { "dst_h_chr_pos", "destination horizontal chroma position in luma grid/256", OFFSET(dst_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 512, VE }, + { "sws_dither", "set dithering algorithm", OFFSET(dither), AV_OPT_TYPE_INT, { .i64 = SWS_DITHER_AUTO }, 0, NB_SWS_DITHER, VE, "sws_dither" }, + { "auto", "leave choice to sws", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_AUTO }, INT_MIN, INT_MAX, VE, "sws_dither" }, + { "bayer", "bayer dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_BAYER }, INT_MIN, INT_MAX, VE, "sws_dither" }, + { "ed", "error diffusion", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_ED }, INT_MIN, INT_MAX, VE, "sws_dither" }, + { NULL } }; diff --git a/libswscale/output.c b/libswscale/output.c index 54b6ebd461..2d390c706c 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -349,7 +349,7 @@ yuv2mono_X_c_template(SwsContext *c, const int16_t *lumFilter, Y1 = av_clip_uint8(Y1); Y2 = av_clip_uint8(Y2); } - if (c->flags & SWS_ERROR_DIFFUSION) { + if (c->dither == SWS_DITHER_ED) { Y1 += (7*err + 1*c->dither_error[0][i] + 5*c->dither_error[0][i+1] + 3*c->dither_error[0][i+2] + 8 - 256)>>4; c->dither_error[0][i] = err; acc = 2*acc + (Y1 >= 128); @@ -386,7 +386,7 @@ yuv2mono_2_c_template(SwsContext *c, const int16_t *buf[2], int yalpha1 = 4096 - yalpha; int i; - if (c->flags & SWS_ERROR_DIFFUSION) { + if (c->dither == SWS_DITHER_ED) { int err = 0; int acc = 0; for (i = 0; i < dstW; i +=2) { @@ -443,7 +443,7 @@ yuv2mono_1_c_template(SwsContext *c, const int16_t *buf0, const uint8_t * const d128 = dither_8x8_220[y & 7]; int i; - if (c->flags & SWS_ERROR_DIFFUSION) { + if (c->dither == SWS_DITHER_ED) { int err = 0; int acc = 0; for (i = 0; i < dstW; i +=2) { diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 6721dc3a2d..87b867d2b7 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -1051,7 +1051,7 @@ int attribute_align_arg sws_scale(struct SwsContext *c, src2[0] = base; } - if (!srcSliceY && (c->flags & SWS_BITEXACT) && (c->flags & SWS_ERROR_DIFFUSION) && c->dither_error[0]) + if (!srcSliceY && (c->flags & SWS_BITEXACT) && c->dither == SWS_DITHER_ED && c->dither_error[0]) for (i = 0; i < 4; i++) memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->dstW+2)); diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 18563eed78..bd5628d081 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -61,6 +61,14 @@ struct SwsContext; +typedef enum SwsDither { + SWS_DITHER_NONE = 0, + SWS_DITHER_AUTO, + SWS_DITHER_BAYER, + SWS_DITHER_ED, + NB_SWS_DITHER, +} SwsDither; + typedef int (*SwsFunc)(struct SwsContext *context, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]); @@ -593,6 +601,8 @@ typedef struct SwsContext { void (*chrConvertRange)(int16_t *dst1, int16_t *dst2, int width); int needs_hcscale; ///< Set if there are chroma planes to be converted. + + SwsDither dither; } SwsContext; //FIXME check init (where 0) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 8735c62ba3..49338839d4 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -1180,7 +1180,7 @@ void ff_get_unscaled_swscale(SwsContext *c) /* yuv2bgr */ if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P || srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) && - !(flags & (SWS_ACCURATE_RND|SWS_ERROR_DIFFUSION)) && !(dstH & 1)) { + !(flags & SWS_ACCURATE_RND) && c->dither != SWS_DITHER_ED && !(dstH & 1)) { c->swScale = ff_yuv2rgb_get_func_ptr(c); } diff --git a/libswscale/utils.c b/libswscale/utils.c index 5aacd817b8..f5826c37be 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -1196,23 +1196,27 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, } } + if (c->dither == SWS_DITHER_AUTO) { + if (flags & SWS_ERROR_DIFFUSION) + c->dither = SWS_DITHER_ED; + } + if(dstFormat == AV_PIX_FMT_BGR4_BYTE || dstFormat == AV_PIX_FMT_RGB4_BYTE || dstFormat == AV_PIX_FMT_BGR8 || dstFormat == AV_PIX_FMT_RGB8) { - if (flags & SWS_ERROR_DIFFUSION && !(flags & SWS_FULL_CHR_H_INT)) { + if (c->dither == SWS_DITHER_ED && !(flags & SWS_FULL_CHR_H_INT)) { av_log(c, AV_LOG_DEBUG, "Error diffusion dither is only supported in full chroma interpolation for destination format '%s'\n", av_get_pix_fmt_name(dstFormat)); flags |= SWS_FULL_CHR_H_INT; c->flags = flags; } - if (!(flags & SWS_ERROR_DIFFUSION) && (flags & SWS_FULL_CHR_H_INT)) { + if (c->dither != SWS_DITHER_ED && (flags & SWS_FULL_CHR_H_INT)) { av_log(c, AV_LOG_DEBUG, "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n", av_get_pix_fmt_name(dstFormat)); - flags |= SWS_ERROR_DIFFUSION; - c->flags = flags; + c->dither = SWS_DITHER_ED; } } if (isPlanarRGB(dstFormat)) { diff --git a/libswscale/version.h b/libswscale/version.h index 1c4520926a..06f119afb3 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,7 +27,7 @@ #include "libavutil/avutil.h" #define LIBSWSCALE_VERSION_MAJOR 2 -#define LIBSWSCALE_VERSION_MINOR 4 +#define LIBSWSCALE_VERSION_MINOR 5 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \