Я искал простой пример о том, как декодировать поток H264 с аппаратным ускорением, используя ffmpeg в Windows, но я не смог найти ни одного.
Я знаю, что я должен использовать dxva2 с ffmpeg для аппаратного ускорения.
Я могу декодировать H264 с помощью ffmpeg на CPU, затем конвертировать формат NV12 в RGBA и сохранять кадры в виде файлов bmp, благодаря примеру проекта, представленного в сообщение.
Я следовал инструкциям, приведенным в следующем посте, чтобы получить справку о 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?
Задача решена.
Это было связано с неправильным форматом пикселя.
При создании 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 очень неэффективно. Вам следует искать другой способ получения данных из графического процессора.
Других решений пока нет …