[FFmpeg-devel] [PATCH] sws: add dither enum

Michael Niedermayer michaelni at gmx.at
Wed Aug 14 17:33:53 CEST 2013


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

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
---
 libswscale/options.c          |    6 ++++++
 libswscale/output.c           |    6 +++---
 libswscale/swscale.c          |    2 +-
 libswscale/swscale_internal.h |    9 +++++++++
 libswscale/swscale_unscaled.c |    2 +-
 libswscale/utils.c            |   12 ++++++++----
 libswscale/version.h          |    2 +-
 7 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/libswscale/options.c b/libswscale/options.c
index 81d8c28..f7edd21 100644
--- a/libswscale/options.c
+++ b/libswscale/options.c
@@ -69,6 +69,12 @@ 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",      "Dither algorithm",              OFFSET(dither),    AV_OPT_TYPE_INT,    { .i64  = SWS_DITHER_AUTO   }, 0,       1,              VE, "sws_dither" },
+    { "auto",            "leave choice to sws",           0,                 AV_OPT_TYPE_CONST,  { .i64  = SWS_DITHER_AUTO   }, INT_MIN, INT_MAX,        VE, "sws_dither" },
+    { "off",             "no dither",                     0,                 AV_OPT_TYPE_CONST,  { .i64  = SWS_DITHER_NONE   }, 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 54b6ebd..2d390c7 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 6721dc3..87b867d 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 e7cc26e..a14cc02 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -61,6 +61,13 @@
 
 struct SwsContext;
 
+typedef enum SwsDither {
+    SWS_DITHER_NONE = 0,
+    SWS_DITHER_AUTO,
+    SWS_DITHER_BAYER,
+    SWS_DITHER_ED,
+} SwsDither;
+
 typedef int (*SwsFunc)(struct SwsContext *context, const uint8_t *src[],
                        int srcStride[], int srcSliceY, int srcSliceH,
                        uint8_t *dst[], int dstStride[]);
@@ -593,6 +600,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 3b07800..22196bd 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 5aacd81..f5826c3 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 1c45209..06f119a 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, \
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list