Как использовать DXVA2 с ffmpeg для декодирования и получения кадра

Я искал простой пример того, как декодировать поток H264 с аппаратным ускорением с помощью ffmpeg в Windows, но я не смог его найти. Я знаю, что мне следует использовать dxva2 с ffmpeg для аппаратного ускорения.

Я могу декодировать H264 с помощью ffmpeg на ЦП, затем конвертировать формат NV12 в RGBA и сохранять кадры в виде файлов bmp, благодаря примерному проекту, представленному в опубликовать.

Я следил за тем, что представлено в следующем сообщении, чтобы получить справку о dxva2: -with-dxva2">опубликовать

Я считаю, что могу успешно декодировать с помощью dxva2; однако, когда я хочу получить декодированный кадр, преобразовать его в формат RGBA и сохранить в виде файла bmp, я получаю сообщение об ошибке об указателях источника.

Я декодирую и получаю кадр следующим образом:

int videoFrameBytes = avcodec_decode_video2(pCodecCtx_hwaccel, pFrameYuv, &got_picture_ptr, avpkt);

if (got_picture_ptr==1)
{
    if(dxva2_retrieve_data_call(pCodecCtx_hwaccel, pFrameYuv) == 0)
    {
        fprintf(stderr, "Got frame successfully\n");
        result = true;
    }
}

и подайте выходной кадр на:

sws_scale(pImgConvertCtx, pFrameYuv->data, pFrameYuv->linesize, 0, height, frame->data, frame->linesize);  

Я получаю эту ошибку:

[swscaler @ 030c5c20] неправильные указатели изображений src

Очевидно, что-то не так с pFrameYuv->data, но я не знаю что.

Как мы можем преобразовать кадр NV12, декодированный с помощью DXVA2, в RGBA с помощью sws_scale?


person bellekci    schedule 22.06.2016    source источник


Ответы (1)


Проблема решена.

Это произошло из-за неправильного типа формата пикселей. При создании sws_context я использовал пиксельный формат контекста кодека, как показано ниже: (Что было нормально для декодирования SW)

// initialize SWS context for software scaling
sws_ctx = sws_getContext(pCodecCtx->width,
    pCodecCtx->height,
    pCodecCtx->pix_fmt,
    pCodecCtx->width,
    pCodecCtx->height,
    AV_PIX_FMT_RGB24,
    SWS_BILINEAR,
    NULL,
    NULL,
    NULL
    );

А pCodecCtx->pix_fmt был AV_PIX_FMT_YUV420P, но формат декодированного кадра — AV_PIX_FMT_NV12 с DXVA2. После установки правильного формата я мог использовать sws_scale для преобразования кадра NV12 в RGB.

Правильные параметры:

// initialize SWS context for software scaling
sws_ctx = sws_getContext(pCodecCtx->width,
    pCodecCtx->height,
    AV_PIX_FMT_NV12,
    pCodecCtx->width,
    pCodecCtx->height,
    AV_PIX_FMT_RGB24,
    SWS_BILINEAR,
    NULL,
    NULL,
    NULL
    );

Кроме того, обратите внимание на unref извлеченного выходного кадра следующим образом:

av_frame_unref(pFrameYuv);

В противном случае у вас есть утечка памяти.

Кроме того, как указано в post , dxva2_retrieve_data_call очень неэффективен. Вы должны искать другой способ получить данные от GPU.

person bellekci    schedule 23.06.2016