forked from Qortal/Brooklyn
1269 lines
39 KiB
C++
1269 lines
39 KiB
C++
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Copyright 1993-2014 NVIDIA Corporation. All rights reserved.
|
||
|
//
|
||
|
// Please refer to the NVIDIA end user license agreement (EULA) associated
|
||
|
// with this source code for terms and conditions that govern your use of
|
||
|
// this software. Any use, reproduction, disclosure, or distribution of
|
||
|
// this software and related documentation outside the terms of the EULA
|
||
|
// is strictly prohibited.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include "NvHWEncoder.h"
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncOpenEncodeSession(void* device, uint32_t deviceType)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncOpenEncodeSession(device, deviceType, &m_hEncoder);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetEncodeGUIDCount(uint32_t* encodeGUIDCount)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodeGUIDCount(m_hEncoder, encodeGUIDCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetEncodeProfileGUIDCount(GUID encodeGUID, uint32_t* encodeProfileGUIDCount)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodeProfileGUIDCount(m_hEncoder, encodeGUID, encodeProfileGUIDCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetEncodeProfileGUIDs(GUID encodeGUID, GUID* profileGUIDs, uint32_t guidArraySize, uint32_t* GUIDCount)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodeProfileGUIDs(m_hEncoder, encodeGUID, profileGUIDs, guidArraySize, GUIDCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetEncodeGUIDs(GUID* GUIDs, uint32_t guidArraySize, uint32_t* GUIDCount)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodeGUIDs(m_hEncoder, GUIDs, guidArraySize, GUIDCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetInputFormatCount(GUID encodeGUID, uint32_t* inputFmtCount)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetInputFormatCount(m_hEncoder, encodeGUID, inputFmtCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetInputFormats(GUID encodeGUID, NV_ENC_BUFFER_FORMAT* inputFmts, uint32_t inputFmtArraySize, uint32_t* inputFmtCount)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetInputFormats(m_hEncoder, encodeGUID, inputFmts, inputFmtArraySize, inputFmtCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetEncodeCaps(GUID encodeGUID, NV_ENC_CAPS_PARAM* capsParam, int* capsVal)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodeCaps(m_hEncoder, encodeGUID, capsParam, capsVal);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetEncodePresetCount(GUID encodeGUID, uint32_t* encodePresetGUIDCount)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodePresetCount(m_hEncoder, encodeGUID, encodePresetGUIDCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetEncodePresetGUIDs(GUID encodeGUID, GUID* presetGUIDs, uint32_t guidArraySize, uint32_t* encodePresetGUIDCount)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodePresetGUIDs(m_hEncoder, encodeGUID, presetGUIDs, guidArraySize, encodePresetGUIDCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetEncodePresetConfig(GUID encodeGUID, GUID presetGUID, NV_ENC_PRESET_CONFIG* presetConfig)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodePresetConfig(m_hEncoder, encodeGUID, presetGUID, presetConfig);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncCreateInputBuffer(uint32_t width, uint32_t height, void** inputBuffer, uint32_t isYuv444)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_CREATE_INPUT_BUFFER createInputBufferParams;
|
||
|
|
||
|
memset(&createInputBufferParams, 0, sizeof(createInputBufferParams));
|
||
|
SET_VER(createInputBufferParams, NV_ENC_CREATE_INPUT_BUFFER);
|
||
|
|
||
|
createInputBufferParams.width = width;
|
||
|
createInputBufferParams.height = height;
|
||
|
createInputBufferParams.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;
|
||
|
createInputBufferParams.bufferFmt = isYuv444 ? NV_ENC_BUFFER_FORMAT_YUV444_PL : NV_ENC_BUFFER_FORMAT_NV12_PL;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncCreateInputBuffer(m_hEncoder, &createInputBufferParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
*inputBuffer = createInputBufferParams.inputBuffer;
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncDestroyInputBuffer(NV_ENC_INPUT_PTR inputBuffer)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
if (inputBuffer)
|
||
|
{
|
||
|
nvStatus = m_pEncodeAPI->nvEncDestroyInputBuffer(m_hEncoder, inputBuffer);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncCreateBitstreamBuffer(uint32_t size, void** bitstreamBuffer)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_CREATE_BITSTREAM_BUFFER createBitstreamBufferParams;
|
||
|
|
||
|
memset(&createBitstreamBufferParams, 0, sizeof(createBitstreamBufferParams));
|
||
|
SET_VER(createBitstreamBufferParams, NV_ENC_CREATE_BITSTREAM_BUFFER);
|
||
|
|
||
|
createBitstreamBufferParams.size = size;
|
||
|
createBitstreamBufferParams.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncCreateBitstreamBuffer(m_hEncoder, &createBitstreamBufferParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
*bitstreamBuffer = createBitstreamBufferParams.bitstreamBuffer;
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncDestroyBitstreamBuffer(NV_ENC_OUTPUT_PTR bitstreamBuffer)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
if (bitstreamBuffer)
|
||
|
{
|
||
|
nvStatus = m_pEncodeAPI->nvEncDestroyBitstreamBuffer(m_hEncoder, bitstreamBuffer);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncLockBitstream(NV_ENC_LOCK_BITSTREAM* lockBitstreamBufferParams)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncLockBitstream(m_hEncoder, lockBitstreamBufferParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncUnlockBitstream(NV_ENC_OUTPUT_PTR bitstreamBuffer)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncUnlockBitstream(m_hEncoder, bitstreamBuffer);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncLockInputBuffer(void* inputBuffer, void** bufferDataPtr, uint32_t* pitch)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_LOCK_INPUT_BUFFER lockInputBufferParams;
|
||
|
|
||
|
memset(&lockInputBufferParams, 0, sizeof(lockInputBufferParams));
|
||
|
SET_VER(lockInputBufferParams, NV_ENC_LOCK_INPUT_BUFFER);
|
||
|
|
||
|
lockInputBufferParams.inputBuffer = inputBuffer;
|
||
|
nvStatus = m_pEncodeAPI->nvEncLockInputBuffer(m_hEncoder, &lockInputBufferParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
*bufferDataPtr = lockInputBufferParams.bufferDataPtr;
|
||
|
*pitch = lockInputBufferParams.pitch;
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncUnlockInputBuffer(NV_ENC_INPUT_PTR inputBuffer)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncUnlockInputBuffer(m_hEncoder, inputBuffer);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetEncodeStats(NV_ENC_STAT* encodeStats)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodeStats(m_hEncoder, encodeStats);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncGetSequenceParams(NV_ENC_SEQUENCE_PARAM_PAYLOAD* sequenceParamPayload)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetSequenceParams(m_hEncoder, sequenceParamPayload);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncRegisterAsyncEvent(void** completionEvent)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_EVENT_PARAMS eventParams;
|
||
|
|
||
|
memset(&eventParams, 0, sizeof(eventParams));
|
||
|
SET_VER(eventParams, NV_ENC_EVENT_PARAMS);
|
||
|
|
||
|
#if defined (NV_WINDOWS)
|
||
|
eventParams.completionEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||
|
#else
|
||
|
eventParams.completionEvent = NULL;
|
||
|
#endif
|
||
|
nvStatus = m_pEncodeAPI->nvEncRegisterAsyncEvent(m_hEncoder, &eventParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
*completionEvent = eventParams.completionEvent;
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncUnregisterAsyncEvent(void* completionEvent)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_EVENT_PARAMS eventParams;
|
||
|
|
||
|
if (completionEvent)
|
||
|
{
|
||
|
memset(&eventParams, 0, sizeof(eventParams));
|
||
|
SET_VER(eventParams, NV_ENC_EVENT_PARAMS);
|
||
|
|
||
|
eventParams.completionEvent = completionEvent;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncUnregisterAsyncEvent(m_hEncoder, &eventParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncMapInputResource(void* registeredResource, void** mappedResource)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_MAP_INPUT_RESOURCE mapInputResParams;
|
||
|
|
||
|
memset(&mapInputResParams, 0, sizeof(mapInputResParams));
|
||
|
SET_VER(mapInputResParams, NV_ENC_MAP_INPUT_RESOURCE);
|
||
|
|
||
|
mapInputResParams.registeredResource = registeredResource;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncMapInputResource(m_hEncoder, &mapInputResParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
*mappedResource = mapInputResParams.mappedResource;
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncUnmapInputResource(NV_ENC_INPUT_PTR mappedInputBuffer)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
if (mappedInputBuffer)
|
||
|
{
|
||
|
nvStatus = m_pEncodeAPI->nvEncUnmapInputResource(m_hEncoder, mappedInputBuffer);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncDestroyEncoder()
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
if (m_bEncoderInitialized)
|
||
|
{
|
||
|
nvStatus = m_pEncodeAPI->nvEncDestroyEncoder(m_hEncoder);
|
||
|
|
||
|
m_bEncoderInitialized = false;
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncInvalidateRefFrames(const NvEncPictureCommand *pEncPicCommand)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
for (uint32_t i = 0; i < pEncPicCommand->numRefFramesToInvalidate; i++)
|
||
|
{
|
||
|
nvStatus = m_pEncodeAPI->nvEncInvalidateRefFrames(m_hEncoder, pEncPicCommand->refFrameNumbers[i]);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncOpenEncodeSessionEx(void* device, NV_ENC_DEVICE_TYPE deviceType)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS openSessionExParams;
|
||
|
|
||
|
memset(&openSessionExParams, 0, sizeof(openSessionExParams));
|
||
|
SET_VER(openSessionExParams, NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS);
|
||
|
|
||
|
openSessionExParams.device = device;
|
||
|
openSessionExParams.deviceType = deviceType;
|
||
|
openSessionExParams.reserved = NULL;
|
||
|
openSessionExParams.apiVersion = NVENCAPI_VERSION;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncOpenEncodeSessionEx(&openSessionExParams, &m_hEncoder);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncRegisterResource(NV_ENC_INPUT_RESOURCE_TYPE resourceType, void* resourceToRegister, uint32_t width, uint32_t height, uint32_t pitch, void** registeredResource)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_REGISTER_RESOURCE registerResParams;
|
||
|
|
||
|
memset(®isterResParams, 0, sizeof(registerResParams));
|
||
|
SET_VER(registerResParams, NV_ENC_REGISTER_RESOURCE);
|
||
|
|
||
|
registerResParams.resourceType = resourceType;
|
||
|
registerResParams.resourceToRegister = resourceToRegister;
|
||
|
registerResParams.width = width;
|
||
|
registerResParams.height = height;
|
||
|
registerResParams.pitch = pitch;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncRegisterResource(m_hEncoder, ®isterResParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
*registeredResource = registerResParams.registeredResource;
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncUnregisterResource(NV_ENC_REGISTERED_PTR registeredRes)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncUnregisterResource(m_hEncoder, registeredRes);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncReconfigureEncoder(const NvEncPictureCommand *pEncPicCommand)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
if (pEncPicCommand->bBitrateChangePending || pEncPicCommand->bResolutionChangePending)
|
||
|
{
|
||
|
if (pEncPicCommand->bResolutionChangePending)
|
||
|
{
|
||
|
m_uCurWidth = pEncPicCommand->newWidth;
|
||
|
m_uCurHeight = pEncPicCommand->newHeight;
|
||
|
if ((m_uCurWidth > m_uMaxWidth) || (m_uCurHeight > m_uMaxHeight))
|
||
|
{
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
m_stCreateEncodeParams.encodeWidth = m_uCurWidth;
|
||
|
m_stCreateEncodeParams.encodeHeight = m_uCurHeight;
|
||
|
m_stCreateEncodeParams.darWidth = m_uCurWidth;
|
||
|
m_stCreateEncodeParams.darHeight = m_uCurHeight;
|
||
|
}
|
||
|
|
||
|
if (pEncPicCommand->bBitrateChangePending)
|
||
|
{
|
||
|
m_stEncodeConfig.rcParams.averageBitRate = pEncPicCommand->newBitrate;
|
||
|
m_stEncodeConfig.rcParams.maxBitRate = pEncPicCommand->newBitrate;
|
||
|
m_stEncodeConfig.rcParams.vbvBufferSize = pEncPicCommand->newVBVSize != 0 ? pEncPicCommand->newVBVSize : (pEncPicCommand->newBitrate * m_stCreateEncodeParams.frameRateDen) / m_stCreateEncodeParams.frameRateNum;
|
||
|
m_stEncodeConfig.rcParams.vbvInitialDelay = m_stEncodeConfig.rcParams.vbvBufferSize;
|
||
|
}
|
||
|
|
||
|
NV_ENC_RECONFIGURE_PARAMS stReconfigParams;
|
||
|
memset(&stReconfigParams, 0, sizeof(stReconfigParams));
|
||
|
memcpy(&stReconfigParams.reInitEncodeParams, &m_stCreateEncodeParams, sizeof(m_stCreateEncodeParams));
|
||
|
stReconfigParams.version = NV_ENC_RECONFIGURE_PARAMS_VER;
|
||
|
stReconfigParams.forceIDR = pEncPicCommand->bResolutionChangePending ? 1 : 0;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncReconfigureEncoder(m_hEncoder, &stReconfigParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
CNvHWEncoder::CNvHWEncoder()
|
||
|
{
|
||
|
m_hEncoder = NULL;
|
||
|
m_bEncoderInitialized = false;
|
||
|
m_pEncodeAPI = NULL;
|
||
|
m_hinstLib = NULL;
|
||
|
m_EncodeIdx = 0;
|
||
|
m_uCurWidth = 0;
|
||
|
m_uCurHeight = 0;
|
||
|
m_uMaxWidth = 0;
|
||
|
m_uMaxHeight = 0;
|
||
|
|
||
|
memset(&m_stCreateEncodeParams, 0, sizeof(m_stCreateEncodeParams));
|
||
|
SET_VER(m_stCreateEncodeParams, NV_ENC_INITIALIZE_PARAMS);
|
||
|
|
||
|
memset(&m_stEncodeConfig, 0, sizeof(m_stEncodeConfig));
|
||
|
SET_VER(m_stEncodeConfig, NV_ENC_CONFIG);
|
||
|
}
|
||
|
|
||
|
CNvHWEncoder::~CNvHWEncoder()
|
||
|
{
|
||
|
// clean up encode API resources here
|
||
|
if (m_pEncodeAPI)
|
||
|
{
|
||
|
delete m_pEncodeAPI;
|
||
|
m_pEncodeAPI = NULL;
|
||
|
}
|
||
|
|
||
|
if (m_hinstLib)
|
||
|
{
|
||
|
#if defined (NV_WINDOWS)
|
||
|
FreeLibrary(m_hinstLib);
|
||
|
#else
|
||
|
dlclose(m_hinstLib);
|
||
|
#endif
|
||
|
|
||
|
m_hinstLib = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::ValidateEncodeGUID (GUID inputCodecGuid)
|
||
|
{
|
||
|
unsigned int i, codecFound, encodeGUIDCount, encodeGUIDArraySize;
|
||
|
NVENCSTATUS nvStatus;
|
||
|
GUID *encodeGUIDArray;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodeGUIDCount(m_hEncoder, &encodeGUIDCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
encodeGUIDArray = new GUID[encodeGUIDCount];
|
||
|
memset(encodeGUIDArray, 0, sizeof(GUID)* encodeGUIDCount);
|
||
|
|
||
|
encodeGUIDArraySize = 0;
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodeGUIDs(m_hEncoder, encodeGUIDArray, encodeGUIDCount, &encodeGUIDArraySize);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
delete[] encodeGUIDArray;
|
||
|
assert(0);
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
assert(encodeGUIDArraySize <= encodeGUIDCount);
|
||
|
|
||
|
codecFound = 0;
|
||
|
for (i = 0; i < encodeGUIDArraySize; i++)
|
||
|
{
|
||
|
if (inputCodecGuid == encodeGUIDArray[i])
|
||
|
{
|
||
|
codecFound = 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete[] encodeGUIDArray;
|
||
|
|
||
|
if (codecFound)
|
||
|
return NV_ENC_SUCCESS;
|
||
|
else
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::ValidatePresetGUID(GUID inputPresetGuid, GUID inputCodecGuid)
|
||
|
{
|
||
|
uint32_t i, presetFound, presetGUIDCount, presetGUIDArraySize;
|
||
|
NVENCSTATUS nvStatus;
|
||
|
GUID *presetGUIDArray;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodePresetCount(m_hEncoder, inputCodecGuid, &presetGUIDCount);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
presetGUIDArray = new GUID[presetGUIDCount];
|
||
|
memset(presetGUIDArray, 0, sizeof(GUID)* presetGUIDCount);
|
||
|
|
||
|
presetGUIDArraySize = 0;
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodePresetGUIDs(m_hEncoder, inputCodecGuid, presetGUIDArray, presetGUIDCount, &presetGUIDArraySize);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
delete[] presetGUIDArray;
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
assert(presetGUIDArraySize <= presetGUIDCount);
|
||
|
|
||
|
presetFound = 0;
|
||
|
for (i = 0; i < presetGUIDArraySize; i++)
|
||
|
{
|
||
|
if (inputPresetGuid == presetGUIDArray[i])
|
||
|
{
|
||
|
presetFound = 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete[] presetGUIDArray;
|
||
|
|
||
|
if (presetFound)
|
||
|
return NV_ENC_SUCCESS;
|
||
|
else
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::CreateEncoder(const EncodeConfig *pEncCfg)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
if (pEncCfg == NULL)
|
||
|
{
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
|
||
|
m_uCurWidth = pEncCfg->width;
|
||
|
m_uCurHeight = pEncCfg->height;
|
||
|
|
||
|
m_uMaxWidth = (pEncCfg->maxWidth > 0 ? pEncCfg->maxWidth : pEncCfg->width);
|
||
|
m_uMaxHeight = (pEncCfg->maxHeight > 0 ? pEncCfg->maxHeight : pEncCfg->height);
|
||
|
|
||
|
if ((m_uCurWidth > m_uMaxWidth) || (m_uCurHeight > m_uMaxHeight)) {
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
|
||
|
if (!pEncCfg->width || !pEncCfg->height)
|
||
|
{
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
|
||
|
GUID inputCodecGUID = pEncCfg->codec == NV_ENC_H264 ? NV_ENC_CODEC_H264_GUID : NV_ENC_CODEC_HEVC_GUID;
|
||
|
nvStatus = ValidateEncodeGUID(inputCodecGUID);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
PRINTERR("codec not supported \n");
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
codecGUID = inputCodecGUID;
|
||
|
|
||
|
m_stCreateEncodeParams.encodeGUID = inputCodecGUID;
|
||
|
m_stCreateEncodeParams.presetGUID = pEncCfg->presetGUID;
|
||
|
m_stCreateEncodeParams.encodeWidth = pEncCfg->width;
|
||
|
m_stCreateEncodeParams.encodeHeight = pEncCfg->height;
|
||
|
|
||
|
m_stCreateEncodeParams.darWidth = pEncCfg->width;
|
||
|
m_stCreateEncodeParams.darHeight = pEncCfg->height;
|
||
|
m_stCreateEncodeParams.frameRateNum = pEncCfg->fps;
|
||
|
m_stCreateEncodeParams.frameRateDen = 1;
|
||
|
#if defined(NV_WINDOWS)
|
||
|
m_stCreateEncodeParams.enableEncodeAsync = 1;
|
||
|
#else
|
||
|
m_stCreateEncodeParams.enableEncodeAsync = 0;
|
||
|
#endif
|
||
|
m_stCreateEncodeParams.enablePTD = 1;
|
||
|
m_stCreateEncodeParams.reportSliceOffsets = 0;
|
||
|
m_stCreateEncodeParams.enableSubFrameWrite = 0;
|
||
|
m_stCreateEncodeParams.encodeConfig = &m_stEncodeConfig;
|
||
|
m_stCreateEncodeParams.maxEncodeWidth = m_uMaxWidth;
|
||
|
m_stCreateEncodeParams.maxEncodeHeight = m_uMaxHeight;
|
||
|
|
||
|
// apply preset
|
||
|
NV_ENC_PRESET_CONFIG stPresetCfg;
|
||
|
memset(&stPresetCfg, 0, sizeof(NV_ENC_PRESET_CONFIG));
|
||
|
SET_VER(stPresetCfg, NV_ENC_PRESET_CONFIG);
|
||
|
SET_VER(stPresetCfg.presetCfg, NV_ENC_CONFIG);
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncGetEncodePresetConfig(m_hEncoder, m_stCreateEncodeParams.encodeGUID, m_stCreateEncodeParams.presetGUID, &stPresetCfg);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
return nvStatus;
|
||
|
}
|
||
|
memcpy(&m_stEncodeConfig, &stPresetCfg.presetCfg, sizeof(NV_ENC_CONFIG));
|
||
|
|
||
|
m_stEncodeConfig.gopLength = pEncCfg->gopLength;
|
||
|
m_stEncodeConfig.frameIntervalP = pEncCfg->numB + 1;
|
||
|
if (pEncCfg->pictureStruct == NV_ENC_PIC_STRUCT_FRAME)
|
||
|
{
|
||
|
m_stEncodeConfig.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_stEncodeConfig.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
|
||
|
}
|
||
|
|
||
|
m_stEncodeConfig.mvPrecision = NV_ENC_MV_PRECISION_QUARTER_PEL;
|
||
|
|
||
|
if (pEncCfg->bitrate || pEncCfg->vbvMaxBitrate)
|
||
|
{
|
||
|
m_stEncodeConfig.rcParams.rateControlMode = (NV_ENC_PARAMS_RC_MODE)pEncCfg->rcMode;
|
||
|
m_stEncodeConfig.rcParams.averageBitRate = pEncCfg->bitrate;
|
||
|
m_stEncodeConfig.rcParams.maxBitRate = pEncCfg->vbvMaxBitrate;
|
||
|
m_stEncodeConfig.rcParams.vbvBufferSize = pEncCfg->vbvSize;
|
||
|
m_stEncodeConfig.rcParams.vbvInitialDelay = pEncCfg->vbvSize * 9 / 10;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_stEncodeConfig.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
|
||
|
}
|
||
|
|
||
|
if (pEncCfg->rcMode == 0)
|
||
|
{
|
||
|
m_stEncodeConfig.rcParams.constQP.qpInterP = pEncCfg->presetGUID == NV_ENC_PRESET_LOSSLESS_HP_GUID? 0 : pEncCfg->qp;
|
||
|
m_stEncodeConfig.rcParams.constQP.qpInterB = pEncCfg->presetGUID == NV_ENC_PRESET_LOSSLESS_HP_GUID? 0 : pEncCfg->qp;
|
||
|
m_stEncodeConfig.rcParams.constQP.qpIntra = pEncCfg->presetGUID == NV_ENC_PRESET_LOSSLESS_HP_GUID? 0 : pEncCfg->qp;
|
||
|
}
|
||
|
|
||
|
if (pEncCfg->isYuv444)
|
||
|
{
|
||
|
m_stEncodeConfig.encodeCodecConfig.h264Config.chromaFormatIDC = 3;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_stEncodeConfig.encodeCodecConfig.h264Config.chromaFormatIDC = 1;
|
||
|
}
|
||
|
|
||
|
if (pEncCfg->intraRefreshEnableFlag)
|
||
|
{
|
||
|
if (pEncCfg->codec == NV_ENC_HEVC)
|
||
|
{
|
||
|
m_stEncodeConfig.encodeCodecConfig.hevcConfig.enableIntraRefresh = 1;
|
||
|
m_stEncodeConfig.encodeCodecConfig.hevcConfig.intraRefreshPeriod = pEncCfg->intraRefreshPeriod;
|
||
|
m_stEncodeConfig.encodeCodecConfig.hevcConfig.intraRefreshCnt = pEncCfg->intraRefreshDuration;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_stEncodeConfig.encodeCodecConfig.h264Config.enableIntraRefresh = 1;
|
||
|
m_stEncodeConfig.encodeCodecConfig.h264Config.intraRefreshPeriod = pEncCfg->intraRefreshPeriod;
|
||
|
m_stEncodeConfig.encodeCodecConfig.h264Config.intraRefreshCnt = pEncCfg->intraRefreshDuration;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pEncCfg->invalidateRefFramesEnableFlag)
|
||
|
{
|
||
|
if (pEncCfg->codec == NV_ENC_HEVC)
|
||
|
{
|
||
|
m_stEncodeConfig.encodeCodecConfig.hevcConfig.maxNumRefFramesInDPB = 16;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_stEncodeConfig.encodeCodecConfig.h264Config.maxNumRefFrames = 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pEncCfg->qpDeltaMapFile)
|
||
|
{
|
||
|
m_stEncodeConfig.rcParams.enableExtQPDeltaMap = 1;
|
||
|
}
|
||
|
if (pEncCfg->codec == NV_ENC_H264)
|
||
|
{
|
||
|
m_stEncodeConfig.encodeCodecConfig.h264Config.idrPeriod = pEncCfg->gopLength;
|
||
|
}
|
||
|
else if (pEncCfg->codec == NV_ENC_HEVC)
|
||
|
{
|
||
|
m_stEncodeConfig.encodeCodecConfig.hevcConfig.idrPeriod = pEncCfg->gopLength;
|
||
|
}
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncInitializeEncoder(m_hEncoder, &m_stCreateEncodeParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
return nvStatus;
|
||
|
|
||
|
m_bEncoderInitialized = true;
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
GUID CNvHWEncoder::GetPresetGUID(char* encoderPreset, int codec)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
GUID presetGUID = NV_ENC_PRESET_DEFAULT_GUID;
|
||
|
|
||
|
if (encoderPreset && (stricmp(encoderPreset, "hq") == 0))
|
||
|
{
|
||
|
presetGUID = NV_ENC_PRESET_HQ_GUID;
|
||
|
}
|
||
|
else if (encoderPreset && (stricmp(encoderPreset, "lowLatencyHP") == 0))
|
||
|
{
|
||
|
presetGUID = NV_ENC_PRESET_LOW_LATENCY_HP_GUID;
|
||
|
}
|
||
|
else if (encoderPreset && (stricmp(encoderPreset, "hp") == 0))
|
||
|
{
|
||
|
presetGUID = NV_ENC_PRESET_HP_GUID;
|
||
|
}
|
||
|
else if (encoderPreset && (stricmp(encoderPreset, "lowLatencyHQ") == 0))
|
||
|
{
|
||
|
presetGUID = NV_ENC_PRESET_LOW_LATENCY_HQ_GUID;
|
||
|
}
|
||
|
else if (encoderPreset && (stricmp(encoderPreset, "lossless") == 0))
|
||
|
{
|
||
|
presetGUID = NV_ENC_PRESET_LOSSLESS_HP_GUID;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
presetGUID = NV_ENC_PRESET_DEFAULT_GUID;
|
||
|
}
|
||
|
|
||
|
GUID inputCodecGUID = codec == NV_ENC_H264 ? NV_ENC_CODEC_H264_GUID : NV_ENC_CODEC_HEVC_GUID;
|
||
|
nvStatus = ValidatePresetGUID(presetGUID, inputCodecGUID);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
presetGUID = NV_ENC_PRESET_DEFAULT_GUID;
|
||
|
PRINTERR("Unsupported preset guid %s\n", encoderPreset);
|
||
|
}
|
||
|
|
||
|
return presetGUID;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::ProcessOutput(const EncodeBuffer *pEncodeBuffer, DataPacket* dataPacket)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
|
||
|
if (pEncodeBuffer->stOutputBfr.hBitstreamBuffer == NULL && pEncodeBuffer->stOutputBfr.bEOSFlag == FALSE)
|
||
|
{
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
|
||
|
if (pEncodeBuffer->stOutputBfr.bWaitOnEvent == TRUE)
|
||
|
{
|
||
|
if (!pEncodeBuffer->stOutputBfr.hOutputEvent)
|
||
|
{
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
#if defined(NV_WINDOWS)
|
||
|
WaitForSingleObject(pEncodeBuffer->stOutputBfr.hOutputEvent, INFINITE);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if (pEncodeBuffer->stOutputBfr.bEOSFlag)
|
||
|
return NV_ENC_SUCCESS;
|
||
|
|
||
|
nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_LOCK_BITSTREAM lockBitstreamData;
|
||
|
memset(&lockBitstreamData, 0, sizeof(lockBitstreamData));
|
||
|
SET_VER(lockBitstreamData, NV_ENC_LOCK_BITSTREAM);
|
||
|
lockBitstreamData.outputBitstream = pEncodeBuffer->stOutputBfr.hBitstreamBuffer;
|
||
|
lockBitstreamData.doNotWait = false;
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncLockBitstream(m_hEncoder, &lockBitstreamData);
|
||
|
if (nvStatus == NV_ENC_SUCCESS)
|
||
|
{
|
||
|
dataPacket->size = lockBitstreamData.bitstreamSizeInBytes;
|
||
|
memcpy(dataPacket->data, lockBitstreamData.bitstreamBufferPtr, dataPacket->size);
|
||
|
nvStatus = m_pEncodeAPI->nvEncUnlockBitstream(m_hEncoder, pEncodeBuffer->stOutputBfr.hBitstreamBuffer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PRINTERR("lock bitstream function failed \n");
|
||
|
}
|
||
|
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::Initialize(void* device, NV_ENC_DEVICE_TYPE deviceType)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
MYPROC nvEncodeAPICreateInstance; // function pointer to create instance in nvEncodeAPI
|
||
|
|
||
|
#if defined(NV_WINDOWS)
|
||
|
#if defined (_WIN64)
|
||
|
m_hinstLib = LoadLibrary(TEXT("nvEncodeAPI64.dll"));
|
||
|
#else
|
||
|
m_hinstLib = LoadLibrary(TEXT("nvEncodeAPI.dll"));
|
||
|
#endif
|
||
|
#else
|
||
|
m_hinstLib = dlopen("libnvidia-encode.so.1", RTLD_LAZY);
|
||
|
#endif
|
||
|
if (m_hinstLib == NULL)
|
||
|
return NV_ENC_ERR_OUT_OF_MEMORY;
|
||
|
|
||
|
#if defined(NV_WINDOWS)
|
||
|
nvEncodeAPICreateInstance = (MYPROC)GetProcAddress(m_hinstLib, "NvEncodeAPICreateInstance");
|
||
|
#else
|
||
|
nvEncodeAPICreateInstance = (MYPROC)dlsym(m_hinstLib, "NvEncodeAPICreateInstance");
|
||
|
#endif
|
||
|
|
||
|
if (nvEncodeAPICreateInstance == NULL)
|
||
|
return NV_ENC_ERR_OUT_OF_MEMORY;
|
||
|
|
||
|
m_pEncodeAPI = new NV_ENCODE_API_FUNCTION_LIST;
|
||
|
if (m_pEncodeAPI == NULL)
|
||
|
return NV_ENC_ERR_OUT_OF_MEMORY;
|
||
|
|
||
|
memset(m_pEncodeAPI, 0, sizeof(NV_ENCODE_API_FUNCTION_LIST));
|
||
|
m_pEncodeAPI->version = NV_ENCODE_API_FUNCTION_LIST_VER;
|
||
|
nvStatus = nvEncodeAPICreateInstance(m_pEncodeAPI);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
return nvStatus;
|
||
|
|
||
|
nvStatus = NvEncOpenEncodeSessionEx(device, deviceType);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
return nvStatus;
|
||
|
|
||
|
return NV_ENC_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncEncodeFrame(EncodeBuffer *pEncodeBuffer, NvEncPictureCommand *encPicCommand,
|
||
|
uint32_t width, uint32_t height, NV_ENC_PIC_STRUCT ePicStruct,
|
||
|
int8_t *qpDeltaMapArray, uint32_t qpDeltaMapArraySize)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_PIC_PARAMS encPicParams;
|
||
|
|
||
|
memset(&encPicParams, 0, sizeof(encPicParams));
|
||
|
SET_VER(encPicParams, NV_ENC_PIC_PARAMS);
|
||
|
|
||
|
|
||
|
encPicParams.inputBuffer = pEncodeBuffer->stInputBfr.hInputSurface;
|
||
|
encPicParams.bufferFmt = pEncodeBuffer->stInputBfr.bufferFmt;
|
||
|
encPicParams.inputWidth = width;
|
||
|
encPicParams.inputHeight = height;
|
||
|
encPicParams.outputBitstream = pEncodeBuffer->stOutputBfr.hBitstreamBuffer;
|
||
|
encPicParams.completionEvent = pEncodeBuffer->stOutputBfr.hOutputEvent;
|
||
|
encPicParams.inputTimeStamp = m_EncodeIdx;
|
||
|
encPicParams.pictureStruct = ePicStruct;
|
||
|
encPicParams.qpDeltaMap = qpDeltaMapArray;
|
||
|
encPicParams.qpDeltaMapSize = qpDeltaMapArraySize;
|
||
|
|
||
|
|
||
|
if (encPicCommand)
|
||
|
{
|
||
|
if (encPicCommand->bForceIDR)
|
||
|
{
|
||
|
encPicParams.encodePicFlags |= NV_ENC_PIC_FLAG_FORCEIDR;
|
||
|
}
|
||
|
|
||
|
if (encPicCommand->bForceIntraRefresh)
|
||
|
{
|
||
|
if (codecGUID == NV_ENC_CODEC_HEVC_GUID)
|
||
|
{
|
||
|
encPicParams.codecPicParams.hevcPicParams.forceIntraRefreshWithFrameCnt = encPicCommand->intraRefreshDuration;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
encPicParams.codecPicParams.h264PicParams.forceIntraRefreshWithFrameCnt = encPicCommand->intraRefreshDuration;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
nvStatus = m_pEncodeAPI->nvEncEncodePicture(m_hEncoder, &encPicParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS && nvStatus != NV_ENC_ERR_NEED_MORE_INPUT)
|
||
|
{
|
||
|
assert(0);
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
m_EncodeIdx++;
|
||
|
|
||
|
return NV_ENC_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::NvEncFlushEncoderQueue(void *hEOSEvent)
|
||
|
{
|
||
|
NVENCSTATUS nvStatus = NV_ENC_SUCCESS;
|
||
|
NV_ENC_PIC_PARAMS encPicParams;
|
||
|
memset(&encPicParams, 0, sizeof(encPicParams));
|
||
|
SET_VER(encPicParams, NV_ENC_PIC_PARAMS);
|
||
|
encPicParams.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
|
||
|
encPicParams.completionEvent = hEOSEvent;
|
||
|
nvStatus = m_pEncodeAPI->nvEncEncodePicture(m_hEncoder, &encPicParams);
|
||
|
if (nvStatus != NV_ENC_SUCCESS)
|
||
|
{
|
||
|
assert(0);
|
||
|
}
|
||
|
return nvStatus;
|
||
|
}
|
||
|
|
||
|
NVENCSTATUS CNvHWEncoder::ParseArguments(EncodeConfig *encodeConfig, int argc, char *argv[])
|
||
|
{
|
||
|
for (int i = 1; i < argc; i++)
|
||
|
{
|
||
|
if (stricmp(argv[i], "-bmpfilePath") == 0)
|
||
|
{
|
||
|
if (++i >= argc)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
encodeConfig->inputFilePath = argv[i];
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-i") == 0)
|
||
|
{
|
||
|
if (++i >= argc)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
encodeConfig->inputFileName = argv[i];
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-o") == 0)
|
||
|
{
|
||
|
if (++i >= argc)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
encodeConfig->outputFileName = argv[i];
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-size") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->width) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->height) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 2]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-maxSize") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->maxWidth) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->maxHeight) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 2]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-bitrate") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->bitrate) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-vbvMaxBitrate") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->vbvMaxBitrate) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-vbvSize") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->vbvSize) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-fps") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->fps) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-startf") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->startFrameIdx) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-endf") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->endFrameIdx) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-rcmode") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->rcMode) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-goplength") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->gopLength) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-numB") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->numB) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-qp") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->qp) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-preset") == 0)
|
||
|
{
|
||
|
if (++i >= argc)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
encodeConfig->encoderPreset = argv[i];
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-devicetype") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->deviceType) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-codec") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->codec) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-encCmdFile") == 0)
|
||
|
{
|
||
|
if (++i >= argc)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
encodeConfig->encCmdFileName = argv[i];
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-intraRefresh") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->intraRefreshEnableFlag) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-intraRefreshPeriod") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->intraRefreshPeriod) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-intraRefreshDuration") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->intraRefreshDuration) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-picStruct") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->pictureStruct) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-deviceID") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->deviceID) != 1)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-yuv444") == 0)
|
||
|
{
|
||
|
if (++i >= argc || sscanf(argv[i], "%d", &encodeConfig->isYuv444) != 1)
|
||
|
{
|
||
|
fprintf(stderr, "invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-qpDeltaMapFile") == 0)
|
||
|
{
|
||
|
if (++i >= argc)
|
||
|
{
|
||
|
PRINTERR("invalid parameter for %s\n", argv[i - 1]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
encodeConfig->qpDeltaMapFile = argv[i];
|
||
|
}
|
||
|
else if (stricmp(argv[i], "-help") == 0)
|
||
|
{
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PRINTERR("invalid parameter %s\n", argv[i++]);
|
||
|
return NV_ENC_ERR_INVALID_PARAM;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NV_ENC_SUCCESS;
|
||
|
}
|