硬解码流程
- 创建cuda上下文
- 查询硬件解码器解码能力
- 创建解码器实例
- 使用第三方软件(如FFMPEG)进行Demux
- 使用第三方解析器(如FFMPEG)解析视频比特流
- 使用NVDECODE API启动解码
- 获取解码后的YUV进行进一步处理
- 查询解码帧状态
- 根据解码状态,使用解码后的输出进行进一步的处理(如渲染、后处理等)
- 如果应用程序需要显示输出:
a、将解码后的YUV转化为RGBA格式
b、将RGBA映射到DirectX或OpenGL纹理
c、将纹理绘制到屏幕上 - 在译码过程完成后销毁解码器实例
- 销毁cuda上下文
官方源码Video_Codec_SDK_9.1.23解析
1、AppDec (这个示例应用程序演示了媒体文件的解调和解码,然后调整输出帧的大小和剪裁)
主函数如下:
int main(int argc, char **argv)
{
char szInFilePath[256] = "", szOutFilePath[256] = "";
bool bOutPlanar = false;
int iGpu = 0;
Rect cropRect = {
};
Dim resizeDim = {
};
try
{
ParseCommandLine(argc, argv, szInFilePath, szOutFilePath, bOutPlanar, iGpu, cropRect, resizeDim);
CheckInputFile(szInFilePath);
if (!*szOutFilePath) {
sprintf(szOutFilePath, bOutPlanar ? "out.planar" : "out.native");
}
//初始化cuda环境
ck(cuInit(0));
int nGpu = 0;
//查询系统中可用设备数
ck(cuDeviceGetCount(&nGpu));
if (iGpu < 0 || iGpu >= nGpu) {
std::cout << "GPU ordinal out of range. Should be within [" << 0 << ", " << nGpu - 1 << "]" << std::endl;
return 1;
}
//创建cuda上下文
CUcontext cuContext = NULL;
createCudaContext(&cuContext, iGpu, 0);
//创建解码器实例
std::cout << "Decode with demuxing." << std::endl;
DecodeMediaFile(cuContext, szInFilePath, szOutFilePath, bOutPlanar, cropRect, resizeDim);
}
catch (const std::exception& ex)
{
std::cout << ex.what();
exit(1);
}
return 0;
}
DecodeMediaFile()函数:
/**
* @brief Function to decode media file and write raw frames into an output file.
* @param cuContext - Handle to CUDA context
* @param szInFilePath - Path to file to be decoded
* @param szOutFilePath - Path to output file into which raw frames are stored
* @param bOutPlanar - Flag to indicate whether output needs to be converted to planar format
* @param cropRect - Cropping rectangle coordinates
* @param resizeDim - Resizing dimensions for output
*/
void DecodeMediaFile(CUcontext cuContext, const char *szInFilePath, const char *szOutFilePath, bool bOutPlanar,
const Rect &cropRect, const Dim &resizeDim)
{
std::ofstream fpOut(szOutFilePath, std::ios::out | std::ios::binary);
if (!fpOut)
{
std::ostringstream err;
err << "Unable to open output file: " << szOutFilePath << std::endl;
throw std::invalid_argument(err.str());
}
FFmpegDemuxer demuxer(szInFilePath);
//初始化解码器
NvDecoder dec