Пример #1
0
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);
	}
Пример #3
0
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);
    }
}
Пример #4
0
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;
}
Пример #5
0
/*
 * 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;
}