static const VSFrameRef *VS_CC mvsuperGetFrame(int32_t n, int32_t activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { MVSuperData *d = reinterpret_cast<MVSuperData *>(*instanceData); if (activationReason == arInitial) { vsapi->requestFrameFilter(n, d->node, frameCtx); if (d->usePelClip) vsapi->requestFrameFilter(n, d->pelclip, frameCtx); } else if (activationReason == arAllFramesReady) { const VSFrameRef *src = vsapi->getFrameFilter(n, d->node, frameCtx); const uint8_t *pSrc[3] = { nullptr }; uint8_t *pDst[3] = { nullptr }; const uint8_t *pSrcPel[3] = { nullptr }; int32_t nSrcPitch[3] = { 0 }; int32_t nDstPitch[3] = { 0 }; int32_t nSrcPelPitch[3] = { 0 }; const VSFrameRef *srcPel = nullptr; if (d->usePelClip) srcPel = vsapi->getFrameFilter(n, d->pelclip, frameCtx); VSFrameRef *dst = vsapi->newVideoFrame(d->vi.format, d->vi.width, d->vi.height, src, core); for (int32_t plane = 0; plane < d->vi.format->numPlanes; ++plane) { pSrc[plane] = vsapi->getReadPtr(src, plane); nSrcPitch[plane] = vsapi->getStride(src, plane); pDst[plane] = vsapi->getWritePtr(dst, plane); nDstPitch[plane] = vsapi->getStride(dst, plane); memset(pDst[plane], 0, nDstPitch[plane] * vsapi->getFrameHeight(dst, plane)); } MVGroupOfFrames *pSrcGOF = new MVGroupOfFrames(d->nLevels, d->nWidth, d->nHeight, d->nPel, d->nHPad, d->nVPad, d->nModeYUV, d->xRatioUV, d->yRatioUV); pSrcGOF->Update(d->nModeYUV, pDst[0], nDstPitch[0], pDst[1], nDstPitch[1], pDst[2], nDstPitch[2]); MVPlaneSet planes[3] = { YPLANE, UPLANE, VPLANE }; for (int32_t plane = 0; plane < d->vi.format->numPlanes; ++plane) pSrcGOF->SetPlane(pSrc[plane], nSrcPitch[plane], planes[plane]); pSrcGOF->Reduce(d->nModeYUV, d->rfilter); pSrcGOF->Pad(d->nModeYUV); if (d->usePelClip) { MVFrame *srcFrames = pSrcGOF->GetFrame(0); for (int32_t plane = 0; plane < d->vi.format->numPlanes; ++plane) { pSrcPel[plane] = vsapi->getReadPtr(srcPel, plane); nSrcPelPitch[plane] = vsapi->getStride(srcPel, plane); MVPlane *srcPlane = srcFrames->GetPlane(planes[plane]); if (d->nModeYUV & planes[plane]) srcPlane->RefineExt(pSrcPel[plane], nSrcPelPitch[plane], d->isPelClipPadded); } } else pSrcGOF->Refine(d->nModeYUV, d->sharp); vsapi->freeFrame(src); if (d->usePelClip) vsapi->freeFrame(srcPel); delete pSrcGOF; if (n == 0) { VSMap *props = vsapi->getFramePropsRW(dst); vsapi->propSetInt(props, "Super_height", d->nHeight, paReplace); vsapi->propSetInt(props, "Super_hpad", d->nHPad, paReplace); vsapi->propSetInt(props, "Super_vpad", d->nVPad, paReplace); vsapi->propSetInt(props, "Super_pel", d->nPel, paReplace); vsapi->propSetInt(props, "Super_modeyuv", d->nModeYUV, paReplace); vsapi->propSetInt(props, "Super_levels", d->nLevels, paReplace); } return dst; } return nullptr; }
static const VSFrameRef *VS_CC mvrecalculateGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { MVRecalculateData *d = (MVRecalculateData *) * instanceData; if (activationReason == arInitial) { vsapi->requestFrameFilter(n, d->vectors, frameCtx); int offset = ( d->analysisData.isBackward ) ? d->analysisData.nDeltaFrame : -d->analysisData.nDeltaFrame; int nref = n + offset; if (nref >= 0 && (nref < d->vi->numFrames || !d->vi->numFrames)) { if (n < nref) { vsapi->requestFrameFilter(n, d->node, frameCtx); vsapi->requestFrameFilter(nref, d->node, frameCtx); } else { vsapi->requestFrameFilter(nref, d->node, frameCtx); vsapi->requestFrameFilter(n, d->node, frameCtx); } } else { // too close to beginning/end of clip vsapi->requestFrameFilter(n, d->node, frameCtx); } } else if (activationReason == arAllFramesReady) { GroupOfPlanes *vectorFields = new GroupOfPlanes(d->analysisData.nBlkSizeX, d->analysisData.nBlkSizeY, d->analysisData.nLvCount, d->analysisData.nPel, d->analysisData.nMotionFlags, d->analysisData.nCPUFlags, d->analysisData.nOverlapX, d->analysisData.nOverlapY, d->analysisData.nBlkX, d->analysisData.nBlkY, d->analysisData.xRatioUV, d->analysisData.yRatioUV, d->divideExtra, d->supervi->format->bitsPerSample); const uint8_t *pSrc[3]; const uint8_t *pRef[3]; uint8_t *pDst; int nSrcPitch[3]; int nRefPitch[3]; int offset = ( d->analysisData.isBackward ) ? d->analysisData.nDeltaFrame : -d->analysisData.nDeltaFrame; int nref = n + offset; const VSFrameRef *src = vsapi->getFrameFilter(n, d->node, frameCtx); const VSMap *srcprops = vsapi->getFramePropsRO(src); int err; bool srctff = !!vsapi->propGetInt(srcprops, "_Field", 0, &err); if (err && d->fields && !d->tffexists) { vsapi->setFilterError("Recalculate: _Field property not found in input frame. Therefore, you must pass tff argument.", frameCtx); delete vectorFields; vsapi->freeFrame(src); return NULL; } // if tff was passed, it overrides _Field. if (d->tffexists) srctff = d->tff && (n % 2 == 0); //child->GetParity(n); // bool tff; for (int plane = 0; plane < d->supervi->format->numPlanes; plane++) { pSrc[plane] = vsapi->getReadPtr(src, plane); nSrcPitch[plane] = vsapi->getStride(src, plane); } int dst_height = 1; int dst_width = d->headerSize / sizeof(int) + vectorFields->GetArraySize(); //v1.8.1 // In Avisynth the frame was packed BGR32, which has 4 bytes per pixel. // It's GRAY8 here. dst_width *= 4; VSFrameRef *dst = vsapi->newVideoFrame(d->vi->format, dst_width, dst_height, src, core); pDst = vsapi->getWritePtr(dst, 0); // write analysis parameters as a header to frame memcpy(pDst, &d->headerSize, sizeof(int)); if (d->divideExtra) memcpy(pDst+sizeof(int), &d->analysisDataDivided, sizeof(d->analysisData)); else memcpy(pDst+sizeof(int), &d->analysisData, sizeof(d->analysisData)); pDst += d->headerSize; const VSFrameRef *mvn = vsapi->getFrameFilter(n, d->vectors, frameCtx); MVClipBalls balls(d->mvClip, vsapi); balls.Update(mvn); vsapi->freeFrame(mvn); if (balls.IsUsable() && nref >= 0 && (nref < d->vi->numFrames || !d->vi->numFrames)) { const VSFrameRef *ref = vsapi->getFrameFilter(nref, d->node, frameCtx); const VSMap *refprops = vsapi->getFramePropsRO(ref); bool reftff = !!vsapi->propGetInt(refprops, "_Field", 0, &err); if (err && d->fields && !d->tffexists) { vsapi->setFilterError("Recalculate: _Field property not found in input frame. Therefore, you must pass tff argument.", frameCtx); delete vectorFields; vsapi->freeFrame(src); vsapi->freeFrame(ref); vsapi->freeFrame(dst); return NULL; } // if tff was passed, it overrides _Field. if (d->tffexists) reftff = d->tff && (nref % 2 == 0); //child->GetParity(n); // bool tff; int fieldShift = 0; if (d->fields && d->analysisData.nPel > 1 && (d->analysisData.nDeltaFrame % 2)) { fieldShift = (srctff && !reftff) ? d->analysisData.nPel/2 : ( (reftff && !srctff) ? -(d->analysisData.nPel/2) : 0); // vertical shift of fields for fieldbased video at finest level pel2 } for (int plane = 0; plane < d->supervi->format->numPlanes; plane++) { pRef[plane] = vsapi->getReadPtr(ref, plane); nRefPitch[plane] = vsapi->getStride(ref, plane); } MVGroupOfFrames *pSrcGOF = new MVGroupOfFrames(d->nSuperLevels, d->analysisData.nWidth, d->analysisData.nHeight, d->nSuperPel, d->nSuperHPad, d->nSuperVPad, d->nSuperModeYUV, d->isse, d->analysisData.xRatioUV, d->analysisData.yRatioUV, d->supervi->format->bitsPerSample); MVGroupOfFrames *pRefGOF = new MVGroupOfFrames(d->nSuperLevels, d->analysisData.nWidth, d->analysisData.nHeight, d->nSuperPel, d->nSuperHPad, d->nSuperVPad, d->nSuperModeYUV, d->isse, d->analysisData.xRatioUV, d->analysisData.yRatioUV, d->supervi->format->bitsPerSample); // cast away the const, because why not. pSrcGOF->Update(d->nModeYUV, (uint8_t *)pSrc[0], nSrcPitch[0], (uint8_t *)pSrc[1], nSrcPitch[1], (uint8_t *)pSrc[2], nSrcPitch[2]); // v2.0 pRefGOF->Update(d->nModeYUV, (uint8_t *)pRef[0], nRefPitch[0], (uint8_t *)pRef[1], nRefPitch[1], (uint8_t *)pRef[2], nRefPitch[2]); // v2.0 DCTClass *DCTc = NULL; if (d->dctmode != 0) { /* // FIXME: deal with this inline asm shit if (d->isse && (d->blksize == 8) && d->blksizev == 8) DCTc = new DCTINT(d->blksize, d->blksizev, d->dctmode); else */ DCTc = new DCTFFTW(d->blksize, d->blksizev, d->dctmode, d->vi->format->bitsPerSample); } vectorFields->RecalculateMVs(balls, pSrcGOF, pRefGOF, d->searchType, d->nSearchParam, d->nLambda, d->pnew, reinterpret_cast<int*>(pDst), NULL, fieldShift, d->thSAD, DCTc, d->smooth, d->meander); if (d->divideExtra) { // make extra level with divided sublocks with median (not estimated) motion vectorFields->ExtraDivide(reinterpret_cast<int*>(pDst)); } delete vectorFields; if (DCTc) delete DCTc; delete pSrcGOF; delete pRefGOF; vsapi->freeFrame(ref); } else // too close to the beginning or end to do anything { vectorFields->WriteDefaultToArray(reinterpret_cast<int*>(pDst)); delete vectorFields; } // FIXME: Get rid of all mmx shit. mvtools_cpu_emms(); vsapi->freeFrame(src); return dst; } return 0; }