经过一些调查,我能够在OS X(VDA)和Linux(VDPAU)上实现必要的硬件加速解码.我也会在掌握Windows实现后更新答案.
Mac OS X
要在Mac OS上实现硬件加速,只需使用以下功能:
Linux VDPAU
在Linux上,事情要复杂得多(谁会感到惊讶呢?)FFmpeg在Linux上有两个硬件加速器:VDPAU(Nvidia)和VAAPI(Intel),只有一个硬件解码器:用于VDPAU.使用上面的Mac OS示例中的vdpau解码器似乎完全合理:
avcodec_find_decoder_by_name("h264_vdpau");
个
你可能会惊讶地发现,它不会改变任何东西,你根本没有加速度.这是因为这只是一个开始,你必须编写更多的代码来加速.幸运的是,你不必自己想出解决方案:至少有两个很好的例子可以说明如何实现这一点:libavg和FFmpeg本身.libavg有一个非常清晰的VDPAUDecoder类,我是基于这个类实现的.您还可以参考ffmpeg_vdpau.c,以获得另一个要比较的实现.不过,在我看来,libavg的实现更容易掌握.
上述两个示例唯一缺少的是将解码帧正确复制到主存储器.这两个示例都使用VdpVideoSurfaceGetBitsYCbCr
,这会毁掉我在机器上获得的所有性能.这就是您可能需要使用以下过程从GPU提取数据的原因:
bool VdpauDecoder::fillFrameWithData(AVCodecContext* context,
AVFrame* frame)
{
VdpauDecoder* vdpauDecoder = static_cast<VdpauDecoder*>(context->opaque);
VdpOutputSurface surface;
vdp_output_surface_create(m_VdpDevice, VDP_RGBA_FORMAT_B8G8R8A8, frame->width, frame->height, &surface);
auto renderState = reinterpret_cast<vdpau_render_state*>(frame->data[0]);
VdpVideoSurface videoSurface = renderState->surface;
auto status = vdp_video_mixer_render(vdpauDecoder->m_VdpMixer,
VDP_INVALID_HANDLE,
nullptr,
VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
0, nullptr,
videoSurface,
0, nullptr,
nullptr,
surface,
nullptr, nullptr, 0, nullptr);
if(status == VDP_STATUS_OK)
{
auto tmframe = av_frame_alloc();
tmframe->format = AV_PIX_FMT_BGRA;
tmframe->width = frame->width;
tmframe->height = frame->height;
if(av_frame_get_buffer(tmframe, 32) >= 0)
{
VdpStatus status = vdp_output_surface_get_bits_native(surface, nullptr,
reinterpret_cast<void * const *>(tmframe->data),
reinterpret_cast<const uint32_t *>(tmframe->linesize));
if(status == VDP_STATUS_OK && av_frame_copy_props(tmframe, frame) == 0)
{
av_frame_unref(frame);
av_frame_move_ref(frame, tmframe);
return;
}
}
av_frame_unref(tmframe);
}
vdp_output_surface_destroy(surface);
return 0;
}
虽然它内部使用了一些"外部"对象,但是一旦实现了"get buffer"部分(前面的示例对此很有帮助),您就应该能够理解它了.另外,我已经使用了更适合我需要的BGRA
格式,也许您会 Select 另一种格式.
所有这些的问题是,您不能仅仅通过FFmpeg让它工作,您至少需要了解VDPAU API的基础知识.我希望我的回答能对某些人在Linux上实现硬件加速有所帮助.我自己花了很多时间在上面,直到我意识到在Linux上没有简单的单行方式实现硬件加速解码.
Linux VA-API
因为我最初的问题是关于VA-API的,所以我不能不回答它.
首先,FFmpeg中没有VA-API的解码器,所以avcodec_find_decoder_by_name("h264_vaapi")
没有任何意义:它是nullptr
.
我不知道有多难(或者可能更简单?)是通过VA-API实现解码,因为我看到的所有示例都非常吓人.因此,我 Select 根本不使用VA-API,并且我必须实现英特尔卡的加速.对我来说足够幸运的是,有一个VDPAU库(驱动程序?)它在VA-API上工作.因此,您可以在英特尔卡上使用VDPAU!
我已经使用下面的link在我的Ubuntu上进行了设置.
此外,您可能希望判断对原始问题的 comments ,其中@TIMOTHY_G还提到了一些关于VA-API的链接.