Problemas de memoria de MF SinkWriter

Intento codificar imágenes de mi escritorio (1920x1080) en un archivo de video usando DXGI Desktop Duplication API y MF Sink Writer. Mi hilo de codificación se ve así:

#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();
}

Las rutinas de inicialización se toman directamente deMuestra de duplicación de escritorio yTutorial de escritor de fregadero. La definición del formato de video también se toma del tutorial de Sink Writer, con cambios en la resolución de cuadros yVIDEO_INPUT_FORMAT = MFVideoFormat_ARGB32.

Sin embargo, después de pasar por este ciclo ~ 20 veces (a veces un poco más, a veces un poco menos), falla en cualquiera de los dosmSinkWriter->WriteSample() omDeskDupl->AcquireNextFrame() con el siguiente mensaje HRESULT:

La aplicación realizó una llamada que no es válida. Los parámetros de la llamada o el estado de algún objeto eran incorrectos. Habilite la capa de depuración D3D para ver detalles a través de mensajes de depuración.

Con la capa de depuración D3D habilitada, veo que mis marcos (supongo que esos objetos son mis marcos) por alguna razón no se liberan y siguen acumulándose:

D3D11 ADVERTENCIA: Objeto vivo en 0x0000006504FFC290, Recuento: 17. [ADVERTENCIA DE CREACIÓN DE ESTADO # 0: DESCONOCIDO]

Estoy bastante seguro de que los errores de HRESULT provienen de que mi GPU se está quedando sin memoria (también se confirma al ver el uso de memoria de GPU a través de la utilidad GPU-Z). Sin embargo, no tengo idea de qué causa esta pérdida de memoria, porque estoy liberando todos los recursos que estoy asignando (Implementación SafeRelease)

EDITAR: Se cambiaron los punteros a punteros inteligentes y se agregó una definición de macro.

Respuestas a la pregunta(0)

Su respuesta a la pregunta