ixS*_*Sci 43 c c++ ffmpeg hardware-acceleration
我需要使用硬件加速来ffmpeg解码我的视频(例如h264).我正在使用解码帧的常用方法:读取数据包 - >解码帧.而且我想让ffmpeg加速解码.所以,我有内置它--enable-vaapi
和--enable-hwaccel=h264
.但我真的不知道接下来该怎么做.我试过使用avcodec_find_decoder_by_name("h264_vaapi")
但它返回nullptr.无论如何,我可能想要使用其他API而不仅仅是VA API.如何加速ffmpeg解码?
PS我没有在互联网上找到任何使用ffmpeg和hwaccel的例子.
ixS*_*Sci 41
经过一番调查后,我能够在OS X(VDA)和Linux(VDPAU)上实现必要的硬件加速解码.当我接触到Windows实现时,我将更新答案.所以让我们从最简单的开始:
要在Mac OS上使用硬件加速,您应该使用以下内容:
avcodec_find_decoder_by_name("h264_vda");
请注意,您只能在带有FFmpeg的Mac OS上加速h264视频.
在Linux上,事情要复杂得多(谁感到惊讶?).FFmpeg在Linux上有2个HW加速器:VDPAU(Nvidia)和VAAPI(Intel),只有一个HW解码器:用于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;
}
Run Code Online (Sandbox Code Playgroud)
虽然它内部使用了一些"外部"对象,但是一旦实现了"get buffer"部分(上述示例对其有很大帮助),您应该能够理解它.我也使用了BGRA
更适合我需要的格式,也许你会选择另一种格式.
所有这一切的问题在于,你不能只从FFmpeg开始工作,至少需要了解VDPAU API的基础知识.我希望我的回答可以帮助某人在Linux上实现硬件加速.在我意识到在Linux上没有简单的单行方式实现硬件加速解码之前,我自己花了很多时间.
由于我最初的问题是关于VA-API,我不能不给它答案.首先,在FFmpeg avcodec_find_decoder_by_name("h264_vaapi")
中没有VA-API的解码器所以没有任何意义:它是nullptr
.我不知道通过VA-API实现解码有多难(或者更简单?),因为我看到的所有例子都非常令人生畏.所以我选择不使用VA-API,我必须实现英特尔卡的加速.幸运的是,有一个VDPAU库(驱动程序?)可以在VA-API上运行.所以你可以在英特尔卡上使用VDPAU!
我已经使用以下链接在我的Ubuntu上设置它.
此外,您可能想查看原始问题的评论,其中@Timothy_G还提到了一些关于VA-API的链接.
归档时间: |
|
查看次数: |
51532 次 |
最近记录: |