FFMPEG NVIDIA硬件加速总结

目录

1.NVDIA概述

2.FFmpeg集成到GPU

3.FFmpeg uses Video Codec SDK

4.ffmpeg对NVIDIA GPU的编译步骤

 4.1configure命令

4.2 make

4.3 ffmpeg测试

4.4 编解码器使用方法

4.5 程序开发使用方法

5.源码分析

5.1 h264部分

5.2h265部分


1.NVDIA概述

FFmpeg可通过Nvidia的GPU进行加速,其中高层接口是通过Video Codec SDK来实现GPU资源的调用。Video Codec SDK包含完整的的高性能工具、源码及文档,支持,可以运行在Windows和Linux系统之上。从软件上来说,SDK包含两类硬件加速接口,用于编码加速的NVENCODE API和用于解码加速的NVDECODE API(之前被称为NVCUVID API)。从硬件上来说,Nvidia GPU有一到多个编解码器(解码器又称硬件加速引擎),它们独立于CUDA核。从视频格式上来说,编码支持H.264、H.265、无损压缩,位深度支持8bit、10bit,色域空间支持YUV 4:4:4和4:2:0,分辨率支持最高8K;解码支持MPEG-2、VC1、VP8、VP9、H.264、H.265、无损压缩,位深度支持8 bit、10bit、12bit,色域空间支持YUV 4:2:0,分辨率支持最高8K。Video Codec SDK已经被集成在ffmpeg工程中,但是ffmpeg对编解码器配置参数较少,如果需要充分的发挥编解码器特性,还需要直接使用SDK进行编程。

2.FFmpeg集成到GPU

FFmpeg被许多项目使用,包括googlechrome和VLC播放器。通过配置FFmpeg将NVIDIA gpu用于视频编码和解码任务,您可以轻松地将NVIDIA硬件加速集成到这些应用程序中,GPU加速视频处理集成到最流行的开源多媒体工具中。           

视频编码、解码和转码是FFmpeg最流行的应用之一。由于FFmpeg和libav社区的支持以及NVIDIA工程师的贡献,这两个工具现在都支持本机NVIDIA GPU硬件加速的视频编码和解码,通过整合NVIDIA视频编解码器SDK。             

利用FFmpeg的音频编解码器、流muxing和RTP协议,FFmpeg与NVIDIA视频编解码器SDK的集成实现了高性能硬件加速的视频管道。

3.FFmpeg uses Video Codec SDK

FFmpeg支持由NVIDIA GPU上的视频硬件加速的以下功能:             

  • 支持h.264和hevc硬件加速编码; 支持h.264, hevc, VP9, VP8, MPEG2和MPEG4的硬件加速解码;
  • 可设置跟视频编码质量相关的参数,如:preset, rate等;
  • 可使用FFmpeg中的filters进行端对端1:n编码或1:n转码视频硬件加速通道;
  • 能添加自己编写的高性能CUDA filters;
  • 同时支持Windows和Linux support;

 

Nvidia编码器与CPU上的x264的性能对比与质量对比如下图所示,性能以每秒钟编码帧数为参考指标,质量以PSNR为参考指标。

 可看出性能方面Nvidia编码器是x264的2~5倍,质量方面对于fast stream场景来说Nvidia编码器优于x264,高质量场景来说低于x264,但没有说明是哪款Nvidia的产品,以及对比测试的x264运行平台的CPU的型号及平台能力。下图可以看出对于1080P@30fps,NVENC可支持21路的编码或9路的高质量编码。

4.ffmpeg对NVIDIA GPU的编译步骤

  • 下载FFmpeg源码 (https://git.FFmpeg.org/FFmpeg.git) 下载NVIDIA的最新Video Codec SDK 将NVIDIA的头文件复制到ffmpeg的编译环境中;
  • 下载安装NVIDIA驱动(apt install nvidia-375)
  • CUDA工具集
  • 添加如下的configure命令(nv_sdk应包含cuda的库和头文件) 

 4.1configure命令

configure \
  --enable-version3 \
  --enable-libfdk-aac \
  --enable-libmp3lame \
  --enable-libx264 \
  --enable-nvenc \
  --extra-cflags=-I/root/workspace/Video_Codec_SDK_7.1.9/Samples/common/inc \
  --extra-ldflags=-L/root/workspace/Video_Codec_SDK_7.1.9/Samples/common/lib/linux/x86_64 \
  --enable-shared \
  --enable-gpl \
  --enable-postproc \
  --enable-nonfree \
  --enable-avfilter \
  --enable-pthreads

 

4.2 make

运行make & make install

4.3 ffmpeg测试

运行ffmpeg -codecs|grep nvenc
显示一下信息说明

ffmpeg version 3.0.git Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.1) 20160609
  configuration: --enable-version3 --enable-libfdk-aac --enable-libmp3lame --enable-libx264 --enable-nvenc --extra-cflags=-I/workspace/Video_Codec_SDK_7.1.9/Samples/common/inc --extra-ldflags=-L/workspace/Video_Codec_SDK_7.1.9/Samples/common/lib/linux/x86_64 --enable-shared --enable-gpl --enable-postproc --enable-nonfree --enable-avfilter --enable-pthreads
  libavutil      55. 29.100 / 55. 29.100
  libavcodec     57. 54.100 / 57. 54.100
  libavformat    57. 48.100 / 57. 48.100
  libavdevice    57.  0.102 / 57.  0.102
  libavfilter     6. 57.100 /  6. 57.100
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  1.100 /  2.  1.100
  libpostproc    54.  0.100 / 54.  0.100
 DEV.LS h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (encoders: libx264 libx264rgb h264_nvenc nvenc nvenc_h264 )
 DEV.L. hevc                 H.265 / HEVC (High Efficiency Video Coding) (encoders: nvenc_hevc hevc_nvenc )

其中前缀含义如下:
前缀含义
D….. = Decoding supported
.E…. = Encoding supported
..V… = Video codec
..A… = Audio codec
..S… = Subtitle codec
…I.. = Intra frame-only codec
….L. = Lossy compression
…..S = Lossless compression

4.4 编解码器使用方法

h265编码测试
(1). ffmpeg -s 1920x1080 -pix_fmt yuv420p -i BQTerrace_1920x1080_60.yuv -vcodec hevc_nvenc -r 60 -y 2_60.265
(2). ffmpeg -s 1920x1080 -pix_fmt yuv420p -i BQTerrace_1920x1080_60.yuv -vcodec hevc_nvenc -r 30 -y 2_30.265

h264编码测试
(3). ffmpeg -s 1920x1080 -pix_fmt yuv420p -i BQTerrace_1920x1080_60.yuv -vcodec h264_nvenc -r 60 -y 2_60.264
(4). ffmpeg -s 1920x1080 -pix_fmt yuv420p -i BQTerrace_1920x1080_60.yuv -vcodec h264_nvenc -r 30 -y 2_30.264

h264转h265
(5). ffmpeg -i 1_60.264 -vcodec hevc_nvenc -r 60 -y 2_60_264to265.265
(6). ffmpeg -i 1_30.264 -vcodec hevc_nvenc -r 30 -y 2_30_264to265.265

h265转h264
(7). ffmpeg -i 1_60.265 -vcodec h264_nvenc -r 60 -y 2_60_265to264.264
(8). ffmpeg -i 1_30.265 -vcodec h264_nvenc -r 30 -y 2_30_265to264.264

4.5 程序开发使用方法

av_find_encoder_by_name(“h264_nvenc”);
av_find_encoder_by_name(“hevc_nvenc”);

5.源码分析

集成在ffmpeg框架内的视频编解码器需要定义一个AVCodec结构体包含(私有结构体AVClass、三个函数等)

5.1 h264部分

(1). 结构体(nvenc_h264.c)

AVCodec ff_h264_nvenc_encoder = {
    .name           = "h264_nvenc",
    .long_name      = NULL_IF_CONFIG_SMALL("NVIDIA NVENC H.264 encoder"),
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = AV_CODEC_ID_H264,
    .init           = ff_nvenc_encode_init, //初始化函数
    .encode2        = ff_nvenc_encode_frame, //编码函数
    .close          = ff_nvenc_encode_close, //关闭函数
    .priv_data_size = sizeof(NvencContext),  //内部数据结构,见nvenc.h
    .priv_class     = &h264_nvenc_class,     //私有结构体
    .defaults       = defaults,
    .capabilities   = AV_CODEC_CAP_DELAY,
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
    .pix_fmts       = ff_nvenc_pix_fmts,
};

static const AVClass h264_nvenc_class = {
    .class_name = "h264_nvenc",
    .item_name = av_default_item_name,
    .option = options, //编码器选项参数在这个AVOption结构体中
    .version = LIBAVUTIL_VERSION_INT,
};

处理函数(nvenc.c)

av_cold int ff_nvenc_encode_init(AVCodecContext *avctx)
{
   NvencContext *ctx = avctx->priv_data; //读入私有结构体
   ...
   //下面是一些nvenc的api
   nvenc_load_libraries
   nvenc_setup_device
   nvenc_setup_encoder
   nvenc_setup_surfaces
   nvenc_setup_extradata
   ...
}
int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                          const AVFrame *frame, int *got_packet)
{
    ...
    if (frame) {
        inSurf = get_free_frame(ctx); //来一帧
        ...
        res = nvenc_upload_frame(avctx, frame, inSurf);//编一帧
        ...
    }
}
av_cold int ff_nvenc_encode_close(AVCodecContext *avctx)
{
   ...
   //一些free和destroy的工作
}

5.2h265部分

(1). 结构体(nvenc_hevc.c)

AVCodec ff_hevc_nvenc_encoder = {
    .name           = "hevc_nvenc",
    .long_name      = NULL_IF_CONFIG_SMALL("NVIDIA NVENC hevc encoder"),
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = AV_CODEC_ID_HEVC,
    .init           = ff_nvenc_encode_init, //初始化函数
    .encode2        = ff_nvenc_encode_frame, //编码函数
    .close          = ff_nvenc_encode_close, //关闭函数
    .priv_data_size = sizeof(NvencContext),  //内部数据结构,见nvenc.h
    .priv_class     = &hevc_nvenc_class, //私有结构体
    .defaults       = defaults,
    .pix_fmts       = ff_nvenc_pix_fmts,
    .capabilities   = AV_CODEC_CAP_DELAY,
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
};

static const AVClass hevc_nvenc_class = {
    .class_name = "hevc_nvenc",
    .item_name = av_default_item_name,
    .option = options,//编码器选项参数在这个AVOption结构体中
    .version = LIBAVUTIL_VERSION_INT,
};

(2) 处理函数(nvenc.c)
同h264的处理函数

参考文章:

https://www.cnblogs.com/wujianming-110117/p/13235658.html

https://blog.csdn.net/liuhengxiao/article/details/105989820

https://blog.csdn.net/LeoChen1983/article/details/72742656

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值