如何在ffmpeg中使用硬件加速
How to use hardware acceleration with ffmpeg
我需要使用硬件加速让ffmpeg解码我的视频(例如h264)。我使用的是解码帧的常用方法:读取数据包->解码帧。我想让ffmpeg加速解码。所以我用--enable-vaapi
和--enable-hwaccel=h264
构建了它。但我真的不知道下一步该怎么办。我尝试过使用avcodec_find_decoder_by_name("h264_vaapi")
,但它返回nullptr。无论如何,我可能想使用其他API,而不仅仅是VA API。如何加速ffmpeg解码?
第页。S.我在互联网上没有找到任何使用ffmpeg和hwccel的例子。
经过一些研究,我能够在OS X(VDA)和Linux(VDPAU)上实现必要的硬件加速解码。当我拿到Windows实现的时候,我会更新答案。所以让我们从最简单的开始:
Mac OS X
要使硬件加速在Mac操作系统上工作,您只需使用以下操作:avcodec_find_decoder_by_name("h264_vda");
但是,请注意,您只能在带有FFmpeg的Mac操作系统上加速h264视频。
Linux VDPAU
在Linux上,事情要复杂得多(谁会感到惊讶呢?)。FFmpeg在Linux上有两个硬件加速器:VDPAU(Nvidia)和VAAPI(Intel),只有一个硬件解码器:用于VDPAU。而且使用vdpau解码器似乎完全合理,就像上面的Mac OS示例一样:avcodec_find_decoder_by_name("h264_vdpau");
你可能会惊讶地发现,它不会改变任何东西,你根本没有加速度。这是因为这只是一个开始,您必须编写更多的代码才能使加速工作。令人高兴的是,您不必自己想出解决方案:至少有两个很好的例子可以说明如何实现这一点:libavg和FFmpeg本身。libavg有一个VDPAUDoder类,它非常清楚,我的实现就是基于这个类的。你也可以参考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;
}
虽然它内部使用了一些"外部"对象,但一旦实现了"获取缓冲区"部分(前面提到的示例对此有很大帮助),您就应该能够理解它。此外,我使用了BGRA
格式,它更适合我的需求,也许你会选择另一种。
所有这一切的问题在于,你不能让它从FFmpeg工作,你至少需要了解VDPAU API的基本知识。我希望我的答案能帮助人们在Linux上实现硬件加速。在我意识到在Linux上实现硬件加速解码没有简单的单行方法之前,我自己花了很多时间。
Linux VA-API
由于我最初的问题是关于VA-API的,我不能不回答。首先,在FFmpeg中没有用于VA-API的解码器,所以avcodec_find_decoder_by_name("h264_vaapi")
没有任何意义:它是nullptr
。我不知道通过VA-API实现解码有多困难(或者更简单?),因为我看到的所有例子都很吓人。所以我选择根本不使用VA-API,我不得不为英特尔卡实现加速。对我来说足够幸运的是,有一个VDPAU库(驱动程序?)可以在VA-API上工作。因此,您可以在Intel卡上使用VDPAU!
我已经用下面的链接在我的Ubuntu上设置了它。
此外,您可能需要查看对原始问题的评论,其中@Timothy_G还提到了一些关于VA-API的链接。
- 加速C++练习2.4
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- 如果编译的源代码是特定于它编译的硬件的,我们如何分发它
- 使用FFMPEG将RGB图像序列保存到.mp4时出现问题
- FFMPEG配置文件级别id大小无效
- FFMpeg库:如何在音频文件中精确查找
- 找不到以下加速库:boost_fiber
- 玩家加速穿越世界(C++)
- 为什么我的程序在使用预留后没有加速?
- 错误:(-210:不支持的格式或格式组合)功能'create'中的硬件视频解码器不支持视频源
- 为什么 CUDA 不会导致C++代码加速?
- FFmpeg——使用硬件加速进行视频解码
- SDL2硬件加速渲染器在Xubuntu上使用专有驱动程序时会崩溃Linux
- YUV -> RGB 转换可以硬件加速吗?
- sdl软件渲染器不工作,工作在硬件加速的一个
- 硬件加速了 Windows7 中的 MFT 扩展
- 使用 C++ 在窗口中进行硬件加速图像缩放
- 有没有开源的、硬件加速的、带有c++绑定的跨平台物理库?
- 硬件加速在MFC
- 如何在ffmpeg中使用硬件加速