Визуализировать IDirect3DSurface9 из DXVA2? - PullRequest
0 голосов
/ 13 января 2019

Я получил IDirect3DSurface9 от DXVA2 видеодекодера с аппаратным ускорением.

Я пытаюсь визуализировать это оборудование IDirect3DSurface9 в Моем окне через его дескриптор. Ниже приведен мой сводный код.

Первым я звоню dxva2_init(AVCodecContext *s, HWND hwnd); с hwnd дескриптор окна

int dxva2_init(AVCodecContext *s, HWND hwnd)
{
    InputStream *ist = (InputStream *)s->opaque;
    int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
    DXVA2Context *ctx;
    int ret;

    if (!ist->hwaccel_ctx) {
        ret = dxva2_alloc(s);
        if (ret < 0)
            return ret;
    }
    ctx = (DXVA2Context *)ist->hwaccel_ctx;
    ctx->deviceHandle = hwnd;
    if (s->codec_id == AV_CODEC_ID_H264 &&
        (s->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) {
        av_log(NULL, loglevel, "Unsupported H.264 profile for DXVA2 HWAccel: %d\n", s->profile);
        return AVERROR(EINVAL);
    }

    if (ctx->decoder)
        dxva2_destroy_decoder(s);

    ret = dxva2_create_decoder(s);
    if (ret < 0) {
        av_log(NULL, loglevel, "Error creating the DXVA2 decoder\n");
        return ret;
    }

    return 0;
}

После успешного декодирования я получил IDirect3DSurface9, и я рендерил его с помощью следующей функции.

 int dxva2_render(AVCodecContext *s, AVFrame *frame)
{
    LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)frame->data[3];
    InputStream        *ist = (InputStream *)s->opaque;
    DXVA2Context       *ctx = (DXVA2Context *)ist->hwaccel_ctx;

    try
    {
        lockRenderCS.Enter();
        HRESULT hr = ctx->d3d9device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 0);
        if (hr != D3D_OK)
            return 0;

        hr = ctx->d3d9device->BeginScene();
        if (hr != D3D_OK)
            return 0;

        hr = ctx->d3d9device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
        if (hr != D3D_OK)
            return 0;

        hr = ctx->d3d9device->StretchRect(surface, NULL, pBackBuffer, NULL, D3DTEXF_LINEAR);
        if (hr != D3D_OK)
            return 0;

        hr = ctx->d3d9device->EndScene();
        if (hr != D3D_OK)
            return 0;

        hr = ctx->d3d9device->Present(NULL, NULL, NULL, NULL);
        if (hr != D3D_OK)
            return 0;
    }
    finally
    {
        lockRenderCS.Leave();
    }
    return 0;
}

Примечание: все функции D3D выше: Clear(), BeginScene(), GetBackBuffer(), StretchRect(), EndScene(), Present() были возвращены успешно. Но кадр не отображался в Моем окне.

Думаю, мне не хватает некоторого кода для интегрированного дескриптора My Window с DXVA2Context. В этом коде я назначаю только: ctx->deviceHandle = hwnd; в функции dxva2_init().

Я ищу много раз, но до сих пор не могу найти решение, Кто-нибудь может мне помочь?

Большое спасибо!

1 Ответ

0 голосов
/ 18 января 2019

Я мог бы помочь с полным кодом.

Без полного кода я предлагаю вам проверить использование StretchRect, вот так:

IDirect3DDevice9 :: StretchRect

Ограничения StretchRect

  • Поддержка драйверов может быть разной. См. Раздел о поддержке драйверов (ниже), чтобы узнать, какие драйверы поддерживают какие форматы источника и назначения.
  • Исходная и целевая поверхности должны быть созданы в пуле памяти по умолчанию.
  • Если указана фильтрация, необходимо установить соответствующие крышки фильтра (см. StretchRectFilterCaps в D3DCAPS9).
  • и т.д ...

Идея этого заключается в том, что мы ничего не знаем о вашем d3d9device / surface9 (создание / инициализация / параметр / etc ...), например.

Также вы можете изучить этот код из моего проекта для декодирования dxva2:

H264Dxva2Decoder

...