Skip to content

Commit 4d2e075

Browse files
committed
Update to 0.9.2
1 parent 7117c28 commit 4d2e075

File tree

8 files changed

+886
-369
lines changed

8 files changed

+886
-369
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
##### 0.9.2:
2+
Added parameter `clip2`. (vinverse only)
3+
14
##### 0.9.1:
25
Changed MT mode from MT_NICE_FILTER to MT_MULTI_INSTANCE.
36
Added support for 10..16-bit clips.
47
Added AVX2 and AVX512 code.
5-
Added parameter opt.
8+
Added parameter `opt`.
69
Added support for frame properties passthrough.
710
Added version.
811

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ This plugin also includes a fast implementation of [Vinverse2 function](https://
1313
### Usage:
1414

1515
```
16-
vinverse (clip input, float "sstr", int "amnt", int "uv", float "scl", int "opt")
16+
vinverse (clip input, float "sstr", int "amnt", int "uv", float "scl", int "opt", clip "clip2")
1717
```
1818
```
1919
vinverse2 (clip input, float "sstr", int "amnt", int "uv", float "scl", int "opt")
@@ -53,6 +53,9 @@ vinverse2 (clip input, float "sstr", int "amnt", int "uv", float "scl", int "opt
5353
3: Use AVX512 code.\
5454
Default: -1.
5555

56+
- clip2\
57+
External clip from which to take contra sharpening.\
58+
This clip must be the same length, width, height, and colorspace as the input clip.
5659

5760
### Building:
5861

vinverse/vinverse.cpp

Lines changed: 118 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -140,45 +140,76 @@ static void vertical_sbr_c(void* __restrict dstp_, void* __restrict tempp_, cons
140140
}
141141
}
142142

143-
template <typename T>
144-
static void finalize_plane_c(void* __restrict dstp_, const void* srcp_, const void* pb3_, const void* pb6_, float sstr, float scl, int src_pitch, int dst_pitch, int pb_pitch, int width, int height, int amnt) noexcept
143+
template <typename T, bool eclip>
144+
static void finalize_plane_c(void* __restrict dstp_, const void* srcp_, const void* pb3_, const void* pb6_, float sstr, float scl, int src_pitch, int dst_pitch, int pb_pitch, int clip2_pitch, int width, int height, int amnt) noexcept
145145
{
146146
const T* srcp = reinterpret_cast<const T*>(srcp_);
147147
const T* pb3 = reinterpret_cast<const T*>(pb3_);
148148
const T* pb6 = reinterpret_cast<const T*>(pb6_);
149149
T* __restrict dstp = reinterpret_cast<T*>(dstp_);
150150

151-
for (int y = 0; y < height; ++y)
151+
if (eclip)
152152
{
153-
for (int x = 0; x < width; ++x)
153+
for (int y = 0; y < height; ++y)
154154
{
155-
const float d1 = static_cast<float>(srcp[x] - pb3[x]);
156-
const int d2 = pb3[x] - pb6[x];
157-
const float t = d2 * sstr;
155+
for (int x = 0; x < width; ++x)
156+
{
157+
const float d1 = static_cast<float>(srcp[x] - pb3[x]);
158+
const float d2 = static_cast<float>(srcp[x] - pb6[x]);
158159

159-
const float da = (std::abs(d1) < std::abs(t)) ? d1 : t;
160-
const float desired = da * scl;
160+
const float da = (std::abs(d1) < std::abs(d2)) ? d1 : d2;
161+
const float desired = da * scl;
161162

162-
const int add = static_cast<int>(((d1 * t) < 0.0f) ? desired : da);
163-
int df = pb3[x] + add;
163+
const int add = static_cast<int>(((d1 * d2) < 0.0f) ? desired : da);
164+
int df = pb6[x] + add;
164165

165-
const int minm = srcp[x] - amnt;
166-
const int maxf = srcp[x] + amnt;
166+
const int minm = srcp[x] - amnt;
167+
const int maxf = srcp[x] + amnt;
167168

168-
df = std::max(df, minm);
169-
dstp[x] = std::min(df, maxf);
169+
df = std::max(df, minm);
170+
dstp[x] = std::min(df, maxf);
171+
}
172+
173+
srcp += src_pitch;
174+
pb3 += pb_pitch;
175+
pb6 += clip2_pitch;
176+
dstp += dst_pitch;
170177
}
178+
}
179+
else
180+
{
181+
for (int y = 0; y < height; ++y)
182+
{
183+
for (int x = 0; x < width; ++x)
184+
{
185+
const float d1 = static_cast<float>(srcp[x] - pb3[x]);
186+
const int d2 = pb3[x] - pb6[x];
187+
const float t = d2 * sstr;
171188

172-
srcp += src_pitch;
173-
pb3 += pb_pitch;
174-
pb6 += pb_pitch;
175-
dstp += dst_pitch;
189+
const float da = (std::abs(d1) < std::abs(t)) ? d1 : t;
190+
const float desired = da * scl;
191+
192+
const int add = static_cast<int>(((d1 * t) < 0.0f) ? desired : da);
193+
int df = pb3[x] + add;
194+
195+
const int minm = srcp[x] - amnt;
196+
const int maxf = srcp[x] + amnt;
197+
198+
df = std::max(df, minm);
199+
dstp[x] = std::min(df, maxf);
200+
}
201+
202+
srcp += src_pitch;
203+
pb3 += pb_pitch;
204+
pb6 += pb_pitch;
205+
dstp += dst_pitch;
206+
}
176207
}
177208
}
178209

179-
template <typename T>
180-
Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int opt, VinverseMode mode, IScriptEnvironment* env)
181-
: GenericVideoFilter(child), sstr_(sstr), amnt_(amnt), uv_(uv), scl_(scl), opt_(opt), mode_(mode), blur3_buffer(nullptr), blur6_buffer(nullptr)
210+
template <typename T, VinverseMode mode, bool eclip>
211+
Vinverse<T, mode, eclip>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int opt, PClip clip2, IScriptEnvironment* env)
212+
: GenericVideoFilter(child), sstr_(sstr), amnt_(amnt), uv_(uv), scl_(scl), opt_(opt), clip2_(clip2), blur3_buffer(nullptr), blur6_buffer(nullptr)
182213
{
183214
if (!vi.IsPlanar())
184215
env->ThrowError("Vinverse: only planar input is supported!");
@@ -206,19 +237,28 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
206237
if (!sse2 && opt_ == 1)
207238
env->ThrowError("Vinverse: opt=1 requires SSE2.");
208239

209-
int align = 16;
240+
if (eclip)
241+
{
242+
const VideoInfo& vi_ = clip2_->GetVideoInfo();
243+
244+
if (!vi.IsSameColorspace(vi_))
245+
env->ThrowError("Vinverse: clip2's colorspace doesn't match.");
246+
if (vi.width != vi_.width || vi.height != vi_.height)
247+
env->ThrowError("Vinverse: input and clip2 must be the same resolution.");
248+
if (vi.num_frames != vi_.num_frames)
249+
env->ThrowError("Vinverse: clip2's number of frames doesn't match.");
250+
}
210251

211252
if ((avx512 && opt_ < 0) || opt_ == 3)
212253
{
213254
pb_pitch = (vi.width + 63) & ~63;
214-
align = 64;
215255

216256
if (sizeof(T) == 1)
217257
{
218258
blur3 = vertical_blur3_avx512_8;
219259
blur5 = vertical_blur5_avx512_8;
220260
sbr = vertical_sbr_avx512_8;
221-
fin_plane = finalize_plane_avx512_8;
261+
fin_plane = finalize_plane_avx512_8<eclip>;
222262
}
223263
else
224264
{
@@ -254,20 +294,19 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
254294
}
255295
}
256296

257-
fin_plane = finalize_plane_avx512_16;
297+
fin_plane = finalize_plane_avx512_16<eclip>;
258298
}
259299
}
260300
else if ((avx2 && opt_ < 0) || opt_ == 2)
261301
{
262302
pb_pitch = (vi.width + 31) & ~31;
263-
align = 32;
264303

265304
if (sizeof(T) == 1)
266305
{
267306
blur3 = vertical_blur3_avx2_8;
268307
blur5 = vertical_blur5_avx2_8;
269308
sbr = vertical_sbr_avx2_8;
270-
fin_plane = finalize_plane_avx2_8;
309+
fin_plane = finalize_plane_avx2_8<eclip>;
271310
}
272311
else
273312
{
@@ -303,7 +342,7 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
303342
}
304343
}
305344

306-
fin_plane = finalize_plane_avx2_16;
345+
fin_plane = finalize_plane_avx2_16<eclip>;
307346
}
308347
}
309348
else if ((sse2 && opt_ < 0) || opt_ == 1)
@@ -315,7 +354,7 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
315354
blur3 = vertical_blur3_sse2_8;
316355
blur5 = vertical_blur5_sse2_8;
317356
sbr = vertical_sbr_sse2_8;
318-
fin_plane = finalize_plane_sse2_8;
357+
fin_plane = finalize_plane_sse2_8<eclip>;
319358
}
320359
else
321360
{
@@ -351,7 +390,7 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
351390
}
352391
}
353392

354-
fin_plane = finalize_plane_sse2_16;
393+
fin_plane = finalize_plane_sse2_16<eclip>;
355394
}
356395
}
357396
else
@@ -399,32 +438,26 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
399438
}
400439
}
401440

402-
fin_plane = finalize_plane_c<T>;
441+
fin_plane = finalize_plane_c<T, eclip>;
403442
}
404443

405444
size_t pbuf_size = vi.height * pb_pitch;
406445

407-
buffer = reinterpret_cast<T*>(aligned_malloc(pbuf_size * 2 * sizeof(T), align));
446+
buffer = std::make_unique<T[]>(pbuf_size * 2 * sizeof(T));
408447

409448
if (buffer == nullptr)
410449
env->ThrowError("Vinverse: malloc failure!");
411450

412-
blur3_buffer = buffer;
451+
blur3_buffer = buffer.get();
413452
blur6_buffer = blur3_buffer + pbuf_size;
414453

415454
v8 = true;
416455
try { env->CheckVersion(8); }
417456
catch (const AvisynthError&) { v8 = false; }
418457
}
419458

420-
template <typename T>
421-
Vinverse<T>::~Vinverse()
422-
{
423-
aligned_free(buffer);
424-
}
425-
426-
template <typename T>
427-
PVideoFrame __stdcall Vinverse<T>::GetFrame(int n, IScriptEnvironment* env)
459+
template <typename T, VinverseMode mode, bool eclip>
460+
PVideoFrame __stdcall Vinverse<T, mode, eclip>::GetFrame(int n, IScriptEnvironment* env)
428461
{
429462
PVideoFrame src = child->GetFrame(n, env);
430463
PVideoFrame dst = (v8) ? env->NewVideoFrameP(vi, &src) : env->NewVideoFrame(vi);
@@ -437,23 +470,25 @@ PVideoFrame __stdcall Vinverse<T>::GetFrame(int n, IScriptEnvironment* env)
437470
if (current_plane != PLANAR_Y && (vi.IsY8() || uv_ == 1))
438471
continue;
439472

473+
const uint8_t* srcp = src->GetReadPtr(current_plane);
474+
const int src_pitch = src->GetPitch(current_plane) / sizeof(T);
475+
const int dst_pitch = dst->GetPitch(current_plane);
476+
const int height = src->GetHeight(current_plane);
477+
const int width = src->GetRowSize(current_plane) / sizeof(T);
478+
uint8_t* dstp = dst->GetWritePtr(current_plane);
479+
440480
if (current_plane != PLANAR_Y && uv_ == 2)
441481
{
442-
env->BitBlt(dst->GetWritePtr(current_plane), dst->GetPitch(current_plane), src->GetReadPtr(current_plane), src->GetPitch(current_plane), src->GetRowSize(current_plane), src->GetHeight(current_plane));
482+
env->BitBlt(dstp, dst_pitch, srcp, src->GetPitch(current_plane), src->GetRowSize(current_plane), height);
443483
continue;
444484
}
445485

446-
const T* srcp = reinterpret_cast<const T*>(src->GetReadPtr(current_plane));
447-
const int src_pitch = src->GetPitch(current_plane) / sizeof(T);
448-
const int height = src->GetHeight(current_plane);
449-
const int width = src->GetRowSize(current_plane) / sizeof(T);
450-
T* dstp = reinterpret_cast<T*>(dst->GetWritePtr(current_plane));
451-
const int dst_pitch = dst->GetPitch(current_plane) / sizeof(T);
452-
453-
if (mode_ == VinverseMode::Vinverse)
486+
if (mode == VinverseMode::Vinverse)
454487
{
455488
blur3(blur3_buffer, srcp, pb_pitch, src_pitch, width, height);
456-
blur5(blur6_buffer, blur3_buffer, pb_pitch, pb_pitch, width, height);
489+
490+
if (!eclip)
491+
blur5(blur6_buffer, blur3_buffer, pb_pitch, pb_pitch, width, height);
457492
}
458493
else
459494
{
@@ -464,36 +499,57 @@ PVideoFrame __stdcall Vinverse<T>::GetFrame(int n, IScriptEnvironment* env)
464499
blur3(blur6_buffer, blur3_buffer, pb_pitch, pb_pitch, width, height);
465500
}
466501

467-
fin_plane(dstp, srcp, blur3_buffer, blur6_buffer, sstr_, scl_, src_pitch, dst_pitch, pb_pitch, width, height, amnt_);
502+
if (eclip)
503+
{
504+
PVideoFrame clp2 = clip2_->GetFrame(n, env);
505+
506+
fin_plane(dstp, srcp, blur3_buffer, clp2->GetReadPtr(current_plane), sstr_, scl_, src_pitch,
507+
dst_pitch / sizeof(T), pb_pitch, clp2->GetPitch(current_plane) / sizeof(T), width, height, amnt_);
508+
}
509+
else
510+
fin_plane(dst->GetWritePtr(current_plane), srcp, blur3_buffer, blur6_buffer, sstr_, scl_, src_pitch, dst_pitch / sizeof(T), pb_pitch, 0, width, height, amnt_);
468511
}
469512

470513
return dst;
471514
}
472515

473516
AVSValue __cdecl Create_Vinverse(AVSValue args, void*, IScriptEnvironment* env)
474517
{
475-
enum { CLIP, SSTR, AMNT, UV, SCL, OPT };
518+
enum { CLIP, SSTR, AMNT, UV, SCL, OPT, CLIP2 };
476519

477520
PClip clip = args[CLIP].AsClip();
521+
PClip clip2 = (args[CLIP2].Defined()) ? args[CLIP2].AsClip() : nullptr;
478522

479-
switch (clip->GetVideoInfo().ComponentSize())
523+
if (clip2)
480524
{
481-
case 1: return new Vinverse<uint8_t>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), VinverseMode::Vinverse, env);
482-
case 2: return new Vinverse<uint16_t>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), VinverseMode::Vinverse, env);
483-
default: env->ThrowError("Vinverse: only 8..16-bit input is supported!");
525+
switch (clip->GetVideoInfo().ComponentSize())
526+
{
527+
case 1: return new Vinverse<uint8_t, VinverseMode::Vinverse, true>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), clip2, env);
528+
case 2: return new Vinverse<uint16_t, VinverseMode::Vinverse, true>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), clip2, env);
529+
default: env->ThrowError("Vinverse: only 8..16-bit input is supported!");
530+
}
531+
}
532+
else
533+
{
534+
switch (clip->GetVideoInfo().ComponentSize())
535+
{
536+
case 1: return new Vinverse<uint8_t, VinverseMode::Vinverse, false>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), clip2, env);
537+
case 2: return new Vinverse<uint16_t, VinverseMode::Vinverse, false>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), clip2, env);
538+
default: env->ThrowError("Vinverse: only 8..16-bit input is supported!");
539+
}
484540
}
485541
}
486542

487543
AVSValue __cdecl Create_Vinverse2(AVSValue args, void*, IScriptEnvironment* env)
488544
{
489-
enum { CLIP, SSTR, AMNT, UV, SCL, OPT };
545+
enum { CLIP, SSTR, AMNT, UV, SCL, OPT, CLIP2 };
490546

491547
PClip clip = args[CLIP].AsClip();
492548

493549
switch (clip->GetVideoInfo().ComponentSize())
494550
{
495-
case 1: return new Vinverse<uint8_t>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), VinverseMode::Vinverse2, env);
496-
case 2: return new Vinverse<uint16_t>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), VinverseMode::Vinverse2, env);
551+
case 1: return new Vinverse<uint8_t, VinverseMode::Vinverse2, false>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), nullptr, env);
552+
case 2: return new Vinverse<uint16_t, VinverseMode::Vinverse2, false>(clip, args[SSTR].AsFloatf(2.7f), args[AMNT].AsInt(-1), args[UV].AsInt(3), args[SCL].AsFloatf(0.25f), args[OPT].AsInt(-1), nullptr, env);
497553
default: env->ThrowError("Vinverse: only 8..16-bit input is supported!");
498554
}
499555
}
@@ -504,7 +560,7 @@ extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit3(IScri
504560
{
505561
AVS_linkage = vectors;
506562

507-
env->AddFunction("vinverse", "c[sstr]f[amnt]i[uv]i[scl]f[opt]i", Create_Vinverse, 0);
563+
env->AddFunction("vinverse", "c[sstr]f[amnt]i[uv]i[scl]f[opt]i[clip2]c", Create_Vinverse, 0);
508564
env->AddFunction("vinverse2", "c[sstr]f[amnt]i[uv]i[scl]f[opt]i", Create_Vinverse2, 0);
509565
return "Doushimashita?";
510566
}

0 commit comments

Comments
 (0)