void VSVideoSource::OutputFrame(const FFMS_Frame *Frame, VSFrameRef *Dst, const VSAPI *vsapi) { const int RGBPlaneOrder[3] = {2, 0, 1}; const VSFormat *fi = vsapi->getFrameFormat(Dst); if (fi->colorFamily == cmRGB) { for (int i = 0; i < fi->numPlanes; i++) vs_bitblt(vsapi->getWritePtr(Dst, i), vsapi->getStride(Dst, i), Frame->Data[RGBPlaneOrder[i]], Frame->Linesize[RGBPlaneOrder[i]], vsapi->getFrameWidth(Dst, i) * fi->bytesPerSample, vsapi->getFrameHeight(Dst, i)); } else { for (int i = 0; i < fi->numPlanes; i++) vs_bitblt(vsapi->getWritePtr(Dst, i), vsapi->getStride(Dst, i), Frame->Data[i], Frame->Linesize[i], vsapi->getFrameWidth(Dst, i) * fi->bytesPerSample, vsapi->getFrameHeight(Dst, i)); } }
void processCL_sse2(const VSFrameRef * src, const VSFrameRef * scp, VSFrameRef * dst, VSFrameRef ** pad, const int field_n, const EEDI3CLData * d, const VSAPI * vsapi) { for (int plane = 0; plane < d->vi.format->numPlanes; plane++) { if (d->process[plane]) { copyPad<T>(src, pad[plane], plane, 1 - field_n, d->dh, vsapi); const int srcWidth = vsapi->getFrameWidth(pad[plane], 0); const int dstWidth = vsapi->getFrameWidth(dst, plane); const int srcHeight = vsapi->getFrameHeight(pad[plane], 0); const int dstHeight = vsapi->getFrameHeight(dst, plane); const int srcStride = vsapi->getStride(pad[plane], 0) / sizeof(T); const int dstStride = vsapi->getStride(dst, plane) / sizeof(T); const T * _srcp = reinterpret_cast<const T *>(vsapi->getReadPtr(pad[plane], 0)); T * VS_RESTRICT _dstp = reinterpret_cast<T *>(vsapi->getWritePtr(dst, plane)); const auto threadId = std::this_thread::get_id(); auto queue = d->queue.at(threadId); auto calculateConnectionCosts = d->calculateConnectionCosts.at(threadId); auto srcImage = d->src.at(threadId); auto _ccosts = d->ccosts.at(threadId); float * pcosts = d->pcosts.at(threadId) + d->mdisVector; int * _pbackt = d->pbackt.at(threadId) + d->mdisVector; int * fpath = d->fpath.at(threadId); int * _dmap = d->dmap.at(threadId); float * tline = d->tline.at(threadId); const size_t globalWorkSize[] = { static_cast<size_t>((dstWidth + 15) & -16), static_cast<size_t>(d->vectorSize) }; constexpr size_t localWorkSize[] = { 16, 4 }; const int bufferSize = dstWidth * d->tpitchVector * sizeof(cl_float); vs_bitblt(_dstp + dstStride * (1 - field_n), vsapi->getStride(dst, plane) * 2, _srcp + srcStride * (4 + 1 - field_n) + 12, vsapi->getStride(pad[plane], 0) * 2, dstWidth * sizeof(T), dstHeight / 2); queue.enqueue_write_image(srcImage, compute::dim(0, 0), compute::dim(srcWidth, srcHeight), _srcp, vsapi->getStride(pad[plane], 0)); for (int y = 4 + field_n; y < srcHeight - 4; y += 2 * d->vectorSize) { const int off = (y - 4 - field_n) >> 1; calculateConnectionCosts.set_args(srcImage, _ccosts, dstWidth, srcHeight - 4, y); queue.enqueue_nd_range_kernel(calculateConnectionCosts, 2, nullptr, globalWorkSize, localWorkSize); float * ccosts = reinterpret_cast<float *>(queue.enqueue_map_buffer(_ccosts, CL_MAP_READ, 0, bufferSize)) + d->mdisVector; // calculate path costs Vec4f().load(ccosts).store_a(pcosts); for (int x = 1; x < dstWidth; x++) { const float * tT = ccosts + d->tpitchVector * x; const float * ppT = pcosts + d->tpitchVector * (x - 1); float * pT = pcosts + d->tpitchVector * x; int * piT = _pbackt + d->tpitchVector * (x - 1); const int umax = std::min({ x, dstWidth - 1 - x, d->mdis }); const int umax2 = std::min({ x - 1, dstWidth - x, d->mdis }); for (int u = -umax; u <= umax; u++) { Vec4i idx = zero_128b(); Vec4f bval = FLT_MAX; for (int v = std::max(-umax2, u - 1); v <= std::min(umax2, u + 1); v++) { const Vec4f z = Vec4f().load_a(ppT + v * d->vectorSize) + d->gamma * std::abs(u - v); const Vec4f ccost = min(z, FLT_MAX * 0.9f); idx = select(Vec4ib(ccost < bval), v, idx); bval = min(ccost, bval); } const Vec4f z = bval + Vec4f().load(tT + u * d->vectorSize); min(z, FLT_MAX * 0.9f).store_a(pT + u * d->vectorSize); idx.stream(piT + u * d->vectorSize); } } for (int vs = 0; vs < d->vectorSize; vs++) { const int realY = 4 + field_n + 2 * (off + vs); if (realY >= srcHeight - 4) break; const T * srcp = _srcp + srcStride * realY + 12; T * dstp = _dstp + dstStride * (field_n + 2 * (off + vs)); int * dmap = _dmap + dstWidth * (off + vs); const T * src3p = srcp - srcStride * 3; const T * src1p = srcp - srcStride; const T * src1n = srcp + srcStride; const T * src3n = srcp + srcStride * 3; const int * pbackt = _pbackt + vs; // backtrack fpath[dstWidth - 1] = 0; for (int x = dstWidth - 2; x >= 0; x--) fpath[x] = pbackt[(d->tpitch * x + fpath[x + 1]) * d->vectorSize]; interpolate<T>(src3p, src1p, src1n, src3n, fpath, dmap, dstp, dstWidth, d->ucubic, d->peak); } queue.enqueue_unmap_buffer(_ccosts, ccosts - d->mdisVector); } if (d->vcheck) { const T * srcp = _srcp + srcStride * (4 + field_n) + 12; const T * scpp = nullptr; if (d->sclip) scpp = reinterpret_cast<const T *>(vsapi->getReadPtr(scp, plane)) + dstStride * field_n; T * dstp = _dstp + dstStride * field_n;; vCheck<T>(srcp, scpp, dstp, _dmap, tline, field_n, dstWidth, srcHeight, srcStride, dstStride, d->vcheck, d->vthresh2, d->rcpVthresh0, d->rcpVthresh1, d->rcpVthresh2, d->peak); } } }
void VSVideoSource::OutputAlphaFrame(const FFMS_Frame *Frame, int Plane, VSFrameRef *Dst, const VSAPI *vsapi) { const VSFormat *fi = vsapi->getFrameFormat(Dst); vs_bitblt(vsapi->getWritePtr(Dst, 0), vsapi->getStride(Dst, 0), Frame->Data[Plane], Frame->Linesize[Plane], vsapi->getFrameWidth(Dst, 0) * fi->bytesPerSample, vsapi->getFrameHeight(Dst, 0)); }
const VSFrameRef *VS_CC d2vGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { d2vData *d = (d2vData *) *instanceData; const VSFrameRef *s; VSFrameRef *f; VSMap *props; string msg; int ret; int plane; /* Unreference the previously decoded frame. */ av_frame_unref(d->frame); ret = decodeframe(n, d->d2v, d->dec, d->frame, msg); if (ret < 0) { vsapi->setFilterError(msg.c_str(), frameCtx); return NULL; } /* Grab our direct-rendered frame. */ s = (const VSFrameRef *) d->frame->opaque; if (!s) { vsapi->setFilterError("Seek pattern broke d2vsource! Please send a sample.", frameCtx); return NULL; } /* If our width and height are the same, just return it. */ if (d->vi.width == d->aligned_width && d->vi.height == d->aligned_height) { f = vsapi->copyFrame(s, core); } else { f = vsapi->newVideoFrame(d->vi.format, d->vi.width, d->vi.height, NULL, core); /* Copy into VS's buffers. */ for (plane = 0; plane < d->vi.format->numPlanes; plane++) { uint8_t *dstp = vsapi->getWritePtr(f, plane); const uint8_t *srcp = vsapi->getReadPtr(s, plane); int dst_stride = vsapi->getStride(f, plane); int src_stride = vsapi->getStride(s, plane); int width = vsapi->getFrameWidth(f, plane); int height = vsapi->getFrameHeight(f, plane); vs_bitblt(dstp, dst_stride, srcp, src_stride, width * d->vi.format->bytesPerSample, height); } } props = vsapi->getFramePropsRW(f); /* * The DGIndex manual simply says: * "The matrix field displays the currently applicable matrix_coefficients value (colorimetry)." * * I can only assume this lines up with the tables VS uses correctly. */ vsapi->propSetInt(props, "_Matrix", d->d2v->gops[d->d2v->frames[n].gop].matrix, paReplace); vsapi->propSetInt(props, "_DurationNum", d->d2v->fps_den, paReplace); vsapi->propSetInt(props, "_DurationDen", d->d2v->fps_num, paReplace); vsapi->propSetFloat(props, "_AbsoluteTime", (static_cast<double>(d->d2v->fps_den) * n) / static_cast<double>(d->d2v->fps_num), paReplace); /* * YUVRGB_Scale describes the output range. * _ColorRange describes the input range. */ if (d->d2v->yuvrgb_scale == PC) vsapi->propSetInt(props, "_ColorRange", 1, paReplace); else if (d->d2v->yuvrgb_scale == TV) vsapi->propSetInt(props, "_ColorRange", 0, paReplace); switch (d->frame->pict_type) { case AV_PICTURE_TYPE_I: vsapi->propSetData(props, "_PictType", "I", 1, paReplace); break; case AV_PICTURE_TYPE_P: vsapi->propSetData(props, "_PictType", "P", 1, paReplace); break; case AV_PICTURE_TYPE_B: vsapi->propSetData(props, "_PictType", "B", 1, paReplace); break; default: break; } int fieldbased; if (d->d2v->gops[d->d2v->frames[n].gop].flags[d->d2v->frames[n].offset] & FRAME_FLAG_PROGRESSIVE) fieldbased = 0; else fieldbased = 1 + !!(d->d2v->gops[d->d2v->frames[n].gop].flags[d->d2v->frames[n].offset] & FRAME_FLAG_TFF); vsapi->propSetInt(props, "_FieldBased", fieldbased, paReplace); vsapi->propSetInt(props, "_ChromaLocation", d->d2v->mpeg_type == 1 ? 1 : 0, paReplace); return f; }
const VSFrameRef *VS_CC rffGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { const rffData *d = (const rffData *) *instanceData; const VSFrameRef *st, *sb; VSFrameRef *f; VSMap *props; int top, bottom; int fieldbased; int i; bool samefields; /* What frames to use for fields. */ const rffField *top_field = &d->fields[n * 2]; const rffField *bottom_field = &d->fields[n * 2 + 1]; if (top_field->type == Bottom) std::swap(top_field, bottom_field); top = top_field->frame; bottom = bottom_field->frame; samefields = top == bottom; /* Request out source frames. */ if (activationReason == arInitial) { if (samefields) { vsapi->requestFrameFilter(top, d->node, frameCtx); } else { vsapi->requestFrameFilter(min(top, bottom), d->node, frameCtx); vsapi->requestFrameFilter(max(top, bottom), d->node, frameCtx); } return NULL; } /* Check if we're ready yet. */ if (activationReason != arAllFramesReady) return NULL; /* Source and destination frames. */ st = vsapi->getFrameFilter(top, d->node, frameCtx); sb = samefields ? NULL : vsapi->getFrameFilter(bottom, d->node, frameCtx); /* Copy into VS's buffers. */ if (samefields) { f = vsapi->copyFrame(st, core); } else { int dst_stride[3], srct_stride[3], srcb_stride[3]; /* * Copy properties from the first field's source frame. * Some of them will be wrong for this frame, but ¯\_(ツ)_/¯. */ const VSFrameRef *prop_src = bottom_field < top_field ? sb : st; f = vsapi->newVideoFrame(d->vi.format, d->vi.width, d->vi.height, prop_src, core); for (i = 0; i < d->vi.format->numPlanes; i++) { dst_stride[i] = vsapi->getStride(f, i); srct_stride[i] = vsapi->getStride(st, i); srcb_stride[i] = vsapi->getStride(sb, i); uint8_t *dstp = vsapi->getWritePtr(f, i); const uint8_t *srctp = vsapi->getReadPtr(st, i); const uint8_t *srcbp = vsapi->getReadPtr(sb, i); int width = vsapi->getFrameWidth(f, i); int height = vsapi->getFrameHeight(f, i); vs_bitblt(dstp, dst_stride[i] * 2, srctp, srct_stride[i] * 2, width * d->vi.format->bytesPerSample, height / 2); vs_bitblt(dstp + dst_stride[i], dst_stride[i] * 2, srcbp + srcb_stride[i], srcb_stride[i] * 2, width * d->vi.format->bytesPerSample, height / 2); } } if (!samefields) { /* Set field order. */ props = vsapi->getFramePropsRW(f); // They point to elements of an array, so pointer comparison is fine. if (bottom_field < top_field) fieldbased = 1; // bff else fieldbased = 2; // tff vsapi->propSetInt(props, "_FieldBased", fieldbased, paReplace); } vsapi->freeFrame(st); if (!samefields) vsapi->freeFrame(sb); return f; }
void mvpFillPlane(MVPlane *mvp, const uint8_t *pNewPlane, int nNewPitch) { if (!mvp->isFilled) vs_bitblt(mvp->pPlane[0] + mvp->nOffsetPadding, mvp->nPitch, pNewPlane, nNewPitch, mvp->nWidth * mvp->bytesPerSample, mvp->nHeight); mvp->isFilled = 1; }
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; }
const VSFrameRef *VS_CC rffGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { const rffData *d = (const rffData *) *instanceData; const VSFrameRef *st, *sb; VSFrameRef *f; VSMap *props; string msg; int top, bottom; int fieldbased; int i; bool samefields; /* What frames to use for fields. */ top = d->frames[n].top; bottom = d->frames[n].bottom; samefields = top == bottom; /* Request out source frames. */ if (activationReason == arInitial) { if (samefields) { vsapi->requestFrameFilter(top, d->node, frameCtx); } else { vsapi->requestFrameFilter(min(top, bottom), d->node, frameCtx); vsapi->requestFrameFilter(max(top, bottom), d->node, frameCtx); } return NULL; } /* Check if we're ready yet. */ if (activationReason != arAllFramesReady) return NULL; /* Source and destination frames. */ st = vsapi->getFrameFilter(top, d->node, frameCtx); sb = samefields ? NULL : vsapi->getFrameFilter(bottom, d->node, frameCtx); /* Copy into VS's buffers. */ if (samefields) { f = vsapi->copyFrame(st, core); } else { int dst_stride[3], srct_stride[3], srcb_stride[3]; f = vsapi->newVideoFrame(d->vi.format, d->vi.width, d->vi.height, NULL, core); for (i = 0; i < d->vi.format->numPlanes; i++) { dst_stride[i] = vsapi->getStride(f, i); srct_stride[i] = vsapi->getStride(st, i); srcb_stride[i] = vsapi->getStride(sb, i); uint8_t *dstp = vsapi->getWritePtr(f, i); const uint8_t *srctp = vsapi->getReadPtr(st, i); const uint8_t *srcbp = vsapi->getReadPtr(sb, i); int width = vsapi->getFrameWidth(f, i); int height = vsapi->getFrameHeight(f, i); vs_bitblt(dstp, dst_stride[i] * 2, srctp, srct_stride[i] * 2, width * d->vi.format->bytesPerSample, height / 2); vs_bitblt(dstp + dst_stride[i], dst_stride[i] * 2, srcbp + srcb_stride[i], srcb_stride[i] * 2, width * d->vi.format->bytesPerSample, height / 2); } } /* Set field order. */ props = vsapi->getFramePropsRW(f); fieldbased = 1; if (samefields) { frame top_f = d->d2v->frames[top]; fieldbased += !!(d->d2v->gops[top_f.gop].flags[top_f.offset] & FRAME_FLAG_TFF); } else { fieldbased += (top < bottom); } vsapi->propSetInt(props, "_FieldBased", fieldbased, paReplace); vsapi->freeFrame(st); if (!samefields) vsapi->freeFrame(sb); return f; }