Как использовать DXVA2 с ffmpeg для декодирования и получения кадра
Я искал простой пример о том, как декодировать поток H264 с аппаратным ускорением, используя ffmpeg в Windows, но я не смог найти ни одного. Я знаю, что я должен использовать dxva2 с ffmpeg для аппаратного ускорения.
Я могу декодировать H264 с помощью ffmpeg на CPU, затем конвертировать формат NV12 в RGBA и сохранять кадры в виде файлов bmp, благодаря примеру проекта, приведенному в посте.
Я следовал инструкциям, приведенным в следующем сообщении, чтобы получить справку о dxva2: post
Я верю, что могу успешно декодировать с помощью 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?
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
);
Кроме того, обратите внимание, чтобы разыскивать выводимый кадр следующим образом:
av_frame_unref(pFrameYuv);
В противном случае у вас утечка памяти.
Плюс, как указано в посте, dxva2_retrieve_data_call очень неэффективно. Вам следует искать другой способ получения данных из графического процессора.