In the Video Codec SDK 8.2.16, the NVCUVID documentation for the callbacks PFNVIDSEQUENCECALLBACK, PFNVIDDECODECALLBACK, and PFNVIDDISPLAYCALLBACK says they return integers where, “0: fail, 1: suceeded”. If I return 0 from a PFNVIDSEQUENCECALLBACK, the PFNVIDDECODECALLBACK is still triggered. That has to be wrong, and is not the behavior I want. How do I prevent the PFNVIDDECODECALLBACK from being called if I encounter a problem in PFNVIDSEQUENCECALLBACK?
The following program demonstrates this behavior:
#include <cuviddec.h>
#include <nvcuvid.h>
#include <fstream>
#include <iostream>
#include <iterator>
#include <stdexcept>
#include <string>
#include <vector>
std::string checkCUDACall(CUresult r)
{
if(r != CUDA_SUCCESS) {
const char *errorName = NULL;
std::string errorString("CUDA_ERROR_INVALID_VALUE");
if(cuGetErrorName(r, &errorName) == CUDA_SUCCESS) {
errorString = std::string(errorName);
}
return errorString;
}
return std::string();
}
#define CUDA_THROW_IF_FAIL(call, errorString) \
do { \
const std::string result = checkCUDACall(call); \
if(!result.empty()) { \
throw std::runtime_error( \
std::string(errorString) + result); \
} \
} while(0)
int CUDAAPI HandleVideoSequenceProc(void *pUserData, CUVIDEOFORMAT *pVideoFormat)
{
std::cout << "Hit: " << __FUNCTION__ << std::endl;
return 0;
}
int CUDAAPI HandlePictureDecodeProc(void *pUserData, CUVIDPICPARAMS *pPicParams)
{
std::cout << "Hit: " << __FUNCTION__ << std::endl;
return 0;
}
int CUDAAPI HandlePictureDisplayProc(void *pUserData, CUVIDPARSERDISPINFO *pDispInfo)
{
std::cout << "Hit: " << __FUNCTION__ << std::endl;
return 0;
}
std::vector<unsigned char> readFile(const std::string &path)
{
std::ifstream infile(path, std::ios::in | std::ios::binary | std::ios::ate);
if(!infile.is_open()) {
throw std::runtime_error("Could not open file: " + path);
}
infile.unsetf(std::ios::skipws);
const std::ifstream::pos_type fileSize = infile.tellg();
infile.seekg(0, std::ios::beg);
std::vector<unsigned char> ret;
ret.reserve(fileSize);
ret.insert(
ret.begin(),
std::istream_iterator<unsigned char>(infile),
std::istream_iterator<unsigned char>());
return ret;
}
int main(int argc, char **argv)
{
if(argc <= 1) {
std::cerr << "Usage: " << argv[0] << " <Path to H.264 file>" << std::endl;
return 1;
}
CUVIDPARSERPARAMS videoParserParameters = {};
videoParserParameters.CodecType = cudaVideoCodec_H264;
videoParserParameters.ulMaxNumDecodeSurfaces = 1;
videoParserParameters.ulMaxDisplayDelay = 0;
videoParserParameters.pUserData = NULL;
videoParserParameters.pfnSequenceCallback = HandleVideoSequenceProc;
videoParserParameters.pfnDecodePicture = HandlePictureDecodeProc;
videoParserParameters.pfnDisplayPicture = HandlePictureDisplayProc;
CUvideoparser parser = NULL;
CUDA_THROW_IF_FAIL(cuvidCreateVideoParser(&parser, &videoParserParameters),
"Failed to create CUVID video parser: ");
std::vector<unsigned char> data = readFile(argv[1]);
CUVIDSOURCEDATAPACKET packet = {0};
packet.payload = &data[0];
packet.payload_size = data.size();
packet.flags |= CUVID_PKT_ENDOFSTREAM;
CUDA_THROW_IF_FAIL(cuvidParseVideoData(parser, &packet),
"Failed to parse video data: ");
return 0;
}
Output:
$ ./a.out Single1080p.h264
Hit: HandleVideoSequenceProc
Hit: HandlePictureDecodeProc
$