VLC核显编解码简介 + Linux平台vlc编译

今日头条

1091人已加入

描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Tosonw/article/details/89509356
概要:

vlc编译, 硬解基于libva库(VAAPI), live555(liblivemedia-dev), --enable-live555才能播放rtsp流, 基于liveMedia库, vlc对ffmpeg是运行时依赖,把libavcodec_plugin.so删了就可以。
ps:

重点章节:
“二、VLC编译与安装” :
“1.依赖相关”
“2.VLC编译”
“4.vainfo”
该章节是我亲自编译的记录,基于Ubuntu 16.04。
另外,本来想用intel核显解码,但可惜libva库的VAAPI驱动一直未调通。
一、VLC中GPU解码简介

参考:(https://wiki.videolan.org/VLC_VAAPI/)
1.VLC基于libva库(VAAPI):

一个开源库和API规范,可以访问图形硬件加速功能以进行视频处理。它由一个主库和每个支持的硬件供应商的特定于驱动程序的加速后端组成。
另请参阅:VLC GPU解码:https://wiki.videolan.org/VLC_GPU_Decoding/
在某些情况下,VLC框架可以使用您的图形卡(也称为GPU)来解码H.264流(错误地称为HD视频)。
VLC在其模块化方法及其转码/流媒体功能中,仅在解码阶段在GPU中进行解码,然后将数据恢复到其他阶段(流式传输,过滤或插入任何视频输出)。
这意味着,与其他一些实现相比,VLC中的GPU解码速度较慢,因为它需要从GPU获取数据。 但您可以将任何视频输出(接收器)插入其中并使用所有VLC视频过滤器。
2.VAAPI的介绍

此页面是关于在Linux上支持GPU加速的VLC编译。
这个howto由Jean-Baptiste Kempf编写并使用nVidia GPU进行测试。
vaapi:https://www.freedesktop.org/wiki/Software/vaapi/
在Linux / X11上,有两个用于硬件视频解码的竞争接口:
来自Intel的VA-API,和来自NVIDIA的VDPAU。
通常,VAAPI用于Intel和Broadcom图形卡,而VDPAU用于AMD / ATI和NVIDIA卡。
VA-API:

在Ubuntu发行版上,首先安装硬件支持包:i965-va-driver,libva-intel-vaapi-driver和vainfo,然后在Preferences→Input&Codecs中激活GPU硬件加速。

    $ sudo apt-get install i965-va-driver libva-intel-vaapi-driver vainfo

VDPAU:

自VLC版本2.1.0起,VDPAU支持解码,自VLC 2.2.0起支持后处理和渲染(截至2013年底仍处于开发阶段)。
默认情况下,VLC版本2.2.0以后将自动启用VDPAU。
有关技术详细信息,请参阅http://www.remlab.net/op/vlc-vdpau.shtml。
3.在编译vlc之前保证以下正确安装

安装libva(注:We do not support other libraries than the one from Mr Beauchesne.)
https://github.com/intel/libva (https://www.freedesktop.org/wiki/Software/vaapi/)
nvidia驱动(注:Use at least version 0.6.2 )
ATI(注:Use at least 0.6.4.)

#检查是否正确配置了libva环境变量:
$ set | grep LIBVA
#应输出如下内容:
LIBVA_DRIVER_NAME=xvba
LIBVA_DRIVERS_PATH=/usr/lib64/va/drivers
#如果没有,请根据库路径将这些添加到系统环境变量(/etc/environment ?)


VLC基于FFmpeg插件。
FFmpeg: https://github.com/FFmpeg/FFmpeg

./configure --enable-gpl --enable-postproc --prefix=/path/to/ --enable-shared --enable-vaapi
make -j12
make install
#将vaapi.h复制到includes


二、VLC编译与安装
1.依赖相关

sudo apt install libva-dev
sudo apt -y install libvdpau-dev
sudo apt -y install vdpau-va-driver
sudo apt -y install vdpauinfo
sudo apt -y install libavcodec-dev
sudo apt -y install libvdpau-va-gl1
sudo apt install libdrm-dev
sudo apt-get install autoconf automake libtool //运行autogen.sh用
sudo apt-get install libffi-dev
sudo apt-get install libx11-dev libxext-dev libxfixes-dev
sudo apt install libxcb-dev //提供X window protocol access
sudo apt install libpciaccess-dev //提供PCI access


以下是我在实际编译的时候仍然缺少的,和异常的依赖项:

sudo apt install -y libmad-ocaml-dev
sudo apt install -y libgstreamer-ocaml-dev
sudo apt install -y liba52-0.7.4
sudo apt install -y liba52-0.7.4-dev
sudo apt install -y libxcb-composite0-dev
sudo apt install -y libxcb-xv0-dev
sudo apt install -y libxcb-randr0-dev
sudo apt install -y libxcb-keysyms1-dev
sudo apt install -y wayland-protocols
sudo apt install -y libalsa-ocaml-dev
sudo apt install -y libxcb-xkb-dev
sudo apt install -y libsidplay2-dev
sudo apt install -y libogg-dev
sudo apt install -y libdca-dev
sudo apt install -y libflac-dev
sudo apt install -y libmpeg2-4-dev
sudo apt install -y libvorbis-dev
sudo apt install -y libspeex-dev
sudo apt install -y libtheora-dev
sudo apt install -y libfreetype6-dev
sudo apt install -y libcaca-dev
sudo apt install -y libncursesw5-dev
sudo apt install libbluray-dev
sudo apt install -y libssh2-1-dev
sudo apt install -y libvncserver-dev
sudo apt install -y libfreerdp-dev
sudo apt install libdvbpsi-dev
sudo apt install -y libpulse-dev
sudo apt install -y libcddb2-dev
sudo apt install -y libdbus-1-dev
sudo apt install -y libsystemd-dev
sudo apt install -y libsmbclient-dev

# 版本太高,configure: error: libavutil versions 55 and later are not supported.
#sudo apt purge libavutil-dev
#sudo apt purge libavutil-ffmpeg54

# 依赖问题:configure: error: Could not find the LUA byte compiler.
# 可以在编译时使用--disable-lua。或者安装lua,如下:
sudo apt install liblua5.2-dev
sudo apt install liblua50-dev
sudo apt install liblualib50-dev

# 编译问题:yacc: command not found
sudo apt install byacc

# ERROR: flex is not installed.
sudo apt install flex

# ERROR: GNU bison is not installed.
sudo apt install bison

# configure: error: No package 'Qt5Core' found
# No package 'Qt5Widgets' found
# No package 'Qt5Gui' found
# No package 'Qt5Quick' found
# No package 'Qt5QuickWidgets' found
# No package 'Qt5QuickControls2' found
# No package 'Qt5Svg' found. If you want to build VLC without GUI, pass --disable-qt.
# 对上述问题,我使用的是:$ ./configure --disable-qt
# 也可以参考下面一句,自行安装:(我好像这样试过,然而不行)
sudo apt install -y qt5-default qtcreator libqt5svg5-dev

# configure: error: Skins2 interface requires FreeType, libxpm, libxext and libxinerama
sudo apt install -y libfreetype6 libfreetype6-dev libxpm-dev libxext-dev libxinerama-dev

# Makefile:1806: recipe for target 'lua/intf/modules/httprequests.luac' failed
# make[2]: *** [lua/intf/modules/httprequests.luac] Error 1
#   LUAC   lua/intf/telnet.luac
sudo apt install -y liblua5.1-0-dev liblua5.1-bitop-dev liblua5.1-rrd-dev liblua5.2-dev liblua5.3-dev
sudo apt install -y lua5.1-policy-dev
sudo apt install -y libghc-hslua-dev libluabind-dev libluajit-5.1-dev libtexlua52-dev libtexluajit-dev
sudo apt install -y libtolua++5.1-dev libtolua-dev lua-ansicolors-dev lua-apr-dev lua-bit32-dev lua-cjson-dev
sudo apt install -y lua-cliargs-dev lua-curl-dev lua-curses-dev lua-cyrussasl-dev lua-dbi-mysql-dev
sudo apt install -y lua-dbi-postgresql-dev lua-dbi-sqlite3-dev lua-discount-dev lua-dkjson-dev
sudo apt install -y lua-event-dev lua-expat-dev lua-filesystem-dev lua-iconv-dev lua-ldap-dev lua-leg-dev
sudo apt install -y lua-lemock-dev lua-lgi-dev lua-lpeg-dev lua-lpty-dev lua-luassert-dev lua-md5-dev
sudo apt install -y lua-mediator-dev lua-messagepack-dev lua-penlight-dev lua-posix-dev lua-redis-dev
sudo apt install -y lua-rex-gnu-dev lua-rex-onig-dev lua-rex-pcre-dev lua-rex-posix-dev lua-rex-tre-dev
sudo apt install -y lua-rings-dev lua-rrd-dev lua-say-dev lua-sec-dev lua-socket-dev lua-sql-mysql-dev
sudo apt install -y lua-sql-postgres-dev lua-sql-sqlite3-dev lua-svn-dev lua-term-dev lua-uri-dev
sudo apt install -y lua-wsapi-fcgi-dev lua-yaml-dev lua-zip-dev lua-zlib-dev


需要–enable-live555才能播放rtsp流,基于liveMedia库。
注意:不要用apt直接安装live555(liblivemedia-dev),我刚开始就这样操作,导致vlc打开rtsp时出现段错误。
手动下载live555编译安装后,手动建立文件(索引包):/usr/lib/x86_64-linux-gnu/pkgconfig/live555.pc

sudo vim /usr/lib/x86_64-linux-gnu/pkgconfig/live555.pc


写入如下内容:(注:路径根据自己的系统,自行修改)

prefix=/usr/local
libdir=/usr/local/lib #库路径目录,注:源码编译出来的库是.la库。
includedir=${prefix}/include #安装的头文件的目录
Name: live555
Description: multimedia RTSP streaming library
Version: 2016.02.09
Cflags: -I${includedir}/liveMedia -I${includedir}/groupsock -I${includedir}/BasicUsageEnvironment -I${includedir}/UsageEnvironment
Libs: -L${libdir} -lliveMedia -lgroupsock -lBasicUsageEnvironment -lUsageEnvironment


2.VLC编译

源码编译:

    下载vlc-3.0.6-20190114-0223.tar.xz:http://nightlies.videolan.org/build/source/
    我是在Git下载的:https://github.com/videolan/vlc
    (并且使用的是就是最新代码编译通过的:4.0.0-dev-7527-g6a4f370)

或者直接下载现成的软件应用:

    Ubuntu软件管理中心:搜索vlc,点击安装。参考:https://wiki.videolan.org/Configure/
    然后将安装路径下的库取出来直接用。

依赖项(有点多。。。)
注:除了前面的“1.依赖相关”里安装的依赖项之外,这里我也同样操作过下面的命令,安装了以下依赖项:
sudo apt-get install libvorbis-dev libogg-dev libtheora-dev speex libspeex-dev flac libflac-dev x264 libx264-dev a52-0.7.4 liba52-0.7.4-dev mpeg2dec libmpeg2-4-dev faad libfaad-dev faac libfaac-dev lame libmp3lame-dev libavdevice-dev libmad0 libmad0-dev libschroedinger-dev libebml-dev libdca-dev twolame libtwolame-dev libmpcdec-dev libvorbisidec1 libvorbisidec-dev libass-dev libmatroska-dev libdvbpsi-dev libmodplug1 libmodplug-dev libshout3 libshout3-dev libdvdread4 libdvdnav4 libdvdnav-dev livemedia-utils liblivemedia-dev libcddb2 libcddb2-dev libcdio13 libcdio-dev libxcb-composite0-dev libcdio-utils vcdimager libvcdinfo0 libvcdinfo-dev libgpg-error0 libgpg-error-dev libgcrypt11-dev gnutls-bin libgnutls-dev libdap-bin libdap-dev libxml2 libxml2-dev libpng12-0 libpng12-dev libjpeg8 libtiff5 libsdl1.2-dev libsdl-image1.2 libsdl-image1.2-dev libc-bin gettext libfreetype6 libfreetype6-dev libfribidi-dev libfribidi0 zlib1g zlib1g-dev libtag1-dev libcaca0 libcaca-dev caca-utils libqt4-dev libportaudio2 libupnp-dev libupnp6 libexpat1 libexpat1-dev yasm libxcb-xv0 libxcb-xv0-dev libx11-xcb1 libx11-xcb-dev liblua5.2-dev libswscale-dev
编译:

# 源码clone
git clone https://github.com/videolan/vlc.git

# 查看版本信息
git log

# 根据需要,可以更新到指定release版本:
#例vlc-4.0.0:
#git checkout 1f2e534f3033aab9dd31442f7b3956728b62b3d3
#例vlc-3.0.0:
#git checkout 8d432b090e08f141ce9156dc728afbed4636301b

# 开始编译(注:备注:要支持播放rtsp流,必须enable live。要能打印debug,也要enable debug选项。)
./bootstrap
mkdir build; cd build
#../configure --disable-lua --disable-qt --enable-live555 --enable-debug  --enable-x264
../configure --enable-avcodec --enable-avformat --enable-swscale --enable-mad --enable-a52 --enable-libmpeg2 --enable-faad --enable-vorbis --enable-ogg --enable-theora --enable-freetype --enable-fribidi --enable-speex --enable-flac --enable-live555 --enable-caca --enable-alsa --enable-ncurses --enable-debug --enable-x264 --disable-lua --disable-qt --enable-dsm --enable-dvbpsi --enable-dvdnav --enable-dvdread --enable-bluray --enable-nfs --enable-pulse --enable-freerdp --enable-sftp --enable-vnc --enable-run-as-root --enable-archive --enable-dc1394 --enable-dv1394 --enable-smbclient
sudo make -j12 #或者 ./compile
sudo make install


启动VLC:

#直接在命令行上:
vlc --ffmpeg-hw #hw:硬解  sw:软解
#其实可以直接启动:
vlc
#Exemple: on playback log output (with -v debug and ATI VAAPI)
[0x7f8c4cc03ba8] avcodec decoder: Using VA API version 0.32 for hardware decoding.


以下“3.”“4.”“5.”节,与VLC硬解相关
3.libva-2.1.1编译安装

#依赖
$ sudo apt install -y libc6 libdrm-intel1 libdrm2 libva-x11-1 libva1 multiarch-support
#源码
$ git clone https://github.com/intel/libva.git
$ cd libva
#编译
$ sudo ./autogen.sh -with-drivers-path=/usr/lib/x86_64-linux-gnu/dri
$ sudo make -j12
$ sudo make install


4.vainfo

vainfo工具用于查看libva库调用信息。

$ sudo apt install vainfo
$ vainfo
# 将会输出一些调用信息
libva info: VA-API version 0.39.0
libva info: va_getDriverName() returns 0
libva info: User requested driver 'i965'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: va_openDriver() returns -1
vaInitialize failed with error code -1 (unknown libva error),exit


vainfo支持调用nvidia显卡,但需要先安装nvidia_video驱动:

$ sudo apt install vdpau-va-driver
#查看库文件
$ ll /usr/lib/x86_64-linux-gnu/dri/
#将查看到有个nvidia_drv_video.so文件
lrwxrwxrwx   1 root root       18 4月   7  2016 nvidia_drv_video.so -> vdpau_drv_video.so
#此时使用vainfo查看调用情况
$ vainfo
libva info: VA-API version 0.39.0
libva info: va_getDriverName() returns 0
libva info: User requested driver 'nvidia'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/nvidia_drv_video.so
libva info: Found init function __vaDriverInit_0_39
libva info: va_openDriver() returns 0
vainfo: VA-API version: 0.39 (libva 1.7.0)
vainfo: Driver version: Splitted-Desktop Systems VDPAU backend for VA-API - 0.7.4
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            :    VAEntrypointVLD
      VAProfileMPEG2Main              :    VAEntrypointVLD
      VAProfileMPEG4Simple            :    VAEntrypointVLD
      VAProfileMPEG4AdvancedSimple    :    VAEntrypointVLD
      VAProfileH264Baseline           :    VAEntrypointVLD
      VAProfileH264Main               :    VAEntrypointVLD
      VAProfileH264High               :    VAEntrypointVLD
      VAProfileVC1Simple              :    VAEntrypointVLD
      VAProfileVC1Main                :    VAEntrypointVLD
      VAProfileVC1Advanced            :    VAEntrypointVLD


vainfo支持调用intel核显,但需要先安装i965-va-driver驱动:
(但是我的i965-va-driver库调用一直是下面的问题,无法解决。)

#查看是否安装了驱动
$ apt list i965-va-driver
Listing... Done
i965-va-driver/xenial,now 1.7.0-1 amd64 [installed,automatic]
#如果没有安装,则进行安装
$ sudo apt install -y i965-va-driver

#此时使用vainfo查看调用情况(注:要先将libva调用库改为i965,即intel的VAAPI库。)
$ export LIBVA_DRIVER_NAME=i965
$ vainfo
libva info: VA-API version 0.39.0
libva info: va_getDriverName() returns 0
libva info: User requested driver 'i965'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_0_39
vainfo: intel_driver.c:100: intel_driver_init: Assertion `(((struct drm_state *)(ctx)->drm_state)->auth_type == (VA_DRM_AUTH_DRI1)) || (((struct drm_state *)(ctx)->drm_state)->auth_type == (VA_DRM_AUTH_DRI2)) || (((struct drm_state *)(ctx)->drm_state)->auth_type == (VA_DRM_AUTH_CUSTOM))' failed.
Aborted (core dumped)


可能是直接使用apt安装存在支持问题,于是尝试自己编译intel的vaapi驱动:

$ sudo apt-get install libx11-dev libtool libdrm-dev build-essential autoconf libva-dev
$ git clone https://github.com/intel/intel-vaapi-driver.git
$ cd intel-vaapi-driver/
$ ./autogen.sh
#此时存在一些依赖项的版本问题:
#configure: error: Package requirements (libva >= 1.4.0) were not met:
#Requested 'libva >= 1.4.0' but version of libva is 1.3.0
$ git clone https://github.com/intel/libva.git
$ cd libva/
$ ./autogen.sh -with-drivers-path=/usr/lib/x86_64-linux-gnu/dri
$ make -j12
$ sudo make install
#完成后返回intel-vaapi-driver目录,再次配置并编译:
$ cd ../intel-vaapi-driver/
$ ./autogen.sh
#我在配置路径的时候发现配置无用,路径仍然是默认的/usr/local/lib/dri/
#没去深究,我继续编译安装,最后手动将/usr/local/lib/dri/i965_drv_video.so库链接到/usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
#后来发现是libva必须要先修改安装路径,然后intel-vaapi-driver的修改才能起作用
$ ./configure --prefix=/usr/lib/x86_64-linux-gnu/dri/
$ make -j12
$ sudo make install
#$ sudo ln -s /usr/local/lib/dri/i965_drv_video.so /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
#$ sudo ln -s /usr/local/lib/dri/i965_drv_video.la /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.la


此时使用vainfo查看调用情况,这次异常不一样了,似乎是某函数问题:

$ vainfo
libva info: VA-API version 0.39.0
libva info: va_getDriverName() returns 0
libva info: User requested driver 'i965'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva error: /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so has no function __vaDriverInit_0_32
libva info: va_openDriver() returns -1
vaInitialize failed with error code -1 (unknown libva error),exit


我在GitHub上有找到类似的问题,但并不能解决我这出现的情况,后来提了issue:https://github.com/intel/intel-vaapi-driver/issues/455

继续尝试,经过仔细考虑怀疑是这些驱动的版本兼容问题,比如我查到的大部分人们的版本为:libva info: VA-API version 0.34.0,而我的是0.39.0。
经查询:0.34.0对应的libva版本是1.2.1,所以下载对应版本:https://github.com/intel/libva/archive/libva-1.2.1.tar.gz
解压后进入目录,进行编译安装:

$ ./autogen.sh -with-drivers-path=/usr/lib/x86_64-linux-gnu/dri
$ make -j12
$ sudo make install
#完成后使用vainfo查看
$ vainfo
libva info: VA-API version 0.34.0
libva info: va_getDriverName() returns 0
libva info: User requested driver 'i965'
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva error: /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so has no function __vaDriverInit_0_32
libva info: va_openDriver() returns -1
vaInitialize failed with error code -1 (unknown libva error),exit
#可以看到VA-API版本已经为0.34.0了,接下来重新编译intel-vaapi-driver
$ cd intel-vaapi-driver
$ ./autogen.sh
#会出现错误:
configure: error: Package requirements (libva >= 1.4.0) were not met:
Requested 'libva >= 1.4.0' but version of libva is 0.34.0


我们的intel-vaapi-driver也应该使用旧版本,经检查应该使用:intel-vaapi-driver_1.2.1版本。下载:https://github.com/intel/intel-vaapi-driver/archive/1.2.1.tar.gz
解压后进入目录,进行编译安装:

$ cd ../intel-vaapi-driver-1.2.1/
$ ./autogen.sh
$ make -j12


但是编译出现了错误,问题可能出在源码里吧,因为新版本编译都正常,`
只可惜新版本运行有问题,旧版本又编译不过。

Traceback (most recent call last):
  File "../../gpp.py", line 200, in
    writeblocks(outfile, blocks)
  File "../../gpp.py", line 168, in writeblocks
    do_writeblock(block, [])
  File "../../gpp.py", line 161, in do_writeblock
    while check_cond(block.param_op, for_curs[0], block.param_limit):
  File "../../gpp.py", line 138, in check_cond
    assert type(cur) == int
AssertionError
make[5]: Leaving directory '/home/toson/soft/intel-vaapi-driver-1.2.0/src/shaders/post_processing/gen5_6'
Makefile:376: recipe for target 'all-recursive' failed
make[4]: *** [all-recursive] Error 1
make[4]: Leaving directory '/home/toson/soft/intel-vaapi-driver-1.2.0/src/shaders/post_processing'
Makefile:377: recipe for target 'all-recursive' failed
make[3]: *** [all-recursive] Error 1
make[3]: Leaving directory '/home/toson/soft/intel-vaapi-driver-1.2.0/src/shaders'
Makefile:941: recipe for target 'all-recursive' failed
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory '/home/toson/soft/intel-vaapi-driver-1.2.0/src'
Makefile:533: recipe for target 'all' failed
make[1]: *** [all] Error 2
make[1]: Leaving directory '/home/toson/soft/intel-vaapi-driver-1.2.0/src'
Makefile:410: recipe for target 'all-recursive' failed
make: *** [all-recursive] Error 1


5.检查版本

#查看libva版本
dpkg-query --showformat='${Package}: ${Version}\n' --show | grep libva
#查看vainfo版本
dpkg-query --showformat='${Package}: ${Version}\n' --show | grep vainfo
#查看i965版本
dpkg-query --showformat='${Package}: ${Version}\n' --show | grep i965


例:(我运行的结果)

# List installed libva packages
$ dpkg-query --showformat='${Package}: ${Version}\n' --show | grep libva
libva-dev: 1.7.0-1ubuntu0.1
libva-drm1: 1.7.0-1ubuntu0.1
libva-egl1: 1.7.0-1ubuntu0.1
libva-glx1: 1.7.0-1ubuntu0.1
libva-tpi1: 1.7.0-1ubuntu0.1
libva-wayland1: 1.7.0-1ubuntu0.1
libva-x11-1: 1.7.0-1ubuntu0.1
libva1: 1.7.0-1ubuntu0.1
libva1: 1.7.0-1ubuntu0.1
# The vainfo installed
$ dpkg-query --showformat='${Package}: ${Version}\n' --show | grep vainfo
vainfo: 1.7.0-1ubuntu0.1
# List installed i915 Intel VAAPI driver
$ dpkg-query --showformat='${Package}: ${Version}\n' --show | grep i965
i965-va-driver: 1.7.0-1


6.我在编译VLC时问过的问题
依赖库编译与调用:

Toson_桐:有谁知道编译vlc的时候怎样让它不依赖ffmpeg的那些解码模块?
不断电的梦:依不依赖是代码调用时决定的, 不是编译时决定的.
Toson_桐:编译时可以加编译参数“–disable-***”,但是没有–disable-ffmpeg这个
Toson_桐:vlc是不是必须依赖ffmpeg
爨纛鼟:那你得自己编ffmpeg禁用那些模块 然后再编vlc 链你自己编的那版ffmpeg
爨纛鼟:@Toson_桐 你直接把libavcodec_plugin.so删了就行
爨纛鼟:vlc对ffmpeg是运行时依赖 你把插件一删就没有了
爨纛鼟:ffmpeg的解码器比较全面 我不知道你为什么要禁用它 但是我告诉你可以通过运行时参数指定使用哪个解码器 如果你要自己写一个解码器 可以把分数设得比ffmpeg高 这样会优先找你的
Toson_桐:@爨纛鼟 厉害了!,问一下禁用ffmpeg会不会vlc对某些编码格式就不支持了
爨纛鼟:肯定的啊
Toson_桐:我主要想看vlc自己的解码能力,做个对比
爨纛鼟: libvlc什么功能都没有 vlc所有的功能都是插件提供的
爨纛鼟:libvlccore是插件加载器 libvlc实现音视频播放逻辑和负责线程调度
Toson_桐:我明白了,vlc依赖的x264也是它的插件了,我是解码相机的H264格式视频流,我可以跳过vlc直接使用底下的插件库,应该可以达到快速解码吧
Toson_桐:现在我这挂载20多个摄像头之后,cpu资源全耗光了
Eric:牛逼
Toson_桐:听说vlc解码效果好,就来研究
爨纛鼟:用硬编硬解 你有显卡没有
Toson_桐:刚开始就想用核显,linux上编译,一直没调通。独显倒是能用,不过独显都拿去跑模型用了
爨纛鼟:跑模型跟编解码不是同一块核心
爨纛鼟:跑模型用的是cuda核心 编码是nvenc 解码是cuvid
三、VLC代码

参考雷霄骅文档:https://blog.csdn.net/leixiaohua1020/article/details/42363079
流程图中包含了3个结构体:

libvlc_instance_t:代表一个libVLC的实例。
libvlc_media_t:代表一个可以播放的媒体。
libvlc_media_player_t:代表一个VLC媒体播放器(一个视频播放器播放一个视频)。注意VLC并不仅仅用于媒体播放。


创建或者以上3个结构体通过以下6个函数:

libvlc_new():创建libvlc_instance_t。
libvlc_media_new_path():创建libvlc_media_t。
libvlc_media_player_new_from_media():创建libvlc_media_player_t。
libvlc_media_player_release():释放libvlc_media_player_t
libvlc_media_release():释放libvlc_media_t。
libvlc_release():释放libvlc_instance_t。


可以通过下面的函数控制媒体的播放或者暂停:

这些函数都需要使用libvlc_media_player_t作为参数。这里处于简化的目的,只使用了播放和停止函数。

libvlc_media_player_play():播放。
libvlc_media_player_pause():暂停。
libvlc_media_player_stop():停止。


获取视频的时长,宽,高等信息:

在libVLC中可以通过如下等函数获取。

libvlc_media_player_get_length()
//libvlc_video_get_width()
//libvlc_video_get_height()
实测已经没有上述2个函数,以下面一个函数代替:
libvlc_video_get_size(mp, 0, &width, &height);


但是有一个很奇怪的现象:如果在调用完libvlc_media_player_play()之后,立即调用上述3个函数的话,返回的值都是0,只有“等待”一段时间(例如调用sleep())后再调用上述函数,才能得到正确的数值。
四、例程

以下是我运行过的程序,实现vlc代码提取摄像机图像:

//
// Created by toson on 19-4-15.
//
#include
#include
#include
#include
#include

#include "unistd.h"

using namespace std;
using namespace cv;

int IMG_WIDTH = 3840;//2592//1920;//1280//1280
int IMG_HEIGHT= 2160;//1520//1080;//960//720

namespace vlcreader_ns {

//#pragma comment(lib,"libvlc.so.5")
//#pragma comment(lib,"libvlccore.so.8")

    class VLCReader
    {
    public:
        VLCReader(char* url = 0);
        ~VLCReader();
        void start(int wantW = IMG_WIDTH, int wantH = IMG_HEIGHT);
        void pause(bool paused);
        void ctrl(const char *psz_options);
        cv::Mat frame() { return img; }
        unsigned int w, h;

    private:
        char* rtspAddress = "rtsp://admin:admin123@192.168.1.102:554/cam/realmonitor?channel=1&subtype=0";
        libvlc_instance_t *inst;
        libvlc_media_player_t *mp;
        unsigned char *pixel;
        cv::Mat img;
        libvlc_media_t *media;

        static void *cb_lock(void *opaque, void **plane);
        static void cb_unlock(void *opaque, void *picture, void * const *plane);
        static void cb_display(void *opaque, void *picture);
        unsigned char * updataSize();
    };

    VLCReader::VLCReader(char*url)
            : inst(0), mp(0), pixel(0), w(0), h(0), rtspAddress(url)
    {
        const char * vlc_args[] = {
                "--ipv4", //将会默认为所有连接使用 IPv4。 (默认关闭)
                "--no-prefer-system-codecs", //无论是否有可用的选择都优先使用您系统中的原生插件替代VLC自己的插件。 (默认关闭)
                "--rtsp-caching=300", //延迟速度ms //允许您修改 RTSP 流的默认缓存值。此值必须以毫秒为单位设置。
                "--network-caching=500", //设高可减少花屏 //远程文件额外增加的缓存值,以毫秒为单位。
                "--demux=h264", //去复用器被用于分离 "复合" 流 (类似音频和视频流)。
                "--rtsp-tcp", //--rtsp-host //--rtsp-tcp //使用 RTP over RTSP (TCP) (默认关闭)
        };
        std::string rstp_str(rtspAddress);
        if (rstp_str.substr(0, 4) == "file")
        {
            vlc_args[4] = "";
            vlc_args[5] = "";
        }

        inst = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
        mp = libvlc_media_player_new(inst);

        libvlc_video_set_callbacks(mp, cb_lock, cb_unlock, cb_display, this);
    }

    VLCReader::~VLCReader()
    {
        libvlc_media_player_stop(mp);
        libvlc_media_player_release(mp);
        libvlc_release(inst);
    }

    void VLCReader::start(int wantW, int wantH)
    {
        libvlc_media_player_pause(mp);
        media = libvlc_media_new_location(inst, rtspAddress);
        libvlc_media_player_set_media(mp, media);
        libvlc_media_release(media);

        libvlc_video_set_format(mp, "RV24", wantW, wantH, wantW * 3);
        libvlc_media_player_play(mp);
    }

    void VLCReader::pause(bool paused)
    {
        if (mp) {
            libvlc_media_player_set_pause(mp, paused);
        }
    }

    unsigned char * VLCReader::updataSize()
    {
        libvlc_video_get_size(mp, 0, &w, &h);
        //int w = libvlc_video_get_width(mp);
        //int h = libvlc_video_get_height(mp);
        if (!w || !h)
            return 0;
        if (pixel && (this->w != w || this->h != h)) {
            delete[] pixel;
            pixel = 0;
        }
        if (!pixel) {
            pixel = new unsigned char[w*h * 3];
            this->w = w;
            this->h = h;
        }
        return pixel;
    }

    void* VLCReader::cb_lock(void *opaque, void **plane)
    {
        VLCReader *p = (VLCReader*)opaque;
        *plane = p->updataSize(); //tell VLC to put decoded data to this buffer
        return *plane;
    }
    void VLCReader::cb_unlock(void *opaque, void *picture, void * const *plane)
    {
        VLCReader *p = (VLCReader*)opaque;
        unsigned char *pix = (unsigned char*)picture;
        if (pix) {
            p->img = cv::Mat(p->h, p->w, CV_8UC3, pix);
        }
    }
    void VLCReader::cb_display(void *opaque, void *picture)
    {
        VLCReader *p = (VLCReader*)opaque;
        if (!p->img.empty()) {
//            cv::cvtColor(p->img, p->img, cv::COLOR_BGR2RGB);
//            cv::namedWindow("1", CV_WINDOW_NORMAL);
//            resize(p->img, p->img, Size(0,0), 0.5, 0.5, INTER_LINEAR);
            cv::imshow("1", p->img);
            cv::waitKey(1);
        }
    }

    void VLCReader::ctrl(const char *psz_options)
    {
        libvlc_media_add_option(media, psz_options);
    }
}
using namespace vlcreader_ns;

int main(int argc, char* argv[])
{
    VLCReader vlc_reader("rtsp://admin:admin123@192.168.1.106:554/cam/realmonitor?channel=1&subtype=0");
//    VLCReader vlc_reader("file:////home/toson/videos/BigBuckBunny_320x180.mp4");
    vlc_reader.start();
    sleep(3);
    vlc_reader.pause(true); //暂停
    sleep(3);
    vlc_reader.pause(false);
    sleep(3);
//    vlc_reader.ctrl("-f"); //"--fullscreen"
    sleep(3);
    sleep(100);

    return 0;
}

 
————————————————
版权声明:本文为CSDN博主「Tosonw」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Tosonw/article/details/89509356

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分