static inline PixelType MEDIAN(PixelType a, PixelType b, PixelType c) { PixelType mn = VSMIN(a, b); PixelType mx = VSMAX(a, b); PixelType m = VSMIN(mx, c); m = VSMAX(mn, m); return m; }
static const VSFrameRef *VS_CC reverseGetframe(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { SingleClipData *d = (SingleClipData *) * instanceData; if (activationReason == arInitial) { vsapi->requestFrameFilter(VSMAX(d->vi->numFrames - n - 1, 0), d->node, frameCtx); } else if (activationReason == arAllFramesReady) { return vsapi->getFrameFilter(VSMAX(d->vi->numFrames - n - 1, 0), d->node, frameCtx); } return 0; }
static void VS_CC interleaveCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi) { InterleaveData d; InterleaveData *data; VSNodeRef *cref; int i; int err; int compat; int mismatch = !!vsapi->propGetInt(in, "mismatch", 0, &err); int extend = !!vsapi->propGetInt(in, "extend", 0, &err); d.numclips = vsapi->propNumElements(in, "clips"); if (d.numclips == 1) { // passthrough for the special case with only one clip cref = vsapi->propGetNode(in, "clips", 0, 0); vsapi->propSetNode(out, "clip", cref, 0); vsapi->freeNode(cref); } else { d.node = malloc(sizeof(d.node[0]) * d.numclips); compat = 0; for (i = 0; i < d.numclips; i++) { d.node[i] = vsapi->propGetNode(in, "clips", i, 0); if (isCompatFormat(vsapi->getVideoInfo(d.node[i]))) compat = 1; } if (findCommonVi(d.node, d.numclips, &d.vi, 1, vsapi) && (!mismatch || compat)) { for (i = 0; i < d.numclips; i++) vsapi->freeNode(d.node[i]); free(d.node); RETERROR("Interleave: clip property mismatch"); } if (extend) { d.vi.numFrames *= d.numclips; } else if (d.vi.numFrames) { // this is exactly how avisynth does it d.vi.numFrames = (vsapi->getVideoInfo(d.node[0])->numFrames - 1) * d.numclips + 1; for (i = 1; i < d.numclips; i++) d.vi.numFrames = VSMAX(d.vi.numFrames, (vsapi->getVideoInfo(d.node[i])->numFrames - 1) * d.numclips + i + 1); } d.vi.fpsNum *= d.numclips; data = malloc(sizeof(d)); *data = d; vsapi->createFilter(in, out, "Interleave", interleaveInit, interleaveGetframe, interleaveFree, fmParallel, nfNoCache, data, core); } }
static char *strrepl(const char *in, const char *str, const char *repl) { size_t siz; char *res, *outptr; const char *inptr; int count = 0; inptr = in; while((inptr = strstr(inptr, str))) { count++; inptr++; } if(count == 0) { size_t in_len = strlen(in); res = malloc(in_len + 1); memcpy(res, in, in_len + 1); return res; } siz = (strlen(in) - strlen(str) * count + strlen(repl) * count) * sizeof(char) + 1; res = malloc(VSMAX(siz, strlen(in) * sizeof(char) + 1)); strcpy(res, in); outptr = res; inptr = in; while((outptr = strstr(outptr, str)) && (inptr = strstr(inptr, str))) { outptr[0] = '\0'; strcat(outptr, repl); strcat(outptr, (inptr + strlen(str))); outptr++; inptr++; } return res; }
static const VSFrameRef * VS_CC vs_depth_get_frame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { vs_depth_data *data = *instanceData; VSFrameRef *ret = 0; char fail_str[1024]; int err = 0; if (activationReason == arInitial) { vsapi->requestFrameFilter(n, data->node, frameCtx); } else { const VSFrameRef *src_frame = 0; VSFrameRef *dst_frame = 0; void *tmp = 0; const void *src_plane[3] = { 0 }; void *dst_plane[3] = { 0 }; ptrdiff_t src_stride[3] = { 0 }; ptrdiff_t dst_stride[3] = { 0 }; int width; int height; unsigned num_planes; size_t tmp_size; size_t tmp_size_uv; VSMap *props; unsigned p; width = data->vi.width; height = data->vi.height; num_planes = data->vi.format->numPlanes; src_frame = vsapi->getFrameFilter(n, data->node, frameCtx); dst_frame = vsapi->newVideoFrame(data->vi.format, width, height, src_frame, core); if ((err = zimg2_plane_filter_get_tmp_size(data->filter, &tmp_size))) { zimg_get_last_error(fail_str, sizeof(fail_str)); goto fail; } if (data->filter_uv) { if ((err = zimg2_plane_filter_get_tmp_size(data->filter_uv, &tmp_size_uv))) { zimg_get_last_error(fail_str, sizeof(fail_str)); goto fail; } } else { tmp_size_uv = 0; } VS_ALIGNED_MALLOC(&tmp, VSMAX(tmp_size, tmp_size_uv), 32); if (!tmp) { strcpy(fail_str, "error allocating temporary buffer"); err = 1; goto fail; } for (p = 0; p < num_planes; ++p) { const zimg_filter *filter; if ((p == 1 || p == 2) && data->filter_uv) filter = data->filter_uv; else filter = data->filter; src_plane[0] = vsapi->getReadPtr(src_frame, p); src_stride[0] = vsapi->getStride(src_frame, p); dst_plane[0] = vsapi->getWritePtr(dst_frame, p); dst_stride[0] = vsapi->getStride(dst_frame, p); if ((err = zimg2_plane_filter_process(filter, tmp, src_plane, dst_plane, src_stride, dst_stride))) { zimg_get_last_error(fail_str, sizeof(fail_str)); goto fail; } } props = vsapi->getFramePropsRW(dst_frame); vsapi->propSetInt(props, "_ColorRange", !data->fullrange, paReplace); ret = dst_frame; dst_frame = 0; fail: vsapi->freeFrame(src_frame); vsapi->freeFrame(dst_frame); VS_ALIGNED_FREE(tmp); } if (err) vsapi->setFilterError(fail_str, frameCtx); return ret; }
static void VS_CC mvrecalculateCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi) { MVRecalculateData d; MVRecalculateData *data; int err; d.thSAD = int64ToIntS(vsapi->propGetInt(in, "thsad", 0, &err)); if (err) d.thSAD = 200; d.smooth = int64ToIntS(vsapi->propGetInt(in, "smooth", 0, &err)); if (err) d.smooth = 1; d.blksize = int64ToIntS(vsapi->propGetInt(in, "blksize", 0, &err)); if (err) d.blksize = 8; d.blksizev = int64ToIntS(vsapi->propGetInt(in, "blksizev", 0, &err)); if (err) d.blksizev = d.blksize; d.search = int64ToIntS(vsapi->propGetInt(in, "search", 0, &err)); if (err) d.search = 4; d.searchparam = int64ToIntS(vsapi->propGetInt(in, "searchparam", 0, &err)); if (err) d.searchparam = 2; d.chroma = !!vsapi->propGetInt(in, "chroma", 0, &err); if (err) d.chroma = 1; d.truemotion = !!vsapi->propGetInt(in, "truemotion", 0, &err); if (err) d.truemotion = 1; d.nLambda = int64ToIntS(vsapi->propGetInt(in, "lambda", 0, &err)); if (err) d.nLambda = d.truemotion ? (1000 * d.blksize * d.blksizev / 64) : 0; d.pnew = int64ToIntS(vsapi->propGetInt(in, "pnew", 0, &err)); if (err) d.pnew = d.truemotion ? 50 : 0; // relative to 256 d.overlap = int64ToIntS(vsapi->propGetInt(in, "overlap", 0, &err)); d.overlapv = int64ToIntS(vsapi->propGetInt(in, "overlapv", 0, &err)); if (err) d.overlapv = d.overlap; d.dctmode = int64ToIntS(vsapi->propGetInt(in, "dct", 0, &err)); d.divideExtra = int64ToIntS(vsapi->propGetInt(in, "divide", 0, &err)); d.isse = !!vsapi->propGetInt(in, "isse", 0, &err); if (err) d.isse = 1; d.meander = !!vsapi->propGetInt(in, "meander", 0, &err); if (err) d.meander = 1; d.fields = !!vsapi->propGetInt(in, "fields", 0, &err); d.tff = !!vsapi->propGetInt(in, "tff", 0, &err); d.tffexists = err; if (d.search < 0 || d.search > 7) { vsapi->setError(out, "Recalculate: search must be between 0 and 7 (inclusive)."); return; } if (d.dctmode < 0 || d.dctmode > 10) { vsapi->setError(out, "Recalculate: dct must be between 0 and 10 (inclusive)."); return; } if (d.dctmode >= 5 && !((d.blksize == 4 && d.blksizev == 4) || (d.blksize == 8 && d.blksizev == 4) || (d.blksize == 8 && d.blksizev == 8) || (d.blksize == 16 && d.blksizev == 8) || (d.blksize == 16 && d.blksizev == 16))) { vsapi->setError(out, "Recalculate: dct 5..10 can only work with 4x4, 8x4, 8x8, 16x8, and 16x16 blocks."); return; } if (d.divideExtra < 0 || d.divideExtra > 2) { vsapi->setError(out, "Recalculate: divide must be between 0 and 2 (inclusive)."); return; } d.analysisData.nBlkSizeX = d.blksize; d.analysisData.nBlkSizeY = d.blksizev; if ((d.analysisData.nBlkSizeX != 4 || d.analysisData.nBlkSizeY != 4) && (d.analysisData.nBlkSizeX != 8 || d.analysisData.nBlkSizeY != 4) && (d.analysisData.nBlkSizeX != 8 || d.analysisData.nBlkSizeY != 8) && (d.analysisData.nBlkSizeX != 16 || d.analysisData.nBlkSizeY != 2) && (d.analysisData.nBlkSizeX != 16 || d.analysisData.nBlkSizeY != 8) && (d.analysisData.nBlkSizeX != 16 || d.analysisData.nBlkSizeY != 16) && (d.analysisData.nBlkSizeX != 32 || d.analysisData.nBlkSizeY != 32) && (d.analysisData.nBlkSizeX != 32 || d.analysisData.nBlkSizeY != 16)) { vsapi->setError(out, "Recalculate: the block size must be 4x4, 8x4, 8x8, 16x2, 16x8, 16x16, 32x16, or 32x32."); return; } if (d.overlap < 0 || d.overlap > d.blksize / 2 || d.overlapv < 0 || d.overlapv > d.blksizev / 2) { vsapi->setError(out, "Recalculate: overlap must be at most half of blksize, overlapv must be at most half of blksizev, and they both need to be at least 0."); return; } if (d.divideExtra && (d.blksize < 8 && d.blksizev < 8) ) { vsapi->setError(out, "Recalculate: blksize and blksizev must be at least 8 when divide=True."); return; } d.analysisData.nOverlapX = d.overlap; d.analysisData.nOverlapY = d.overlapv; SearchType searchTypes[] = { ONETIME, NSTEP, LOGARITHMIC, EXHAUSTIVE, HEX2SEARCH, UMHSEARCH, HSEARCH, VSEARCH }; d.searchType = searchTypes[d.search]; if (d.searchType == NSTEP) d.nSearchParam = ( d.searchparam < 0 ) ? 0 : d.searchparam; else d.nSearchParam = ( d.searchparam < 1 ) ? 1 : d.searchparam; // XXX maybe get rid of these two // Bleh, they're checked by client filters. Though it's kind of pointless. d.analysisData.nMagicKey = MOTION_MAGIC_KEY; d.analysisData.nVersion = MVANALYSIS_DATA_VERSION; // MVAnalysisData and outfile format version: last update v1.8.1 d.headerSize = VSMAX(4 + sizeof(d.analysisData), 256); // include itself, but usually equal to 256 :-) d.node = vsapi->propGetNode(in, "super", 0, 0); d.supervi = vsapi->getVideoInfo(d.node); if (d.overlap % (1 << d.supervi->format->subSamplingW) || d.overlapv % (1 << d.supervi->format->subSamplingH)) { vsapi->setError(out, "Recalculate: The requested overlap is incompatible with the super clip's subsampling."); vsapi->freeNode(d.node); return; } if (d.divideExtra && (d.overlap % (2 << d.supervi->format->subSamplingW) || d.overlapv % (2 << d.supervi->format->subSamplingH))) { // subsampling times 2 vsapi->setError(out, "Recalculate: overlap and overlapv must be multiples of 2 or 4 when divide=True, depending on the super clip's subsampling."); vsapi->freeNode(d.node); return; } char errorMsg[1024]; const VSFrameRef *evil = vsapi->getFrame(0, d.node, errorMsg, 1024); if (!evil) { vsapi->setError(out, std::string("Recalculate: failed to retrieve first frame from super clip. Error message: ").append(errorMsg).c_str()); vsapi->freeNode(d.node); return; } const VSMap *props = vsapi->getFramePropsRO(evil); int evil_err[6]; int nHeight = int64ToIntS(vsapi->propGetInt(props, "Super_height", 0, &evil_err[0])); d.nSuperHPad = int64ToIntS(vsapi->propGetInt(props, "Super_hpad", 0, &evil_err[1])); d.nSuperVPad = int64ToIntS(vsapi->propGetInt(props, "Super_vpad", 0, &evil_err[2])); d.nSuperPel = int64ToIntS(vsapi->propGetInt(props, "Super_pel", 0, &evil_err[3])); d.nSuperModeYUV = int64ToIntS(vsapi->propGetInt(props, "Super_modeyuv", 0, &evil_err[4])); d.nSuperLevels = int64ToIntS(vsapi->propGetInt(props, "Super_levels", 0, &evil_err[5])); vsapi->freeFrame(evil); for (int i = 0; i < 6; i++) if (evil_err[i]) { vsapi->setError(out, "Recalculate: required properties not found in first frame of super clip. Maybe clip didn't come from mv.Super? Was the first frame trimmed away?"); vsapi->freeNode(d.node); return; } if (d.supervi->format->colorFamily == cmGray) d.chroma = 0; d.nModeYUV = d.chroma ? YUVPLANES : YPLANE; if ((d.nModeYUV & d.nSuperModeYUV) != d.nModeYUV) { //x vsapi->setError(out, "Recalculate: super clip does not contain needed colour data."); vsapi->freeNode(d.node); return; } d.vectors = vsapi->propGetNode(in, "vectors", 0, NULL); d.vi = vsapi->getVideoInfo(d.vectors); evil = vsapi->getFrame(0, d.vectors, errorMsg, 1024); if (!evil) { vsapi->setError(out, std::string("Recalculate: failed to retrieve first frame from vectors clip. Error message: ").append(errorMsg).c_str()); vsapi->freeNode(d.node); vsapi->freeNode(d.vectors); return; } // XXX This really should be passed as a frame property. const MVAnalysisData *pAnalyseFilter = reinterpret_cast<const MVAnalysisData *>(vsapi->getReadPtr(evil, 0) + sizeof(int)); d.analysisData.yRatioUV = pAnalyseFilter->GetYRatioUV(); d.analysisData.xRatioUV = pAnalyseFilter->GetXRatioUV(); d.analysisData.nWidth = pAnalyseFilter->GetWidth(); d.analysisData.nHeight = pAnalyseFilter->GetHeight(); d.analysisData.nDeltaFrame = pAnalyseFilter->GetDeltaFrame(); d.analysisData.isBackward = pAnalyseFilter->IsBackward(); vsapi->freeFrame(evil); d.analysisData.bitsPerSample = d.supervi->format->bitsPerSample; int pixelMax = (1 << d.supervi->format->bitsPerSample) - 1; d.thSAD = int((double)d.thSAD * pixelMax / 255.0 + 0.5); // normalize threshold to block size int referenceBlockSize = 8 * 8; d.thSAD = d.thSAD * (d.analysisData.nBlkSizeX * d.analysisData.nBlkSizeY) / referenceBlockSize; if (d.chroma) d.thSAD += d.thSAD / (d.analysisData.xRatioUV * d.analysisData.yRatioUV) * 2; d.analysisData.nMotionFlags = 0; d.analysisData.nMotionFlags |= d.isse ? MOTION_USE_ISSE : 0; d.analysisData.nMotionFlags |= d.analysisData.isBackward ? MOTION_IS_BACKWARD : 0; d.analysisData.nMotionFlags |= d.chroma ? MOTION_USE_CHROMA_MOTION : 0; if (d.isse) { d.analysisData.nCPUFlags = cpu_detect(); } if (d.supervi->format->bitsPerSample > 8) d.isse = 0; // needed here because MVPlane can't have isse=1 with more than 8 bits d.analysisData.nPel = d.nSuperPel;//x int nSuperWidth = d.supervi->width; if (nHeight != d.analysisData.nHeight || nSuperWidth - 2 * d.nSuperHPad != d.analysisData.nWidth) { vsapi->setError(out, "Recalculate: wrong frame size."); vsapi->freeNode(d.node); vsapi->freeNode(d.vectors); return; } d.analysisData.nHPadding = d.nSuperHPad; //v2.0 //x d.analysisData.nVPadding = d.nSuperVPad; int nBlkX = (d.analysisData.nWidth - d.analysisData.nOverlapX) / (d.analysisData.nBlkSizeX - d.analysisData.nOverlapX);//x int nBlkY = (d.analysisData.nHeight - d.analysisData.nOverlapY) / (d.analysisData.nBlkSizeY - d.analysisData.nOverlapY); d.analysisData.nBlkX = nBlkX; d.analysisData.nBlkY = nBlkY; d.analysisData.nLvCount = 1; if (d.divideExtra) { //v1.8.1 memcpy(&d.analysisDataDivided, &d.analysisData, sizeof(d.analysisData)); d.analysisDataDivided.nBlkX = d.analysisData.nBlkX * 2; d.analysisDataDivided.nBlkY = d.analysisData.nBlkY * 2; d.analysisDataDivided.nBlkSizeX = d.analysisData.nBlkSizeX / 2; d.analysisDataDivided.nBlkSizeY = d.analysisData.nBlkSizeY / 2; d.analysisDataDivided.nOverlapX = d.analysisData.nOverlapX / 2; d.analysisDataDivided.nOverlapY = d.analysisData.nOverlapY / 2; d.analysisDataDivided.nLvCount = d.analysisData.nLvCount + 1; } try { d.mvClip = new MVClipDicks(d.vectors, 8 * 8 * 255, 255, vsapi); } catch (MVException &e) { vsapi->setError(out, std::string("Recalculate: ").append(e.what()).c_str()); vsapi->freeNode(d.node); vsapi->freeNode(d.vectors); return; } data = (MVRecalculateData *)malloc(sizeof(d)); *data = d; vsapi->createFilter(in, out, "Recalculate", mvrecalculateInit, mvrecalculateGetFrame, mvrecalculateFree, fmParallel, 0, data, core); }
static const VSFrameRef *VS_CC mvmaskGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { (void)frameData; MVMaskData *d = (MVMaskData *)*instanceData; if (activationReason == arInitial) { vsapi->requestFrameFilter(n, d->vectors, frameCtx); vsapi->requestFrameFilter(n, d->node, frameCtx); } else if (activationReason == arAllFramesReady) { const VSFrameRef *src = vsapi->getFrameFilter(n, d->node, frameCtx); VSFrameRef *dst = vsapi->newVideoFrame(d->vi.format, d->vi.width, d->vi.height, src, core); const uint8_t *pSrc[3]; uint8_t *pDst[3]; int nDstPitches[3]; int nSrcPitches[3]; pSrc[0] = vsapi->getReadPtr(src, 0); nSrcPitches[0] = vsapi->getStride(src, 0); for (int i = 0; i < 3; i++) { pDst[i] = vsapi->getWritePtr(dst, i); nDstPitches[i] = vsapi->getStride(dst, i); } FakeGroupOfPlanes fgop; const VSFrameRef *mvn = vsapi->getFrameFilter(n, d->vectors, frameCtx); fgopInit(&fgop, &d->vectors_data); const VSMap *mvprops = vsapi->getFramePropsRO(mvn); fgopUpdate(&fgop, (const uint8_t *)vsapi->propGetData(mvprops, prop_MVTools_vectors, 0, NULL)); vsapi->freeFrame(mvn); const int kind = d->kind; const int nWidth = d->vectors_data.nWidth; const int nHeight = d->vectors_data.nHeight; const int nWidthUV = d->nWidthUV; const int nHeightUV = d->nHeightUV; const int nSceneChangeValue = d->nSceneChangeValue; if (fgopIsUsable(&fgop, d->thscd1, d->thscd2)) { const int nBlkX = d->vectors_data.nBlkX; const int nBlkY = d->vectors_data.nBlkY; const int nBlkCount = nBlkX * nBlkY; const float fMaskNormFactor = d->fMaskNormFactor; const float fMaskNormFactor2 = d->fMaskNormFactor2; const float fGamma = d->fGamma; const float fHalfGamma = d->fHalfGamma; const int nPel = d->vectors_data.nPel; const int nBlkSizeX = d->vectors_data.nBlkSizeX; const int nBlkSizeY = d->vectors_data.nBlkSizeY; const int nOverlapX = d->vectors_data.nOverlapX; const int nOverlapY = d->vectors_data.nOverlapY; const int nWidthB = d->nWidthB; const int nHeightB = d->nHeightB; const int nWidthBUV = d->nWidthBUV; const int nHeightBUV = d->nHeightBUV; SimpleResize *upsizer = &d->upsizer; SimpleResize *upsizerUV = &d->upsizerUV; const int time256 = d->time256; const int bitsPerSample = vsapi->getFrameFormat(src)->bitsPerSample; uint8_t *smallMask = (uint8_t *)malloc(nBlkX * nBlkY); uint8_t *smallMaskV = (uint8_t *)malloc(nBlkX * nBlkY); if (kind == 0) { // vector length mask for (int j = 0; j < nBlkCount; j++) smallMask[j] = mvmaskLength(fgopGetBlock(&fgop, 0, j)->vector, nPel, fMaskNormFactor2, fHalfGamma); } else if (kind == 1) { // SAD mask MakeSADMaskTime(&fgop, nBlkX, nBlkY, 4.0 * fMaskNormFactor / (nBlkSizeX * nBlkSizeY), fGamma, nPel, smallMask, nBlkX, time256, nBlkSizeX - nOverlapX, nBlkSizeY - nOverlapY, bitsPerSample); } else if (kind == 2) { // occlusion mask MakeVectorOcclusionMaskTime(&fgop, d->vectors_data.isBackward, nBlkX, nBlkY, 1.0 / fMaskNormFactor, fGamma, nPel, smallMask, nBlkX, time256, nBlkSizeX - nOverlapX, nBlkSizeY - nOverlapY); } else if (kind == 3) { // vector x mask for (int j = 0; j < nBlkCount; j++) smallMask[j] = VSMAX(0, VSMIN(255, (int)(fgopGetBlock(&fgop, 0, j)->vector.x * fMaskNormFactor * 100 + 128))); // shited by 128 for signed support } else if (kind == 4) { // vector y mask for (int j = 0; j < nBlkCount; j++) smallMask[j] = VSMAX(0, VSMIN(255, (int)(fgopGetBlock(&fgop, 0, j)->vector.y * fMaskNormFactor * 100 + 128))); // shited by 128 for signed support } else if (kind == 5) { // vector x mask in U, y mask in V for (int j = 0; j < nBlkCount; j++) { VECTOR v = fgopGetBlock(&fgop, 0, j)->vector; smallMask[j] = VSMAX(0, VSMIN(255, (int)(v.x * fMaskNormFactor * 100 + 128))); // shited by 128 for signed support smallMaskV[j] = VSMAX(0, VSMIN(255, (int)(v.y * fMaskNormFactor * 100 + 128))); // shited by 128 for signed support } } if (kind == 5) { // do not change luma for kind=5 memcpy(pDst[0], pSrc[0], nSrcPitches[0] * nHeight); } else { upsizer->simpleResize_uint8_t(upsizer, pDst[0], nDstPitches[0], smallMask, nBlkX); if (nWidth > nWidthB) for (int h = 0; h < nHeight; h++) for (int w = nWidthB; w < nWidth; w++) *(pDst[0] + h * nDstPitches[0] + w) = *(pDst[0] + h * nDstPitches[0] + nWidthB - 1); if (nHeight > nHeightB) vs_bitblt(pDst[0] + nHeightB * nDstPitches[0], nDstPitches[0], pDst[0] + (nHeightB - 1) * nDstPitches[0], nDstPitches[0], nWidth, nHeight - nHeightB); } // chroma upsizerUV->simpleResize_uint8_t(upsizerUV, pDst[1], nDstPitches[1], smallMask, nBlkX); if (kind == 5) upsizerUV->simpleResize_uint8_t(upsizerUV, pDst[2], nDstPitches[2], smallMaskV, nBlkX); else memcpy(pDst[2], pDst[1], nHeightUV * nDstPitches[1]); if (nWidthUV > nWidthBUV) for (int h = 0; h < nHeightUV; h++) for (int w = nWidthBUV; w < nWidthUV; w++) { *(pDst[1] + h * nDstPitches[1] + w) = *(pDst[1] + h * nDstPitches[1] + nWidthBUV - 1); *(pDst[2] + h * nDstPitches[2] + w) = *(pDst[2] + h * nDstPitches[2] + nWidthBUV - 1); } if (nHeightUV > nHeightBUV) { vs_bitblt(pDst[1] + nHeightBUV * nDstPitches[1], nDstPitches[1], pDst[1] + (nHeightBUV - 1) * nDstPitches[1], nDstPitches[1], nWidthUV, nHeightUV - nHeightBUV); vs_bitblt(pDst[2] + nHeightBUV * nDstPitches[2], nDstPitches[2], pDst[2] + (nHeightBUV - 1) * nDstPitches[2], nDstPitches[2], nWidthUV, nHeightUV - nHeightBUV); } free(smallMask); free(smallMaskV); } else { // not usable if (kind == 5) memcpy(pDst[0], pSrc[0], nSrcPitches[0] * nHeight); else memset(pDst[0], nSceneChangeValue, nHeight * nDstPitches[0]); memset(pDst[1], nSceneChangeValue, nHeightUV * nDstPitches[1]); memset(pDst[2], nSceneChangeValue, nHeightUV * nDstPitches[2]); } fgopDeinit(&fgop); vsapi->freeFrame(src); return dst; } return 0; }