bool nstringToInt(const nstring &ns, int &result) { size_t pos = 0; std::string s = nstringToUtf8(ns); try { result = std::stoi(s, &pos); } catch (std::invalid_argument &) { return false; } catch (std::out_of_range &) { return false; } return pos == s.length(); }
int wmain(int argc, wchar_t **argv) { if (_setmode(_fileno(stdout), _O_BINARY) == -1) fprintf(stderr, "Failed to set stdout to binary mode\n"); SetConsoleCtrlHandler(HandlerRoutine, TRUE); #else int main(int argc, char **argv) { #endif if (argc == 2) { if (nstring(argv[1]) == NSTRING("-version")) { if (!vsscript_init()) { fprintf(stderr, "Failed to initialize VapourSynth environment\n"); return 1; } vsapi = vsscript_getVSApi(); if (!vsapi) { fprintf(stderr, "Failed to get VapourSynth API pointer\n"); vsscript_finalize(); return 1; } VSCore *core = vsapi->createCore(0); if (!core) { fprintf(stderr, "Failed to create core\n"); vsscript_finalize(); return 1; } const VSCoreInfo *info = vsapi->getCoreInfo(core); printf("%s", info->versionString); vsapi->freeCore(core); return 0; } } if (argc < 3) { fprintf(stderr, "VSPipe usage:\n"); fprintf(stderr, "Show version info: vspipe -version\n"); fprintf(stderr, "Show script info: vspipe script.vpy - -info\n"); fprintf(stderr, "Write to stdout: vspipe script.vpy - [options]\n"); fprintf(stderr, "Write to file: vspipe script.vpy <outFile> [options]\n"); fprintf(stderr, "Available options:\n"); fprintf(stderr, "Select output index: -index N\n"); fprintf(stderr, "Set number of concurrent frame requests: -requests N\n"); fprintf(stderr, "Add YUV4MPEG headers: -y4m\n"); fprintf(stderr, "Print progress to stderr: -progress\n"); fprintf(stderr, "Show video info: -info (overrides other options)\n"); return 1; } nstring outputFilename = argv[2]; if (outputFilename == NSTRING("-")) { outFile = stdout; } else { #ifdef VS_TARGET_OS_WINDOWS outFile = _wfopen(outputFilename.c_str(), L"wb"); #else outFile = fopen(outputFilename.c_str(), "wb"); #endif if (!outFile) { fprintf(stderr, "Failed to open output for writing\n"); return 1; } } for (int arg = 3; arg < argc; arg++) { nstring argString = argv[arg]; if (argString == NSTRING("-y4m")) { y4m = true; } else if (argString == NSTRING("-info")) { showInfo = true; } else if (argString == NSTRING("-index")) { bool ok = false; if (argc <= arg + 1) { fprintf(stderr, "No index number specified\n"); return 1; } if (!nstringToInt(argv[arg + 1], outputIndex)) { fprintf(stderr, "Couldn't convert %s to an integer\n", nstringToUtf8(argv[arg + 1]).c_str()); return 1; } arg++; } else if (argString == NSTRING("-requests")) { bool ok = false; if (argc <= arg + 1) { fprintf(stderr, "No request number specified\n"); return 1; } if (!nstringToInt(argv[arg + 1], requests)) { fprintf(stderr, "Couldn't convert %s to an integer\n", nstringToUtf8(argv[arg + 1]).c_str()); return 1; } arg++; } else if (argString == NSTRING("-progress")) { printFrameNumber = true; } else { fprintf(stderr, "Unknown argument: %s\n", nstringToUtf8(argString).c_str()); return 1; } } if (!vsscript_init()) { fprintf(stderr, "Failed to initialize VapourSynth environment\n"); return 1; } vsapi = vsscript_getVSApi(); if (!vsapi) { fprintf(stderr, "Failed to get VapourSynth API pointer\n"); vsscript_finalize(); return 1; } std::chrono::time_point<std::chrono::high_resolution_clock> start(std::chrono::high_resolution_clock::now()); if (vsscript_evaluateFile(&se, nstringToUtf8(argv[1]).c_str(), efSetWorkingDir)) { fprintf(stderr, "Script evaluation failed:\n%s\n", vsscript_getError(se)); vsscript_freeScript(se); vsscript_finalize(); return 1; } node = vsscript_getOutput(se, outputIndex); if (!node) { fprintf(stderr, "Failed to retrieve output node. Invalid index specified?\n"); vsscript_freeScript(se); vsscript_finalize(); return 1; } bool error = false; const VSVideoInfo *vi = vsapi->getVideoInfo(node); if (showInfo) { fprintf(outFile, "Width: %d\n", vi->width); fprintf(outFile, "Height: %d\n", vi->height); fprintf(outFile, "Frames: %d\n", vi->numFrames); fprintf(outFile, "FPS: %" PRId64 "/%" PRId64 "\n", vi->fpsNum, vi->fpsDen); if (vi->format) { fprintf(outFile, "Format Name: %s\n", vi->format->name); fprintf(outFile, "Color Family: %s\n", colorFamilyToString(vi->format->colorFamily)); fprintf(outFile, "Bits: %d\n", vi->format->bitsPerSample); fprintf(outFile, "SubSampling W: %d\n", vi->format->subSamplingW); fprintf(outFile, "SubSampling H: %d\n", vi->format->subSamplingH); } else { fprintf(outFile, "Format Name: Variable\n"); } } else { if (!isConstantFormat(vi) || vi->numFrames == 0) { fprintf(stderr, "Cannot output clips with varying dimensions or unknown length\n"); vsapi->freeNode(node); vsscript_freeScript(se); vsscript_finalize(); return 1; } lastFpsReportTime = std::chrono::high_resolution_clock::now(); error = outputNode(); } fflush(outFile); std::chrono::time_point<std::chrono::high_resolution_clock> end(std::chrono::high_resolution_clock::now()); std::chrono::duration<double> elapsedSeconds = end - start; fprintf(stderr, "Output %d frames in %.2f seconds (%.2f fps)\n", outputFrames, elapsedSeconds.count(), outputFrames / elapsedSeconds.count()); vsapi->freeNode(node); vsscript_freeScript(se); vsscript_finalize(); return error; }
static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt ) { vs_hnd_t *h = new vs_hnd_t; if( !h ) return -1; FILE *fh = x264_fopen(psz_filename, "rb"); if (!fh) return -1; int b_regular = x264_is_regular_file(fh); fclose(fh); FAIL_IF_ERROR(!b_regular, "VS input is incompatible with non-regular file `%s'\n", psz_filename); FAIL_IF_ERROR(!vsscript_init(), "Failed to initialize VapourSynth environment\n"); h->vsapi = vsscript_getVSApi(); if (!h->vsapi) { fprintf(stderr, "Failed to get VapourSynth API pointer\n"); vsscript_finalize(); return -1; } // Should always succeed if (vsscript_createScript(&h->se)) { fprintf(stderr, "Script environment initialization failed:\n%s\n", vsscript_getError(h->se)); vsscript_freeScript(h->se); vsscript_finalize(); return -1; } std::string strfilename = psz_filename; nstring scriptFilename = s2ws(strfilename); if (vsscript_evaluateFile(&h->se, nstringToUtf8(scriptFilename).c_str(), efSetWorkingDir)) { fprintf(stderr, "Script evaluation failed:\n%s\n", vsscript_getError(h->se)); vsscript_freeScript(h->se); vsscript_finalize(); return -1; } h->node = vsscript_getOutput(h->se, 0);//outputIndex if (!h->node) { fprintf(stderr, "Failed to retrieve output node. Invalid index specified?\n"); vsscript_freeScript(h->se); vsscript_finalize(); return -1; } const VSCoreInfo *vsInfo = h->vsapi->getCoreInfo(vsscript_getCore(h->se)); h->sea = new semaphore(vsInfo->numThreads); const VSVideoInfo *vi = h->vsapi->getVideoInfo(h->node); if (vi->format->colorFamily != cmYUV) { fprintf(stderr, "Can only read YUV format clips"); h->vsapi->freeNode(h->node); vsscript_freeScript(h->se); vsscript_finalize(); return -1; } if (!isConstantFormat(vi)) { fprintf(stderr, "Cannot output clips with varying dimensions\n"); h->vsapi->freeNode(h->node); vsscript_freeScript(h->se); vsscript_finalize(); return -1; } info->width = vi->width; info->height = vi->height; info->fps_num = vi->fpsNum; info->fps_den = vi->fpsDen; info->thread_safe = 1; info->num_frames = vi->numFrames; if (vi->format->subSamplingW == 1 && vi->format->subSamplingH == 1) info->csp = X264_CSP_I420; else if (vi->format->subSamplingW == 1 && vi->format->subSamplingH == 0) info->csp = X264_CSP_I422; else if (vi->format->subSamplingW == 0 && vi->format->subSamplingH == 0) info->csp = X264_CSP_I444; h->bit_depth = vi->format->bitsPerSample; if (h->bit_depth > 8) { info->csp |= X264_CSP_HIGH_DEPTH; } *p_handle = (void*)h; return 0; }
int wmain(int argc, wchar_t **argv) { if (_setmode(_fileno(stdout), _O_BINARY) == -1) fprintf(stderr, "Failed to set stdout to binary mode\n"); SetConsoleCtrlHandler(HandlerRoutine, TRUE); #else int main(int argc, char **argv) { #endif nstring outputFilename, scriptFilename; bool showHelp = false; std::map<std::string, std::string> scriptArgs; int startFrame = 0; for (int arg = 1; arg < argc; arg++) { nstring argString = argv[arg]; if (argString == NSTRING("-v") || argString == NSTRING("--version")) { showVersion = true; } else if (argString == NSTRING("-y") || argString == NSTRING("--y4m")) { y4m = true; } else if (argString == NSTRING("-p") || argString == NSTRING("--progress")) { printFrameNumber = true; } else if (argString == NSTRING("-i") || argString == NSTRING("--info")) { showInfo = true; } else if (argString == NSTRING("-h") || argString == NSTRING("--help")) { showHelp = true; } else if (argString == NSTRING("-s") || argString == NSTRING("--start")) { if (argc <= arg + 1) { fprintf(stderr, "No start frame specified\n"); return 1; } if (!nstringToInt(argv[arg + 1], startFrame)) { fprintf(stderr, "Couldn't convert %s to an integer (start)\n", nstringToUtf8(argv[arg + 1]).c_str()); return 1; } if (startFrame < 0) { fprintf(stderr, "Negative start frame specified\n"); return 1; } completedFrames = startFrame; outputFrames = startFrame; requestedFrames = startFrame; lastFpsReportFrame = startFrame; arg++; } else if (argString == NSTRING("-e") || argString == NSTRING("--end")) { if (argc <= arg + 1) { fprintf(stderr, "No end frame specified\n"); return 1; } if (!nstringToInt(argv[arg + 1], totalFrames)) { fprintf(stderr, "Couldn't convert %s to an integer (end)\n", nstringToUtf8(argv[arg + 1]).c_str()); return 1; } if (totalFrames < 0) { fprintf(stderr, "Negative end frame specified\n"); return 1; } totalFrames++; arg++; } else if (argString == NSTRING("-o") || argString == NSTRING("--outputindex")) { if (argc <= arg + 1) { fprintf(stderr, "No output index specified\n"); return 1; } if (!nstringToInt(argv[arg + 1], outputIndex)) { fprintf(stderr, "Couldn't convert %s to an integer (index)\n", nstringToUtf8(argv[arg + 1]).c_str()); return 1; } arg++; } else if (argString == NSTRING("-r") || argString == NSTRING("--requests")) { if (argc <= arg + 1) { fprintf(stderr, "Number of requests not specified\n"); return 1; } if (!nstringToInt(argv[arg + 1], requests)) { fprintf(stderr, "Couldn't convert %s to an integer (requests)\n", nstringToUtf8(argv[arg + 1]).c_str()); return 1; } arg++; } else if (argString == NSTRING("-a") || argString == NSTRING("--arg")) { if (argc <= arg + 1) { fprintf(stderr, "No argument specified\n"); return 1; } std::string aLine = nstringToUtf8(argv[arg + 1]).c_str(); size_t equalsPos = aLine.find("="); if (equalsPos == std::string::npos) { fprintf(stderr, "No value specified for argument: %s\n", aLine.c_str()); return 1; } scriptArgs[aLine.substr(0, equalsPos)] = aLine.substr(equalsPos + 1); arg++; } else if (scriptFilename.empty() && !argString.empty() && argString.substr(0, 1) != NSTRING("-")) { scriptFilename = argString; } else if (outputFilename.empty() && !argString.empty() && (argString == NSTRING("-") || (argString.substr(0, 1) != NSTRING("-")))) { outputFilename = argString; } else { fprintf(stderr, "Unknown argument: %s\n", nstringToUtf8(argString).c_str()); return 1; } } if (showVersion && argc > 2) { fprintf(stderr, "Cannot combine version information with other options\n"); return 1; } else if (showVersion) { return printVersion() ? 0 : 1; } else if (showHelp || argc <= 1) { printHelp(); return 1; } else if (scriptFilename.empty()) { fprintf(stderr, "No script file specified\n"); return 1; } else if (outputFilename.empty()) { fprintf(stderr, "No output file specified\n"); return 1; } if (outputFilename == NSTRING("-")) { outFile = stdout; } else { #ifdef VS_TARGET_OS_WINDOWS outFile = _wfopen(outputFilename.c_str(), L"wb"); #else outFile = fopen(outputFilename.c_str(), "wb"); #endif if (!outFile) { fprintf(stderr, "Failed to open output for writing\n"); return 1; } } if (!vsscript_init()) { fprintf(stderr, "Failed to initialize VapourSynth environment\n"); return 1; } vsapi = vsscript_getVSApi(); if (!vsapi) { fprintf(stderr, "Failed to get VapourSynth API pointer\n"); vsscript_finalize(); return 1; } // Should always succeed if (vsscript_createScript(&se)) { fprintf(stderr, "Script environment initialization failed:\n%s\n", vsscript_getError(se)); vsscript_freeScript(se); vsscript_finalize(); return 1; } { VSMap *foldedArgs = vsapi->createMap(); for (const auto &iter : scriptArgs) vsapi->propSetData(foldedArgs, iter.first.c_str(), iter.second.c_str(), static_cast<int>(iter.second.size()), paAppend); vsscript_setVariable(se, foldedArgs); vsapi->freeMap(foldedArgs); } start = std::chrono::high_resolution_clock::now(); if (vsscript_evaluateFile(&se, nstringToUtf8(scriptFilename).c_str(), efSetWorkingDir)) { fprintf(stderr, "Script evaluation failed:\n%s\n", vsscript_getError(se)); vsscript_freeScript(se); vsscript_finalize(); return 1; } node = vsscript_getOutput(se, outputIndex); if (!node) { fprintf(stderr, "Failed to retrieve output node. Invalid index specified?\n"); vsscript_freeScript(se); vsscript_finalize(); return 1; } bool error = false; const VSVideoInfo *vi = vsapi->getVideoInfo(node); if (showInfo) { if (vi->width && vi->height) { fprintf(outFile, "Width: %d\n", vi->width); fprintf(outFile, "Height: %d\n", vi->height); } else { fprintf(outFile, "Width: Variable\n"); fprintf(outFile, "Height: Variable\n"); } if (vi->numFrames) fprintf(outFile, "Frames: %d\n", vi->numFrames); else fprintf(outFile, "Frames: Unknown\n"); if (vi->fpsNum && vi->fpsDen) fprintf(outFile, "FPS: %" PRId64 "/%" PRId64 " (%.3f fps)\n", vi->fpsNum, vi->fpsDen, vi->fpsNum/(double)vi->fpsDen); else fprintf(outFile, "FPS: Variable\n"); if (vi->format) { fprintf(outFile, "Format Name: %s\n", vi->format->name); fprintf(outFile, "Color Family: %s\n", colorFamilyToString(vi->format->colorFamily)); fprintf(outFile, "Bits: %d\n", vi->format->bitsPerSample); fprintf(outFile, "SubSampling W: %d\n", vi->format->subSamplingW); fprintf(outFile, "SubSampling H: %d\n", vi->format->subSamplingH); } else { fprintf(outFile, "Format Name: Variable\n"); } } else { const VSVideoInfo *vi = vsapi->getVideoInfo(node); if (totalFrames == -1) totalFrames = vi->numFrames; if ((vi->numFrames && vi->numFrames < totalFrames) || completedFrames >= totalFrames) { fprintf(stderr, "Invalid range of frames to output specified:\nfirst: %d\nlast: %d\nclip length: %d\nframes to output: %d\n", completedFrames, totalFrames, vi->numFrames, totalFrames - completedFrames); vsapi->freeNode(node); vsscript_freeScript(se); vsscript_finalize(); return 1; } if (!isConstantFormat(vi) || !totalFrames) { fprintf(stderr, "Cannot output clips with varying dimensions or unknown length\n"); vsapi->freeNode(node); vsscript_freeScript(se); vsscript_finalize(); return 1; } lastFpsReportTime = std::chrono::high_resolution_clock::now();; error = outputNode(); } fflush(outFile); if (!showInfo) { int totalFrames = outputFrames - startFrame; std::chrono::duration<double> elapsedSeconds = std::chrono::high_resolution_clock::now() - start; fprintf(stderr, "Output %d frames in %.2f seconds (%.2f fps)\n", totalFrames, elapsedSeconds.count(), totalFrames / elapsedSeconds.count()); } vsapi->freeNode(node); vsscript_freeScript(se); vsscript_finalize(); return error ? 1 : 0; }