v0.6 Beta - NVIDIA GTC April 2021 Release
Update to v0.6 Beta
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "nvCVOpenCV.h"
|
||||
#include "nvVideoEffects.h"
|
||||
@@ -41,15 +42,24 @@
|
||||
|
||||
#define BAIL_IF_ERR(err) do { if (0 != (err)) { goto bail; } } while(0)
|
||||
#define BAIL_IF_NULL(x, err, code) do { if ((void*)(x) == NULL) { err = code; goto bail; } } while(0)
|
||||
#define NVCV_ERR_HELP 411
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DEFAULT_CODEC "avc1"
|
||||
#else // !_WIN32
|
||||
#define DEFAULT_CODEC "H264"
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
bool FLAG_debug = false,
|
||||
FLAG_verbose = false,
|
||||
FLAG_show = false,
|
||||
FLAG_progress = false;
|
||||
FLAG_progress = false,
|
||||
FLAG_webcam = false;
|
||||
float FLAG_strength = 0.f;
|
||||
int FLAG_resolution = 0;
|
||||
std::string FLAG_codec = "H264",
|
||||
std::string FLAG_codec = DEFAULT_CODEC,
|
||||
FLAG_camRes = "1280x720",
|
||||
FLAG_inFile,
|
||||
FLAG_outFile,
|
||||
FLAG_outDir,
|
||||
@@ -126,18 +136,26 @@ static void Usage() {
|
||||
"VideoEffectsApp [args ...]\n"
|
||||
" where args is:\n"
|
||||
" --in_file=<path> input file to be processed\n"
|
||||
" --webcam use a webcam as the input\n"
|
||||
" --out_file=<path> output file to be written\n"
|
||||
" --effect=<effect> the effect to apply\n"
|
||||
" --show display the results in a window\n"
|
||||
" --show display the results in a window (for webcam, it is always true)\n"
|
||||
" --strength=<value> strength of an effect, 0 or 1 for super res and artifact reduction,\n"
|
||||
" and [0.0, 1.0] for upscaling\n"
|
||||
" --cam_res=[WWWx]HHH specify camera resolution as height or width x height\n"
|
||||
" supports 720 and 1080 resolutions (default \"720\") \n"
|
||||
" --resolution=<height> the desired height of the output\n"
|
||||
" --model_dir=<path> the path to the directory that contains the models\n"
|
||||
" --codec=<fourcc> the fourcc code for the desired codec (default \"H264\")\n"
|
||||
" --codec=<fourcc> the fourcc code for the desired codec (default " DEFAULT_CODEC ")\n"
|
||||
" --progress show progress\n"
|
||||
" --verbose verbose output\n"
|
||||
" --debug print extra debugging information\n"
|
||||
);
|
||||
const char* cStr;
|
||||
NvCV_Status err = NvVFX_GetString(nullptr, NVVFX_INFO, &cStr);
|
||||
if (NVCV_SUCCESS != err)
|
||||
printf("Cannot get effects: %s\n", NvCV_GetErrorStringFromCode(err));
|
||||
printf("where effects are:\n%s", cStr);
|
||||
}
|
||||
|
||||
static int ParseMyArgs(int argc, char **argv) {
|
||||
@@ -155,6 +173,8 @@ static int ParseMyArgs(int argc, char **argv) {
|
||||
GetFlagArgVal("out_file", arg, &FLAG_outFile) ||
|
||||
GetFlagArgVal("effect", arg, &FLAG_effect) ||
|
||||
GetFlagArgVal("show", arg, &FLAG_show) ||
|
||||
GetFlagArgVal("webcam", arg, &FLAG_webcam) ||
|
||||
GetFlagArgVal("cam_res", arg, &FLAG_camRes) ||
|
||||
GetFlagArgVal("strength", arg, &FLAG_strength) ||
|
||||
GetFlagArgVal("resolution", arg, &FLAG_resolution) ||
|
||||
GetFlagArgVal("model_dir", arg, &FLAG_modelDir) ||
|
||||
@@ -164,7 +184,7 @@ static int ParseMyArgs(int argc, char **argv) {
|
||||
)) {
|
||||
continue;
|
||||
} else if (GetFlagArgVal("help", arg, &help)) {
|
||||
Usage();
|
||||
return NVCV_ERR_HELP;
|
||||
} else if (arg[1] != '-') {
|
||||
for (++arg; *arg; ++arg) {
|
||||
if (*arg == 'v') {
|
||||
@@ -257,7 +277,11 @@ static int StringToFourcc(const std::string& str) {
|
||||
|
||||
struct FXApp {
|
||||
enum Err {
|
||||
errNone = NVCV_SUCCESS, // Video Effects SDK errors
|
||||
errQuit = +1, // Application errors
|
||||
errFlag = +2,
|
||||
errRead = +3,
|
||||
errWrite = +4,
|
||||
errNone = NVCV_SUCCESS, // Video Effects SDK errors
|
||||
errGeneral = NVCV_ERR_GENERAL,
|
||||
errUnimplemented = NVCV_ERR_UNIMPLEMENTED,
|
||||
errMemory = NVCV_ERR_MEMORY,
|
||||
@@ -276,7 +300,8 @@ struct FXApp {
|
||||
errResolution = NVCV_ERR_RESOLUTION,
|
||||
errUnsupportedGPU = NVCV_ERR_UNSUPPORTEDGPU,
|
||||
errWrongGPU = NVCV_ERR_WRONGGPU,
|
||||
errCudaMemory = NVCV_ERR_CUDA_MEMORY, // CUDA errors
|
||||
errUnsupportedDriver = NVCV_ERR_UNSUPPORTEDDRIVER,
|
||||
errCudaMemory = NVCV_ERR_CUDA_MEMORY, // CUDA errors
|
||||
errCudaValue = NVCV_ERR_CUDA_VALUE,
|
||||
errCudaPitch = NVCV_ERR_CUDA_PITCH,
|
||||
errCudaInit = NVCV_ERR_CUDA_INIT,
|
||||
@@ -286,14 +311,10 @@ struct FXApp {
|
||||
errCudaUnsupported = NVCV_ERR_CUDA_UNSUPPORTED,
|
||||
errCudaIllegalAddress = NVCV_ERR_CUDA_ILLEGAL_ADDRESS,
|
||||
errCuda = NVCV_ERR_CUDA,
|
||||
errQuit = -50, // Application errors
|
||||
errFlag = -51,
|
||||
errRead = -52,
|
||||
errWrite = -53,
|
||||
};
|
||||
|
||||
FXApp() { _eff = nullptr; _effectName = nullptr; _inited = false; _showFPS = false; _progress = false;
|
||||
_show = false; _framePeriod = 0.f; }
|
||||
_show = false; _enableEffect = true, _drawVisualization = true, _framePeriod = 0.f; }
|
||||
~FXApp() { NvVFX_DestroyEffect(_eff); }
|
||||
|
||||
void setShow(bool show) { _show = show; }
|
||||
@@ -303,8 +324,10 @@ struct FXApp {
|
||||
NvCV_Status allocTempBuffers();
|
||||
Err processImage(const char *inFile, const char *outFile);
|
||||
Err processMovie(const char *inFile, const char *outFile);
|
||||
Err initCamera(cv::VideoCapture& cap);
|
||||
Err processKey(int key);
|
||||
void drawFrameRate(cv::Mat& img);
|
||||
void drawEffectStatus(cv::Mat& img);
|
||||
Err appErrFromVfxStatus(NvCV_Status status) { return (Err)status; }
|
||||
const char* errorStringFromCode(Err code);
|
||||
|
||||
@@ -320,6 +343,8 @@ struct FXApp {
|
||||
bool _inited;
|
||||
bool _showFPS;
|
||||
bool _progress;
|
||||
bool _enableEffect;
|
||||
bool _drawVisualization;
|
||||
const char* _effectName;
|
||||
float _framePeriod;
|
||||
std::chrono::high_resolution_clock::time_point _lastTime;
|
||||
@@ -333,11 +358,9 @@ const char* FXApp::errorStringFromCode(Err code) {
|
||||
{ errQuit, "The user chose to quit the application" },
|
||||
{ errFlag, "There was a problem with the command-line arguments" },
|
||||
};
|
||||
if ((int)code >= (int)errCuda)
|
||||
return NvCV_GetErrorStringFromCode((NvCV_Status)code);
|
||||
if ((int)code <= 0) return NvCV_GetErrorStringFromCode((NvCV_Status)code);
|
||||
for (const LutEntry *p = lut; p != &lut[sizeof(lut) / sizeof(lut[0])]; ++p)
|
||||
if (p->code == code)
|
||||
return p->str;
|
||||
if (p->code == code) return p->str;
|
||||
return "UNKNOWN ERROR";
|
||||
}
|
||||
|
||||
@@ -372,6 +395,11 @@ FXApp::Err FXApp::processKey(int key) {
|
||||
break;
|
||||
case 'p': case 'P': case '%':
|
||||
_progress = !_progress;
|
||||
case 'e': case 'E':
|
||||
break;
|
||||
case 'd': case'D':
|
||||
if (FLAG_webcam)
|
||||
_drawVisualization = !_drawVisualization;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -379,6 +407,41 @@ FXApp::Err FXApp::processKey(int key) {
|
||||
return errNone;
|
||||
}
|
||||
|
||||
FXApp::Err FXApp::initCamera(cv::VideoCapture& cap) {
|
||||
const int camIndex = 0;
|
||||
cap.open(camIndex);
|
||||
if (!FLAG_camRes.empty()) {
|
||||
int camWidth, camHeight, n;
|
||||
n = sscanf(FLAG_camRes.c_str(), "%d%*[xX]%d", &camWidth, &camHeight);
|
||||
switch (n) {
|
||||
case 2:
|
||||
break; // We have read both width and height
|
||||
case 1:
|
||||
camHeight = camWidth;
|
||||
camWidth = (int)(camHeight * (16. / 9.) + .5);
|
||||
break;
|
||||
default:
|
||||
camHeight = 0;
|
||||
camWidth = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (camWidth) cap.set(cv::CAP_PROP_FRAME_WIDTH, camWidth);
|
||||
if (camHeight) cap.set(cv::CAP_PROP_FRAME_HEIGHT, camHeight);
|
||||
if (camWidth != cap.get(cv::CAP_PROP_FRAME_WIDTH) || camHeight != cap.get(cv::CAP_PROP_FRAME_HEIGHT)) {
|
||||
printf("Error: Camera does not support %d x %d resolution\n", camWidth, camHeight);
|
||||
return errGeneral;
|
||||
}
|
||||
}
|
||||
return errNone;
|
||||
}
|
||||
|
||||
void FXApp::drawEffectStatus(cv::Mat& img) {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "Effect: %s", _enableEffect ? "on" : "off");
|
||||
cv::putText(img, buf, cv::Point(10, img.rows - 40), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 1);
|
||||
}
|
||||
|
||||
FXApp::Err FXApp::createEffect(const char *effectSelector, const char *modelDir) {
|
||||
NvCV_Status vfxErr;
|
||||
BAIL_IF_ERR(vfxErr = NvVFX_CreateEffect(effectSelector, &_eff));
|
||||
@@ -407,6 +470,15 @@ bail:
|
||||
return vfxErr;
|
||||
}
|
||||
|
||||
static NvCV_Status CheckScaleIsotropy(const NvCVImage *src, const NvCVImage *dst) {
|
||||
if (src->width * dst->height != src->height * dst->width) {
|
||||
printf("%ux%u --> %ux%u: different scale for width and height is not supported\n",
|
||||
src->width, src->height, dst->width, dst->height);
|
||||
return NVCV_ERR_RESOLUTION;
|
||||
}
|
||||
return NVCV_SUCCESS;
|
||||
}
|
||||
|
||||
NvCV_Status FXApp::allocBuffers(unsigned width, unsigned height) {
|
||||
NvCV_Status vfxErr = NVCV_SUCCESS;
|
||||
|
||||
@@ -439,6 +511,7 @@ NvCV_Status FXApp::allocBuffers(unsigned width, unsigned height) {
|
||||
BAIL_IF_NULL(_dstImg.data, vfxErr, NVCV_ERR_MEMORY);
|
||||
BAIL_IF_ERR(vfxErr = NvCVImage_Alloc(&_srcGpuBuf, _srcImg.cols, _srcImg.rows, NVCV_BGR, NVCV_F32, NVCV_PLANAR, NVCV_GPU, 1)); // src GPU
|
||||
BAIL_IF_ERR(vfxErr = NvCVImage_Alloc(&_dstGpuBuf, _dstImg.cols, _dstImg.rows, NVCV_BGR, NVCV_F32, NVCV_PLANAR, NVCV_GPU, 1)); // dst GPU
|
||||
BAIL_IF_ERR(vfxErr = CheckScaleIsotropy(&_srcGpuBuf, &_dstGpuBuf));
|
||||
}
|
||||
else if (!strcmp(_effectName, NVVFX_FX_SR_UPSCALE)) {
|
||||
if (!FLAG_resolution) {
|
||||
@@ -451,9 +524,10 @@ NvCV_Status FXApp::allocBuffers(unsigned width, unsigned height) {
|
||||
_dstImg.create(FLAG_resolution, dstWidth, _srcImg.type()); // dst CPU
|
||||
BAIL_IF_NULL(_dstImg.data, vfxErr, NVCV_ERR_MEMORY);
|
||||
BAIL_IF_ERR(vfxErr = NvCVImage_Alloc(&_srcGpuBuf, _srcImg.cols, _srcImg.rows, NVCV_RGBA, NVCV_U8, NVCV_INTERLEAVED,
|
||||
NVCV_GPU, 1)); // src GPU
|
||||
NVCV_GPU, 32)); // src GPU
|
||||
BAIL_IF_ERR(vfxErr = NvCVImage_Alloc(&_dstGpuBuf, _dstImg.cols, _dstImg.rows, NVCV_RGBA, NVCV_U8, NVCV_INTERLEAVED,
|
||||
NVCV_GPU, 1)); // dst GPU
|
||||
NVCV_GPU, 32)); // dst GPU
|
||||
BAIL_IF_ERR(vfxErr = CheckScaleIsotropy(&_srcGpuBuf, &_dstGpuBuf));
|
||||
}
|
||||
NVWrapperForCVMat(&_srcImg, &_srcVFX); // _srcVFX is an alias for _srcImg
|
||||
NVWrapperForCVMat(&_dstImg, &_dstVFX); // _dstVFX is an alias for _dstImg
|
||||
@@ -511,23 +585,34 @@ bail:
|
||||
}
|
||||
|
||||
FXApp::Err FXApp::processMovie(const char *inFile, const char *outFile) {
|
||||
const int fourcc_h264 = CV_FOURCC('H','2','6','4');
|
||||
const int fourcc_h264 = cv::VideoWriter::fourcc('H','2','6','4');
|
||||
CUstream stream = 0;
|
||||
FXApp::Err appErr = errNone;
|
||||
bool ok;
|
||||
cv::VideoCapture reader;
|
||||
cv::VideoWriter writer;
|
||||
NvCV_Status vfxErr;
|
||||
unsigned frameNum;
|
||||
VideoInfo info;
|
||||
|
||||
cv::VideoCapture reader(inFile);
|
||||
if (inFile && !inFile[0]) inFile = nullptr; // Set file paths to NULL if zero length
|
||||
|
||||
if (!FLAG_webcam && inFile) {
|
||||
reader.open(inFile);
|
||||
} else {
|
||||
appErr = initCamera(reader);
|
||||
if (appErr != errNone)
|
||||
return appErr;
|
||||
}
|
||||
|
||||
if (!reader.isOpened()) {
|
||||
printf("Error: Could not open video: \"%s\"\n", inFile);
|
||||
if (!FLAG_webcam) printf("Error: Could not open video: \"%s\"\n", inFile);
|
||||
else printf("Error: Webcam not found\n");
|
||||
return errRead;
|
||||
}
|
||||
|
||||
GetVideoInfo(reader, inFile, &info);
|
||||
if (!(fourcc_h264 == info.codec || CV_FOURCC('a', 'v', 'c', '1') == info.codec)) // avc1 is alias for h264
|
||||
GetVideoInfo(reader, (inFile ? inFile : "webcam"), &info);
|
||||
if (!(fourcc_h264 == info.codec || cv::VideoWriter::fourcc('a', 'v', 'c', '1') == info.codec)) // avc1 is alias for h264
|
||||
printf("Filters only target H264 videos, not %.4s\n", (char*)&info.codec);
|
||||
|
||||
BAIL_IF_ERR(vfxErr = allocBuffers(info.width, info.height));
|
||||
@@ -559,9 +644,13 @@ FXApp::Err FXApp::processMovie(const char *inFile, const char *outFile) {
|
||||
}
|
||||
|
||||
// _srcVFX --> _srcTmpVFX --> _srcGpuBuf --> _dstGpuBuf --> _dstTmpVFX --> _dstVFX
|
||||
BAIL_IF_ERR(vfxErr = NvCVImage_Transfer(&_srcVFX, &_srcGpuBuf, 1.f/255.f, stream, &_tmpVFX));
|
||||
BAIL_IF_ERR(vfxErr = NvVFX_Run(_eff, 0));
|
||||
BAIL_IF_ERR(vfxErr = NvCVImage_Transfer(&_dstGpuBuf, &_dstVFX, 255.f, stream, &_tmpVFX));
|
||||
if (_enableEffect) {
|
||||
BAIL_IF_ERR(vfxErr = NvCVImage_Transfer(&_srcVFX, &_srcGpuBuf, 1.f / 255.f, stream, &_tmpVFX));
|
||||
BAIL_IF_ERR(vfxErr = NvVFX_Run(_eff, 0));
|
||||
BAIL_IF_ERR(vfxErr = NvCVImage_Transfer(&_dstGpuBuf, &_dstVFX, 255.f, stream, &_tmpVFX));
|
||||
} else {
|
||||
BAIL_IF_ERR(vfxErr = NvCVImage_Transfer(&_srcVFX, &_dstVFX, 1.f / 255.f, stream, &_tmpVFX));
|
||||
}
|
||||
|
||||
if (outFile)
|
||||
writer.write(_dstImg);
|
||||
@@ -602,9 +691,13 @@ int main(int argc, char **argv) {
|
||||
NvVFX_GetString(nullptr, NVVFX_INFO, &cstr);
|
||||
std::cerr << "Effects:" << std::endl << cstr << std::endl;
|
||||
}
|
||||
|
||||
if (FLAG_inFile.empty()) {
|
||||
std::cerr << "Please specify --in_file=XXX\n";
|
||||
if (FLAG_webcam) {
|
||||
// If webcam is on, enable showing the results and turn off displaying the progress
|
||||
if (FLAG_progress) FLAG_progress = !FLAG_progress;
|
||||
if (!FLAG_show) FLAG_show = !FLAG_show;
|
||||
}
|
||||
if (FLAG_inFile.empty() && !FLAG_webcam) {
|
||||
std::cerr << "Please specify --in_file=XXX or --webcam=true\n";
|
||||
++nErrs;
|
||||
}
|
||||
if (FLAG_outFile.empty() && !FLAG_show) {
|
||||
|
||||
Reference in New Issue
Block a user