static const VSFrameRef *VS_CC mvrecalculateGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { (void)frameData; MVRecalculateData *d = (MVRecalculateData *)*instanceData; if (activationReason == arInitial) { vsapi->requestFrameFilter(n, d->vectors, frameCtx); int nref; int offset = d->analysisData.nDeltaFrame; if (offset > 0) { nref = d->analysisData.isBackward ? n + offset : n - offset; } else { nref = -offset; } if (nref >= 0 && nref < 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; gopInit(&vectorFields, 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->vi->format->bitsPerSample); const uint8_t *pSrc[3] = { NULL }; const uint8_t *pRef[3] = { NULL }; int nSrcPitch[3] = { 0 }; int nRefPitch[3] = { 0 }; int nref; int offset = d->analysisData.nDeltaFrame; if (offset > 0) { nref = d->analysisData.isBackward ? n + offset : n - offset; } else { nref = -offset; } const VSFrameRef *src = vsapi->getFrameFilter(n, d->node, frameCtx); const VSMap *srcprops = vsapi->getFramePropsRO(src); int err; int src_top_field = !!vsapi->propGetInt(srcprops, "_Field", 0, &err); if (err && d->fields && !d->tff_exists) { vsapi->setFilterError("Recalculate: _Field property not found in input frame. Therefore, you must pass tff argument.", frameCtx); gopDeinit(&vectorFields); vsapi->freeFrame(src); return NULL; } // if tff was passed, it overrides _Field. if (d->tff_exists) src_top_field = d->tff ^ (n % 2); for (int plane = 0; plane < d->vi->format->numPlanes; plane++) { pSrc[plane] = vsapi->getReadPtr(src, plane); nSrcPitch[plane] = vsapi->getStride(src, plane); } FakeGroupOfPlanes fgop; fgopInit(&fgop, &d->vectors_data); const VSFrameRef *mvn = vsapi->getFrameFilter(n, d->vectors, frameCtx); const VSMap *mvprops = vsapi->getFramePropsRO(mvn); fgopUpdate(&fgop, (const int *)vsapi->propGetData(mvprops, prop_MVTools_vectors, 0, NULL)); vsapi->freeFrame(mvn); int vectors_size = gopGetArraySize(&vectorFields) * sizeof(int); int *vectors = (int *)malloc(vectors_size); if (fgopIsValid(&fgop) && nref >= 0 && nref < d->vi->numFrames) { const VSFrameRef *ref = vsapi->getFrameFilter(nref, d->node, frameCtx); const VSMap *refprops = vsapi->getFramePropsRO(ref); int ref_top_field = !!vsapi->propGetInt(refprops, "_Field", 0, &err); if (err && d->fields && !d->tff_exists) { vsapi->setFilterError("Recalculate: _Field property not found in input frame. Therefore, you must pass tff argument.", frameCtx); gopDeinit(&vectorFields); vsapi->freeFrame(src); vsapi->freeFrame(ref); free(vectors); fgopDeinit(&fgop); return NULL; } // if tff was passed, it overrides _Field. if (d->tff_exists) ref_top_field = d->tff ^ (nref % 2); int fieldShift = 0; if (d->fields && d->analysisData.nPel > 1 && (d->analysisData.nDeltaFrame % 2)) { fieldShift = (src_top_field && !ref_top_field) ? d->analysisData.nPel / 2 : ((ref_top_field && !src_top_field) ? -(d->analysisData.nPel / 2) : 0); // vertical shift of fields for fieldbased video at finest level pel2 } for (int plane = 0; plane < d->vi->format->numPlanes; plane++) { pRef[plane] = vsapi->getReadPtr(ref, plane); nRefPitch[plane] = vsapi->getStride(ref, plane); } MVGroupOfFrames pSrcGOF, pRefGOF; mvgofInit(&pSrcGOF, d->nSuperLevels, d->analysisData.nWidth, d->analysisData.nHeight, d->nSuperPel, d->nSuperHPad, d->nSuperVPad, d->nSuperModeYUV, d->opt, d->analysisData.xRatioUV, d->analysisData.yRatioUV, d->vi->format->bitsPerSample); mvgofInit(&pRefGOF, d->nSuperLevels, d->analysisData.nWidth, d->analysisData.nHeight, d->nSuperPel, d->nSuperHPad, d->nSuperVPad, d->nSuperModeYUV, d->opt, d->analysisData.xRatioUV, d->analysisData.yRatioUV, d->vi->format->bitsPerSample); // cast away the const, because why not. mvgofUpdate(&pSrcGOF, (uint8_t **)pSrc, nSrcPitch); mvgofUpdate(&pRefGOF, (uint8_t **)pRef, nRefPitch); DCTFFTW *DCTc = NULL; if (d->dctmode >= 1 && d->dctmode <= 4) { DCTc = (DCTFFTW *)malloc(sizeof(DCTFFTW)); dctInit(DCTc, d->analysisData.nBlkSizeX, d->analysisData.nBlkSizeY, d->vi->format->bitsPerSample, d->opt); } gopRecalculateMVs(&vectorFields, &fgop, &pSrcGOF, &pRefGOF, d->searchType, d->nSearchParam, d->nLambda, d->pnew, vectors, fieldShift, d->thSAD, DCTc, d->dctmode, d->smooth, d->meander); if (d->divideExtra) { // make extra level with divided sublocks with median (not estimated) motion gopExtraDivide(&vectorFields, vectors); } gopDeinit(&vectorFields); if (DCTc) { dctDeinit(DCTc); free(DCTc); } mvgofDeinit(&pSrcGOF); mvgofDeinit(&pRefGOF); vsapi->freeFrame(ref); } else {// too close to the beginning or end to do anything gopWriteDefaultToArray(&vectorFields, vectors); gopDeinit(&vectorFields); } VSFrameRef *dst = vsapi->copyFrame(src, core); VSMap *dstprops = vsapi->getFramePropsRW(dst); vsapi->propSetData(dstprops, prop_MVTools_MVAnalysisData, (const char *)(d->divideExtra ? &d->analysisDataDivided : &d->analysisData), sizeof(MVAnalysisData), paReplace); vsapi->propSetData(dstprops, prop_MVTools_vectors, (const char *)vectors, vectors_size, paReplace); free(vectors); #if defined(MVTOOLS_X86) // FIXME: Get rid of all mmx shit. mvtools_cpu_emms(); #endif vsapi->freeFrame(src); fgopDeinit(&fgop); return dst; } return 0; }
static const VSFrameRef *VS_CC mvsuperGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { (void)frameData; MVSuperData *d = (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] = { NULL }; uint8_t *pDst[3] = { NULL }; const uint8_t *pSrcPel[3] = { NULL }; int nSrcPitch[3] = { 0 }; int nDstPitch[3] = { 0 }; int nSrcPelPitch[3] = { 0 }; const VSFrameRef *srcPel = NULL; 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 (int 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; mvgofInit(&pSrcGOF, d->nLevels, d->nWidth, d->nHeight, d->nPel, d->nHPad, d->nVPad, d->nModeYUV, d->opt, d->xRatioUV, d->yRatioUV, d->vi.format->bitsPerSample); mvgofUpdate(&pSrcGOF, pDst, nDstPitch); MVPlaneSet planes[3] = { YPLANE, UPLANE, VPLANE }; for (int plane = 0; plane < d->vi.format->numPlanes; plane++) mvfFillPlane(pSrcGOF.frames[0], pSrc[plane], nSrcPitch[plane], plane); mvgofReduce(&pSrcGOF, d->nModeYUV, d->rfilter); mvgofPad(&pSrcGOF, d->nModeYUV); if (d->usePelClip) { MVFrame *srcFrames = pSrcGOF.frames[0]; for (int plane = 0; plane < d->vi.format->numPlanes; plane++) { pSrcPel[plane] = vsapi->getReadPtr(srcPel, plane); nSrcPelPitch[plane] = vsapi->getStride(srcPel, plane); MVPlane *srcPlane = srcFrames->planes[plane]; if (d->nModeYUV & planes[plane]) mvpRefineExt(srcPlane, pSrcPel[plane], nSrcPelPitch[plane], d->isPelClipPadded); } } else mvgofRefine(&pSrcGOF, d->nModeYUV, d->sharp); vsapi->freeFrame(src); if (d->usePelClip) vsapi->freeFrame(srcPel); mvgofDeinit(&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 0; }