Hello,
I am trying to launch your sample AppEncD3D11 from this link: NVIDIA VIDEO CODEC SDK | NVIDIA Developer.
I am running this sample in Windows 10 x64.
I edited the sample to only initialize DXGI and encoder in a loop.
int main(int argc, char** argv)
{
/// The app will try to capture 60 times, by default
int nFrames = 60;
int ret = 0;
bool useNvenc = true;
/// all parsing arguments code
/// Kick off the demo
while (true) {
ret = Grab60FPS(nFrames);
}
return ret;
}
And I commented the code about duplication and colors.
//main.cpp
/// Initialize demo application
HRESULT Init()
{
HRESULT hr = S_OK;
hr = InitDXGI();
returnIfError(hr);
hr = InitEnc();
returnIfError(hr);
return hr;
}
/// Demo 60 FPS (approx.) capture
int Grab60FPS(int nFrames)
{
DemoApplication Demo;
HRESULT hr = S_OK;
/// Initialize Demo app
hr = Demo.Init();
if (FAILED(hr))
{
printf("Initialization failed with error 0x%08x\n", hr);
return -1;
}
Sleep(1000);
return 0;
}
Using drivers like 436.48 or older, everything goes well and the program uses around 165MB of process memory.
The problem is that using the driver 440.97 or newer, there is a huge leak of memory. Around 30MB are leaked for every iteration of the loop.
Did you notice it ? Is there any workaround to release properly all resources and thus avoiding this leak ?
EDIT:
It appears that ānvEncRegisterResourceā function from the NvAPI adds reference on the ID3D11Device which is not released when ānbEncUnregisteredResourceā is called.
// NvEncoderD3D11.cpp
void NvEncoder::RegisterResources(std::vector<void*> inputframes, NV_ENC_INPUT_RESOURCE_TYPE eResourceType,
int width, int height, int pitch, NV_ENC_BUFFER_FORMAT bufferFormat, bool bReferenceFrame)
{
for (uint32_t i = 0; i < inputframes.size(); ++i)
{
NV_ENC_REGISTER_RESOURCE registerResource = { NV_ENC_REGISTER_RESOURCE_VER };
registerResource.resourceType = eResourceType;
registerResource.resourceToRegister = (void *)inputframes[i];
registerResource.width = width;
registerResource.height = height;
registerResource.pitch = pitch;
registerResource.bufferFormat = bufferFormat;
// a reference is added on m_pDevice here
NVENC_API_CALL(m_nvenc.nvEncRegisterResource(m_hEncoder, ®isterResource));
std::vector<uint32_t> _chromaOffsets;
NvEncoder::GetChromaSubPlaneOffsets(bufferFormat, pitch, height, _chromaOffsets);
NvEncInputFrame inputframe = {};
inputframe.inputPtr = (void *)inputframes[i];
inputframe.chromaOffsets[0] = 0;
inputframe.chromaOffsets[1] = 0;
for (uint32_t ch = 0; ch < _chromaOffsets.size(); ch++)
{
inputframe.chromaOffsets[ch] = _chromaOffsets[ch];
}
inputframe.numChromaPlanes = NvEncoder::GetNumChromaPlanes(bufferFormat);
inputframe.pitch = pitch;
inputframe.chromaPitch = NvEncoder::GetChromaPitch(bufferFormat, pitch);
inputframe.bufferFormat = bufferFormat;
inputframe.resourceType = eResourceType;
if (bReferenceFrame)
{
m_vRegisteredResourcesForReference.push_back(registerResource.registeredResource);
m_vReferenceFrames.push_back(inputframe);
}
else
{
m_vRegisteredResources.push_back(registerResource.registeredResource);
m_vInputFrames.push_back(inputframe);
}
}
}
Thank you
Stephen