Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

NVENCMgr.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010 * RCS INFORMATION:
00011 *
00012 *      $RCSfile: OptiXDisplayDevice.h
00013 *      $Author: johns $      $Locker:  $               $State: Exp $
00014 *      $Revision: 1.5 $         $Date: 2019/01/17 21:21:00 $
00015 *
00016 ***************************************************************************
00017 * DESCRIPTION:
00018 *   VMD interface for NVIDIA GPU hardware video encoding APIs
00019 *
00020 *   The implementation here could in principal use either high level
00021 *   libraries like NvPipe or GRID, or lower level video encode APIs 
00022 *   like NvEnc, depending on what hardware the target platform has and
00023 *   whether we want to use codecs not supported by certain APIs.
00024 *
00025 *   NvPipe: 
00026 *     https://github.com/NVIDIA/NvPipe/blob/master/README.md
00027 *
00028 ***************************************************************************/
00029 
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 
00035 #include "NVENCMgr.h"
00036 #include "Inform.h"
00037 #include "vmddlopen.h"
00038 
00039 #include "cuda.h"
00040 
00041 #define DBG() printf("NVENCMgr) %s\n", __func__);
00042 
00043 typedef NVENCSTATUS (NVENCAPI* PNVENCODEAPICREATEINSTANCE)(NV_ENCODE_API_FUNCTION_LIST *functionList);
00044 
00045 class nvencfctns {
00046   PNVENCODEAPICREATEINSTANCE nvEncodeAPICreateInstance;
00047   NV_ENCODE_API_FUNCTION_LIST fctns; 
00048 };
00049 
00050 
00051 NVENCMgr::NVENCMgr(void) {
00052   DBG();
00053 
00054   nvenc_lib = NULL;
00055   enc_ready = 0;
00056   inbuf_count = 0;
00057   memset(&nvenc_fctns, 0, sizeof(nvenc_fctns));
00058 
00059   memset(&session_parms, 0, sizeof(session_parms));
00060   session_parms.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
00061   session_parms.apiVersion = NVENCAPI_VERSION;
00062 
00063   memset(&preset_conf, 0, sizeof(preset_conf));
00064   preset_conf.version = NV_ENC_PRESET_CONFIG_VER;
00065   preset_conf.presetCfg.version = NV_ENC_CONFIG_VER;
00066 
00067   memset(&init_parms, 0, sizeof(init_parms));
00068   init_parms.version = NV_ENC_INITIALIZE_PARAMS_VER;
00069 
00070   memset(&conf, 0, sizeof(conf));
00071   conf.version = NV_ENC_CONFIG_VER;
00072 
00073   memset(&create_inbuf, 0, sizeof(create_inbuf));
00074   create_inbuf.version = NV_ENC_CREATE_INPUT_BUFFER_VER;
00075 
00076   memset(&create_outbuf, 0, sizeof(create_outbuf));
00077   create_outbuf.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;
00078 
00079   memset(&enc_preset, 0, sizeof(enc_preset));
00080 }
00081 
00082 
00083 NVENCMgr::~NVENCMgr(void) {
00084   DBG();
00085 
00086   if (nvenc_lib)
00087     vmddlclose(nvenc_lib);
00088 }
00089 
00090 
00091 int NVENCMgr::init(void) {
00092   DBG();
00093  
00094   nvenc_lib = vmddlopen("libnvidia-encode.so.1");
00095   if (!nvenc_lib) {
00096     msgInfo << "NVENCMgr) Failed to open NVENC hardware video encoder library." 
00097             << sendmsg;
00098     vmddlclose(nvenc_lib);
00099     return -1;
00100   } 
00101 
00102   nvenc_fctns.version = NV_ENCODE_API_FUNCTION_LIST_VER;
00103 
00104   nvEncodeAPICreateInstance = (PNVENCODEAPICREATEINSTANCE) vmddlsym(nvenc_lib, "NvEncodeAPICreateInstance");
00105   if (!nvEncodeAPICreateInstance) {
00106     msgInfo << "NVENCMgr) Failed to load NVENC hardware video encoder instance fctn." 
00107             << sendmsg;
00108     vmddlclose(nvenc_lib);
00109     return -1;
00110   }
00111 
00112   NVENCSTATUS rc;
00113   rc = nvEncodeAPICreateInstance(&nvenc_fctns);
00114   if (rc != NV_ENC_SUCCESS) {
00115     msgInfo << "NVENCMgr) Failed to load NVENC hardware video encoder instance fctn table." 
00116             << sendmsg;
00117   }
00118 
00119   return 0;
00120 }
00121 
00122 
00123 int NVENCMgr::open_session(void) {
00124   DBG();
00125 
00126   CUcontext cuctx = NULL;
00127   CUresult curc;
00128   CUcontext cuctxcurrent = NULL;
00129   int cudevcount = 0;
00130   CUdevice cudev = 0;
00131 
00132 #if 0
00133   if ((curc = cuInit(0)) != CUDA_SUCCESS) {
00134     printf("NVENCMgr) failed to initialize CUDA driver API\n");
00135     return -1;
00136   }
00137 #endif
00138  
00139   if ((curc = cuDeviceGetCount(&cudevcount)) != CUDA_SUCCESS) {
00140     printf("NVENCMgr) failed to query CUDA driver API device count\n");
00141     return -1;
00142   }
00143 
00144   if (cudevcount < 1) {
00145     printf("NVENCMgr) no CUDA devices found for NVENC video encoding\n");
00146     return -1;
00147   } else {
00148     printf("NVENCMgr) CUDA dev count: %d\n", cudevcount);
00149   }
00150 
00151   if ((curc = cuDeviceGet(&cudev, 0)) != CUDA_SUCCESS) {
00152     printf("NVENCMgr) Unable to bind CUDA device 0\n");
00153     return -1;
00154   }
00155 
00156   if ((curc = cuCtxCreate(&cuctx, 0, cudev)) != CUDA_SUCCESS) {
00157     printf("NVENCMgr) Unable create CUDA ctx\n");
00158     return -1;
00159   }
00160 
00161   if ((curc = cuCtxPopCurrent(&cuctxcurrent)) != CUDA_SUCCESS) {
00162     printf("NVENCMgr) Unable pop current CUDA ctx\n");
00163     return -1;
00164   }
00165 //  curc = cuCtxGetCurrent(&cuctx);
00166 
00167 
00168   session_parms.device = cuctx;
00169   session_parms.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
00170   // XXX client keys are not presently required
00171   // session_parms.clientKeyPtr = &NV_CLIENT_KEY;
00172 
00173 //  printf("NVENCMgr) Creating NVENC hardware encoder session...\n");
00174 
00175   NVENCSTATUS encstat;
00176   encstat = nvenc_fctns.nvEncOpenEncodeSessionEx(&session_parms, &nvenc_ctx);
00177   if (encstat != NV_ENC_SUCCESS) {
00178     printf("NVENCMgr) nvEncOpenEncodeSessionEx() returned an error!\n");
00179     return -1;
00180   }
00181 
00182   // setup encoder presets
00183   enc_preset = NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID;
00184   // enc_preset = NV_ENC_PRESET_LOW_LATENCY_HP_GUID;
00185   // enc_preset = NV_ENC_PRESET_LOW_LATENCY_HQ_GUID;
00186   // enc_preset = NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID;
00187   // enc_preset = NV_ENC_PRESET_LOSSLESS_HP_GUID;
00188   // enc_preset = NV_ENC_PRESET_HQ_GUID;
00189   // enc_preset = NV_ENC_PRESET_DEFAULT_GUID;
00190 
00191 #if 1
00192   codec = NV_ENC_CODEC_H264_GUID;
00193 #else
00194   codec = NV_ENC_CODEC_HEVC_GUID;
00195 #endif
00196 
00197   printf("NVENCMgr) establishing NVENC hardware encoder preset config\n");
00198   encstat = nvenc_fctns.nvEncGetEncodePresetConfig(nvenc_ctx, codec, 
00199                                                    enc_preset, &preset_conf);
00200   if (encstat != NV_ENC_SUCCESS) {
00201     printf("NVENCMgr) nvEncGetEncodePresetConfig() returned an error!\n");
00202     return -1;
00203   }
00204 
00205   init_parms.version = NV_ENC_INITIALIZE_PARAMS_VER;
00206   init_parms.encodeWidth = 1920;
00207   init_parms.encodeHeight = 1080;
00208   init_parms.darWidth = 1920;
00209   init_parms.darHeight = 1080;
00210   init_parms.maxEncodeWidth = 1920;
00211   init_parms.maxEncodeHeight = 1080;
00212   init_parms.frameRateNum = 1;
00213   init_parms.frameRateDen = 30;
00214   init_parms.enableEncodeAsync = 0;
00215   init_parms.enablePTD = 1;
00216 
00217   init_parms.encodeGUID = codec;
00218   init_parms.presetGUID = enc_preset;
00219   init_parms.encodeConfig = &preset_conf.presetCfg;
00220 
00221 //  printf("NVENCMgr) Initializing NVENC hardware encoder ...\n");
00222   encstat = nvenc_fctns.nvEncInitializeEncoder(nvenc_ctx, &init_parms);
00223   if (encstat != NV_ENC_SUCCESS) {
00224     printf("NVENCMgr) nvEncInitializeEncoder() returned an error!\n");
00225     return -1;
00226   }
00227 
00228 #if 0
00229   // setting refs to zero allows hardware encoder to decide
00230   conf.encodeCodecConfig.h264Config.maxNumRefFrames = 0;
00231   conf.encodeCodecConfig.hevcConfig.maxNumRefFramesInDPB = 0;
00232 
00233   // infinite GOP == 0, I-only == 1?
00234   conf.gopLength = 30;
00235   if (conf.gopLength > 0) {
00236     conf.frameIntervalP = 3; // 0=I only, 1=IP, 2=IBP, 3=IBBP, ...
00237   } else {
00238     conf.frameIntervalP = 0; // 0=I only, 1=IP, 2=IBP, 3=IBBP, ...
00239     conf.gopLength = 1;
00240   }
00241 
00242   conf.encodeCodecConfig.h264Config.idrPeriod = conf.gopLength;
00243   // H.264 only
00244   conf.encodeCodecConfig.h264Config.hierarchicalPFrames = 1;
00245   conf.encodeCodecConfig.h264Config.hierarchicalBFrames = 1;
00246 
00247   conf.rcParams.averageBitRate = 15000000; // 15Mbps
00248   conf.rcParams.maxBitRate     = 20000000; // 20Mbps
00249 #endif
00250 
00251   // flag encoder as ready
00252   enc_ready = 1;
00253   printf("NVENCMgr) NVENC hardware encoder ready.\n");
00254 
00255   return 0;
00256 }
00257 
00258 
00259 int NVENCMgr::create_inbufs(int bufcount) {
00260   DBG();
00261   NVENCSTATUS encstat;
00262 
00263   if (!enc_ready) {
00264     printf("NVENCMgr) Error creating input buffers, encoder not ready!\n");
00265     return -1;
00266   }
00267 
00268   // must be multiples of 32
00269   create_inbuf.width = 1920;
00270   create_inbuf.height= 1080;
00271   create_inbuf.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;
00272   create_inbuf.bufferFmt = NV_ENC_BUFFER_FORMAT_NV12_PL;
00273 
00274   inbuf_count = bufcount;
00275   int i;
00276   for (i=0; i<inbuf_count; i++) {
00277     encstat = nvenc_fctns.nvEncCreateInputBuffer(nvenc_ctx, &create_inbuf); 
00278     if (encstat != NV_ENC_SUCCESS) {
00279       printf("NVENCMgr) Failed to create input buffers!\n");
00280       return -1;
00281     }
00282   } 
00283 
00284   return 0;
00285 }
00286 

Generated on Fri Oct 4 02:44:23 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002