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(¶ms, &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); } }
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); }
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); }
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; }