文章目录

  • Javacv实现QSV硬件解码
    • 一、前景知识
      • 认识javacv
      • javacv_ffmpeg maven依赖
    • 二、前期关于javacv 实现硬件加速的调查
    • 三、Javacv实战
    • 四、Javacv 硬件加速效果

Javacv实现QSV硬件解码

注:笔者服务器系统为Ubuntu 22.04 linux-x86_64,其他操作系统或许可参考于该博客,但笔者也没有完全试过

一、前景知识

在笔者之前的专栏博客中,已经完成ubuntu系统中编译安装ffmpeg集成qsv,实现硬件加速解码;实际应用过程中,使用javacv进行推流、解码、抽帧等,若要将硬件加速落地于javacv实处,需要做些什么工作呢

认识javacv

注:笔者这里只讨论javacv 调用ffmpeg

  • JavaCV是一个基于Java语言的开源计算机视觉库,它是通过调用底层的计算机视觉库实现图形图像处理和计算机视觉任务的。
  • JavaCV依赖于JavaCPP,JavaCPP是一个用于与本地C++代码交互的Java库,它通过生成JNI代码来实现Java与C++之间的相互调用。而FFmpeg是一组开源的音视频处理工具集,JavaCV使用了FFmpeg作为底层的视频处理库。
  • JavaCV的视频处理能力主要来自FFmpeg,而JavaCPP则提供了本地代码与Java代码之间的桥梁。
  • 通过上述描述 可以理解为一个调用的层级关系:javacv -> javacpp -> ffmpeg
  • 表现在pom文件上的jar包组成:
    • javacpp-platformjavacv为调用javacpp所产生的文件
    • ffmpeg-platform相关jar包 是不同平台下编译ffmpeg后产生的库依赖文件,如linux系统是so文件;
    • ffmpeg.jar:提供对FFmpeg命令行工具的包装,使用户可以在Java应用程序中执行FFmpeg命令以读取、处理和写入音视频文件;是 javacpp编译出来调用ffmpeg的jni

javacv_ffmpeg maven依赖

以往如果只是调用javacv,最省流的依赖导入方式

        <!-- javacv 多平台 --><dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.7</version></dependency>

实际你会发现很多依赖jar包是不需要用到的,那么精确于ffmpeg的依赖,有什么不需要导入多余依赖的方式呢
结合上述javacv认知的描述,依赖可以简化为以下图片所框选部分的依赖 + javacpp-你的操作系统:1.5.7 + ffmpeg.jar + ffmpeg-你的操作系统.jar包

那么回归正题,要在javacv 实现硬件加速需要注重的是哪些jar包呢:

答案:ffmpeg.jar ffmpeg-你的操作系统.jar包

二、前期关于javacv 实现硬件加速的调查

  • 实际上现有可以依赖引入的ffmpeg已经支持Intel QSV ,但仅限于windows 、linux-x86 and linux-x86_64 ;参考github Issue ffmpeg支持qsv的说明
  • java代码上实现硬件加速,参考Github Issue 使用硬件加速相关解码器的方法
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(your video file);
frameGrabber.setVideoCodecName("h264_qsv");
frameGrabber.setOption("hwaccel","qsv");
frameGrabber.setOption("hwaccel_output_format","qsv");

笔者认为以上设置相当于ffmpeg 命令行形式

ffmpeg -hwaccel qsv -hwaccel_output_format qsv -c:v h264_qsv -i 10min39.mp4 -f null

三、Javacv实战

基于前期调查,笔者一顿操作猛如虎,完成以下操作:

  • 安装 vaapi、intel media driver 等相关依赖
  • 直接引入javacv:5.0-1.5.7 现有依赖,简单的编写以下代码,打包了一个demo jar包,在服务器上运行
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(dir);
frameGrabber.setVideoCodecName("h264_qsv");
frameGrabber.setOption("hwaccel","qsv");
frameGrabber.setOption("hwaccel_output_format","qsv");
frameGrabber.start();
Frame f = frameGrabber.grab();
while (frameGrabber.grab() != null){}
frameGrabber.close();

运行结果如截图所示:现有ffmpeg依赖内置的VAAPI版本太低,无法使用系统安装的基于1.0 VAAPI版本的驱动程序,在Github Issue中也发现了与笔者遇到相同问题的人,ffmpeg官网作者说法是在 javacpp-presets下自行编译安装ffmpeg javacpp-presets

由此,笔者开始了漫长的自行编译之路,终于完成了ffmpeg的编译并mvn为jar包,成功实现javacv硬件解码。

可归纳为以下步骤:

  • 下载libva、git 、intel 驱动程序等相关依赖
apt-get install -y  git vim
bzip2 xz-utils # 解压缩包使用
build-essential gcc cmake autoconf automake libtool pkg-config libdrm-dev # 编译使用
libmfx1 libmfx-tools libva-dev libmfx-dev vainfo  intel-media-va-driver-non-free# vaapi + driverexport LIBVA_DRIVER_NAME=iHD
  • 下载intel media sdk
git clone https://github.com/Intel-Media-SDK/MediaSDK msdk
  • javacpp-preset下重新编译ffmpeg
    注:笔者基于ffmpeg5.0版本进行重新构建
git clone https://github.com/bytedeco/javacpp-presets.git
cd javacpp-presets
git checkout 1.5.7vim ffmpeg/cppbuild.sh
#5.0版本的zlib是1.2.11 修改为1.2.13
ffmpeg 编译配置对头文件的路径增加一个 -I../include/mfx获取到libmfx库的头文件路径
# 删除mfx_dispatch的部分
注释掉mfx_dispatch 参照于ffmpeg_cppbuild.sh 否则会出现Error setting child device handle -17
# 具体还未找到原因#清除原先编译的依赖
./cppbuild.sh -platform linux-x86_64 clean
#编译安装
./cppbuild.sh -platform linux-x86_64 install ffmpeg
  • 对安装目录下的ffmpeg进行qsv命令执行
# 笔者这里使用基于javacpp-presets目录下的相对路径
./ffmpeg/cppbuild/linux-x86_64/ffmpeg-5.0/ffmpeg -hwaccel qsv -hwaccel_output_format qsv -c:v h264_qsv -i 10min39.mp4 -f null - -benchmark
# 若出现对应错误:找不到某个so文件
sudo vim /etc/ld.so.conf
#添加安装库依赖路径到文件末尾
# INSTALL_PATH你的安装目录, 相对于javacpp-presets的位置是./ffmpeg/cppbuild/linux-x86_64/$INSTALL_PATH/lib
#刷新
sudo /sbin/ldconfig -v
sudo ldconfig
  • 如果编译安装ffmpeg之后,使用ffmpeg命令行形式能够实现硬件加速,那么就可以直接进行mvn 打包
  • 替换ffmpeg-version .jar & ffmpeg- platform-version.jar包依赖

四、Javacv 硬件加速效果

// 命令行形式String ffmpeg = Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);StopWatch stopWatch2 = new StopWatch();ProcessBuilder pb = new ProcessBuilder(ffmpeg, "-hwaccel","qsv","-hwaccel_output_format", "qsv","-c:v", "h264_qsv", "-i", dir, "-f", "null", "-", "-benchmark");stopWatch2.start();pb.inheritIO().start().waitFor();stopWatch2.stop();System.out.println(" qsv command way =======" + stopWatch2.getTotalTimeSeconds());// javacv API形式FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(dir);frameGrabber.setVideoCodecName("h264_qsv");frameGrabber.setOption("hwaccel","qsv");frameGrabber.setOption("hwaccel_output_format","qsv");StopWatch stopWatch = new StopWatch();stopWatch.start();frameGrabber.start();System.out.println("帧数:" + frameGrabber.getLengthInVideoFrames());Frame f =frameGrabber.grab();while (f != null){f = frameGrabber.grab();}stopWatch.stop();frameGrabber.stop();System.out.println(" qsv =======" + stopWatch.getTotalTimeSeconds());
  • 运行结果:
    发现javacv API 方式耗时竟然是命令行形式的三倍,经过debug发现javacv调用ffmpeg所设置的默认像素格式是bgr24,而ffmpeg本身默认的像素格式是yuv420p
    设置frameGrabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); 即可
    当然具体像素格式还取决于具体你所应用的场景

到此本文结束,欢迎大家纠错及分享ffmpeg重构建出现子设备句柄设置失败的原因。

Javacv实现QSV硬件解码相关推荐

  1. FFMPEG 硬件解码API介绍

    https://zhuanlan.zhihu.com/p/168240163 软解和硬解的区别: 一般来说我们把使用CPU通用计算单元(无论是Intel还是AMD)就是软解:用专用芯片模组(GPU.Q ...

  2. 全平台硬件解码渲染方法与优化实践

    硬件解码后不恰当地使用OpenGL渲染会导致性能下降,甚至不如软解.本文来自PPTV移动端研发经理王斌在LiveVideoStackCon 2017大会上的分享,并由LiveVideoStack整理而 ...

  3. WebRTC-集成qsv硬解码实现

    1.Window下QSV硬解码配置 在libavcodec/codec_list.c下添加 &ff_h264_qsv_decoder, 在ffmpeg_generate.gni下加入 &quo ...

  4. IOS硬件解码VTDecompressionSession失效

    原文:http://blog.5ibc.net/p/33817.html 编码.解码失效都可以restart一下. IOS硬件解码VideoToolbox在应用中进入后台VTDecompression ...

  5. RIoTBoard开发板系列笔记(四)—— 使用VPU硬件解码

    视频解码分为软解和硬解两种,简单的来说纯粹依靠CPU来解码的称为软解,而使用GPU/VPU解码的称为硬解.常规地直接用CPU解码会极大地消耗CPU的运算能力,硬件解码是通过显卡的视频加速功能对高清视频 ...

  6. RIoTBoard开发板系列笔记(十二)—— gstreamer + vpu实现视频硬件解码播放

    i.mx6 solo芯片中包含一个VPU (video processing unit),可以进行视频硬件编解码加速,之前RIoTBoard开发板系列笔记(四)-- 使用VPU硬件解码文章简单的记录了 ...

  7. rk3588 ffmpeg使用硬件解码

    rk3588 ffmpeg使用硬件解码 安装ffmpeg最新的静态构建版本 方法1 安装rkmpp 安装264 安装libdrm 下载ffmpeg源码 方法2 ppa搜索需要的软件包 安装支持rkmp ...

  8. Mediacodec 如何硬件解码到纹理的

    Mediacodec 如何硬件解码到纹理的 背景: 网上很多关于mediacodec,surface ,surfacetexture的源码分析,以及内部原理,但是都局限于各自的内容,今天我们就从med ...

  9. AIR 3实现iOS下对H.264视频硬件解码

    本帖最后由 nextria 于 2011-10-9 11:27 编辑 在此之前,AIR开发的应用程序在iOS下是不可能实现对H.264视频硬解码的, 也许是以一个多比特率的方式传送. 我知道,是吧? ...

最新文章

  1. 近20个绚丽实用的jQuery/CSS3侧边栏菜单(转载)
  2. 消息队列系列(二):.Rabbitmq的使用及Web监控工具使用
  3. 1. 机器学习-特征工程
  4. 【IT笔试面试题整理】字符串的排列
  5. 9.kotlin安卓实践课程-用kotlin写第一个fragment的recyclerView的adapter具体实现
  6. 信息系统项目管理师论文_「高项论文」谨防信息系统项目管理师论文12个写作丢分点...
  7. (四)Neo4j删除数据需要注意的问题
  8. 【机器学习|数学基础】Mathematics for Machine Learning系列之矩阵理论(15):矩阵的范数
  9. linux 中文ssid 显示乱码,把中文SSID变成乱码!一切正常了?_网络设备-中关村在线...
  10. gma 教程 | 气候气象 | 计算标准化降水指数(SPI)
  11. 关于不同长度PEG的丙炔:Pyrene-PEG2/PEG3/PEG4/PEG5-propargyl,1817735-33-3
  12. php实现金币提现,PHP调用支付宝转账接口实现支付宝提现
  13. eval在python中的作用_浅谈Python中eval的强大与危害
  14. php中errorreporting,php中error_reporting函数用法详解_PHP教程
  15. Centos7 出现xxx不在sudoers文件中的解决方案
  16. 我认得embdedding
  17. 区块链软件开发NFT平台开发移动APP开发预约预定APP定制开发
  18. 游戏建模的那些常用软件?建模行业之间的发展趋势?
  19. elastic产品各个版本下载地址
  20. 兔子生兔子之递归问题(递归实现斐波那契数列)

热门文章

  1. 《Web前端设计与开发-HTML+CSS+JavaScript+HTML 5+jQuery》-漫步时尚广场代码-1
  2. idea配置python虚拟环境
  3. Vue _ 后台管理
  4. 【transformer】ViT
  5. python3.5把py文件转换为exe文件(by PyInstaller)
  6. Android系统源码分析--Activity的finish过程
  7. python 异常处理结构
  8. 关于“珊瑚生长率用于重建历史时期海表温度变化”写一段3000字的国内外研究现状,引用文献不少于10篇...
  9. 16.Atomic原子类体系概览
  10. 比Postman更适合国人的接口调试工具