bool VideoDecoderCUDAPrivate::releaseCuda() { available = false; if (!can_load) return true; if (dec) { cuvidDestroyDecoder(dec); dec = 0; } if (parser) { cuvidDestroyVideoParser(parser); parser = 0; } if (stream) { cuStreamDestroy(stream); stream = 0; } if (host_data) { cuMemFreeHost(host_data); host_data = 0; host_data_size = 0; } if (vid_ctx_lock) { cuvidCtxLockDestroy(vid_ctx_lock); vid_ctx_lock = 0; } if (cuctx) { checkCudaErrors(cuCtxDestroy(cuctx)); } // TODO: dllapi unload return true; }
void CudaVideoRender::terminateCudaVideo(bool bDestroyContext) { if (m_pVideoParser) delete m_pVideoParser; if (m_pVideoDecoder) delete m_pVideoDecoder; if (m_pVideoSource) delete m_pVideoSource; if (m_pFrameQueue) delete m_pFrameQueue; if (m_CtxLock) { cutilDrvSafeCallNoSync( cuvidCtxLockDestroy(m_CtxLock) ); } if (m_cuContext && bDestroyContext) { cutilDrvSafeCallNoSync( cuCtxDestroy(m_cuContext) ); m_cuContext = NULL; } if (m_ReadbackSID) cuStreamDestroy(m_ReadbackSID); if (m_KernelSID) cuStreamDestroy(m_KernelSID); }
void freeCudaResources(bool bDestroyContext) { if (g_pVideoParser) { delete g_pVideoParser; } if (g_pVideoDecoder) { delete g_pVideoDecoder; } if (g_pVideoSource) { delete g_pVideoSource; } if (g_pFrameQueue) { delete g_pFrameQueue; } if (g_CtxLock) { checkCudaErrors(cuvidCtxLockDestroy(g_CtxLock)); } if (g_oContext && bDestroyContext) { checkCudaErrors(cuCtxDestroy(g_oContext)); g_oContext = NULL; } if (g_ReadbackSID) { cuStreamDestroy(g_ReadbackSID); } if (g_KernelSID) { cuStreamDestroy(g_KernelSID); } }
bool VideoDecoderCUDAPrivate::releaseCuda() { if (!can_load) return true; if (dec) { cuvidDestroyDecoder(dec); dec = 0; } if (parser) { cuvidDestroyVideoParser(parser); parser = 0; } if (stream) { cuStreamDestroy(stream); stream = 0; } cuvidCtxLockDestroy(vid_ctx_lock); if (cuctx) { checkCudaErrors(cuCtxDestroy(cuctx)); } return true; }
/* * Main transcoding thread * Initializes CUDA device, decodes frames with NVCUVID API and adds them to frame queue, which passes them to NVENC for encoding, then output */ void NVENCGUI::Transcode() { CUresult result; // initialize CUDA result = cuInit(0); if (result != CUDA_SUCCESS) { emit Error(ERR_CUDA_INIT); return; } NVENCSTATUS nvStatus = NV_ENC_SUCCESS; // no input file if (encodeConfig.inputFileName == NULL) { emit Error(ERR_INPUT); return; } // no output file if (encodeConfig.outputFileName == NULL) { emit Error(ERR_OUTPUT); return; } // unable to open input file if (!fopen(encodeConfig.inputFileName, "r")) { emit Error(ERR_INPUT); return; } encodeConfig.fOutput = fopen(encodeConfig.outputFileName, "wb"); // unable to open output file if (encodeConfig.fOutput == NULL) { emit Error(ERR_OUTPUT); return; } // initialize CUDA on device and set CUDA context CUcontext cudaCtx; CUdevice device; result = cuDeviceGet(&device, encodeConfig.deviceID); if (result != CUDA_SUCCESS) { emit Error(ERR_CUDA_DEVICE); return; } result = cuCtxCreate(&cudaCtx, CU_CTX_SCHED_AUTO, device); if (result != CUDA_SUCCESS) { emit Error(ERR_CUDA_CTX); return; } // initialize NVCUVID context CUcontext curCtx; CUvideoctxlock ctxLock; result = cuCtxPopCurrent(&curCtx); if (result != CUDA_SUCCESS) { emit Error(ERR_CUDA_CTX); return; } result = cuvidCtxLockCreate(&ctxLock, curCtx); if (result != CUDA_SUCCESS) { emit Error(ERR_CUDA_CTX); return; } CudaDecoder* pDecoder = new CudaDecoder; FrameQueue* pFrameQueue = new CUVIDFrameQueue(ctxLock); pDecoder->InitVideoDecoder(encodeConfig.inputFileName, ctxLock, pFrameQueue, encodeConfig.width, encodeConfig.height); int decodedW, decodedH, decodedFRN, decodedFRD; pDecoder->GetCodecParam(&decodedW, &decodedH, &decodedFRN, &decodedFRD); // If the width/height is not set, set to same as source if (encodeConfig.width <= 0 || encodeConfig.height <= 0) { encodeConfig.width = decodedW; encodeConfig.height = decodedH; } // same, except for fps if (encodeConfig.fps <= 0) { if (decodedFRN <= 0 || decodedFRD <= 0) encodeConfig.fps = 30; else encodeConfig.fps = decodedFRN / decodedFRD; } // initialize frame queue with width/height pFrameQueue->init(encodeConfig.width, encodeConfig.height); VideoEncoder* pEncoder = new VideoEncoder(ctxLock); assert(pEncoder->GetHWEncoder()); // initialize NVENC HW Encoder nvStatus = pEncoder->GetHWEncoder()->Initialize(cudaCtx, NV_ENC_DEVICE_TYPE_CUDA); if (nvStatus != NV_ENC_SUCCESS) { emit Error(ERR_NVENC_ENC_INIT); return; } // get preset GUID encodeConfig.presetGUID = pEncoder->GetHWEncoder()->GetPresetGUID(encodeConfig.encoderPreset, encodeConfig.codec); // create encoder nvStatus = pEncoder->GetHWEncoder()->CreateEncoder(&encodeConfig); if (nvStatus != NV_ENC_SUCCESS) { emit Error(ERR_NVENC_ENC_CREATE); return; } // create buffer nvStatus = pEncoder->AllocateIOBuffers(&encodeConfig); if (nvStatus != NV_ENC_SUCCESS) { emit Error(ERR_NVENC_ENC_BUFFER); return; } // print details to text window, start counter emit PrintDetails(); NvQueryPerformanceCounter(&results.lStart); //start decoding thread #ifdef _WIN32 HANDLE decodeThread = CreateThread(NULL, 0, DecodeProc, (LPVOID)pDecoder, 0, NULL); #else pthread_t pid; pthread_create(&pid, NULL, DecodeProc, (void*)pDecoder); #endif int encodedFrames = 0; //start encoding thread while (!(pFrameQueue->isEndOfDecode() && pFrameQueue->isEmpty())) { CUVIDPARSERDISPINFO pInfo; if (pFrameQueue->dequeue(&pInfo)) { CUdeviceptr dMappedFrame = 0; unsigned int pitch; CUVIDPROCPARAMS oVPP = { 0 }; oVPP.unpaired_field = 1; oVPP.progressive_frame = 1; cuvidMapVideoFrame(pDecoder->GetDecoder(), pInfo.picture_index, &dMappedFrame, &pitch, &oVPP); EncodeFrameConfig stEncodeConfig = { 0 }; stEncodeConfig.dptr = dMappedFrame; stEncodeConfig.pitch = pitch; stEncodeConfig.width = encodeConfig.width; stEncodeConfig.height = encodeConfig.height; pEncoder->EncodeFrame(&stEncodeConfig); cuvidUnmapVideoFrame(pDecoder->GetDecoder(), dMappedFrame); pFrameQueue->releaseFrame(&pInfo); //emit IncrementEncodedFrames(); } } // flush pEncoder->EncodeFrame(NULL, true); // end decoding thread #ifdef _WIN32 WaitForSingleObject(decodeThread, INFINITE); #else pthread_join(pid, NULL); #endif // print transcoding details if (pEncoder->GetEncodedFrames() > 0) { results.decodedFrames = pDecoder->m_decodedFrames; results.encodedFrames = pEncoder->GetEncodedFrames(); NvQueryPerformanceCounter(&results.lEnd); NvQueryPerformanceFrequency(&results.lFreq); results.elapsedTime = (double)(results.lEnd - results.lStart) / (double)results.lFreq; } emit TranscodingEnd(); // clean up cuvidCtxLockDestroy(ctxLock); pEncoder->Deinitialize(); delete pDecoder; delete pEncoder; delete pFrameQueue; result = cuCtxDestroy(cudaCtx); if (result != CUDA_SUCCESS) { emit Error(ERR_CUDA_CTX_DESTROY); return; } return; }