From 97d69c6d9f4b8ab4647fb1b3fa829432066ef76d Mon Sep 17 00:00:00 2001 From: msg7086 Date: Tue, 30 Sep 2014 23:23:13 -0700 Subject: [PATCH] VS_IT Initial Porting --- vs_it.sln | 22 ++ vs_it/IScriptEnvironment.cpp | 35 ++ vs_it/IScriptEnvironment.h | 83 +++++ vs_it/vs_it.cpp | 236 ++++++++++++++ vs_it/vs_it.h | 175 ++++++++++ vs_it/vs_it.vcxproj | 102 ++++++ vs_it/vs_it_interface.cpp | 108 ++++++ vs_it/vs_it_interface.h | 51 +++ vs_it/vs_it_misc.cpp | 615 +++++++++++++++++++++++++++++++++++ vs_it/vs_it_process.cpp | 485 +++++++++++++++++++++++++++ 10 files changed, 1912 insertions(+) create mode 100644 vs_it.sln create mode 100644 vs_it/IScriptEnvironment.cpp create mode 100644 vs_it/IScriptEnvironment.h create mode 100644 vs_it/vs_it.cpp create mode 100644 vs_it/vs_it.h create mode 100644 vs_it/vs_it.vcxproj create mode 100644 vs_it/vs_it_interface.cpp create mode 100644 vs_it/vs_it_interface.h create mode 100644 vs_it/vs_it_misc.cpp create mode 100644 vs_it/vs_it_process.cpp diff --git a/vs_it.sln b/vs_it.sln new file mode 100644 index 0000000..c45763e --- /dev/null +++ b/vs_it.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vs_it", "vs_it\vs_it.vcxproj", "{296F3E49-8C9B-47E2-BF8A-B1EDD6A322CB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {296F3E49-8C9B-47E2-BF8A-B1EDD6A322CB}.Debug|Win32.ActiveCfg = Debug|Win32 + {296F3E49-8C9B-47E2-BF8A-B1EDD6A322CB}.Debug|Win32.Build.0 = Debug|Win32 + {296F3E49-8C9B-47E2-BF8A-B1EDD6A322CB}.Release|Win32.ActiveCfg = Release|Win32 + {296F3E49-8C9B-47E2-BF8A-B1EDD6A322CB}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vs_it/IScriptEnvironment.cpp b/vs_it/IScriptEnvironment.cpp new file mode 100644 index 0000000..8e221b0 --- /dev/null +++ b/vs_it/IScriptEnvironment.cpp @@ -0,0 +1,35 @@ +/* +VS_IT Copyright(C) 2002 thejam79, 2003 minamina, 2014 msg7086 + +This program is free software; you can redistribute it and / or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA. +*/ + +#include "IScriptEnvironment.h" + +IScriptEnvironment::IScriptEnvironment(VSFrameContext *_frameCtx, VSCore *_core, const VSAPI *_vsapi) +: frameCtx(_frameCtx), core(_core), vsapi(_vsapi) +{ + m_iSumC = m_iSumP = m_iSumN = 0; + m_iUsePrev = m_iUseNext = 0; +} + +IScriptEnvironment::~IScriptEnvironment() +{ +} + +VSFrameRef *IScriptEnvironment::NewVideoFrame(const VSVideoInfo *vi) +{ + return vsapi->newVideoFrame(vi->format, vi->width, vi->height, nullptr, core); +} diff --git a/vs_it/IScriptEnvironment.h b/vs_it/IScriptEnvironment.h new file mode 100644 index 0000000..5238075 --- /dev/null +++ b/vs_it/IScriptEnvironment.h @@ -0,0 +1,83 @@ +/* +VS_IT Copyright(C) 2002 thejam79, 2003 minamina, 2014 msg7086 + +This program is free software; you can redistribute it and / or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA. +*/ + +#pragma once +#include "vs_it_interface.h" + +enum REFTYPE; + +class CFrameInfo { +public: + char pos; + char match; + char matchAcc; + char ip; + char out; + char mflag; + int diffP0; + int diffP1; + int diffS0; + int diffS1; + long ivC, ivP, ivN, ivM; + long ivPC, ivPP, ivPN; +}; + +class CTFblockInfo { +public: + int cfi; + char level; + char itype; +}; + +class IScriptEnvironment +{ +public: + int m_iRealFrame; + CFrameInfo *m_frameInfo; + CTFblockInfo *m_blockInfo; + unsigned char *m_edgeMap, *m_motionMap4DI, *m_motionMap4DIMax; + + long m_iSumC, m_iSumP, m_iSumN, m_iSumM; + long m_iSumPC, m_iSumPP, m_iSumPN, m_iSumPM; + int m_iCurrentFrame; + bool m_bRefP; + int m_iUsePrev, m_iUseNext; + int m_iUseFrame; + + VSFrameContext *frameCtx; + VSCore *core; + const VSAPI *vsapi; + IScriptEnvironment(VSFrameContext *_frameCtx, VSCore *_core, const VSAPI *_vsapi); + ~IScriptEnvironment(); + VSFrameRef *IScriptEnvironment::NewVideoFrame(const VSVideoInfo * vi); + void BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) { + if ((!height) || (!row_size)) return; + + if (height == 1 || (dst_pitch == src_pitch && src_pitch == row_size)) { + memcpy(dstp, srcp, row_size*height); + } + else { + for (int y = height; y > 0; --y) { + memcpy(dstp, srcp, row_size); + dstp += dst_pitch; + srcp += src_pitch; + } + } + } +}; + diff --git a/vs_it/vs_it.cpp b/vs_it/vs_it.cpp new file mode 100644 index 0000000..70ee3c1 --- /dev/null +++ b/vs_it/vs_it.cpp @@ -0,0 +1,236 @@ +/* +VS_IT Copyright(C) 2002 thejam79, 2003 minamina, 2014 msg7086 + +This program is free software; you can redistribute it and / or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA. +*/ + +#include "vs_it.h" + +IT::IT(VSVideoInfo * vi, + VSNodeRef * node, + int _fps, + int _threshold, + int _pthreshold, + const VSAPI *vsapi) : + vi(vi), + node(node), + m_iFPS(_fps), + m_iThreshold(_threshold), + m_iPThreshold(_pthreshold) +{ + m_iMaxFrames = vi->numFrames; + m_iCounter = 0; + width = vi->width; + height = vi->height; + m_bSwap = false; + m_iField = false; + + for (int k = 0; k < 32; ++k) { + m_pvf[k] = 0; + m_ipvfIndex[k] = -1; + } + + m_iPThreshold = AdjPara(m_iPThreshold); + + if (m_iFPS == 24) { + vi->numFrames = vi->numFrames * 4 / 5; + vi->fpsNum *= 4; + if (vi->fpsNum % 5 == 0) + vi->fpsNum /= 5; + else + vi->fpsDen *= 5; + } +} + + +void IT::GetFramePre(IScriptEnvironment* env, int n) +{ + if (m_iFPS == 24) + { + int base = n + n / 4; + base = (base / 5) * 5; + int i; + for (i = 0; i < 6; ++i) + env->vsapi->requestFrameFilter(base + i, node, env->frameCtx); + } + else + env->vsapi->requestFrameFilter(n, node, env->frameCtx); +} + +PVideoFrame IT::GetFrame(IScriptEnvironment* env, int n) +{ + ++m_iCounter; + env->m_iRealFrame = n; + env->m_frameInfo = new CFrameInfo[m_iMaxFrames + 6]; + + int i; + for (i = 0; i < 8; ++i) { + m_PVOut[i] = 0; + m_iPVOutIndex[i] = -1; + } + for (i = 0; i < m_iMaxFrames + 6; ++i) { + env->m_frameInfo[i].match = 'U'; + env->m_frameInfo[i].matchAcc = 'U'; + env->m_frameInfo[i].pos = 'U'; + env->m_frameInfo[i].ip = 'U'; + env->m_frameInfo[i].mflag = 'U'; + env->m_frameInfo[i].diffP0 = -1; + env->m_frameInfo[i].diffP1 = -1; + } + env->m_blockInfo = new CTFblockInfo[m_iMaxFrames / 5 + 6]; + for (i = 0; i < m_iMaxFrames / 5 + 1; ++i) { + env->m_blockInfo[i].level = 'U'; + env->m_blockInfo[i].itype = 'U'; + } + + env->m_edgeMap = new unsigned char[width * height]; + memset(env->m_edgeMap, width * height, 0); + + env->m_motionMap4DI = new unsigned char[width * height]; + memset(env->m_motionMap4DI, width * height, 0); + + env->m_motionMap4DIMax = new unsigned char[width * height]; + memset(env->m_motionMap4DIMax, width * height, 0); + + + int tfFrame; + if (m_iFPS == 24) { + tfFrame = n + n / (5 - 1); + + int base = (tfFrame / 5) * 5; + int i; + + for (i = 0; i < 5; ++i) + GetFrameSub(env, base + i); + Decide(env, base); + + bool iflag = true; + for (i = 0; i < 5; ++i) { + if (FII(base + i).ivC >= m_iPThreshold) { + iflag = false; + } + } + if (iflag) { + env->m_blockInfo[base / 5].itype = '3'; + } + else { + env->m_blockInfo[base / 5].itype = '2'; + } + int no = tfFrame - base; + for (i = 0; i < 5; ++i) { + char f = FII(base + i).mflag; + if (f != 'D' && f != 'd' && f != 'X' && f != 'x' && f != 'y' && f != 'z' && f != 'R') { + if (no == 0) + break; + --no; + } + } + if (m_iFPS != 30) + n = clipFrame(i + base); + } + else { + GetFrameSub(env, n); + } + VSFrameRef * dst = env->NewVideoFrame(vi); + MakeOutput(env, dst, n); + delete[] env->m_frameInfo; + delete[] env->m_blockInfo; + delete[] env->m_edgeMap; + delete[] env->m_motionMap4DI; + delete[] env->m_motionMap4DIMax; + return dst; +} + +void IT::GetFrameSub(IScriptEnvironment* env, int n) +{ + if (n >= m_iMaxFrames) + return; + if (env->m_frameInfo[n].ip != 'U') { + return; + } + env->m_iCurrentFrame = n; + + env->m_iUseFrame = 'C'; + env->m_iSumC = env->m_iSumP = env->m_iSumN = env->m_iSumM = 720 * 480; + env->m_bRefP = true; + + ChooseBest(env, n); + env->m_frameInfo[n].match = (unsigned char)env->m_iUseFrame; + switch (toupper(env->m_iUseFrame)) { + case 'C': + env->m_iSumM = env->m_iSumC; + env->m_iSumPM = env->m_iSumPC; + break; + case 'P': + env->m_iSumM = env->m_iSumP; + env->m_iSumPM = env->m_iSumPP; + break; + case 'N': + env->m_iSumM = env->m_iSumN; + env->m_iSumPM = env->m_iSumPN; + break; + } + + env->m_frameInfo[n].ivC = env->m_iSumC; + env->m_frameInfo[n].ivP = env->m_iSumP; + env->m_frameInfo[n].ivN = env->m_iSumN; + env->m_frameInfo[n].ivM = env->m_iSumM; + env->m_frameInfo[n].ivPC = env->m_iSumPC; + env->m_frameInfo[n].ivPP = env->m_iSumPP; + env->m_frameInfo[n].ivPN = env->m_iSumPN; + if (env->m_iSumM < m_iPThreshold && env->m_iSumPM < m_iPThreshold * 3) { + env->m_frameInfo[n].ip = 'P'; + } + else { + env->m_frameInfo[n].ip = 'I'; + } + return; +} + +const VSFrameRef* IT::MakeOutput(IScriptEnvironment* env, VSFrameRef* dst, int n) +{ + env->m_iCurrentFrame = n; + + env->m_iSumC = env->m_frameInfo[n].ivC; + env->m_iSumP = env->m_frameInfo[n].ivP; + env->m_iSumN = env->m_frameInfo[n].ivN; + env->m_iSumM = env->m_frameInfo[n].ivM; + env->m_iSumPC = env->m_frameInfo[n].ivPC; + env->m_iSumPP = env->m_frameInfo[n].ivPP; + env->m_iSumPN = env->m_frameInfo[n].ivPN; + + env->m_bRefP = true; + + env->m_iUseFrame = toupper(env->m_frameInfo[n].match); + +#ifdef DEBUG_SHOW_INTERLACE + // ShowInterlaceArea(dst, n); + // PrintDebugInfo(dst, n); + USE_MMX2 + return dst; +#endif // DEBUG_SHOW_INTERLACE + + if (env->m_frameInfo[n].ip == 'P') + { + CopyCPNField(env, dst, n); + } + else { + if (!DrawPrevFrame(env, dst, n)) + DeintOneField_YV12(env, dst, n); + } + + return dst; +} + diff --git a/vs_it/vs_it.h b/vs_it/vs_it.h new file mode 100644 index 0000000..0558a26 --- /dev/null +++ b/vs_it/vs_it.h @@ -0,0 +1,175 @@ +/* +VS_IT Copyright(C) 2002 thejam79, 2003 minamina, 2014 msg7086 + +This program is free software; you can redistribute it and / or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA. +*/ + +#ifndef __VS_IT_H__ +#define __VS_IT_H__ + +#include "vs_it_interface.h" +#include "IScriptEnvironment.h" + +#define PVideoFrame const VSFrameRef * +#define GetChildFrame(n) env->vsapi->getFrame(clipFrame(n), node, nullptr, 0) +#define FreeFrame(f) env->vsapi->freeFrame(f) + +#define _MM_SHUFFLE(z, y, x, w) (z<<6) | (y<<4) | (x<<2) | w + +#define USE_MMX2 _asm { emms } _asm { sfence } + +#define FALSE 0 +#define TRUE 1 + +#define FI(name, n) env->m_frameInfo[clipFrame(n)].##name +#define FII(n) env->m_frameInfo[clipFrame(n)] + +static double GetF(double x) { + x = fabs(x); + return (x < 1.0) ? 1.0 - x : 0.0; +} + +enum { + PLANAR_Y, + PLANAR_U, + PLANAR_V +}; + +class IT { +private: + int m_iPThreshold; + int m_iThreshold; + int m_iCounter; + int m_iFPS; + const VSFrameRef* m_PVOut[8]; + int m_iPVOutIndex[8]; + + int width; + int height; + int m_bSwap; + int m_iField; + VSFrameRef* m_pvf[32]; + int m_ipvfIndex[32]; + int m_iMaxFrames; +public: + const VSVideoInfo* vi; + VSNodeRef * node; + IT(VSVideoInfo * vi, + VSNodeRef * node, + int _fps, + int _threshold, + int _pthreshold, + const VSAPI *vsapi); + int AdjPara(int v) { + return (((v * width) / 720) * height) / 480; + } + int GetDiffVal(IScriptEnvironment*env, int n, int p = 0) { + if (p == 0) + return env->m_frameInfo[clipFrame(n)].diffP0; + else + return env->m_frameInfo[clipFrame(n)].diffS0; + } + inline int clipFrame(int n) { + return max(0, min(n, m_iMaxFrames - 1)); + } + inline int clipOutFrame(int n) { + return max(0, min(n, vi->numFrames - 1)); + } + inline int clipX(int x) { + x = max(0, min(width - 1, x)); + return x; + } + inline int clipY(int y) { + return max(0, min(height - 1, y)); + } + inline int clipYH(int y) { + return max(0, min((height >> 1) - 1, y)); + } + inline const unsigned char* SYP(IScriptEnvironment* env, const VSFrameRef * pv, int y, int plane = PLANAR_Y) { + y = max(0, min(height - 1, y)); + if (m_bSwap) + y = y ^ 1; + auto rPtr = env->vsapi->getReadPtr(pv, plane); + auto rStr = env->vsapi->getStride(pv, plane); + if (plane == PLANAR_Y) + return rPtr + y * rStr; + else + return rPtr + (((y >> 2) << 1) + (y % 2)) * rStr; + //if (plane == PLANAR_Y) + // return &pv->GetReadPtr()[y * pv->GetPitch()]; + //else + // return &pv->GetReadPtr(plane)[(((y >> 2) << 1) + (y % 2)) * pv->GetPitch(plane)]; + } + inline unsigned char* DYP(IScriptEnvironment* env, VSFrameRef * pv, int y, int plane = PLANAR_Y) { + y = max(0, min(height - 1, y)); + auto wPtr = env->vsapi->getWritePtr(pv, plane); + auto wStr = env->vsapi->getStride(pv, plane); + if (plane == PLANAR_Y) + return wPtr + y * wStr; + else + return wPtr + (((y >> 2) << 1) + (y % 2)) * wStr; + return env->vsapi->getWritePtr(pv, plane) + y * env->vsapi->getStride(pv, plane); + //if (plane == PLANAR_Y) + // return pv->GetWritePtr() + y * pv->GetPitch(); + //else + // return pv->GetWritePtr(plane) + (((y >> 2) << 1) + (y % 2)) * pv->GetPitch(plane); + } + inline unsigned char* B2YP(unsigned char *dst, int y) { + y = max(0, min(height - 1, y)); + return dst + y * width * 2; + } + inline unsigned char* BYP(unsigned char *dst, int y) { + y = max(0, min(height - 1, y)); + return dst + y * width; + } + void __stdcall GetFramePre(IScriptEnvironment* env, int n); + const VSFrameRef* __stdcall GetFrame(IScriptEnvironment* env, int n); + const VSFrameRef* __stdcall MakeOutput(IScriptEnvironment* env, VSFrameRef* dst, int n); + bool CheckSceneChange(IScriptEnvironment* env, int n); + void GetFrameSub(IScriptEnvironment* env, int n); + void __stdcall EvalIV_YV12(IScriptEnvironment* env, int n, const VSFrameRef * ref, long &counter, long &counterp); + void __stdcall MakeDEmap_YV12(IScriptEnvironment* env, const VSFrameRef * ref, int offset); + void __stdcall MakeMotionMap_YV12(IScriptEnvironment* env, int fno, bool flag); + // void __stdcall MakeMotionMap2_YV12(IScriptEnvironment* env, int fno, bool flag); + void __stdcall MakeMotionMap2Max_YV12(IScriptEnvironment* env, int fno); + void __stdcall MakeSimpleBlurMap_YV12(IScriptEnvironment* env, int fno); + void __stdcall CopyCPNField(IScriptEnvironment* env, VSFrameRef * dst, int n); + // void __stdcall Deinterlace_YV12(IScriptEnvironment* env, VSFrameRef * dst, int n, int nParameterMode = DI_MODE_DEINTERLACE); + // void __stdcall SimpleBlur_YV12(IScriptEnvironment* env, VSFrameRef * dst, int n); + void __stdcall DeintOneField_YV12(IScriptEnvironment* env, VSFrameRef * dst, int n); + // void __stdcall BlendFrame_YV12(IScriptEnvironment* env, VSFrameRef * dst, int base, int n); + // void __stdcall ShowInterlaceArea(const VSAPI * vsapi, VSFrameRef * dst, int n); + // void __stdcall ShowDifference(); + void __stdcall ChooseBest(IScriptEnvironment* env, int n); + bool __stdcall CompCP(IScriptEnvironment* env); + // bool __stdcall CompCN(); + void __stdcall Decide(IScriptEnvironment* env, int n); + void __stdcall SetFT(IScriptEnvironment* env, int base, int n, char c); + // void __stdcall ReadLog(); + // void __stdcall WriteLog(); + bool __stdcall DrawPrevFrame(IScriptEnvironment* env, VSFrameRef * dst, int n); + +}; + +void VS_CC +itInit(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi); + +void VS_CC +itFree(void *instanceData, VSCore *core, const VSAPI *vsapi); + +const VSFrameRef *VS_CC +itGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi); + +#endif \ No newline at end of file diff --git a/vs_it/vs_it.vcxproj b/vs_it/vs_it.vcxproj new file mode 100644 index 0000000..ab39239 --- /dev/null +++ b/vs_it/vs_it.vcxproj @@ -0,0 +1,102 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {296F3E49-8C9B-47E2-BF8A-B1EDD6A322CB} + Win32Proj + vs_it + + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + true + C:\Programs (x86)\Visual Leak Detector\include;$(IncludePath) + C:\Programs (x86)\Visual Leak Detector\lib;$(LibraryPath) + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;VS_IT_EXPORTS;%(PreprocessorDefinitions) + true + ./include + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;VS_IT_EXPORTS;%(PreprocessorDefinitions) + true + ./include + Speed + StreamingSIMDExtensions2 + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vs_it/vs_it_interface.cpp b/vs_it/vs_it_interface.cpp new file mode 100644 index 0000000..98f69f7 --- /dev/null +++ b/vs_it/vs_it_interface.cpp @@ -0,0 +1,108 @@ +/* +VS_IT Copyright(C) 2002 thejam79, 2003 minamina, 2014 msg7086 + +This program is free software; you can redistribute it and / or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA. +*/ + +#include "vs_it_interface.h" +#include "vs_it.h" + +static IT *d = NULL; + +static void VS_CC +itCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, +const VSAPI *vsapi) { + int err; + char msg_buff[256] = "IT(" IT_VERSION "): "; + char *msg = msg_buff + strlen(msg_buff); + + VSNodeRef * node = vsapi->propGetNode(in, "clip", 0, 0); + VSVideoInfo * vi = new VSVideoInfo; + *vi = *vsapi->getVideoInfo(node); + + FAIL_IF_ERROR(!vi->format || vi->width == 0 || vi->height == 0, + "clip must be constant format"); + + FAIL_IF_ERROR(vi->format->sampleType != stInteger || + vi->format->bitsPerSample != 8 || + vi->format->colorFamily != cmYUV, + "only YUV420P8 input supported. You can you up."); + + FAIL_IF_ERROR(vi->width & 15, + "width must be mod 16"); + + FAIL_IF_ERROR(vi->height & 1, + "height must be even") + { + int fps = vsapi->propGetInt(in, "fps", 0, &err); + if (err) { fps = 24; } + + int threshold = vsapi->propGetInt(in, "threshold", 0, &err); + if (err) { threshold = 20; } + + int pthreshold = vsapi->propGetInt(in, "pthreshold", 0, &err); + if (err) { pthreshold = 75; } + + d = new IT(vi, node, fps, threshold, pthreshold, vsapi); + } + vsapi->createFilter(in, out, "it", itInit, + itGetFrame, itFree, fmParallel, + 0, NULL, core); + return; + +fail: + vsapi->freeNode(node); + vsapi->setError(out, msg_buff); +} + +void VS_CC +itInit(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi) +{ + vsapi->setVideoInfo(d->vi, 1, node); +} + +void VS_CC +itFree(void *instanceData, VSCore *core, const VSAPI *vsapi) +{ + vsapi->freeNode(d->node); + delete d; +} + +const VSFrameRef *VS_CC +itGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) +{ + IScriptEnvironment env(frameCtx, core, vsapi); + if (activationReason == arInitial) { + d->GetFramePre(&env, n); + return NULL; + } + if (activationReason != arAllFramesReady) { + return NULL; + } + + return d->GetFrame(&env, n); +} + +VS_EXTERNAL_API(void) +VapourSynthPluginInit(VSConfigPlugin configFunc, +VSRegisterFunction registerFunc, VSPlugin *plugin) +{ + configFunc("in.7086.it", "it", + "VapourSynth IVTC Filter v" IT_VERSION, + VAPOURSYNTH_API_VERSION, 1, plugin); + registerFunc("it", + "clip:clip;fps:int:opt;threshold:int:opt;pthreshold:int:opt;", + itCreate, 0, plugin); +} diff --git a/vs_it/vs_it_interface.h b/vs_it/vs_it_interface.h new file mode 100644 index 0000000..d4c187b --- /dev/null +++ b/vs_it/vs_it_interface.h @@ -0,0 +1,51 @@ +/* +VS_IT Copyright(C) 2002 thejam79, 2003 minamina, 2014 msg7086 + +This program is free software; you can redistribute it and / or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA. +*/ + +#ifndef __VS_IT_INTERFACE_H__ +#define __VS_IT_INTERFACE_H__ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define snprintf(a,b,c) _snprintf_s(a,b,b,c) +#define TS_ALIGN __declspec(align(16)) +#define TS_FUNC_ALIGN +#define stricmp _stricmp +#else +#define TS_ALIGN __attribute__((aligned(16))) +#define TS_FUNC_ALIGN __attribute__((force_align_arg_pointer)) +#endif + +#define IT_VERSION "0103.0.1" + +#define FAIL_IF_ERROR(cond, ...) {\ + if (cond) {\ + snprintf(msg, 235, __VA_ARGS__);\ + goto fail;\ + }\ +} + +class IT; + +#endif diff --git a/vs_it/vs_it_misc.cpp b/vs_it/vs_it_misc.cpp new file mode 100644 index 0000000..6e1439e --- /dev/null +++ b/vs_it/vs_it_misc.cpp @@ -0,0 +1,615 @@ +/* +VS_IT Copyright(C) 2002 thejam79, 2003 minamina, 2014 msg7086 + +This program is free software; you can redistribute it and / or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA. +*/ + +#include "vs_it.h" +#include "IScriptEnvironment.h" + +void IT::SetFT(IScriptEnvironment*env, int base, int n, char c) +{ + FI(mflag, base + n) = c; + env->m_blockInfo[base / 5].cfi = n; + env->m_blockInfo[base / 5].level = '0'; +} + +void IT::ChooseBest(IScriptEnvironment* env, int n) +{ + PVideoFrame srcC = GetChildFrame(n); + // MakeMotionMap(m_iCurrentFrame - 1, false); + MakeMotionMap_YV12(env, env->m_iCurrentFrame, false); + MakeMotionMap_YV12(env, env->m_iCurrentFrame + 1, false); + MakeDEmap_YV12(env, srcC, 0); + EvalIV_YV12(env, n, srcC, env->m_iSumC, env->m_iSumPC); + PVideoFrame srcP = GetChildFrame(n - 1); + EvalIV_YV12(env, n, srcP, env->m_iSumP, env->m_iSumPP); + CompCP(env); + FreeFrame(srcC); + FreeFrame(srcP); +} + +#define EVAL_IV_ASM_INIT(C, T, B) \ + __asm mov eax, C \ + __asm mov ebx, T \ + __asm mov ecx, B + +#define EVAL_IV_ASM(mmm, step) \ + __asm movq mmm, [eax + esi*step] \ + __asm movq mm1, [ebx + esi*step] \ + __asm movq mm2, mmm \ + __asm movq mm4, mmm \ + __asm psubusb mmm, [ebx + esi*step] \ + __asm psubusb mm1, mm2 \ + __asm movq mm3, [ecx + esi*step] \ + __asm por mmm, mm1 \ + __asm movq mm1, [ebx + esi*step] \ + __asm psubusb mm3, mm2 \ + __asm pavgb mm1, [ecx + esi*step] \ + __asm psubusb mm2, [ecx + esi*step] \ + __asm psubusb mm4, mm1 \ + __asm por mm2, mm3 \ + __asm psubusb mm1, [eax + esi*step] \ + __asm pminub mmm, mm2 \ + __asm por mm1, mm4 \ + __asm pminub mmm, mm1 + +/////////////////////////////////////////////////////////////////////////// +void IT::EvalIV_YV12(IScriptEnvironment *env, int n, const VSFrameRef * ref, long &counter, long &counterp) +{ + const __int64 mask1 = 0x0101010101010101i64; + unsigned char th[8], th2[8]; + unsigned char rsum[8], psum[8]; + unsigned short psum0[4], psum1[4]; + + PVideoFrame srcC = GetChildFrame(n); + for (int i = 0; i < 8; ++i) { + th[i] = 40; + th2[i] = 6; + } + + MakeDEmap_YV12(env, ref, 1); + + const int widthminus16 = (width - 16) >> 1; + int sum = 0, sum2 = 0; //, sumS = 0; + for (int yy = 16; yy < height - 16; yy += 2) { + int y; + if (m_iField == 0) { + y = yy + 1; + } + else { + y = yy + 0; + } + const unsigned char *pT = SYP(env, srcC, y - 1); + const unsigned char *pC = SYP(env, ref, y); + const unsigned char *pB = SYP(env, srcC, y + 1); + const unsigned char *pT_U = SYP(env, srcC, y - 1, PLANAR_U); + const unsigned char *pC_U = SYP(env, ref, y, PLANAR_U); + const unsigned char *pB_U = SYP(env, srcC, y + 1, PLANAR_U); + const unsigned char *pT_V = SYP(env, srcC, y - 1, PLANAR_V); + const unsigned char *pC_V = SYP(env, ref, y, PLANAR_V); + const unsigned char *pB_V = SYP(env, srcC, y + 1, PLANAR_V); + + const unsigned char *peT = &env->m_edgeMap[clipY(y - 1) * width]; + const unsigned char *peC = &env->m_edgeMap[clipY(y) * width]; + const unsigned char *peB = &env->m_edgeMap[clipY(y + 1) * width]; + + // unsigned char *pmW = m_pImap + width * y; + __asm { + pxor mm7, mm7 + // mov edi,pmW + mov esi, 16 + + movq rsum, mm7 + movq psum, mm7 + movq psum0, mm7 + movq psum1, mm7 + align 16 + loopB: + EVAL_IV_ASM_INIT(pC, pT, pB) + EVAL_IV_ASM(mm0, 2) + + EVAL_IV_ASM_INIT(pC_U, pT_U, pB_U) + EVAL_IV_ASM(mm5, 1) + + EVAL_IV_ASM_INIT(pC_V, pT_V, pB_V) + EVAL_IV_ASM(mm6, 1) + + pmaxub mm5, mm6 + punpcklbw mm5, mm5 + pmaxub mm0, mm5; mm0 < -max(y, max(u, v)) + + mov edx, peC + movq mm3, [edx + esi * 2] + mov edx, peT + pmaxub mm3, [edx + esi * 2] + mov edx, peB + pmaxub mm3, [edx + esi * 2]; mm3 <-max(peC[x], max(peT[x], peB[x])) + + psubusb mm0, mm3 + psubusb mm0, mm3 + movq mm1, mm0 + + psubusb mm0, th + pcmpeqb mm0, mm7 + pcmpeqb mm0, mm7 + pand mm0, mask1 + paddusb mm0, rsum; if (max - maxpe * 2 > 40) sum++ + movq rsum, mm0 + + psubusb mm1, th2 + pcmpeqb mm1, mm7 + pcmpeqb mm1, mm7 + pand mm1, mask1 + paddusb mm1, psum; if (max - maxpe * 2 > 6) sum2++ + movq psum, mm1 + + lea esi, [esi + 4] + cmp esi, widthminus16 + jl loopB + } + sum += rsum[0] + rsum[1] + rsum[2] + rsum[3] + rsum[4] + rsum[5] + rsum[6] + rsum[7]; + sum2 += psum[0] + psum[1] + psum[2] + psum[3] + psum[4] + psum[5] + psum[6] + psum[7]; + // sum2 += psum0[0] + psum0[1] + psum0[2] + psum0[3]; + // sum2 += psum1[0] + psum1[1] + psum1[2] + psum1[3]; + if (sum > m_iPThreshold) { + sum = m_iPThreshold; + break; + } + } + counter = sum; + counterp = sum2; + + FreeFrame(srcC); + USE_MMX2; + return; +} + +#define MAKE_DE_MAP_ASM_INIT(C, TT, BB) \ + __asm mov eax, C \ + __asm mov ebx, TT \ + __asm mov ecx, BB + +#define MAKE_DE_MAP_ASM(mmm, step, offset) \ + __asm movq mm7, [ebx + esi*step + offset] \ + __asm movq mmm, [eax + esi*step + offset] \ + __asm pavgb mm7, [ecx + esi*step + offset] \ + __asm psubusb mmm, mm7 \ + __asm psubusb mm7, [eax + esi*step + offset] \ + __asm por mmm, mm7 + +/////////////////////////////////////////////////////////////////////////// +void IT::MakeDEmap_YV12(IScriptEnvironment*env, const VSFrameRef * ref, int offset) +{ + const int twidth = width >> 1; + + for (int yy = 0; yy < height; yy += 2) { + int y = yy + offset; + const unsigned char *pTT = SYP(env, ref, y - 2); + const unsigned char *pC = SYP(env, ref, y); + const unsigned char *pBB = SYP(env, ref, y + 2); + const unsigned char *pTT_U = SYP(env, ref, y - 2, PLANAR_U); + const unsigned char *pC_U = SYP(env, ref, y, PLANAR_U); + const unsigned char *pBB_U = SYP(env, ref, y + 2, PLANAR_U); + const unsigned char *pTT_V = SYP(env, ref, y - 2, PLANAR_V); + const unsigned char *pC_V = SYP(env, ref, y, PLANAR_V); + const unsigned char *pBB_V = SYP(env, ref, y + 2, PLANAR_V); + unsigned char *pED = env->m_edgeMap + y * width; + __asm { + mov edi, pED + xor esi, esi + align 16 + loopA: + MAKE_DE_MAP_ASM_INIT(pC, pTT, pBB) + MAKE_DE_MAP_ASM(mm0, 2, 0) + MAKE_DE_MAP_ASM(mm3, 2, 8) + MAKE_DE_MAP_ASM_INIT(pC_U, pTT_U, pBB_U) + MAKE_DE_MAP_ASM(mm1, 1, 0) + MAKE_DE_MAP_ASM(mm4, 1, 4) + MAKE_DE_MAP_ASM_INIT(pC_V, pTT_V, pBB_V) + MAKE_DE_MAP_ASM(mm2, 1, 0) + MAKE_DE_MAP_ASM(mm5, 1, 4) + + pmaxub mm2, mm1 + pmaxub mm5, mm4 + punpcklbw mm2, mm2 + punpcklbw mm5, mm5 + pmaxub mm0, mm2 + pmaxub mm3, mm5 + + lea esi, [esi + 8] + movntq[edi + esi * 2 - 16], mm0 + cmp esi, twidth + movntq[edi + esi * 2 - 8], mm3 + jl loopA + } + } + USE_MMX2 +} + +void IT::MakeMotionMap_YV12(IScriptEnvironment*env, int n, bool flag) +{ + n = clipFrame(n); + if (flag == false && env->m_frameInfo[n].diffP0 >= 0) { + return; + } + + const __int64 mask1 = 0x0101010101010101i64; + + const int twidth = width; + const int widthminus8 = width - 8; + const int widthminus16 = width - 16; + unsigned short th[4], th2[4]; + unsigned char mbTh[8], mbTh2[8]; + int i; + for (i = 0; i < 4; ++i) { + th[i] = 12 * 3; + th2[i] = 6 * 3; + } + for (i = 0; i < 8; ++i) { + mbTh[i] = 12 * 3; + mbTh2[i] = 6 * 3; + } + + + PVideoFrame srcP = GetChildFrame(n - 1); + PVideoFrame srcC = GetChildFrame(n); + short bufP0[2048]; + unsigned char bufP1[2048]; + int pe0 = 0, po0 = 0, pe1 = 0, po1 = 0; + for (int yy = 16; yy < height - 16; ++yy) { + int y = yy; + const unsigned char *pC = SYP(env, srcC, y); + const unsigned char *pP = SYP(env, srcP, y); + { + _asm { + pxor mm7, mm7 + mov eax, pC + mov ebx, pP + lea edi, bufP0 + xor esi, esi + align 16 + loopA: + prefetchnta[eax + esi + 16] + prefetchnta[ebx + esi + 16] + movd mm0, [eax + esi] + movd mm1, [ebx + esi] + punpcklbw mm0, mm7 + punpcklbw mm1, mm7 + lea esi, [esi + 4] + psubw mm0, mm1 + cmp esi, twidth + movntq[edi + esi * 2 - 8], mm0 + jl loopA + } + } + { + _asm { + lea eax, bufP0 + lea edi, bufP1 + mov esi, 8 + align 16 + loopB: + prefetchnta[eax + esi + 16] + movq mm0, [eax + esi * 2 - 2] + movq mm1, mm7 + paddw mm0, [eax + esi * 2 + 2] + movq mm2, [eax + esi * 2] + psubw mm0, mm2 + movq mm3, mm7 + psubw mm0, mm2 + psubw mm3, mm2 + psubw mm1, mm0 + pmaxsw mm2, mm3 + pmaxsw mm0, mm1 + lea esi, [esi + 4] + psubusw mm2, mm0 + cmp esi, widthminus8 + packuswb mm2, mm7 + movd[edi + esi - 4], mm2 + jl loopB + } + } + int tsum = 0, tsum1 = 0; + { + // unsigned char sum[8]; + // unsigned char sum[8]; + _asm { + movq mm5, mbTh + // movq mm4,mask1 + lea eax, bufP1 + mov esi, 16 + // mov edi,pD + pxor mm4, mm4 + pxor mm3, mm3 + align 16 + loopC: + prefetchnta[eax + esi + 16] + movq mm0, [eax + esi - 1] + paddusb mm0, [eax + esi + 1] + paddusb mm0, [eax + esi] + movq mm1, mm0 + psubusb mm0, mm5 + psubusb mm1, mbTh2 + pcmpeqb mm0, mm7 + pcmpeqb mm1, mm7 + pcmpeqb mm0, mm7 + pcmpeqb mm1, mm7 + // movntq [edi+esi],mm0 + lea esi, [esi + 8] + pand mm0, mask1 + pand mm1, mask1 + cmp esi, widthminus16 + paddb mm4, mm0 + paddb mm3, mm1 + jl loopC + + psadbw mm4, mm7 + movd tsum, mm4 + + psadbw mm3, mm7 + movd tsum1, mm3 + } + if ((y & 1) == 0) { + pe0 += tsum; + pe1 += tsum1; + } + else { + po0 += tsum; + po1 += tsum1; + } + } + } + env->m_frameInfo[n].diffP0 = pe0; + env->m_frameInfo[n].diffP1 = po0; + env->m_frameInfo[n].diffS0 = pe1; + env->m_frameInfo[n].diffS1 = po1; + USE_MMX2; + FreeFrame(srcC); + FreeFrame(srcP); +} + +bool IT::CompCP(IScriptEnvironment*env) +{ + int n = env->m_iCurrentFrame; + int p0 = env->m_frameInfo[n].diffP0; + int p1 = env->m_frameInfo[n].diffP1; + int n0 = env->m_frameInfo[clipFrame(n + 1)].diffP0; + int n1 = env->m_frameInfo[clipFrame(n + 1)].diffP1; + int ps0 = env->m_frameInfo[n].diffS0; + int ps1 = env->m_frameInfo[n].diffS1; + int ns0 = env->m_frameInfo[clipFrame(n + 1)].diffS0; + int ns1 = env->m_frameInfo[clipFrame(n + 1)].diffS1; + // int th = 5; + // int thm = 5; + + int th = AdjPara(5); + int thm = AdjPara(5); + int ths = AdjPara(200); + + bool spe = p0 < th && ps0 < ths; + bool spo = p1 < th && ps1 < ths; + bool sne = n0 < th && ns0 < ths; + bool sno = n1 < th && ns1 < ths; + + bool mpe = p0 > thm; + bool mpo = p1 > thm; + bool mne = n0 > thm; + bool mno = n1 > thm; + + //1773 + int thcomb = AdjPara(20); + if (n != 0) { + if ((env->m_iSumC < thcomb && env->m_iSumP < thcomb) || abs(env->m_iSumC - env->m_iSumP) * 10 < env->m_iSumC + env->m_iSumP) { + if (abs(env->m_iSumC - env->m_iSumP) > AdjPara(8)) { + if (env->m_iSumP >= env->m_iSumC) { + env->m_iUseFrame = 'c'; + return true; + } + else { + env->m_iUseFrame = 'p'; + return true; + } + } + if (abs(env->m_iSumPC - env->m_iSumPP) > AdjPara(10)) { + if (env->m_iSumPP >= env->m_iSumPC) { + env->m_iUseFrame = 'c'; + return true; + } + else { + env->m_iUseFrame = 'p'; + return true; + } + } + + if (spe && mpo) { + env->m_iUseFrame = 'p'; + return true; + } + if (mpe && spo) { + env->m_iUseFrame = 'c'; + return true; + } + if (mne && sno) { + env->m_iUseFrame = 'p'; + return true; + } + if (sne && mno) { + env->m_iUseFrame = 'c'; + return true; + } + if (spe && spo) { + env->m_iUseFrame = 'c'; + return false; + } + if (sne && sno) { + env->m_iUseFrame = 'c'; + return false; + } + if (mpe && mpo && mne && mno) { + env->m_iUseFrame = 'c'; + return false; + } + + // return (env->m_iSumPC > env->m_iSumPP); + if (env->m_iSumPC > env->m_iSumPP) { + env->m_iUseFrame = 'p'; + return true; + } + else { + env->m_iUseFrame = 'c'; + return false; + } + } + } + // env->m_frameInfo[clipFrame(n)].matchAcc = '0'; + // if (env->m_iSumC > env->m_iSumP) { + // } else { + // env->m_iUseFrame = 'C'; + // return false; + // } + env->m_frameInfo[n].pos = '.'; + if (env->m_iSumP >= env->m_iSumC) { + env->m_iUseFrame = 'C'; + if (!spe) { + env->m_frameInfo[n].pos = '.'; + } + return true; + } + else { + env->m_iUseFrame = 'P'; + if (spe && !sno) { + env->m_frameInfo[n].pos = '2'; + } + if (!spe && sno) { + env->m_frameInfo[n].pos = '3'; + } + return true; + } +} + +bool IT::DrawPrevFrame(IScriptEnvironment*env, VSFrameRef * dst, int n) +{ + bool bResult = false; + + int nPrevFrame = clipFrame(n - 1); + int nNextFrame = clipFrame(n + 1); + + int nOldCurrentFrame = env->m_iCurrentFrame; + int nOldUseFrame = env->m_iUseFrame; + + GetFrameSub(env, nPrevFrame); + GetFrameSub(env, nNextFrame); + + env->m_iCurrentFrame = nOldCurrentFrame; + + if (env->m_frameInfo[nPrevFrame].ip == 'P' && env->m_frameInfo[nNextFrame].ip == 'P') + { + bResult = CheckSceneChange(env, n); + } + + if (bResult) + { + env->m_iUseFrame = env->m_frameInfo[nPrevFrame].match; + + CopyCPNField(env, dst, nPrevFrame); + } + + env->m_iUseFrame = nOldUseFrame; + + return bResult; +} + +void IT::CopyCPNField(IScriptEnvironment* env, VSFrameRef * dst, int n) +{ + PVideoFrame srcC = GetChildFrame(n); + PVideoFrame srcR; + switch (toupper(env->m_iUseFrame)) { + default: + case 'C': + srcR = srcC; + break; + case 'P': + srcR = GetChildFrame(n - 1); + break; + case 'N': + srcR = GetChildFrame(n + 1); + break; + } + + int nPitch = env->vsapi->getStride(dst, 0); + int nRowSize = width; + int nPitchU = env->vsapi->getStride(dst, 1); + int nRowSizeU = width >> vi->format->subSamplingW; + + for (int yy = 0; yy < height; yy += 2) { + int y, yo; + if (m_iField == 0) { + y = yy + 1; + yo = yy + 0; + } + else { + y = yy + 0; + yo = yy + 1; + } + env->BitBlt(DYP(env, dst, yo), nPitch, SYP(env, srcC, yo), nPitch, nRowSize, 1); + env->BitBlt(DYP(env, dst, y), nPitch, SYP(env, srcR, y), nPitch, nRowSize, 1); + + if ((yy >> 1) % 2) + { + env->BitBlt(DYP(env, dst, yo, PLANAR_U), nPitchU, SYP(env, srcC, yo, PLANAR_U), nPitchU, nRowSizeU, 1); + env->BitBlt(DYP(env, dst, y, PLANAR_U), nPitchU, SYP(env, srcR, y, PLANAR_U), nPitchU, nRowSizeU, 1); + env->BitBlt(DYP(env, dst, yo, PLANAR_V), nPitchU, SYP(env, srcC, yo, PLANAR_V), nPitchU, nRowSizeU, 1); + env->BitBlt(DYP(env, dst, y, PLANAR_V), nPitchU, SYP(env, srcR, y, PLANAR_V), nPitchU, nRowSizeU, 1); + } + } + USE_MMX2; + if (srcC != srcR) + FreeFrame(srcR); + FreeFrame(srcC); +} + +bool IT::CheckSceneChange(IScriptEnvironment*env, int n) +{ + PVideoFrame srcP = GetChildFrame(n - 1); + PVideoFrame srcC = GetChildFrame(n); + + int rowSize = env->vsapi->getStride(srcC, 0); + + int sum3 = 0; + int x, y; + + int startY = 0; + if (m_iField == 0) + { + startY = 1; + } + + for (y = startY; y < height; y += 2) + { + const unsigned char *pC = SYP(env, srcC, y); + const unsigned char *pP = SYP(env, srcP, y); + + for (x = 0; x < rowSize; x++) + { + int a = abs(pC[x] - pP[x]); + if (a > 50) sum3 += 1; + } + } + FreeFrame(srcP); + FreeFrame(srcC); + return sum3 > height * rowSize / 8; +} + diff --git a/vs_it/vs_it_process.cpp b/vs_it/vs_it_process.cpp new file mode 100644 index 0000000..79d1a34 --- /dev/null +++ b/vs_it/vs_it_process.cpp @@ -0,0 +1,485 @@ +/* +VS_IT Copyright(C) 2002 thejam79, 2003 minamina, 2014 msg7086 + +This program is free software; you can redistribute it and / or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA. +*/ + +#include "vs_it.h" +#include "vs_it_interface.h" + +void __stdcall IT::Decide(IScriptEnvironment*env, int n) +{ + if (env->m_blockInfo[n / 5].level != 'U') + return; + + int base = (n / 5) * 5; + int i; + int min0 = FII(base).diffP0; + for (i = 1; i < 5; ++i) { + min0 = min(min0, FII(base + i).diffP0); + } + int mmin = AdjPara(50); + + for (i = 0; i < 5; ++i) { + int m = FII(base + i).diffP0; + if (m >= max(mmin, min0) * 5) { + FII(base + i).mflag = '.'; + } + else { + FII(base + i).mflag = '+'; + } + } + // const int motion1 = 100; + + int ncf = 0; + int cfi = -1; + for (i = 0; i < 5; ++i) { + if (FII(base + i).mflag == '.') + ++ncf; + else + cfi = i; + } + + int mmin2 = AdjPara(50); + if (ncf == 0) { + min0 = FII(base).diffS0; + for (i = 1; i < 5; ++i) { + min0 = min(min0, FII(base + i).diffS0); + } + for (i = 0; i < 5; ++i) { + int m = FII(base + i).diffS0; + if (m >= max(mmin2, min0) * 3) { + FII(base + i).mflag = '.'; + } + else { + FII(base + i).mflag = '+'; + } + } + ncf = 0; + cfi = -1; + for (i = 0; i < 5; ++i) { + if (FII(base + i).mflag == '.') + ++ncf; + else + cfi = i; + } + } + + if (ncf == 4 && cfi >= 0) { + SetFT(env, base, cfi, 'D'); + return; + } + if (ncf != 0 || 1) { + bool flag = false; + for (i = 0; i < 5; ++i) { + int rr = (i + 2 + 5) % 5; + int r = (i + 1 + 5) % 5; + int l = (i - 1 + 5) % 5; + if (FII(base + i).mflag != '.' && FII(base + i).match == 'P') { + if (FII(base + i).mflag == '+') { + FII(base + i).mflag = '*'; + flag = true; + } + if (FII(base + r).mflag == '+') { + FII(base + r).mflag = '*'; + flag = true; + } + if (FII(base + l).mflag == '+') { + FII(base + l).mflag = '*'; + flag = true; + } + } + if (FII(base + i).match == 'N') { + if (FII(base + r).mflag == '+') { + FII(base + r).mflag = '*'; + flag = true; + } + if (FII(base + rr).mflag == '+') { + FII(base + rr).mflag = '*'; + flag = true; + } + } + + } + + //31228 39045 + + if (flag) { + for (i = 0; i < 5; ++i) { + char c = FII(base + i).mflag; + if (c == '+') + FII(base + i).mflag = '*'; + if (c == '*') + FII(base + i).mflag = '+'; + } + } + for (i = 0; i < 5; ++i) { + if (FII(base + i).pos == '2') { + SetFT(env, base, i, 'd'); + return; + } + } + if (base - 5 >= 0 && env->m_blockInfo[base / 5 - 1].level != 'U') { + int tcfi = env->m_blockInfo[base / 5 - 1].cfi; + if (env->m_frameInfo[base + tcfi].mflag == '+') { + SetFT(env, base, tcfi, 'y'); + return; + } + } + int pnpos[5], pncnt = 0; + for (i = 0; i < 5; ++i) { + if (toupper(FII(base + i).match) == 'P') { + pnpos[pncnt++] = i; + } + } + if (pncnt == 2) { + int k = pnpos[0]; + if (pnpos[0] == 0 && pnpos[1] == 4) { + k = 4; + } + if (FII(base + k).mflag != '.') { + SetFT(env, base, k, 'x'); + return; + } + } + + pncnt = 0; + for (i = 0; i < 5; ++i) { + if (toupper(FII(base + i).match) != 'N') { + pnpos[pncnt++] = i; + } + } + if (pncnt == 2) { + int k = pnpos[0]; + if (pnpos[0] == 3 && pnpos[1] == 4) { + k = 4; + } + k = (k + 2) % 5; + if (FII(base + k).mflag != '.') { + SetFT(env, base, k, 'x'); + return; + } + } + + for (i = 0; i < 5; ++i) { + if (FII(base + i).mflag == '+') { + SetFT(env, base, i, 'd'); + return; + } + } + } + + cfi = 0; + int minx = FII(base).diffS0; + for (i = 1; i < 5; ++i) { + int m = FII(base + i).diffS0; + if (m < minx) { + cfi = i; + minx = m; + } + } + SetFT(env, base, cfi, 'z'); + return; +} + +void IT::DeintOneField_YV12(IScriptEnvironment*env, VSFrameRef* dst, int n) +{ + const VSFrameRef * srcC = GetChildFrame(n); + const VSFrameRef *srcR; + switch (toupper(env->m_iUseFrame)) { + default: + case 'C': + srcR = srcC; + break; + case 'P': + srcR = GetChildFrame(n - 1); + break; + case 'N': + srcR = GetChildFrame(n + 1); + break; + } + + const unsigned char *pT; + const unsigned char *pC; + const unsigned char *pB; + const unsigned char *pBB; + const unsigned char *pC_U; + const unsigned char *pB_U; + const unsigned char *pBB_U; + const unsigned char *pC_V; + const unsigned char *pB_V; + const unsigned char *pBB_V; + unsigned char *pDC; + unsigned char *pDB; + unsigned char *pDC_U; + unsigned char *pDC_V; + unsigned char *pDB_U; + unsigned char *pDB_V; + + MakeSimpleBlurMap_YV12(env, env->m_iCurrentFrame); + MakeMotionMap2Max_YV12(env, env->m_iCurrentFrame); + + unsigned char *pFieldMap; + pFieldMap = new unsigned char[width * height]; + ZeroMemory(pFieldMap, width * height); + int x, y; + for (y = 0; y < height; y += 1) + { + unsigned char *pFM = pFieldMap + width * clipY(y); + for (x = 1; x < width - 1; x++) + { + const unsigned char *pmSC = env->m_motionMap4DI + width * clipY(y); + const unsigned char *pmSB = env->m_motionMap4DI + width * clipY(y + 1); + const unsigned char *pmMC = env->m_motionMap4DIMax + width * clipY(y); + const unsigned char *pmMB = env->m_motionMap4DIMax + width * clipY(y + 1); + const int nTh = 12; + const int nThLine = 1; + if (((pmSC[x - 1] > nThLine && pmSC[x] > nThLine && pmSC[x + 1] > nThLine) || + (pmSB[x - 1] > nThLine && pmSB[x] > nThLine && pmSB[x + 1] > nThLine)) && + ((pmMC[x - 1] > nTh && pmMC[x] > nTh && pmMC[x + 1] > nTh) || + (pmMB[x - 1] > nTh && pmMB[x] > nTh && pmMB[x + 1] > nTh))) + { + pFM[x - 1] = 1; + pFM[x] = 1; + pFM[x + 1] = 1; + } + } + } + + const int nPitchSrc = env->vsapi->getStride(srcC, 0); // srcC->GetPitch(); + const int nPitchSrcU = env->vsapi->getStride(srcC, 1); // srcC->GetPitch(PLANAR_U); + const int nPitchDst = env->vsapi->getStride(dst, 0); // dst->GetPitch(); + const int nRowSizeDst = width; // dst->GetRowSize(); DIVIDE BY SIZEOF(T) + const int nPitchDstU = env->vsapi->getStride(dst, 1); // dst->GetPitch(PLANAR_U); + const int nRowSizeDstU = width >> vi->format->subSamplingW; // dst->GetRowSize(PLANAR_U); DIVIDE BY SIZEOF(T) + + for (y = 0; y < height; y += 2) { + pT = SYP(env, srcR, y - 1); + pC = SYP(env, srcC, y); + pB = SYP(env, srcR, y + 1); + pBB = SYP(env, srcC, y + 2); + pC_U = SYP(env, srcC, y, PLANAR_U); + pB_U = SYP(env, srcR, y + 1, PLANAR_U); + pBB_U = SYP(env, srcC, y + 4, PLANAR_U); + pC_V = SYP(env, srcC, y, PLANAR_V); + pB_V = SYP(env, srcR, y + 1, PLANAR_V); + pBB_V = SYP(env, srcC, y + 4, PLANAR_V); + + pDC = DYP(env, dst, y); + pDB = DYP(env, dst, y + 1); + pDC_U = DYP(env, dst, y, PLANAR_U); + pDB_U = DYP(env, dst, y + 1, PLANAR_U); + pDC_V = DYP(env, dst, y, PLANAR_V); + pDB_V = DYP(env, dst, y + 1, PLANAR_V); + + env->BitBlt(pDC, nPitchDst, pC, nPitchSrc, nRowSizeDst, 1); + if ((y >> 1) % 2) + { + env->BitBlt(pDC_U, nPitchDstU, pC_U, nPitchSrcU, nRowSizeDstU, 1); + env->BitBlt(pDC_V, nPitchDstU, pC_V, nPitchSrcU, nRowSizeDstU, 1); + } + + const unsigned char *pFM = pFieldMap + width * clipY(y); + const unsigned char *pFMB = pFieldMap + width * clipY(y + 1); + for (x = 0; x < width; ++x) + { + int x_half = x >> 1; + if ((pFM[x - 1] == 1 || pFM[x] == 1 || pFM[x + 1] == 1) || + (pFMB[x - 1] == 1 || pFMB[x] == 1 || pFMB[x + 1] == 1)) + { + pDB[x] = BYTE((pC[x] + pBB[x] + 1) >> 1); + } + else + { + pDB[x] = pB[x]; + } + + if ((y >> 1) % 2) + { + pDB_U[x_half] = BYTE((pC_U[x_half] + pBB_U[x_half] + 1) >> 1); + pDB_V[x_half] = BYTE((pC_V[x_half] + pBB_V[x_half] + 1) >> 1); + } + } + } + delete[] pFieldMap; + if (srcC != srcR) + FreeFrame(srcR); + FreeFrame(srcC); + + return; +} + +#define MAKE_BLUR_MAP_ASM(mmA, mmB) \ + __asm movq mm7, mmA \ + __asm psubusb mmA, mmB \ + __asm psubusb mmB, mm7 \ + __asm por mmA, mmB + +void IT::MakeSimpleBlurMap_YV12(IScriptEnvironment*env, int n) +{ + int twidth = width; + const VSFrameRef * srcC = GetChildFrame(n); + const VSFrameRef *srcR; + switch (toupper(env->m_iUseFrame)) { + default: + case 'C': + srcR = srcC; + break; + case 'P': + srcR = GetChildFrame(n - 1); + break; + case 'N': + srcR = GetChildFrame(n + 1); + break; + } + const unsigned char *pT; + const unsigned char *pC; + const unsigned char *pB; + for (int y = 0; y < height; y++) + { + unsigned char *pD = env->m_motionMap4DI + y * width; + { + if (y % 2) + { + pT = SYP(env, srcC, y - 1); + pC = SYP(env, srcR, y); + pB = SYP(env, srcC, y + 1); + } + else + { + pT = SYP(env, srcR, y - 1); + pC = SYP(env, srcC, y); + pB = SYP(env, srcR, y + 1); + } + _asm { + mov eax, pC + mov ebx, pT + mov ecx, pB + mov edi, pD + xor esi, esi + align 16 + loopA: + movq mm0, [eax + esi] + movq mm1, [ebx + esi] + movq mm2, mm0 + movq mm3, mm1 + MAKE_BLUR_MAP_ASM(mm0, mm1) + + movq mm4, [ecx + esi] + movq mm1, mm4 + MAKE_BLUR_MAP_ASM(mm2, mm4) + + MAKE_BLUR_MAP_ASM(mm3, mm1) + + paddusb mm0, mm2 + psubusb mm0, mm3 + psubusb mm0, mm3 + + lea esi, [esi + 8] + cmp esi, twidth + movntq[edi + esi - 8], mm0 + jl loopA + } + } + } + USE_MMX2; + if (srcC != srcR) + FreeFrame(srcR); + FreeFrame(srcC); +} + +#define MAKE_MOTION_MAP2_ASM_INIT(C, P) \ + __asm mov eax, C \ + __asm mov ebx, P + +#define MAKE_MOTION_MAP2_ASM(mmm, step) \ + __asm movq mmm, [eax + esi*step] \ + __asm movq mm2, mmm \ + __asm movq mm1, [ebx + esi*step] \ + __asm psubusb mmm, mm1 \ + __asm psubusb mm1, mm2 \ + __asm por mmm, mm1 + +void IT::MakeMotionMap2Max_YV12(IScriptEnvironment*env, int n) +{ + const int twidth = width >> 1; + + PVideoFrame srcP = GetChildFrame(n - 1); + PVideoFrame srcC = GetChildFrame(n); + PVideoFrame srcN = GetChildFrame(n + 1); + + // for(int y = 0; y < height; y += 2) { + for (int y = 0; y < height; y++) { + unsigned char *pD = env->m_motionMap4DIMax + y * width; + // unsigned char *pDB = m_motionMap4DIMax + (y + 1) * width; + { + const unsigned char *pC = SYP(env, srcC, y); + const unsigned char *pP = SYP(env, srcP, y); + const unsigned char *pN = SYP(env, srcN, y); + const unsigned char *pC_U = SYP(env, srcC, y, PLANAR_U); + const unsigned char *pP_U = SYP(env, srcP, y, PLANAR_U); + const unsigned char *pN_U = SYP(env, srcN, y, PLANAR_U); + const unsigned char *pC_V = SYP(env, srcC, y, PLANAR_V); + const unsigned char *pP_V = SYP(env, srcP, y, PLANAR_V); + const unsigned char *pN_V = SYP(env, srcN, y, PLANAR_V); + + _asm { + mov edi, pD + xor esi, esi + align 16 + loopA: + ///P + MAKE_MOTION_MAP2_ASM_INIT(pC, pP) + MAKE_MOTION_MAP2_ASM(mm0, 2) + + MAKE_MOTION_MAP2_ASM_INIT(pC_U, pP_U) + MAKE_MOTION_MAP2_ASM(mm3, 1) + + MAKE_MOTION_MAP2_ASM_INIT(pC_V, pP_V) + MAKE_MOTION_MAP2_ASM(mm4, 1) + + pmaxub mm3, mm4 + punpcklbw mm3, mm3 + pmaxub mm0, mm3 + + ///N + MAKE_MOTION_MAP2_ASM_INIT(pC, pN) + MAKE_MOTION_MAP2_ASM(mm5, 2) + + MAKE_MOTION_MAP2_ASM_INIT(pC_U, pN_U) + MAKE_MOTION_MAP2_ASM(mm3, 1) + + MAKE_MOTION_MAP2_ASM_INIT(pC_V, pN_V) + MAKE_MOTION_MAP2_ASM(mm4, 1) + + pmaxub mm3, mm4 + punpcklbw mm3, mm3 + pmaxub mm5, mm3 + + // pminub mm0,mm5 + pmaxub mm0, mm5 + + lea esi, [esi + 4] + cmp esi, twidth + movntq[edi + esi * 2 - 8], mm0 + jl loopA + } + } + } + USE_MMX2; + FreeFrame(srcC); + FreeFrame(srcP); + FreeFrame(srcN); +} \ No newline at end of file