前言
这篇文章主要介绍了Ubuntu16.04下如何使用JSVM来实现可伸缩视频编码。主要参考了https://github.com/ChristianKreuzberger/DASH-SVC-Toolchain和https://blog.csdn.net/qq_41895113/article/details/80561218
一、JSVM安装和测试
1.安装
JSVM并不是和所有Ubuntu版本都兼容,我之前下载了好几个版本的JSVM都没成功,最后下载这个版本(https://github.com/floriandejonckheere/jsvm)的JSVM在Ubuntu 16.04上终于安装成功了,安装步骤也比较简单。将下载的JSVM压缩包解压,在文件夹jsvm/JSVM/H264Extension/build/linux下直接make就安装成功了。
cd /home/songfeng1256/Desktop/SVCDemo/jsvm/JSVM/H264Extension/build/linux
make
为了能够在其他路径下调用JSVM提供的编解码器,将可执行文件添加到PATH路径中。在root权限下打开配置文件。
#切换到root权限
sudo su
#打开配置文件
gedit ~/.bashrc
#在最后一行添上:
export PATH=/home/songfeng1256/Desktop/SVCDemo/jsvm/bin:$PATH
#生效方法:(有以下两种)
#1、关闭当前终端窗口,重新打开一个新终端窗口就能生效
#2、输入“source ~/.bashrc”命令,立即生效
#有效期限:永久有效
#用户局限:仅对当前用户
2.测试
任意位置打开终端输入
H264AVCDecoderLibTestStatic
出现下图所示即成功安装JSVM,并成功配置路径
二、编码和解码
1.编码-质量伸缩性
参考http://concert.itec.aau.at/SVCDataset/这里面提供的四种编码方式,分别给出了配置文件。
本文选择的是第一种编码方式,通过改变量化步长来改变质量,进而实现可伸缩视频编码。首先新建一个测试文件夹,e.g SVCDemo,在文件夹内新建配置文件,由于本文选择的是360p的视频,配置文件参考http://ftp.itec.aau.at/datasets/SVCDASHDataset2015/config/I/JSVM/360p/。其中一共有四个配置文件。对于输出配置文件,设置如下,其中NumLayers决定需要编码的层数,LayerCfg为各个层的配置文件。
下面为别为一层、两层和三层的配置文件。
#只有一个增强层
# JSVM Main Configuration File for Sintel Spatial
OutputFile output_360p.264 # Bitstream file
FrameRate 24.0 # Maximum frame rate [Hz]
FramesToBeEncoded 300 # Number of frames
BaseLayerMode 2
IntraPeriod 48 # Intra Period
GOPSize 4 # GOP Size (at maximum frame rate)
SearchMode 4
SearchRange 32
FastBiSearch 1
NumLayers 1 #通过改变编码的层数来改变编码的质量
LayerCfg layer0_snr0.cfg #选择的各个层的配置文件
# 两个增强层
# JSVM Main Configuration File for Sintel Spatial
OutputFile output_360p.264 # Bitstream file
FrameRate 24.0 # Maximum frame rate [Hz]
FramesToBeEncoded 300 # Number of frames
BaseLayerMode 2
IntraPeriod 48 # Intra Period
GOPSize 4 # GOP Size (at maximum frame rate)
SearchMode 4
SearchRange 32
FastBiSearch 1
NumLayers 2 #通过改变编码的层数来改变编码的质量
LayerCfg layer0_snr0.cfg #选择的各个层的配置文件
LayerCfg layer0_snr1.cfg
#三个增强层
# JSVM Main Configuration File for Sintel Spatial
OutputFile output_360p.264 # Bitstream file
FrameRate 24.0 # Maximum frame rate [Hz]
FramesToBeEncoded 300 # Number of frames
BaseLayerMode 2
IntraPeriod 48 # Intra Period
GOPSize 4 # GOP Size (at maximum frame rate)
SearchMode 4
SearchRange 32
FastBiSearch 1
NumLayers 3 #通过改变编码的层数来改变编码的质量
LayerCfg layer0_snr0.cfg #选择的各个层的配置文件
LayerCfg layer0_snr1.cfg
LayerCfg layer0_snr2.cfg
每一层的配置文件设置如下,根据自己的输入文件设置文件名、文件的长和宽,其中QP为量化步长,量化步长越大,视频质量越低。
layer0_snr0.cfg:
# JSVM Layer Configuration File
#====================== INPUT / OUTPUT =========================================
InputFile input_360p.yuv # Input file
SourceWidth 352 # Input frame width
SourceHeight 288 # Input frame height
FrameRateIn 24 # Input frame rate [Hz]
FrameRateOut 24 # Output frame rate [Hz]
IDRPeriod 48
#ProfileIdc 0 # 0 auto, 66 baseline, 77 main, 88 extended, 100 high, 83 scalable baseline, 86 scalable high
QP 40 # Quantization parameters
MeQP0 40 # QP for mot. est. / mode decision (stage 0)
MeQP1 40 # QP for mot. est. / mode decision (stage 1)
MeQP2 40 # QP for mot. est. / mode decision (stage 2)
MeQP3 40 # QP for mot. est. / mode decision (stage 3)
MeQP4 40 # QP for mot. est. / mode decision (stage 4)
MeQP5 40 # QP for mot. est. / mode decision (stage 5)
layer0_snr1.cfg:
# JSVM Layer Configuration File
#====================== INPUT / OUTPUT =========================================
InputFile input_360p.yuv # Input file
SourceWidth 352 # Input frame width
SourceHeight 288 # Input frame height
FrameRateIn 24 # Input frame rate [Hz]
FrameRateOut 24 # Output frame rate [Hz]
IDRPeriod 48
InterLayerPred 1 # Inter-layer Pred. (0: no, 1: yes, 2:adap.)
QP 35 # Quantization parameters
MeQP0 35 # QP for mot. est. / mode decision (stage 0)
MeQP1 35 # QP for mot. est. / mode decision (stage 1)
MeQP2 35 # QP for mot. est. / mode decision (stage 2)
MeQP3 35 # QP for mot. est. / mode decision (stage 3)
MeQP4 35 # QP for mot. est. / mode decision (stage 4)
MeQP5 35 # QP for mot. est. / mode decision (stage 5)
layer0_snr2.cfg:
# JSVM Layer Configuration File
#====================== INPUT / OUTPUT =========================================
InputFile input_360p.yuv # Input file
SourceWidth 352 # Input frame width
SourceHeight 288 # Input frame height
FrameRateIn 24 # Input frame rate [Hz]
FrameRateOut 24 # Output frame rate [Hz]
IDRPeriod 48
InterLayerPred 1 # Inter-layer Pred. (0: no, 1: yes, 2:adap.)
QP 30 # Quantization parameters
MeQP0 30 # QP for mot. est. / mode decision (stage 0)
MeQP1 30 # QP for mot. est. / mode decision (stage 1)
MeQP2 30 # QP for mot. est. / mode decision (stage 2)
MeQP3 30 # QP for mot. est. / mode decision (stage 3)
MeQP4 30 # QP for mot. est. / mode decision (stage 4)
MeQP5 30 # QP for mot. est. / mode decision (stage 5)
然后在SVCDemo文件夹中下载需要编码的视频(http://concert.itec.aau.at/SVCDataset/),我这里下载的是比较短的视频akiyo_cif.yuv
然后在文件夹中打开终端,运行命令:
H264AVCEncoderLibTestStatic -pf three_level_360p.cfg
运行结束后生成了文件output_360p.264以及rec.yuv
对输入的视频文件分别进行一层,两层和三层的编码,得到三个编码文件如下:
编码一层、两层和三层的编码文件的大小分别问39.7kB,95.1kB和216.3kB。
2.解码
对于刚刚生成的编码文件Output_360p.264可以直接在终端解码,得到可以播放的文件Output_360p.yuv,
H264AVCDecoderLibTestStatic Output_360p.svc Output_360p.yuv
如果需要播放视频,可以下载mplayer
#安装mplayer
sudo apt-get install mplayer
# 播放视频
mplayer -demuxer rawvideo -rawvideo w=352:h=288:format=i420:fps=24 Output_360p.yuv -loop 0
对于之前不同编码层数的视频,分别进行解码,得到的视频如下,从左往右分别是源视频,三层编码视频、两层编码视频和一层编码视频。
3.解码SVC视频
视频数据集http://concert.itec.aau.at/SVCDataset/这里面也提供了很多SVC编码好的视频,接下来对数据集里面的编码视频进行解码。先从https://github.com/ChristianKreuzberger/DASH-SVC-Toolchain下载得到文件夹DASH-SVC-Toolchain,进入decode文件夹下。
值得注意的是,需要解码视频片段必须要有初始化片段(init.svc),合并的时候也最多可以合并两个不同的segs。
cd decode
#c从数据集下载SVC文件
#下载初始化片段
wget http://concert.itec.aau.at/SVCDataset/dataset/bluesky/II/segs/720p/bluesky-II-720p.init.svc
#下载第0个片段的基本层BL
wget http://concert.itec.aau.at/SVCDataset/dataset/bluesky/II/segs/720p/bluesky-II-720p.seg0-L0.svc
#下载第0个片段的增强层EL1
wget http://concert.itec.aau.at/SVCDataset/dataset/bluesky/II/segs/720p/bluesky-II-720p.seg0-L1.svc
#下载第0个片段的增强层EL2
wget http://concert.itec.aau.at/SVCDataset/dataset/bluesky/II/segs/720p/bluesky-II-720p.seg0-L2.svc
#通过svc_merge.py将基本层和增强层合并在一起
#只有增强层BL
python svc_merge.py bluesky-II-720p.seg0-BL.264 bluesky-II-720p.init.svc bluesky-II-720p.seg0-L0.svc
# 将其解码
H264AVCDecoderLibTestStatic bluesky-II-720p.seg0-BL.264 bluesky-II-720p.seg0-BL.yuv
#BL+EL1
python svc_merge.py bluesky-II-720p.seg0-EL1.264 bluesky-II-720p.init.svc bluesky-II-720p.seg0-L0.svc bluesky-II-720p.seg0-L1.svc
# 将其解码
H264AVCDecoderLibTestStatic bluesky-II-720p.seg0-EL1.264 bluesky-II-720p.seg0-EL1.yuv
#BL+EL1+EL2
python svc_merge.py bluesky-II-720p.seg0-EL2.264 bluesky-II-720p.init.svc bluesky-II-720p.seg0-L0.svc bluesky-II-720p.seg0-L1.svc bluesky-II-720p.seg0-L2.svc
# 将其解码
H264AVCDecoderLibTestStatic bluesky-II-720p.seg0-EL2.264 bluesky-II-720p.seg0-EL2.yuv
#使用mplayer播放视频
mplayer -demuxer rawvideo -rawvideo w=1280:h=720:format=i420:fps=24 bluesky-II-720p.seg0-BL.yuv -loop 0
mplayer -demuxer rawvideo -rawvideo w=1280:h=720:format=i420:fps=24 bluesky-II-720p.seg0-EL1.yuv -loop 0
mplayer -demuxer rawvideo -rawvideo w=1280:h=720:format=i420:fps=24 bluesky-II-720p.seg0-EL2.yuv -loop 0