MF SinkWriter проблемы с памятью

Я пытаюсь закодировать изображения моего рабочего стола (1920×1080) в видеофайл, используя DXGI Desktop Duplication API и MF Sink Writer. Мой поток кодирования выглядит так:

#define RETURN_ON_BAD_HR(expr) \
{ \
HRESULT _hr_ = (expr); \
if (FAILED(_hr_)) { \
qDebug() << "Error encountered with message from HRESULT: " << \
getMessageFromHR(_hr_); \
MFShutdown(); \
CoUninitialize(); \
return; \
} \
}

void DuplicationThread::run() {
if (CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) != S_OK) {
qDebug() << "Failed to initialize COM.";
return;
}

if (MFStartup(MF_VERSION) != S_OK) {
qDebug() << "Failed to initialize Media Foundation.";
CoUninitialize();
return;
}

CComPtr<ID3D11Device> pDevice;
RETURN_ON_BAD_HR(InitializeDx(&pDevice));

CComPtr<IDXGIOutputDuplication> pDeskDupl;
RETURN_ON_BAD_HR(InitiateDupl(pDevice, &pDeskDupl));

CComPtr<IMFSinkWriter> pSinkWriter;
DWORD streamIndex;
RETURN_ON_BAD_HR(InitSinkWriter(&pSinkWriter, &streamIndex));

LONGLONG rtStart = 0;

while (!isInterruptionRequested()) {
DXGI_OUTDUPL_FRAME_INFO frameInfo;
CComPtr<IDXGIResource> pDesktopResource;
RETURN_ON_BAD_HR(pDeskDupl->AcquireNextFrame(500, &frameInfo, &pDesktopResource));

CComPtr<ID3D11Texture2D> pAcquiredDesktopImage;
RETURN_ON_BAD_HR(pDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&pAcquiredDesktopImage)));

CComPtr<IMFMediaBuffer> pMediaBuffer;
RETURN_ON_BAD_HR(MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), pAcquiredDesktopImage, 0, FALSE, &pMediaBuffer));

CComPtr<IMF2DBuffer> p2DBuffer;
DWORD length;
RETURN_ON_BAD_HR(pMediaBuffer->QueryInterface(__uuidof(IMF2DBuffer), reinterpret_cast<void **>(&p2DBuffer)));
RETURN_ON_BAD_HR(p2DBuffer->GetContiguousLength(&length));
RETURN_ON_BAD_HR(pMediaBuffer->SetCurrentLength(length));

CComPtr<IMFSample> pSample;
RETURN_ON_BAD_HR(MFCreateVideoSampleFromSurface(NULL, &pSample));
RETURN_ON_BAD_HR(pSample->AddBuffer(pMediaBuffer));
RETURN_ON_BAD_HR(pSample->SetSampleTime(rtStart));
RETURN_ON_BAD_HR(pSample->SetSampleDuration(VIDEO_FRAME_DURATION));

RETURN_ON_BAD_HR(pSinkWriter->WriteSample(streamIndex, pSample));
RETURN_ON_BAD_HR(pDeskDupl->ReleaseFrame());
rtStart += VIDEO_FRAME_DURATION;

// successful iterations
static int count = 0;
qDebug() << "count: " << count++;
}

RETURN_ON_BAD_HR(pSinkWriter->Finalize());

MFShutdown();
CoUninitialize();
}

Процедуры инициализации взяты непосредственно из Образец дублирования рабочего стола а также Учебник по Раковине. Определение формата видео также взято из руководства Sink Writer с изменениями разрешения кадра и VIDEO_INPUT_FORMAT = MFVideoFormat_ARGB32,

Однако, после прохождения этого цикла ~ 20 раз (иногда немного больше, иногда немного меньше), он терпит неудачу либо mSinkWriter->WriteSample() или же mDeskDupl->AcquireNextFrame() со следующим сообщением HRESULT:

Приложение совершило звонок, который является недействительным. Либо параметры вызова, либо состояние какого-либо объекта было неверным. Включите уровень отладки D3D, чтобы увидеть детали в сообщениях отладки.

С включенным отладочным слоем D3D я вижу, что мои кадры (я полагаю, эти объекты являются моими кадрами) по какой-то причине не освобождаются и просто продолжают копить:

D3D11 ПРЕДУПРЕЖДЕНИЕ: живой объект по адресу 0x0000006504FFC290, счетчик рефинансирования: 17. [STATE_CREATION WARNING # 0: UNKNOWN]

Я совершенно уверен, что сбои HRESULT происходят из-за того, что у моего GPU не хватает памяти (это также подтверждается наблюдением за использованием памяти GPU через утилиту GPU-Z). Тем не менее, я понятия не имею, что вызывает эту утечку памяти, потому что я освобождаю каждый ресурс, который я выделяю (Реализация SafeRelease).

РЕДАКТИРОВАТЬ: Изменены указатели на интеллектуальные указатели и добавлено определение макросов.

3

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector