diff --git a/DeblockPP7/DeblockPP7.cpp b/DeblockPP7/DeblockPP7.cpp index 8e3354c..c86dc83 100644 --- a/DeblockPP7/DeblockPP7.cpp +++ b/DeblockPP7/DeblockPP7.cpp @@ -119,17 +119,37 @@ static void pp7Filter_c(const VSFrameRef * src, VSFrameRef * dst, const DeblockP dctB(tp, block); int64_t v = static_cast(block[0]) * d->factor[0]; - for (int i = 1; i < 16; i++) { - const unsigned threshold1 = d->thresh[i]; - const unsigned threshold2 = threshold1 * 2; - if (block[i] + threshold1 > threshold2) { - if (block[i] + threshold2 > threshold2 * 2) { + if (d->mode == 0) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (block[i] + threshold1 > threshold2) v += static_cast(block[i]) * d->factor[i]; - } else { + } + } else if (d->mode == 1) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (block[i] + threshold1 > threshold2) { if (block[i] > 0) - v += 2LL * (block[i] - static_cast(threshold1)) * d->factor[i]; + v += (block[i] - static_cast(threshold1)) * d->factor[i]; else - v += 2LL * (block[i] + static_cast(threshold1)) * d->factor[i]; + v += (block[i] + static_cast(threshold1)) * d->factor[i]; + } + } + } else { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (block[i] + threshold1 > threshold2) { + if (block[i] + threshold2 > threshold2 * 2) { + v += static_cast(block[i]) * d->factor[i]; + } else { + if (block[i] > 0) + v += 2 * (block[i] - static_cast(threshold1)) * d->factor[i]; + else + v += 2 * (block[i] + static_cast(threshold1)) * d->factor[i]; + } } } } @@ -192,22 +212,42 @@ void pp7Filter_c(const VSFrameRef * src, VSFrameRef * dst, const DeblockP dctB(tp, block); float v = block[0] * d->factor[0]; - for (int i = 1; i < 16; i++) { - const unsigned threshold1 = d->thresh[i]; - const unsigned threshold2 = threshold1 * 2; - if (static_cast(block[i]) + threshold1 > threshold2) { - if (static_cast(block[i]) + threshold2 > threshold2 * 2) { + if (d->mode == 0) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (static_cast(block[i]) + threshold1 > threshold2) v += block[i] * d->factor[i]; - } else { + } + } else if (d->mode == 1) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (static_cast(block[i]) + threshold1 > threshold2) { if (block[i] > 0.f) - v += 2.f * (block[i] - threshold1) * d->factor[i]; + v += (block[i] - threshold1) * d->factor[i]; else - v += 2.f * (block[i] + threshold1) * d->factor[i]; + v += (block[i] + threshold1) * d->factor[i]; + } + } + } else { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (static_cast(block[i]) + threshold1 > threshold2) { + if (static_cast(block[i]) + threshold2 > threshold2 * 2) { + v += block[i] * d->factor[i]; + } else { + if (block[i] > 0.f) + v += 2.f * (block[i] - threshold1) * d->factor[i]; + else + v += 2.f * (block[i] + threshold1) * d->factor[i]; + } } } } - dstp[srcStride * y + x] = v * (1.f / (1 << 18)) * (1.f / 255.f); + dstp[srcStride * y + x] = v * ((1.f / (1 << 18)) * (1.f / 255.f)); } } } @@ -314,9 +354,11 @@ static void VS_CC pp7Create(const VSMap *in, VSMap *out, void *userData, VSCore (d->vi->format->sampleType == stFloat && d->vi->format->bitsPerSample != 32)) throw std::string{ "only constant format 8-16 bit integer and 32 bit float input supported" }; - int qp = int64ToIntS(vsapi->propGetInt(in, "qp", 0, &err)); + double qp = vsapi->propGetFloat(in, "qp", 0, &err); if (err) - qp = 5; + qp = 2.; + + d->mode = int64ToIntS(vsapi->propGetInt(in, "mode", 0, &err)); const int opt = int64ToIntS(vsapi->propGetInt(in, "opt", 0, &err)); @@ -337,8 +379,11 @@ static void VS_CC pp7Create(const VSMap *in, VSMap *out, void *userData, VSCore d->process[n] = true; } - if (qp < 1 || qp > 63) - throw std::string{ "qp must be between 1 and 63 (inclusive)" }; + if (qp < 1. || qp > 63.) + throw std::string{ "qp must be between 1.0 and 63.0 (inclusive)" }; + + if (d->mode < 0 || d->mode > 2) + throw std::string{ "mode must be 0, 1 or 2" }; if (opt < 0 || opt > 3) throw std::string{ "opt must be 0, 1, 2 or 3" }; @@ -379,7 +424,7 @@ static void VS_CC pp7Create(const VSMap *in, VSMap *out, void *userData, VSCore } for (int i = 0; i < 16; i++) - d->thresh[i] = static_cast((((i & 1) ? SN2 : SN0) * ((i & 4) ? SN2 : SN0) * qp * (1 << 2) - 1) * d->peak / 255); + d->thresh[i] = static_cast((((i & 1) ? SN2 : SN0) * ((i & 4) ? SN2 : SN0) * qp * (1 << 2) - 1) * d->peak / 255.); } catch (const std::string & error) { vsapi->setError(out, ("DeblockPP7: " + error).c_str()); vsapi->freeNode(d->node); @@ -421,7 +466,8 @@ VS_EXTERNAL_API(void) VapourSynthPluginInit(VSConfigPlugin configFunc, VSRegiste configFunc("com.holywu.pp7", "pp7", "Postprocess 7 from MPlayer", VAPOURSYNTH_API_VERSION, 1, plugin); registerFunc("DeblockPP7", "clip:clip;" - "qp:int:opt;" + "qp:float:opt;" + "mode:int:opt;" "opt:int:opt;" "planes:int[]:opt;", pp7Create, nullptr, plugin); diff --git a/DeblockPP7/DeblockPP7.hpp b/DeblockPP7/DeblockPP7.hpp index 4e86b5e..471ce93 100644 --- a/DeblockPP7/DeblockPP7.hpp +++ b/DeblockPP7/DeblockPP7.hpp @@ -22,6 +22,7 @@ static constexpr double SN2 = 3.1622776601683795; struct DeblockPP7Data { VSNodeRef * node; const VSVideoInfo * vi; + int mode; bool process[3]; int stride[3]; unsigned thresh[16], peak; diff --git a/DeblockPP7/DeblockPP7_SSE2.cpp b/DeblockPP7/DeblockPP7_SSE2.cpp index c42d9b4..23f7a6e 100644 --- a/DeblockPP7/DeblockPP7_SSE2.cpp +++ b/DeblockPP7/DeblockPP7_SSE2.cpp @@ -135,17 +135,37 @@ void pp7Filter_sse2(const VSFrameRef * src, VSFrameRef * dst, const DeblockPP7Da dctB(tp, block); int64_t v = static_cast(block[0]) * d->factor[0]; - for (int i = 1; i < 16; i++) { - const unsigned threshold1 = d->thresh[i]; - const unsigned threshold2 = threshold1 * 2; - if (block[i] + threshold1 > threshold2) { - if (block[i] + threshold2 > threshold2 * 2) { + if (d->mode == 0) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (block[i] + threshold1 > threshold2) v += static_cast(block[i]) * d->factor[i]; - } else { + } + } else if (d->mode == 1) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (block[i] + threshold1 > threshold2) { if (block[i] > 0) - v += 2LL * (block[i] - static_cast(threshold1)) * d->factor[i]; + v += (block[i] - static_cast(threshold1)) * d->factor[i]; else - v += 2LL * (block[i] + static_cast(threshold1)) * d->factor[i]; + v += (block[i] + static_cast(threshold1)) * d->factor[i]; + } + } + } else { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (block[i] + threshold1 > threshold2) { + if (block[i] + threshold2 > threshold2 * 2) { + v += static_cast(block[i]) * d->factor[i]; + } else { + if (block[i] > 0) + v += 2 * (block[i] - static_cast(threshold1)) * d->factor[i]; + else + v += 2 * (block[i] + static_cast(threshold1)) * d->factor[i]; + } } } } @@ -211,22 +231,42 @@ void pp7Filter_sse2(const VSFrameRef * src, VSFrameRef * dst, const Deblo dctB(tp, block); float v = block[0] * d->factor[0]; - for (int i = 1; i < 16; i++) { - const unsigned threshold1 = d->thresh[i]; - const unsigned threshold2 = threshold1 * 2; - if (static_cast(block[i]) + threshold1 > threshold2) { - if (static_cast(block[i]) + threshold2 > threshold2 * 2) { + if (d->mode == 0) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (static_cast(block[i]) + threshold1 > threshold2) v += block[i] * d->factor[i]; - } else { + } + } else if (d->mode == 1) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (static_cast(block[i]) + threshold1 > threshold2) { if (block[i] > 0.f) - v += 2.f * (block[i] - threshold1) * d->factor[i]; + v += (block[i] - threshold1) * d->factor[i]; else - v += 2.f * (block[i] + threshold1) * d->factor[i]; + v += (block[i] + threshold1) * d->factor[i]; + } + } + } else { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (static_cast(block[i]) + threshold1 > threshold2) { + if (static_cast(block[i]) + threshold2 > threshold2 * 2) { + v += block[i] * d->factor[i]; + } else { + if (block[i] > 0.f) + v += 2.f * (block[i] - threshold1) * d->factor[i]; + else + v += 2.f * (block[i] + threshold1) * d->factor[i]; + } } } } - dstp[srcStride * y + x] = v * (1.f / (1 << 18)) * (1.f / 255.f); + dstp[srcStride * y + x] = v * ((1.f / (1 << 18)) * (1.f / 255.f)); } } } diff --git a/DeblockPP7/DeblockPP7_SSE4.cpp b/DeblockPP7/DeblockPP7_SSE4.cpp index 8bd9df3..82a1930 100644 --- a/DeblockPP7/DeblockPP7_SSE4.cpp +++ b/DeblockPP7/DeblockPP7_SSE4.cpp @@ -139,17 +139,37 @@ void pp7Filter_sse4(const VSFrameRef * src, VSFrameRef * dst, const DeblockPP7Da dctB(tp, block); int64_t v = static_cast(block[0]) * d->factor[0]; - for (int i = 1; i < 16; i++) { - const unsigned threshold1 = d->thresh[i]; - const unsigned threshold2 = threshold1 * 2; - if (block[i] + threshold1 > threshold2) { - if (block[i] + threshold2 > threshold2 * 2) { + if (d->mode == 0) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (block[i] + threshold1 > threshold2) v += static_cast(block[i]) * d->factor[i]; - } else { + } + } else if (d->mode == 1) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (block[i] + threshold1 > threshold2) { if (block[i] > 0) - v += 2LL * (block[i] - static_cast(threshold1)) * d->factor[i]; + v += (block[i] - static_cast(threshold1)) * d->factor[i]; else - v += 2LL * (block[i] + static_cast(threshold1)) * d->factor[i]; + v += (block[i] + static_cast(threshold1)) * d->factor[i]; + } + } + } else { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (block[i] + threshold1 > threshold2) { + if (block[i] + threshold2 > threshold2 * 2) { + v += static_cast(block[i]) * d->factor[i]; + } else { + if (block[i] > 0) + v += 2 * (block[i] - static_cast(threshold1)) * d->factor[i]; + else + v += 2 * (block[i] + static_cast(threshold1)) * d->factor[i]; + } } } } @@ -215,22 +235,42 @@ void pp7Filter_sse4(const VSFrameRef * src, VSFrameRef * dst, const Deblo dctB(tp, block); float v = block[0] * d->factor[0]; - for (int i = 1; i < 16; i++) { - const unsigned threshold1 = d->thresh[i]; - const unsigned threshold2 = threshold1 * 2; - if (static_cast(block[i]) + threshold1 > threshold2) { - if (static_cast(block[i]) + threshold2 > threshold2 * 2) { + if (d->mode == 0) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (static_cast(block[i]) + threshold1 > threshold2) v += block[i] * d->factor[i]; - } else { + } + } else if (d->mode == 1) { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (static_cast(block[i]) + threshold1 > threshold2) { if (block[i] > 0.f) - v += 2.f * (block[i] - threshold1) * d->factor[i]; + v += (block[i] - threshold1) * d->factor[i]; else - v += 2.f * (block[i] + threshold1) * d->factor[i]; + v += (block[i] + threshold1) * d->factor[i]; + } + } + } else { + for (int i = 1; i < 16; i++) { + const unsigned threshold1 = d->thresh[i]; + const unsigned threshold2 = threshold1 * 2; + if (static_cast(block[i]) + threshold1 > threshold2) { + if (static_cast(block[i]) + threshold2 > threshold2 * 2) { + v += block[i] * d->factor[i]; + } else { + if (block[i] > 0.f) + v += 2.f * (block[i] - threshold1) * d->factor[i]; + else + v += 2.f * (block[i] + threshold1) * d->factor[i]; + } } } } - dstp[srcStride * y + x] = v * (1.f / (1 << 18)) * (1.f / 255.f); + dstp[srcStride * y + x] = v * ((1.f / (1 << 18)) * (1.f / 255.f)); } } } diff --git a/README.md b/README.md index 2c4f438..f889b7e 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,16 @@ Variant of the spp filter in MPlayer, similar to spp=6 with 7 point DCT where on Usage ===== - pp7.DeblockPP7(clip clip[, int qp=5, int opt=0, int[] planes]) + pp7.DeblockPP7(clip clip[, float qp=2.0, int mode=0, int opt=0, int[] planes]) * clip: Clip to process. Any planar format with either integer sample type of 8-16 bit depth or float sample type of 32 bit depth is supported. -* qp: Constant quantization parameter. It accepts an integer in range 1 to 63. +* qp: Constant quantization parameter. It accepts a value in range 1.0 to 63.0. + +* mode: + * 0 = hard thresholding + * 1 = soft thresholding (better deringing, but blurrier) + * 2 = medium thresholding (compromise between hard and soft) * opt: Sets which cpu optimizations to use. * 0 = auto detect