예제 #1
0
MVFlowInter::MVFlowInter(PClip _child, PClip super, PClip _mvbw, PClip _mvfw,  int _time256, double _ml,
                           bool _blend, int nSCD1, int nSCD2, bool _isse, bool _planar, IScriptEnvironment* env) :
GenericVideoFilter(_child),
MVFilter(_mvfw, "MFlowInter", env),
mvClipB(_mvbw, nSCD1, nSCD2, env),
mvClipF(_mvfw, nSCD1, nSCD2, env)
{
   time256 = _time256;
   ml = _ml;
   isse = _isse;
   planar = planar;
   blend = _blend;

	if (!mvClipB.IsBackward())
			env->ThrowError("MFlowInter: wrong backward vectors");
	if (mvClipF.IsBackward())
			env->ThrowError("MFlowInter: wrong forward vectors");

   CheckSimilarity(mvClipB, "mvbw", env);
   CheckSimilarity(mvClipF, "mvfw", env);

        SuperParams64Bits params;
        memcpy(&params, &super->GetVideoInfo().num_audio_samples, 8);
        int nHeightS = params.nHeight;
        int nSuperHPad = params.nHPad;
        int nSuperVPad = params.nVPad;
        int nSuperPel = params.nPel;
        int nSuperModeYUV = params.nModeYUV;
        int nSuperLevels = params.nLevels;
        int nSuperWidth = super->GetVideoInfo().width; // really super
        int nSuperHeight = super->GetVideoInfo().height;

        if (nHeight != nHeightS || nWidth != nSuperWidth-nSuperHPad*2)
                env->ThrowError("MFlowInter : wrong super frame clip");

    if (nPel==1)
        finest = super; // v2.0.9.1
    else
    {
    finest = new MVFinest(super, isse, env);
    AVSValue cache_args[1] = { finest };
    finest = env->Invoke("InternalCache", AVSValue(cache_args,1)).AsClip(); // add cache for speed
    }

//   if (nWidth  != vi.width || (nWidth + nHPadding*2)*nPel != finest->GetVideoInfo().width ||
//       nHeight  != vi.height || (nHeight + nVPadding*2)*nPel != finest->GetVideoInfo().height )
//			env->ThrowError("MVFlowInter: wrong source or finest frame size");

	 // may be padded for full frame cover
	 nBlkXP = (nBlkX*(nBlkSizeX - nOverlapX) + nOverlapX < nWidth) ? nBlkX+1 : nBlkX;
	 nBlkYP = (nBlkY*(nBlkSizeY - nOverlapY) + nOverlapY < nHeight) ? nBlkY+1 : nBlkY;
	 nWidthP = nBlkXP*(nBlkSizeX - nOverlapX) + nOverlapX;
	 nHeightP = nBlkYP*(nBlkSizeY - nOverlapY) + nOverlapY;
	 // for YV12
	 nWidthPUV = nWidthP/2;
	 nHeightPUV = nHeightP/yRatioUV;
	 nHeightUV = nHeight/yRatioUV;
	 nWidthUV = nWidth/2;

	 nHPaddingUV = nHPadding/2;
	 nVPaddingUV = nVPadding/yRatioUV;

	 VPitchY = (nWidthP + 15) & (~15);
	 VPitchUV = (nWidthPUV + 15) & (~15);

 	 VXFullYB = new BYTE [nHeightP*VPitchY];
	 VXFullUVB = new BYTE [nHeightPUV*VPitchUV];
 	 VYFullYB = new BYTE [nHeightP*VPitchY];
	 VYFullUVB = new BYTE [nHeightPUV*VPitchUV];

	 VXFullYF = new BYTE [nHeightP*VPitchY];
	 VXFullUVF = new BYTE [nHeightPUV*VPitchUV];
 	 VYFullYF = new BYTE [nHeightP*VPitchY];
	 VYFullUVF = new BYTE [nHeightPUV*VPitchUV];

  	 VXSmallYB = new BYTE [nBlkXP*nBlkYP];
  	 VYSmallYB = new BYTE [nBlkXP*nBlkYP];
	 VXSmallUVB = new BYTE [nBlkXP*nBlkYP];
	 VYSmallUVB = new BYTE [nBlkXP*nBlkYP];

  	 VXSmallYF = new BYTE [nBlkXP*nBlkYP];
  	 VYSmallYF = new BYTE [nBlkXP*nBlkYP];
	 VXSmallUVF = new BYTE [nBlkXP*nBlkYP];
	 VYSmallUVF = new BYTE [nBlkXP*nBlkYP];

 	 VXFullYBB = new BYTE [nHeightP*VPitchY];
	 VXFullUVBB = new BYTE [nHeightPUV*VPitchUV];
 	 VYFullYBB = new BYTE [nHeightP*VPitchY];
	 VYFullUVBB = new BYTE [nHeightPUV*VPitchUV];

	 VXFullYFF = new BYTE [nHeightP*VPitchY];
	 VXFullUVFF = new BYTE [nHeightPUV*VPitchUV];
 	 VYFullYFF = new BYTE [nHeightP*VPitchY];
	 VYFullUVFF = new BYTE [nHeightPUV*VPitchUV];

  	 VXSmallYBB = new BYTE [nBlkXP*nBlkYP];
  	 VYSmallYBB = new BYTE [nBlkXP*nBlkYP];
	 VXSmallUVBB = new BYTE [nBlkXP*nBlkYP];
	 VYSmallUVBB = new BYTE [nBlkXP*nBlkYP];

  	 VXSmallYFF = new BYTE [nBlkXP*nBlkYP];
  	 VYSmallYFF = new BYTE [nBlkXP*nBlkYP];
	 VXSmallUVFF = new BYTE [nBlkXP*nBlkYP];
	 VYSmallUVFF = new BYTE [nBlkXP*nBlkYP];

	 MaskSmallB = new BYTE [nBlkXP*nBlkYP];
	 MaskFullYB = new BYTE [nHeightP*VPitchY];
	 MaskFullUVB = new BYTE [nHeightPUV*VPitchUV];

	 MaskSmallF = new BYTE [nBlkXP*nBlkYP];
	 MaskFullYF = new BYTE [nHeightP*VPitchY];
	 MaskFullUVF = new BYTE [nHeightPUV*VPitchUV];

	 SADMaskSmallB = new BYTE [nBlkXP*nBlkYP];
	 SADMaskSmallF = new BYTE [nBlkXP*nBlkYP];


	 int CPUF_Resize = env->GetCPUFlags();
	 if (!isse) CPUF_Resize = (CPUF_Resize & !CPUF_INTEGER_SSE) & !CPUF_SSE2;

	 upsizer = new SimpleResize(nWidthP, nHeightP, nBlkXP, nBlkYP, CPUF_Resize);
	 upsizerUV = new SimpleResize(nWidthPUV, nHeightPUV, nBlkXP, nBlkYP, CPUF_Resize);

	 LUTVB = new int[256];
	 LUTVF = new int[256];
	Create_LUTV(time256, LUTVB, LUTVF);

	if ( (pixelType & VideoInfo::CS_YUY2) == VideoInfo::CS_YUY2 && !planar)
   {
		DstPlanes =  new YUY2Planes(nWidth, nHeight);
   }

}
예제 #2
0
MVFlow::MVFlow(PClip _child, PClip _mvec, int _time256, int _mode, bool _fields, PClip _pelclip, int _nIdx, 
               int nSCD1, int nSCD2, bool _mmx, bool _isse, IScriptEnvironment* env) :
        GenericVideoFilter(_child),
        MVFilter(_mvec, "MVFlow", env),
        mvClip(_mvec, nSCD1, nSCD2, env, true),
        pelclip(_pelclip)
{
    time256 = _time256;
    mode = _mode;
    nIdx = _nIdx;
    mmx = _mmx;
    isse = _isse;
    fields = _fields;

    mvCore->AddFrames(nIdx, 2, mvClip.GetLevelCount(), nWidth, nHeight, nPel, nHPadding, nVPadding, 
                      YUVPLANES, isse, yRatioUV);

    usePelClipHere = false;
    if (pelclip && (nPel >= 2)) {
        if (pelclip->GetVideoInfo().width != nWidth*nPel || pelclip->GetVideoInfo().height != nHeight*nPel)
            env->ThrowError("MVFlow: pelclip frame size must be Pel size of source!");
        else
            usePelClipHere = true;
    }
    // may be padded for full frame cover
    nBlkXP = (nBlkX*(nBlkSizeX - nOverlapX) + nOverlapX < nWidth) ? nBlkX+1 : nBlkX;
    nBlkYP = (nBlkY*(nBlkSizeY - nOverlapY) + nOverlapY < nHeight) ? nBlkY+1 : nBlkY;
    nWidthP = nBlkXP*(nBlkSizeX - nOverlapX) + nOverlapX;
    nHeightP = nBlkYP*(nBlkSizeY - nOverlapY) + nOverlapY;
    // for YV12
    nWidthPUV = nWidthP/2;
    nHeightPUV = nHeightP/yRatioUV;

    nHeightUV = nHeight/yRatioUV;
    nWidthUV = nWidth/2;

    nHPaddingUV = nHPadding/2;
    nVPaddingUV = nVPadding/yRatioUV;


    VPitchY = (nWidthP + 15) & (~15);
    VPitchUV = (nWidthPUV + 15) & (~15);
    //  char debugbuf[128];
    //   wsprintf(debugbuf,"MVFlow: nBlkX=%d, nOverlap=%d, nBlkXP=%d, nWidth=%d, nWidthP=%d, VPitchY=%d",nBlkX, nOverlap, nBlkXP, nWidth, nWidthP, VPitchY);
    //   OutputDebugString(debugbuf);

    VXFullY = new BYTE [nHeightP*VPitchY];
    VXFullUV = new BYTE [nHeightPUV*VPitchUV];

    VYFullY = new BYTE [nHeightP*VPitchY];
    VYFullUV = new BYTE [nHeightPUV*VPitchUV];

    VXSmallY = new BYTE [nBlkXP*nBlkYP];
    VYSmallY = new BYTE [nBlkXP*nBlkYP];
    VXSmallUV = new BYTE [nBlkXP*nBlkYP];
    VYSmallUV = new BYTE [nBlkXP*nBlkYP];


    int pel2WidthY = (nWidth + 2*nHPadding)*nPel; // and pitch
    pel2HeightY = (nHeight + 2*nVPadding)*nPel;
    int pel2WidthUV = (nWidthUV + 2*nHPaddingUV)*nPel;
    pel2HeightUV = (nHeightUV + 2*nVPaddingUV)*nPel;
    pel2PitchY = (pel2WidthY + 15) & (~15);
    pel2PitchUV = (pel2WidthUV + 15) & (~15);
    pel2OffsetY = pel2PitchY * nVPadding*nPel + nHPadding*nPel;
    pel2OffsetUV = pel2PitchUV * nVPaddingUV*nPel + nHPaddingUV*nPel;
    if (nPel>1) {
        pel2PlaneY = new BYTE [pel2PitchY*pel2HeightY];
        pel2PlaneU = new BYTE [pel2PitchUV*pel2HeightUV];
        pel2PlaneV = new BYTE [pel2PitchUV*pel2HeightUV];
    }

    int CPUF_Resize = env->GetCPUFlags();
    if (!isse) CPUF_Resize = (CPUF_Resize & !CPUF_INTEGER_SSE) & !CPUF_SSE2;

    upsizer = new SimpleResize(nWidthP, nHeightP, nBlkXP, nBlkYP, CPUF_Resize);
    upsizerUV = new SimpleResize(nWidthPUV, nHeightPUV, nBlkXP, nBlkYP, CPUF_Resize);

    Create_LUTV(time256, LUTV);

    DstPlanes = new YUY2Planes(nWidth, nHeight, vi.pixel_type, isse);
}
예제 #3
0
MVFlowInter::MVFlowInter(PClip _child, PClip _mvbw, PClip _mvfw,  int _time256, double _ml, double _mSAD, 
                         double _mSADC, PClip _pelclip, int _nIdx, int nSCD1, int nSCD2, bool _mmx, bool _isse, 
                         IScriptEnvironment* env) :
             GenericVideoFilter(_child),
             MVFilter(_mvfw, "MVFlowInter", env),
             mvClipB(_mvbw, nSCD1, nSCD2, env, true),
             mvClipF(_mvfw, nSCD1, nSCD2, env, true),
             pelclip(_pelclip)
{
    time256 = _time256;
    ml = _ml;
    mSAD  = _mSAD;
    mSADC = _mSADC;
    nIdx = _nIdx;
    mmx = _mmx;
    isse = _isse;

    normSAD1024  = unsigned int( 1024 * 255 / (mSAD * nBlkSizeX*nBlkSizeY) ); //normalize
    normSADC1024 = unsigned int( 1024 * 255 / (mSADC * nBlkSizeX*nBlkSizeY) ); //normalize

    if (!mvClipB.IsBackward())
        env->ThrowError("MVFlowInter: wrong backward vectors");
    if (mvClipF.IsBackward())
        env->ThrowError("MVFlowInter: wrong forward vectors");

    CheckSimilarity(mvClipB, "mvbw", env);
    CheckSimilarity(mvClipF, "mvfw", env);

    mvCore->AddFrames(nIdx, 3, mvClipB.GetLevelCount(), nWidth, nHeight,
                      nPel, nHPadding, nVPadding, YUVPLANES, isse, yRatioUV);

    usePelClipHere = false;
    if (pelclip && (nPel > 1)) {
        if (pelclip->GetVideoInfo().width != nWidth*nPel || pelclip->GetVideoInfo().height != nHeight*nPel)
            env->ThrowError("MVFlowInter: pelclip frame size must be Pel of source!");
        else
            usePelClipHere = true;
    }
    // may be padded for full frame cover
    nBlkXP = (nBlkX*(nBlkSizeX - nOverlapX) + nOverlapX < nWidth) ? nBlkX+1 : nBlkX;
    nBlkYP = (nBlkY*(nBlkSizeY - nOverlapY) + nOverlapY < nHeight) ? nBlkY+1 : nBlkY;
    nWidthP = nBlkXP*(nBlkSizeX - nOverlapX) + nOverlapX;
    nHeightP = nBlkYP*(nBlkSizeY - nOverlapY) + nOverlapY;
    // for YV12
    nWidthPUV = nWidthP/2;
    nHeightPUV = nHeightP/yRatioUV;
    nHeightUV = nHeight/yRatioUV;
    nWidthUV = nWidth/2;

    nHPaddingUV = nHPadding/2;
    nVPaddingUV = nVPadding/yRatioUV;

    VPitchY = (nWidthP + 15) & (~15);
    VPitchUV = (nWidthPUV + 15) & (~15);

    VXFullYB = new BYTE [nHeightP*VPitchY];
    VXFullUVB = new BYTE [nHeightPUV*VPitchUV];
    VYFullYB = new BYTE [nHeightP*VPitchY];
    VYFullUVB = new BYTE [nHeightPUV*VPitchUV];

    VXFullYF = new BYTE [nHeightP*VPitchY];
    VXFullUVF = new BYTE [nHeightPUV*VPitchUV];
    VYFullYF = new BYTE [nHeightP*VPitchY];
    VYFullUVF = new BYTE [nHeightPUV*VPitchUV];

    VXSmallYB = new BYTE [nBlkXP*nBlkYP];
    VYSmallYB = new BYTE [nBlkXP*nBlkYP];
    VXSmallUVB = new BYTE [nBlkXP*nBlkYP];
    VYSmallUVB = new BYTE [nBlkXP*nBlkYP];

    VXSmallYF = new BYTE [nBlkXP*nBlkYP];
    VYSmallYF = new BYTE [nBlkXP*nBlkYP];
    VXSmallUVF = new BYTE [nBlkXP*nBlkYP];
    VYSmallUVF = new BYTE [nBlkXP*nBlkYP];

    VXFullYBB = new BYTE [nHeightP*VPitchY];
    VXFullUVBB = new BYTE [nHeightPUV*VPitchUV];
    VYFullYBB = new BYTE [nHeightP*VPitchY];
    VYFullUVBB = new BYTE [nHeightPUV*VPitchUV];

    VXFullYFF = new BYTE [nHeightP*VPitchY];
    VXFullUVFF = new BYTE [nHeightPUV*VPitchUV];
    VYFullYFF = new BYTE [nHeightP*VPitchY];
    VYFullUVFF = new BYTE [nHeightPUV*VPitchUV];

    VXSmallYBB = new BYTE [nBlkXP*nBlkYP];
    VYSmallYBB = new BYTE [nBlkXP*nBlkYP];
    VXSmallUVBB = new BYTE [nBlkXP*nBlkYP];
    VYSmallUVBB = new BYTE [nBlkXP*nBlkYP];

    VXSmallYFF = new BYTE [nBlkXP*nBlkYP];
    VYSmallYFF = new BYTE [nBlkXP*nBlkYP];
    VXSmallUVFF = new BYTE [nBlkXP*nBlkYP];
    VYSmallUVFF = new BYTE [nBlkXP*nBlkYP];

    MaskSmallB = new BYTE [nBlkXP*nBlkYP];
    MaskFullYB = new BYTE [nHeightP*VPitchY];
    MaskFullUVB = new BYTE [nHeightPUV*VPitchUV];

    MaskSmallF = new BYTE [nBlkXP*nBlkYP];
    MaskFullYF = new BYTE [nHeightP*VPitchY];
    MaskFullUVF = new BYTE [nHeightPUV*VPitchUV];

    SADMaskSmallB = new BYTE [nBlkXP*nBlkYP];
    SADMaskSmallF = new BYTE [nBlkXP*nBlkYP];

    int pel2WidthY = (nWidth + 2*nHPadding)*nPel;
    pel2HeightY = (nHeight + 2*nVPadding)*nPel;
    int pel2WidthUV = (nWidthUV + 2*nHPaddingUV)*nPel;
    pel2HeightUV = (nHeightUV + 2*nVPaddingUV)*nPel;
    pel2PitchY = (pel2WidthY + 15) & (~15);
    pel2PitchUV = (pel2WidthUV + 15) & (~15);
    pel2OffsetY = pel2PitchY * nVPadding*nPel + nHPadding*nPel;
    pel2OffsetUV = pel2PitchUV * nVPaddingUV*nPel + nHPaddingUV*nPel;
    if (nPel>1) {
        pel2PlaneYB = new BYTE [pel2PitchY*pel2HeightY];
        pel2PlaneUB = new BYTE [pel2PitchUV*pel2HeightUV];
        pel2PlaneVB = new BYTE [pel2PitchUV*pel2HeightUV];
        pel2PlaneYF = new BYTE [pel2PitchY*pel2HeightY];
        pel2PlaneUF = new BYTE [pel2PitchUV*pel2HeightUV];
        pel2PlaneVF = new BYTE [pel2PitchUV*pel2HeightUV];
    }

    int CPUF_Resize = env->GetCPUFlags();
    if (!isse) CPUF_Resize = (CPUF_Resize & !CPUF_INTEGER_SSE) & !CPUF_SSE2;

    upsizer = new SimpleResize(nWidthP, nHeightP, nBlkXP, nBlkYP, CPUF_Resize);
    upsizerUV = new SimpleResize(nWidthPUV, nHeightPUV, nBlkXP, nBlkYP, CPUF_Resize);

    Create_LUTV(time256, LUTVB, LUTVF);

    SrcPlanes =  new YUY2Planes(nWidth, nHeight, vi.pixel_type, isse);
    RefPlanes =  new YUY2Planes(nWidth, nHeight, vi.pixel_type, isse);
    DstPlanes =  new YUY2Planes(nWidth, nHeight, vi.pixel_type, isse);
}
예제 #4
0
static const VSFrameRef *VS_CC mvflowfpsGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) {
    MVFlowFPSData *d = (MVFlowFPSData *) * instanceData;

    if (activationReason == arInitial) {
        int off = d->mvClipB->GetDeltaFrame(); // integer offset of reference frame

        int nleft = (int)(n * d->fa / d->fb);
        int nright = nleft + off;

        int time256 = int( (double(n) * double(d->fa) / double(d->fb) - nleft) * 256 + 0.5);
        if (off > 1)
            time256 = time256 / off;

        if (time256 == 0) {
            vsapi->requestFrameFilter(d->vi.numFrames ? VSMIN(nleft, d->vi.numFrames - 1) : nleft, d->node, frameCtx);
            return 0;
        } else if (time256 == 256) {
            vsapi->requestFrameFilter(d->vi.numFrames ? VSMIN(nright, d->vi.numFrames - 1) : nright, d->node, frameCtx);
            return 0;
        }

        if ((nleft < d->vi.numFrames && nright < d->vi.numFrames) || !d->vi.numFrames) { // for the good estimation case
            if (d->maskmode == 2)
                vsapi->requestFrameFilter(nleft, d->mvfw, frameCtx); // requests nleft - off, nleft
            vsapi->requestFrameFilter(nright, d->mvfw, frameCtx); // requests nleft, nleft + off
            vsapi->requestFrameFilter(nleft, d->mvbw, frameCtx); // requests nleft, nleft + off
            if (d->maskmode == 2)
                vsapi->requestFrameFilter(nright, d->mvbw, frameCtx); // requests nleft + off, nleft + off + off

            vsapi->requestFrameFilter(nleft, d->finest, frameCtx);
            vsapi->requestFrameFilter(nright, d->finest, frameCtx);
        } 

        vsapi->requestFrameFilter(d->vi.numFrames ? VSMIN(nleft, d->vi.numFrames - 1) : nleft, d->node, frameCtx);

        if (d->blend)
            vsapi->requestFrameFilter(d->vi.numFrames ? VSMIN(nright, d->vi.numFrames - 1) : nright, d->node, frameCtx);

    } else if (activationReason == arAllFramesReady) {
        int nleft = (int)(n * d->fa / d->fb);
        // intermediate product may be very large! Now I know how to multiply int64
        int time256 = int( (double(n)*double(d->fa)/double(d->fb) - nleft) * 256 + 0.5);

        int off = d->mvClipB->GetDeltaFrame(); // integer offset of reference frame
        // usually off must be = 1
        if (off > 1)
            time256 = time256 / off;

        int nright = nleft + off;

        if (time256 == 0) {
            return vsapi->getFrameFilter(d->vi.numFrames ? VSMIN(nleft, d->vi.numFrames - 1) : nleft, d->node, frameCtx); // simply left
        } else if (time256 == 256) {
            return vsapi->getFrameFilter(d->vi.numFrames ? VSMIN(nright, d->vi.numFrames - 1) : nright, d->node, frameCtx); // simply right
        }

        MVClipBalls ballsF(d->mvClipF, vsapi);
        MVClipBalls ballsB(d->mvClipB, vsapi);

        bool isUsableF = false;
        bool isUsableB = false;

        if ((nleft < d->vi.numFrames && nright < d->vi.numFrames) || !d->vi.numFrames) {
            const VSFrameRef *mvF = vsapi->getFrameFilter(nright, d->mvfw, frameCtx);
            ballsF.Update(mvF);// forward from current to next
            isUsableF = ballsF.IsUsable();
            vsapi->freeFrame(mvF);

            const VSFrameRef *mvB = vsapi->getFrameFilter(nleft, d->mvbw, frameCtx);
            ballsB.Update(mvB);// backward from next to current
            isUsableB = ballsB.IsUsable();
            vsapi->freeFrame(mvB);
        }

        const int nWidth = d->bleh->nWidth;
        const int nHeight = d->bleh->nHeight;
        const int nWidthUV = d->nWidthUV;
        const int nHeightUV = d->nHeightUV;
        const int maskmode = d->maskmode;
        const bool blend = d->blend;
        const bool isse = d->isse;
        const double ml = d->ml;
        const int xRatioUV = d->bleh->xRatioUV;
        const int yRatioUV = d->bleh->yRatioUV;
        const int nBlkX = d->bleh->nBlkX;
        const int nBlkY = d->bleh->nBlkY;
        const int nBlkSizeX = d->bleh->nBlkSizeX;
        const int nBlkSizeY = d->bleh->nBlkSizeY;
        const int nOverlapX = d->bleh->nOverlapX;
        const int nOverlapY = d->bleh->nOverlapY;
        const int nVPadding = d->bleh->nVPadding;
        const int nHPadding = d->bleh->nHPadding;
        const int nVPaddingUV = d->nVPaddingUV;
        const int nHPaddingUV = d->nHPaddingUV;
        const int nPel = d->bleh->nPel;
        const int VPitchY = d->VPitchY;
        const int VPitchUV = d->VPitchUV;
        const int nBlkXP = d->nBlkXP;
        const int nBlkYP = d->nBlkYP;
        SimpleResize *upsizer = d->upsizer;
        SimpleResize *upsizerUV = d->upsizerUV;
        int *LUTVB = d->LUTVB;
        int *LUTVF = d->LUTVF;

        uint8_t *VXFullYB = d->VXFullYB;
        uint8_t *VXFullUVB = d->VXFullUVB;
        uint8_t *VYFullYB = d->VYFullYB;
        uint8_t *VYFullUVB = d->VYFullUVB;
        uint8_t *VXSmallYB = d->VXSmallYB;
        uint8_t *VYSmallYB = d->VYSmallYB;
        uint8_t *VXSmallUVB = d->VXSmallUVB;
        uint8_t *VYSmallUVB = d->VYSmallUVB;
        uint8_t *VXFullYF = d->VXFullYF;
        uint8_t *VXFullUVF = d->VXFullUVF;
        uint8_t *VYFullYF = d->VYFullYF;
        uint8_t *VYFullUVF = d->VYFullUVF;
        uint8_t *VXSmallYF = d->VXSmallYF;
        uint8_t *VYSmallYF = d->VYSmallYF;
        uint8_t *VXSmallUVF = d->VXSmallUVF;
        uint8_t *VYSmallUVF = d->VYSmallUVF;

        uint8_t *VXFullYBB = d->VXFullYBB;
        uint8_t *VXFullUVBB = d->VXFullUVBB;
        uint8_t *VYFullYBB = d->VYFullYBB;
        uint8_t *VYFullUVBB = d->VYFullUVBB;
        uint8_t *VXSmallYBB = d->VXSmallYBB;
        uint8_t *VYSmallYBB = d->VYSmallYBB;
        uint8_t *VXSmallUVBB = d->VXSmallUVBB;
        uint8_t *VYSmallUVBB = d->VYSmallUVBB;
        uint8_t *VXFullYFF = d->VXFullYFF;
        uint8_t *VXFullUVFF = d->VXFullUVFF;
        uint8_t *VYFullYFF = d->VYFullYFF;
        uint8_t *VYFullUVFF = d->VYFullUVFF;
        uint8_t *VXSmallYFF = d->VXSmallYFF;
        uint8_t *VYSmallYFF = d->VYSmallYFF;
        uint8_t *VXSmallUVFF = d->VXSmallUVFF;
        uint8_t *VYSmallUVFF = d->VYSmallUVFF;

        uint8_t *MaskSmallB = d->MaskSmallB;
        uint8_t *MaskFullYB = d->MaskFullYB;
        uint8_t *MaskFullUVB = d->MaskFullUVB;
        uint8_t *MaskSmallF = d->MaskSmallF;
        uint8_t *MaskFullYF = d->MaskFullYF;
        uint8_t *MaskFullUVF = d->MaskFullUVF;

        int bitsPerSample = d->vi.format->bitsPerSample;
        int bytesPerSample = d->vi.format->bytesPerSample;

        if (isUsableB && isUsableF) {
            uint8_t *pDst[3];
            const uint8_t *pRef[3], *pSrc[3];
            int nDstPitches[3], nRefPitches[3];

            // If both are usable, that means both nleft and nright are less than numFrames, or that we don't have numFrames. Thus there is no need to check nleft and nright here.
            const VSFrameRef *src = vsapi->getFrameFilter(nleft, d->finest, frameCtx);
            const VSFrameRef *ref = vsapi->getFrameFilter(nright, d->finest, frameCtx);//  right frame for  compensation
            VSFrameRef *dst = vsapi->newVideoFrame(d->vi.format, d->vi.width, d->vi.height, src, core);

            Create_LUTV(time256, LUTVB, LUTVF); // lookup table

            for (int i = 0; i < d->vi.format->numPlanes; i++) {
                pDst[i] = vsapi->getWritePtr(dst, i);
                pRef[i] = vsapi->getReadPtr(ref, i);
                pSrc[i] = vsapi->getReadPtr(src, i);
                nDstPitches[i] = vsapi->getStride(dst, i);
                nRefPitches[i] = vsapi->getStride(ref, i);
            }

            int nOffsetY = nRefPitches[0] * nVPadding * nPel + nHPadding * bytesPerSample * nPel;
            int nOffsetUV = nRefPitches[1] * nVPaddingUV * nPel + nHPaddingUV * bytesPerSample * nPel;

            if (nright != d->nrightLast) {
                // make  vector vx and vy small masks
                // 1. ATTENTION: vectors are assumed SHORT (|vx|, |vy| < 127) !
                // 2. they will be zeroed if not
                // 3. added 128 to all values
                MakeVectorSmallMasks(&ballsB, nBlkX, nBlkY, VXSmallYB, nBlkXP, VYSmallYB, nBlkXP);
                if (nBlkXP > nBlkX) {// fill right
                    for (int j=0; j<nBlkY; j++) {
                        VXSmallYB[j*nBlkXP + nBlkX] = VSMIN(VXSmallYB[j*nBlkXP + nBlkX-1],128);
                        VYSmallYB[j*nBlkXP + nBlkX] = VYSmallYB[j*nBlkXP + nBlkX-1];
                    }
                }
                if (nBlkYP > nBlkY) {// fill bottom
                    for (int i=0; i<nBlkXP; i++) {
                        VXSmallYB[nBlkXP*nBlkY +i] = VXSmallYB[nBlkXP*(nBlkY-1) +i];
                        VYSmallYB[nBlkXP*nBlkY +i] = VSMIN(VYSmallYB[nBlkXP*(nBlkY-1) +i],128);
                    }
                }

                upsizer->Resize(VXFullYB, VPitchY, VXSmallYB, nBlkXP);
                upsizer->Resize(VYFullYB, VPitchY, VYSmallYB, nBlkXP);

                if (d->vi.format->colorFamily != cmGray) {
                    VectorSmallMaskYToHalfUV(VXSmallYB, nBlkXP, nBlkYP, VXSmallUVB, xRatioUV);
                    VectorSmallMaskYToHalfUV(VYSmallYB, nBlkXP, nBlkYP, VYSmallUVB, yRatioUV);

                    upsizerUV->Resize(VXFullUVB, VPitchUV, VXSmallUVB, nBlkXP);
                    upsizerUV->Resize(VYFullUVB, VPitchUV, VYSmallUVB, nBlkXP);
                }
            }
            // analyse vectors field to detect occlusion
            //        double occNormB = (256-time256)/(256*ml);
            //        MakeVectorOcclusionMask(mvClipB, nBlkX, nBlkY, occNormB, 1.0, nPel, MaskSmallB, nBlkXP);
            MakeVectorOcclusionMaskTime(&ballsB, nBlkX, nBlkY, ml, 1.0, nPel, MaskSmallB, nBlkXP, (256-time256), nBlkSizeX - nOverlapX, nBlkSizeY - nOverlapY);
            if (nBlkXP > nBlkX) // fill right
                for (int j=0; j<nBlkY; j++)
                    MaskSmallB[j*nBlkXP + nBlkX] = MaskSmallB[j*nBlkXP + nBlkX-1];
            if (nBlkYP > nBlkY) // fill bottom
                for (int i=0; i<nBlkXP; i++)
                    MaskSmallB[nBlkXP*nBlkY +i] = MaskSmallB[nBlkXP*(nBlkY-1) +i];

            upsizer->Resize(MaskFullYB, VPitchY, MaskSmallB, nBlkXP);
            if (d->vi.format->colorFamily != cmGray)
                upsizerUV->Resize(MaskFullUVB, VPitchUV, MaskSmallB, nBlkXP);

            d->nrightLast = nright;

            if (nleft != d->nleftLast) {
                // make  vector vx and vy small masks
                // 1. ATTENTION: vectors are assumed SHORT (|vx|, |vy| < 127) !
                // 2. they will be zeroed if not
                // 3. added 128 to all values
                MakeVectorSmallMasks(&ballsF, nBlkX, nBlkY, VXSmallYF, nBlkXP, VYSmallYF, nBlkXP);
                if (nBlkXP > nBlkX) {// fill right
                    for (int j=0; j<nBlkY; j++) {
                        VXSmallYF[j*nBlkXP + nBlkX] = VSMIN(VXSmallYF[j*nBlkXP + nBlkX-1],128);
                        VYSmallYF[j*nBlkXP + nBlkX] = VYSmallYF[j*nBlkXP + nBlkX-1];
                    }
                }
                if (nBlkYP > nBlkY) {// fill bottom
                    for (int i=0; i<nBlkXP; i++) {
                        VXSmallYF[nBlkXP*nBlkY +i] = VXSmallYF[nBlkXP*(nBlkY-1) +i];
                        VYSmallYF[nBlkXP*nBlkY +i] = VSMIN(VYSmallYF[nBlkXP*(nBlkY-1) +i],128);
                    }
                }

                upsizer->Resize(VXFullYF, VPitchY, VXSmallYF, nBlkXP);
                upsizer->Resize(VYFullYF, VPitchY, VYSmallYF, nBlkXP);

                if (d->vi.format->colorFamily != cmGray) {
                    VectorSmallMaskYToHalfUV(VXSmallYF, nBlkXP, nBlkYP, VXSmallUVF, xRatioUV);
                    VectorSmallMaskYToHalfUV(VYSmallYF, nBlkXP, nBlkYP, VYSmallUVF, yRatioUV);

                    upsizerUV->Resize(VXFullUVF, VPitchUV, VXSmallUVF, nBlkXP);
                    upsizerUV->Resize(VYFullUVF, VPitchUV, VYSmallUVF, nBlkXP);
                }
            }
            // analyse vectors field to detect occlusion
            //        double occNormF = time256/(256*ml);
            //        MakeVectorOcclusionMask(mvClipF, nBlkX, nBlkY, occNormF, 1.0, nPel, MaskSmallF, nBlkXP);
            MakeVectorOcclusionMaskTime(&ballsF, nBlkX, nBlkY, ml, 1.0, nPel, MaskSmallF, nBlkXP, time256, nBlkSizeX - nOverlapX, nBlkSizeY - nOverlapY);
            if (nBlkXP > nBlkX) // fill right
                for (int j=0; j<nBlkY; j++)
                    MaskSmallF[j*nBlkXP + nBlkX] = MaskSmallF[j*nBlkXP + nBlkX-1];
            if (nBlkYP > nBlkY) // fill bottom
                for (int i=0; i<nBlkXP; i++)
                    MaskSmallF[nBlkXP*nBlkY +i] = MaskSmallF[nBlkXP*(nBlkY-1) +i];

            upsizer->Resize(MaskFullYF, VPitchY, MaskSmallF, nBlkXP);
            if (d->vi.format->colorFamily != cmGray)
                upsizerUV->Resize(MaskFullUVF, VPitchUV, MaskSmallF, nBlkXP);

            d->nleftLast = nleft;

            if (maskmode == 2) { // These motion vectors should only be needed with maskmode 2. Why was the Avisynth plugin requesting them for all mask modes?
                // Get motion info from more frames for occlusion areas
                const VSFrameRef *mvFF = vsapi->getFrameFilter(nleft, d->mvfw, frameCtx);
                ballsF.Update(mvFF);// forward from prev to cur
                isUsableF = ballsF.IsUsable();
                vsapi->freeFrame(mvFF);

                const VSFrameRef *mvBB = vsapi->getFrameFilter(nright, d->mvbw, frameCtx);
                ballsB.Update(mvBB);// backward from next next to next
                isUsableB = ballsB.IsUsable();
                vsapi->freeFrame(mvBB);
            }

            if (maskmode == 2 && isUsableB && isUsableF) {// slow method with extra frames
                // get vector mask from extra frames
                MakeVectorSmallMasks(&ballsB, nBlkX, nBlkY, VXSmallYBB, nBlkXP, VYSmallYBB, nBlkXP);
                MakeVectorSmallMasks(&ballsF, nBlkX, nBlkY, VXSmallYFF, nBlkXP, VYSmallYFF, nBlkXP);
                if (nBlkXP > nBlkX) {// fill right
                    for (int j=0; j<nBlkY; j++) {
                        VXSmallYBB[j*nBlkXP + nBlkX] = VSMIN(VXSmallYBB[j*nBlkXP + nBlkX-1],128);
                        VYSmallYBB[j*nBlkXP + nBlkX] = VYSmallYBB[j*nBlkXP + nBlkX-1];
                        VXSmallYFF[j*nBlkXP + nBlkX] = VSMIN(VXSmallYFF[j*nBlkXP + nBlkX-1],128);
                        VYSmallYFF[j*nBlkXP + nBlkX] = VYSmallYFF[j*nBlkXP + nBlkX-1];
                    }
                }
                if (nBlkYP > nBlkY) {// fill bottom
                    for (int i=0; i<nBlkXP; i++) {
                        VXSmallYBB[nBlkXP*nBlkY +i] = VXSmallYBB[nBlkXP*(nBlkY-1) +i];
                        VYSmallYBB[nBlkXP*nBlkY +i] = VSMIN(VYSmallYBB[nBlkXP*(nBlkY-1) +i],128);
                        VXSmallYFF[nBlkXP*nBlkY +i] = VXSmallYFF[nBlkXP*(nBlkY-1) +i];
                        VYSmallYFF[nBlkXP*nBlkY +i] = VSMIN(VYSmallYFF[nBlkXP*(nBlkY-1) +i],128);
                    }
                }

                upsizer->Resize(VXFullYBB, VPitchY, VXSmallYBB, nBlkXP);
                upsizer->Resize(VYFullYBB, VPitchY, VYSmallYBB, nBlkXP);

                upsizer->Resize(VXFullYFF, VPitchY, VXSmallYFF, nBlkXP);
                upsizer->Resize(VYFullYFF, VPitchY, VYSmallYFF, nBlkXP);

                FlowInterExtra(pDst[0], nDstPitches[0], pRef[0] + nOffsetY, pSrc[0] + nOffsetY, nRefPitches[0],
                        VXFullYB, VXFullYF, VYFullYB, VYFullYF, MaskFullYB, MaskFullYF, VPitchY,
                        nWidth, nHeight, time256, nPel, LUTVB, LUTVF, VXFullYBB, VXFullYFF, VYFullYBB, VYFullYFF, bitsPerSample);
                if (d->vi.format->colorFamily != cmGray) {
                    VectorSmallMaskYToHalfUV(VXSmallYBB, nBlkXP, nBlkYP, VXSmallUVBB, xRatioUV);
                    VectorSmallMaskYToHalfUV(VYSmallYBB, nBlkXP, nBlkYP, VYSmallUVBB, yRatioUV);
                    VectorSmallMaskYToHalfUV(VXSmallYFF, nBlkXP, nBlkYP, VXSmallUVFF, xRatioUV);
                    VectorSmallMaskYToHalfUV(VYSmallYFF, nBlkXP, nBlkYP, VYSmallUVFF, yRatioUV);

                    upsizerUV->Resize(VXFullUVBB, VPitchUV, VXSmallUVBB, nBlkXP);
                    upsizerUV->Resize(VYFullUVBB, VPitchUV, VYSmallUVBB, nBlkXP);

                    upsizerUV->Resize(VXFullUVFF, VPitchUV, VXSmallUVFF, nBlkXP);
                    upsizerUV->Resize(VYFullUVFF, VPitchUV, VYSmallUVFF, nBlkXP);

                    FlowInterExtra(pDst[1], nDstPitches[1], pRef[1] + nOffsetUV, pSrc[1] + nOffsetUV, nRefPitches[1],
                            VXFullUVB, VXFullUVF, VYFullUVB, VYFullUVF, MaskFullUVB, MaskFullUVF, VPitchUV,
                            nWidthUV, nHeightUV, time256, nPel, LUTVB, LUTVF, VXFullUVBB, VXFullUVFF, VYFullUVBB, VYFullUVFF, bitsPerSample);
                    FlowInterExtra(pDst[2], nDstPitches[2], pRef[2] + nOffsetUV, pSrc[2] + nOffsetUV, nRefPitches[2],
                            VXFullUVB, VXFullUVF, VYFullUVB, VYFullUVF, MaskFullUVB, MaskFullUVF, VPitchUV,
                            nWidthUV, nHeightUV, time256, nPel, LUTVB, LUTVF, VXFullUVBB, VXFullUVFF, VYFullUVBB, VYFullUVFF, bitsPerSample);
                }
            } else if (maskmode == 1) {// old method without extra frames
                FlowInter(pDst[0], nDstPitches[0], pRef[0] + nOffsetY, pSrc[0] + nOffsetY, nRefPitches[0],
                        VXFullYB, VXFullYF, VYFullYB, VYFullYF, MaskFullYB, MaskFullYF, VPitchY,
                        nWidth, nHeight, time256, nPel, LUTVB, LUTVF, bitsPerSample);
                if (d->vi.format->colorFamily != cmGray) {
                    FlowInter(pDst[1], nDstPitches[1], pRef[1] + nOffsetUV, pSrc[1] + nOffsetUV, nRefPitches[1],
                            VXFullUVB, VXFullUVF, VYFullUVB, VYFullUVF, MaskFullUVB, MaskFullUVF, VPitchUV,
                            nWidthUV, nHeightUV, time256, nPel, LUTVB, LUTVF, bitsPerSample);
                    FlowInter(pDst[2], nDstPitches[2], pRef[2] + nOffsetUV, pSrc[2] + nOffsetUV, nRefPitches[2],
                        VXFullUVB, VXFullUVF, VYFullUVB, VYFullUVF, MaskFullUVB, MaskFullUVF, VPitchUV,
                        nWidthUV, nHeightUV, time256, nPel, LUTVB, LUTVF, bitsPerSample);
                }
            } else {// mode=0, faster simple method
                FlowInterSimple(pDst[0], nDstPitches[0], pRef[0] + nOffsetY, pSrc[0] + nOffsetY, nRefPitches[0],
                        VXFullYB, VXFullYF, VYFullYB, VYFullYF, MaskFullYB, MaskFullYF, VPitchY,
                        nWidth, nHeight, time256, nPel, LUTVB, LUTVF, bitsPerSample);
                if (d->vi.format->colorFamily != cmGray) {
                    FlowInterSimple(pDst[1], nDstPitches[1], pRef[1] + nOffsetUV, pSrc[1] + nOffsetUV, nRefPitches[1],
                            VXFullUVB, VXFullUVF, VYFullUVB, VYFullUVF, MaskFullUVB, MaskFullUVF, VPitchUV,
                            nWidthUV, nHeightUV, time256, nPel, LUTVB, LUTVF, bitsPerSample);
                    FlowInterSimple(pDst[2], nDstPitches[2], pRef[2] + nOffsetUV, pSrc[2] + nOffsetUV, nRefPitches[2],
                            VXFullUVB, VXFullUVF, VYFullUVB, VYFullUVF, MaskFullUVB, MaskFullUVF, VPitchUV,
                            nWidthUV, nHeightUV, time256, nPel, LUTVB, LUTVF, bitsPerSample);
                }
            }

            vsapi->freeFrame(src);
            vsapi->freeFrame(ref);

            return dst;
        } else { // poor estimation
            const VSFrameRef *src = vsapi->getFrameFilter(d->vi.numFrames ? VSMIN(nleft, d->vi.numFrames - 1) : nleft, d->node, frameCtx);

            if (blend) {//let's blend src with ref frames like ConvertFPS
                uint8_t *pDst[3];
                const uint8_t *pRef[3], *pSrc[3];
                int nDstPitches[3], nRefPitches[3], nSrcPitches[3];

                const VSFrameRef *ref = vsapi->getFrameFilter(d->vi.numFrames ? VSMIN(nright, d->vi.numFrames - 1) : nright, d->node, frameCtx);

                VSFrameRef *dst = vsapi->newVideoFrame(d->vi.format, d->vi.width, d->vi.height, src, core);

                for (int i = 0; i < d->vi.format->numPlanes; i++) {
                    pDst[i] = vsapi->getWritePtr(dst, i);
                    pRef[i] = vsapi->getReadPtr(ref, i);
                    pSrc[i] = vsapi->getReadPtr(src, i);
                    nDstPitches[i] = vsapi->getStride(dst, i);
                    nRefPitches[i] = vsapi->getStride(ref, i);
                    nSrcPitches[i] = vsapi->getStride(src, i);
                }

                // blend with time weight
                Blend(pDst[0], pSrc[0], pRef[0], nHeight, nWidth, nDstPitches[0], nSrcPitches[0], nRefPitches[0], time256, isse, bitsPerSample);
                if (d->vi.format->colorFamily != cmGray) {
                    Blend(pDst[1], pSrc[1], pRef[1], nHeightUV, nWidthUV, nDstPitches[1], nSrcPitches[1], nRefPitches[1], time256, isse, bitsPerSample);
                    Blend(pDst[2], pSrc[2], pRef[2], nHeightUV, nWidthUV, nDstPitches[2], nSrcPitches[2], nRefPitches[2], time256, isse, bitsPerSample);
                }

                vsapi->freeFrame(src);
                vsapi->freeFrame(ref);

                return dst;
            } else {
                return src; // like ChangeFPS
            }
        }
    }

    return 0;
}