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, \