void VS_CC rffCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi) { rffData *data; string msg; int i; /* Allocate our private data. */ data = new(nothrow) rffData; if (!data) { vsapi->setError(out, "Cannot allocate private data."); return; } /* Parse the D2V to get flags. */ data->d2v = d2vparse((char *) vsapi->propGetData(in, "d2v", 0, 0), msg); if (!data->d2v) { vsapi->setError(out, msg.c_str()); delete data; return; } /* Get our frame info and copy it, so we can modify it after. */ data->node = vsapi->propGetNode(in, "clip", 0, 0); data->vi = *vsapi->getVideoInfo(data->node); /* * Parse all the RFF flags to figure out which fields go * with which frames, and out total number of frames after * apply the RFF flags. */ for(i = 0; i < data->vi.numFrames; i++) { frame f = data->d2v->frames[i]; bool rff = !!(data->d2v->gops[f.gop].flags[f.offset] & FRAME_FLAG_RFF); bool tff = !!(data->d2v->gops[f.gop].flags[f.offset] & FRAME_FLAG_TFF); int progressive_sequence = !!(data->d2v->gops[f.gop].info & GOP_FLAG_PROGRESSIVE_SEQUENCE); if (progressive_sequence) { /* * We repeat whole frames instead of fields, to turn one * coded progressive frame into either two or three * identical progressive frames. */ rffField field; field.frame = i; field.type = Progressive; data->fields.push_back(field); data->fields.push_back(field); if (rff) { data->fields.push_back(field); data->fields.push_back(field); if (tff) { data->fields.push_back(field); data->fields.push_back(field); } } } else { /* Sequence is not progressive. Repeat fields. */ rffField first_field, second_field; first_field.frame = second_field.frame = i; first_field.type = tff ? Top : Bottom; second_field.type = tff ? Bottom : Top; data->fields.push_back(first_field); data->fields.push_back(second_field); if (rff) data->fields.push_back(first_field); } } data->vi.numFrames = (int)data->fields.size() / 2; vsapi->createFilter(in, out, "applyrff", rffInit, rffGetFrame, rffFree, fmParallel, 0, data, core); }
void VS_CC d2vCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi) { d2vData *data; string msg; bool no_crop; bool rff; int threads; int err; /* Need to get thread info before anything to pass to decodeinit(). */ threads = vsapi->propGetInt(in, "threads", 0, &err); if (err) threads = 0; if (threads < 0) { vsapi->setError(out, "Invalid number of threads."); return; } /* Allocate our private data. */ data = (d2vData *) malloc(sizeof(*data)); if (!data) { vsapi->setError(out, "Cannot allocate private data."); return; } data->d2v = d2vparse((char *) vsapi->propGetData(in, "input", 0, 0), msg); if (!data->d2v) { vsapi->setError(out, msg.c_str()); free(data); return; } data->dec = decodeinit(data->d2v, threads, msg); if (!data->dec) { vsapi->setError(out, msg.c_str()); d2vfreep(&data->d2v); free(data); return; } /* * Make our private data available to libavcodec, and * set our custom get/release_buffer funcs. */ data->dec->avctx->opaque = (void *) data; data->dec->avctx->get_buffer2 = VSGetBuffer; data->vi.numFrames = data->d2v->frames.size(); data->vi.width = data->d2v->width; data->vi.height = data->d2v->height; data->vi.fpsNum = data->d2v->fps_num; data->vi.fpsDen = data->d2v->fps_den; /* Stash the pointer to our core. */ data->core = core; data->api = (VSAPI *) vsapi; /* * Stash our aligned width and height for use with our * custom get_buffer, since it could require this. */ data->aligned_width = FFALIGN(data->vi.width, 16); data->aligned_height = FFALIGN(data->vi.height, 32); data->frame = av_frame_alloc(); if (!data->frame) { vsapi->setError(out, "Cannot allocate AVFrame."); d2vfreep(&data->d2v); decodefreep(&data->dec); free(data); return; } /* * Decode 1 frame to find out how the chroma is subampled. * The first time our custom get_buffer is called, it will * fill in data->vi.format. */ data->format_set = false; err = decodeframe(0, data->d2v, data->dec, data->frame, msg); if (err < 0) { msg.insert(0, "Failed to decode test frame: "); vsapi->setError(out, msg.c_str()); d2vfreep(&data->d2v); decodefreep(&data->dec); av_frame_unref(data->frame); av_freep(&data->frame); free(data); return; } /* See if nocrop is enabled, and set the width/height accordingly. */ no_crop = !!vsapi->propGetInt(in, "nocrop", 0, &err); if (err) no_crop = false; if (no_crop) { data->vi.width = data->aligned_width; data->vi.height = data->aligned_height; } vsapi->createFilter(in, out, "d2vsource", d2vInit, d2vGetFrame, d2vFree, fmUnordered, nfMakeLinear, data, core); rff = !!vsapi->propGetInt(in, "rff", 0, &err); if (err) rff = true; if (rff) { VSPlugin *d2vPlugin = vsapi->getPluginById("com.sources.d2vsource", core); VSPlugin *corePlugin = vsapi->getPluginById("com.vapoursynth.std", core); VSNodeRef *before = vsapi->propGetNode(out, "clip", 0, NULL); VSNodeRef *middle; VSNodeRef *after; VSMap *args = vsapi->createMap(); VSMap *ret; const char *error; vsapi->propSetNode(args, "clip", before, paReplace); vsapi->freeNode(before); ret = vsapi->invoke(corePlugin, "Cache", args); middle = vsapi->propGetNode(ret, "clip", 0, NULL); vsapi->freeMap(ret); vsapi->propSetNode(args, "clip", middle, paReplace); vsapi->propSetData(args, "d2v", vsapi->propGetData(in, "input", 0, NULL), vsapi->propGetDataSize(in, "input", 0, NULL), paReplace); vsapi->freeNode(middle); ret = vsapi->invoke(d2vPlugin, "ApplyRFF", args); vsapi->freeMap(args); error = vsapi->getError(ret); if (error) { vsapi->setError(out, error); vsapi->freeMap(ret); return; } after = vsapi->propGetNode(ret, "clip", 0, NULL); vsapi->propSetNode(out, "clip", after, paReplace); vsapi->freeNode(after); vsapi->freeMap(ret); } }
void VS_CC rffCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi) { rffData *data; fieldFrame ff = { -1, -1 }; string msg; int i; /* Allocate our private data. */ data = new(nothrow) rffData; if (!data) { vsapi->setError(out, "Cannot allocate private data."); return; } /* Parse the D2V to get flags. */ data->d2v = d2vparse((char *) vsapi->propGetData(in, "d2v", 0, 0), msg); if (!data->d2v) { vsapi->setError(out, msg.c_str()); delete data; return; } /* Get our frame info and copy it, so we can modify it after. */ data->node = vsapi->propGetNode(in, "clip", 0, 0); data->vi = *vsapi->getVideoInfo(data->node); /* * Parse all the RFF flags to figure out which fields go * with which frames, and out total number of frames after * apply the RFF flags. */ data->frames.push_back(ff); for(i = 0; i < data->vi.numFrames; i++) { frame f = data->d2v->frames[i]; bool rff = !!(data->d2v->gops[f.gop].flags[f.offset] & FRAME_FLAG_RFF); bool tff = !!(data->d2v->gops[f.gop].flags[f.offset] & FRAME_FLAG_TFF); int pos = data->frames.size() - 1; int progressive_sequence = !!(data->d2v->gops[f.gop].info & GOP_FLAG_PROGRESSIVE_SEQUENCE); if (progressive_sequence) { /* * We repeat whole frames instead of fields, to turn one * coded progressive frame into either two or three * identical progressive frames. */ ff.top = ff.bottom = i; if (pos == 0) data->frames[0] = ff; else data->frames.push_back(ff); if (rff) { data->frames.push_back(ff); if (tff) data->frames.push_back(ff); } } else { /* Sequence is not progressive. Repeat fields. */ int *pos_first, *pos_second, *ff_first, *ff_second; if (tff) { pos_first = &data->frames[pos].top; pos_second = &data->frames[pos].bottom; ff_first = &ff.top; ff_second = &ff.bottom; } else { pos_first = &data->frames[pos].bottom; pos_second = &data->frames[pos].top; ff_first = &ff.bottom; ff_second = &ff.top; } if (rff) { if (*pos_first == -1) { *pos_first = i; *pos_second = i; *ff_first = i; *ff_second = -1; } else if (*pos_second == -1) { *pos_second = i; *ff_first = i; *ff_second = i; } else { *ff_first = i; *ff_second = i; data->frames.push_back(ff); *ff_second = -1; } } else { if (*pos_first == -1) { *pos_first = i; *pos_second = i; *ff_first = -1; *ff_second = -1; } else if (*pos_second == -1) { *pos_second = i; *ff_first = i; *ff_second = -1; } else { *ff_first = i; *ff_second = i; } } data->frames.push_back(ff); } } data->vi.numFrames = (int)data->frames.size() - 1; vsapi->createFilter(in, out, "applyrff", rffInit, rffGetFrame, rffFree, fmParallel, 0, data, core); }