Является ли Nvidia H.264 Encoder MFT утечка ресурсов?C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Является ли Nvidia H.264 Encoder MFT утечка ресурсов?

Сообщение Anonymous »

Я боролся с утечкой ресурсов, по -видимому, вызванной энкодером NVIDIA H.264 MFT. Каждый раз, когда кадр отправляется в энкодер, подсчет ссылок моего устройства D3D увеличивается на 1, и эта ссылка не отказана даже после выключения MFT. Куча потоков также просочивается. пропущенный. Пожалуйста, смотрите мою реализацию ниже - я старался сохранить ее максимально кратким и ясным. >


Это происходит только с кодером Nvidia. Утечка не наблюдается при работе, например, Intel's QuickSync. < /Li>
< /ul>

Аргументы о том, почему это может быть проблемой в моем коде: < /p>


Я пытался использовать раковина для написания поверхностей DXGI в файл аналогичным образом, и здесь утечки нет. К сожалению, у меня нет доступа к исходному коду CinkWriter. Я был бы очень рад, если бы кто -то мог указать мне на какой -то рабочий пример кода, с которым я мог бы сравнить. < /Li>
< /ul>

#pragma comment(lib, "D3D11.lib")
#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mf.lib")
#pragma comment(lib, "evr.lib")
#pragma comment(lib, "mfuuid.lib")
#pragma comment(lib, "Winmm.lib")

// std
#include
#include

// Windows
#include
#include

// DirectX
#include

// Media Foundation
#include
#include
#include
#include
#include

// Error handling
#define CHECK(x) if (!(x)) { printf("%s(%d) %s was false\n", __FILE__, __LINE__, #x); throw std::exception(); }
#define CHECK_HR(x) { HRESULT hr_ = (x); if (FAILED(hr_)) { printf("%s(%d) %s failed with 0x%x\n", __FILE__, __LINE__, #x, hr_); throw std::exception(); } }

// Constants
constexpr UINT ENCODE_WIDTH = 1920;
constexpr UINT ENCODE_HEIGHT = 1080;
constexpr UINT ENCODE_FRAMES = 120;

void runEncode();

int main()
{
CHECK_HR(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
CHECK_HR(MFStartup(MF_VERSION));

for (;;)
{
runEncode();
if (getchar() == 'q')
break;
}

CHECK_HR(MFShutdown());

return 0;
}

void runEncode()
{
CComPtr device;
CComPtr context;
CComPtr deviceManager;

CComPtr allocator;
CComPtr transform;
CComPtr transformAttrs;
CComQIPtr eventGen;
DWORD inputStreamID;
DWORD outputStreamID;

// ------------------------------------------------------------------------
// Initialize D3D11
// ------------------------------------------------------------------------

CHECK_HR(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT | D3D11_CREATE_DEVICE_DEBUG, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context));

{
// Probably not necessary in this application, but maybe the MFT requires it?
CComQIPtr mt(device);
CHECK(mt);
mt->SetMultithreadProtected(TRUE);
}

// Create device manager
UINT resetToken;
CHECK_HR(MFCreateDXGIDeviceManager(&resetToken, &deviceManager));
CHECK_HR(deviceManager->ResetDevice(device, resetToken));

// ------------------------------------------------------------------------
// Initialize hardware encoder MFT
// ------------------------------------------------------------------------

{
// Find the encoder
CComHeapPtr activateRaw;
UINT32 activateCount = 0;

// Input & output types
MFT_REGISTER_TYPE_INFO inInfo = { MFMediaType_Video, MFVideoFormat_NV12 };
MFT_REGISTER_TYPE_INFO outInfo = { MFMediaType_Video, MFVideoFormat_H264 };

// Query for the adapter LUID to get a matching encoder for the device.
CComQIPtr dxgiDevice(device);
CHECK(dxgiDevice);
CComPtr adapter;
CHECK_HR(dxgiDevice->GetAdapter(&adapter));

DXGI_ADAPTER_DESC adapterDesc;
CHECK_HR(adapter->GetDesc(&adapterDesc));

CComPtr enumAttrs;
CHECK_HR(MFCreateAttributes(&enumAttrs, 1));
CHECK_HR(enumAttrs->SetBlob(MFT_ENUM_ADAPTER_LUID, (BYTE*)&adapterDesc.AdapterLuid, sizeof(LUID)));

CHECK_HR(MFTEnum2(MFT_CATEGORY_VIDEO_ENCODER, MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_SORTANDFILTER, &inInfo, &outInfo, enumAttrs, &activateRaw, &activateCount));

CHECK(activateCount != 0);

// Choose the first returned encoder
CComPtr activate = activateRaw[0];

// Memory management
for (UINT32 i = 0; i < activateCount; i++)
activateRaw->Release();

// Activate
CHECK_HR(activate->ActivateObject(IID_PPV_ARGS(&transform)));

// Get attributes
CHECK_HR(transform->GetAttributes(&transformAttrs));
}

// ------------------------------------------------------------------------
// Query encoder name (not necessary, but nice) and unlock for async use
// ------------------------------------------------------------------------

{

UINT32 nameLength = 0;
std::wstring name;

CHECK_HR(transformAttrs->GetStringLength(MFT_FRIENDLY_NAME_Attribute, &nameLength));

// IMFAttributes::GetString returns a null-terminated wide string
name.resize((size_t)nameLength + 1);
CHECK_HR(transformAttrs->GetString(MFT_FRIENDLY_NAME_Attribute, &name[0], (UINT32)name.size(), &nameLength));
name.resize(nameLength);

printf("Using %ls\n", name.c_str());

// Unlock the transform for async use and get event generator
CHECK_HR(transformAttrs->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE));
CHECK(eventGen = transform);
}

// Get stream IDs (expect 1 input and 1 output stream)
{
HRESULT hr = transform->GetStreamIDs(1, &inputStreamID, 1, &outputStreamID);
if (hr == E_NOTIMPL)
{
inputStreamID = 0;
outputStreamID = 0;
hr = S_OK;
}
CHECK_HR(hr);
}

// ------------------------------------------------------------------------
// Configure hardware encoder MFT
// ------------------------------------------------------------------------

// Set D3D manager
CHECK_HR(transform->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast(deviceManager.p)));

// Set output type
CComPtr outputType;
CHECK_HR(MFCreateMediaType(&outputType));

CHECK_HR(outputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
CHECK_HR(outputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264));
CHECK_HR(outputType->SetUINT32(MF_MT_AVG_BITRATE, 30000000));
CHECK_HR(MFSetAttributeSize(outputType, MF_MT_FRAME_SIZE, ENCODE_WIDTH, ENCODE_HEIGHT));
CHECK_HR(MFSetAttributeRatio(outputType, MF_MT_FRAME_RATE, 60, 1));
CHECK_HR(outputType->SetUINT32(MF_MT_INTERLACE_MODE, 2));
CHECK_HR(outputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE));

CHECK_HR(transform->SetOutputType(outputStreamID, outputType, 0));

// Set input type
CComPtr inputType;
CHECK_HR(transform->GetInputAvailableType(inputStreamID, 0, &inputType));

CHECK_HR(inputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
CHECK_HR(inputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12));
CHECK_HR(MFSetAttributeSize(inputType, MF_MT_FRAME_SIZE, ENCODE_WIDTH, ENCODE_HEIGHT));
CHECK_HR(MFSetAttributeRatio(inputType, MF_MT_FRAME_RATE, 60, 1));

CHECK_HR(transform->SetInputType(inputStreamID, inputType, 0));

// ------------------------------------------------------------------------
// Create sample allocator
// ------------------------------------------------------------------------

{
MFCreateVideoSampleAllocatorEx(IID_PPV_ARGS(&allocator));
CHECK(allocator);

CComPtr allocAttrs;
MFCreateAttributes(&allocAttrs, 2);

CHECK_HR(allocAttrs->SetUINT32(MF_SA_D3D11_BINDFLAGS, D3D11_BIND_RENDER_TARGET));
CHECK_HR(allocAttrs->SetUINT32(MF_SA_D3D11_USAGE, D3D11_USAGE_DEFAULT));

CHECK_HR(allocator->SetDirectXManager(deviceManager));
CHECK_HR(allocator->InitializeSampleAllocatorEx(1, 2, allocAttrs, inputType));
}

// ------------------------------------------------------------------------
// Start encoding
// ------------------------------------------------------------------------

CHECK_HR(transform->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, NULL));
CHECK_HR(transform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL));
CHECK_HR(transform->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, NULL));

// Encode loop
for (int i = 0; i < ENCODE_FRAMES; i++)
{
// Get next event
CComPtr event;
CHECK_HR(eventGen->GetEvent(0, &event));

MediaEventType eventType;
CHECK_HR(event->GetType(&eventType));

switch (eventType)
{
case METransformNeedInput:
{
CComPtr sample;
CHECK_HR(allocator->AllocateSample(&sample));
CHECK_HR(transform->ProcessInput(inputStreamID, sample, 0));

// Dereferencing the device once after feeding each frame "fixes" the leak.
//device.p->Release();

break;
}

case METransformHaveOutput:
{
DWORD status;
MFT_OUTPUT_DATA_BUFFER outputBuffer = {};
outputBuffer.dwStreamID = outputStreamID;

CHECK_HR(transform->ProcessOutput(0, 1, &outputBuffer, &status));

DWORD bufCount;
DWORD bufLength;
CHECK_HR(outputBuffer.pSample->GetBufferCount(&bufCount));

CComPtr outBuffer;
CHECK_HR(outputBuffer.pSample->GetBufferByIndex(0, &outBuffer));
CHECK_HR(outBuffer->GetCurrentLength(&bufLength));

printf("METransformHaveOutput buffers=%d, bytes=%d\n", bufCount, bufLength);

// Release the sample as it is not processed further.
if (outputBuffer.pSample)
outputBuffer.pSample->Release();
if (outputBuffer.pEvents)
outputBuffer.pEvents->Release();
break;
}
}
}

// ------------------------------------------------------------------------
// Finish encoding
// ------------------------------------------------------------------------

CHECK_HR(transform->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, NULL));
CHECK_HR(transform->ProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, NULL));
CHECK_HR(transform->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, NULL));

// Shutdown
printf("Finished encoding\n");

// I've tried all kinds of things...
//CHECK_HR(transform->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast(nullptr)));

//transform->SetInputType(inputStreamID, NULL, 0);
//transform->SetOutputType(outputStreamID, NULL, 0);

//transform->DeleteInputStream(inputStreamID);

//deviceManager->ResetDevice(NULL, resetToken);

CHECK_HR(MFShutdownObject(transform));
}


Подробнее здесь: https://stackoverflow.com/questions/619 ... -resources
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Имя процесса MFT [закрыто]
    Anonymous » » в форуме Linux
    0 Ответы
    35 Просмотры
    Последнее сообщение Anonymous
  • MFT Recodr без данных $
    Anonymous » » в форуме C++
    0 Ответы
    3 Просмотры
    Последнее сообщение Anonymous
  • Как проанализировать запись MFT без данных?
    Anonymous » » в форуме C++
    0 Ответы
    5 Просмотры
    Последнее сообщение Anonymous
  • Утечка активности AutofillClientController: утечка системы или это моя реализация?
    Anonymous » » в форуме Android
    0 Ответы
    72 Просмотры
    Последнее сообщение Anonymous
  • Утечка ресурсов при использовании ExoPlayer с SimpleCache
    Anonymous » » в форуме Android
    0 Ответы
    21 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C++»