目录
0、硬件平台和测试环境说明
1 、查看usb摄像头可用的分辨率
2、【omxh264enc | omxh265enc】NVIDIA accelerated H.264/H.265 硬件加速编码
2.1 示例:USB相机YUV图像压缩为H.264 格式,保存为MP4文件
2.2 示例:USB相机YUV图像压缩为H.265 格式,保存为MP4文件
3、硬件加速视频格式转换( nvvidconv)
3.1 将USB相机的YUV图像转换成I420格式
我们之所以选择Jetson 系列,肯定是看重了他有GPU,可以帮忙做很多加速,比如图像编解码,比如深度学习的推理运算,下面我们就分享说明,Jetson TX1 平台上如何利用硬件资源,进行编解码的加速。
感觉网上看这一类说明,常常最大的疑惑就是,为什么别人能用,我自己就不成了,其实很多时候都是各自的环境交代不清楚所致。所以我觉得讲操作前,必须先交代自己的测试环境。
我自己使用的是TX1核心模块,安装ubuntu 18.04 的环境。安装了英伟达配套的所有cuda的套件库。
nvidia@nvidia-desktop:~$ sudo lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.5 LTS
Release: 18.04
Codename: bionic
nvidia@nvidia-desktop:~$ v4l2-ctl --device=/dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : Motion-JPEG
Size: Discrete 1280x720
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 800x600
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 640x360
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 352x288
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.033s (30.000 fps)
Index : 1
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUYV 4:2:2
Size: Discrete 1280x720
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 800x600
Interval: Discrete 0.050s (20.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.040s (25.000 fps)
Size: Discrete 640x360
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 352x288
Interval: Discrete 0.033s (30.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.033s (30.000 fps)
可以看到,我测试使用的USB相机可以支持MJPG格式的压缩视频,恒定30HZ帧率,也可以提供YUYV这种RAW格式的视频,但是图像分辨率越大,帧率也会变低,需要根据情况做一定的调整。
查询环境中的对应插件omxh264enc信息:
nvidia@nvidia-desktop:~$ gst-inspect-1.0 omxh264enc
Pad Templates:
SRC template: 'src'
Availability: Always
Capabilities:
video/x-h264
width: [ 16, 4096 ]
height: [ 16, 4096 ]
stream-format: { (string)byte-stream, (string)avc }
alignment: au
SINK template: 'sink'
Availability: Always
Capabilities:
video/x-raw(memory:NVMM)
format: { (string)I420, (string)NV12 }
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
video/x-raw
format: { (string)I420, (string)NV12 }
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
查询环境中的对应插件omxh265enc信息:
nvidia@nvidia-desktop:~$ gst-inspect-1.0 omxh265enc
Pad Templates:
SRC template: 'src'
Availability: Always
Capabilities:
video/x-h265
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
stream-format: { (string)byte-stream, (string)hvc1 }
alignment: au
SINK template: 'sink'
Availability: Always
Capabilities:
video/x-raw(memory:NVMM)
format: { (string)I420, (string)I420_10LE, (string)NV12 }
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
video/x-raw
format: { (string)I420, (string)NV12 }
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
下面是使用x264enc插件压缩并保存文件,我们可以先试试看CPU占用情况,为了便于观察,我们让多录制一会
#x264enc 其输入为 video/x-raw ,输出为video/x-h264
# mp4mux MP4 文件格式封装插件
# filesink location 老朋友了,保存文件
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=1000 \
! 'video/x-raw,format=YUY2,width=640, height=480, framerate=25/1' \
! videoconvert \
! x264enc ! mp4mux ! filesink location=/home/nvidia/Pictures/x264enc-video-640-480-25-1000.mp4
开始前的资源占用情况:
开始后的资源占用:
使用硬件加速:
#x264enc 其输入为 video/x-raw ,输出为video/x-h264
# mp4mux MP4 文件格式封装插件
# filesink location 老朋友了,保存文件
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=1000 \
! 'video/x-raw,format=YUY2,width=640, height=480, framerate=25/1' \
! videoconvert \
! omxh264enc ! h264parse \
! mp4mux ! filesink location=/home/nvidia/Pictures/omxh264enc-video-640-480-25-1000.mp4 -e
开始压缩前的资源占用:
压缩开始后的资源占用:
可以偶尔看到GPU资源波动,但是整体上CPU占用一直维持在一个比较小的状态。而且速度也感觉快了不少。
其它参考示例
gst-launch-1.0 videotestsrc \
! 'video/x-raw, format=(string)I420, width=(int)640, height=(int)480' \
! omxh264enc ! 'video/x-h264, streamformat=(string)byte-stream' ! h264parse \
! qtmux ! filesink location=test.mp4 -e
gst-launch-1.0 videotestsrc \
! 'video/x-raw, format=(string)I420, width=(int)640, height=(int)480' \
! omxh264enc ! 'video/x-h264, stream•format=(string)byte-stream' ! h264parse \
! qtmux ! filesink location=test.mp4 -e
很多地方会直接说,将x264enc替换成x265enc就可以,其实并不是全对的,这两个插件有一些细微差别。
x265enc与x264enc sink PAD区别
# x265enc
SINK template: 'sink'
Availability: Always
Capabilities:
video/x-raw
format: { (string)I420, (string)Y444, (string)I420_10LE, (string)Y444_10LE }
framerate: [ 0/1, 2147483647/1 ]
width: [ 4, 2147483647 ]
height: [ 4, 2147483647 ]
# x264enc
SINK template: 'sink'
Availability: Always
Capabilities:
video/x-raw
framerate: [ 0/1, 2147483647/1 ]
width: [ 16, 2147483647 ]
height: [ 16, 2147483647 ]
format: { (string)Y444, (string)Y42B, (string)I420, (string)YV12, (string)NV12, (string)Y444_10LE, (string)I422_10LE, (string)I420_10LE }
可以以看到,有些格式的数据可以直接进x264enc,如Y42B、YV12、NV12、I422_10LE等,但是这些数据输入x265enc 插件就不支持。所以他们并不是能直接替换的,对于一样支持的数据格式来说,很多可以替换,对于有差异的数据格式来说,就没法替换了。
比如,上面USB相机输出的格式 YUYV 4:2:2,
如果实际应用中,从camera那边取到的数据流是UYVY的格式,但是gl显示或者图像处理的相关接口又需要用到BGR或I420(YV12或NV12)的格式,那么就需要进行转换。
x265enc使用原始的CPU为主的压缩插件
#x265enc 其输入为 video/x-raw ,输出为video/x-h264
# videoconvert 做格式转码 YUY2 转成 I420
# filesink location 老朋友了,保存文件
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=100 \
! 'video/x-raw, format=YUY2, width=640, height=480, framerate=25/1' \
! videoconvert ! video/x-raw,format=I420, width=640, height=480, framerate=25/1 \
! x265enc ! h265parse \
! matroskamux ! filesink location=/home/nvidia/Pictures/x265enc-video-640-480-25-100.mkv
执行命令前:
执行命令时,资源占用:
这个过程耗时很长。
omxh265enc使用硬件加速
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=100 \
! 'video/x-raw, format=YUY2, width=640, height=480, framerate=25/1' \
! videoconvert ! video/x-raw,format=I420, width=640, height=480, framerate=25/1 \
! omxh265enc ! h265parse \
! matroskamux ! filesink location=/home/nvidia/Pictures/omxh265enc-video-640-480-25-100.mkv
未执行命令前:
执行命令过程中:
大约耗时10秒,比CPU快很多。
其它一些示例:
#播放265压缩的文件
gst-launch-1.0 filesrc location=test.h265 ! h265parse ! omxh265dec ! nvoverlaysink
#保存265压缩文件至MKV格式
gst-launch-1.0 videotestsrc num-buffers=100 \
! 'video/x-raw, format=(string)I420, width=(int)640, height=(int)480' \
! omxh265enc ! matroskamux ! filesink location=/home/nvidia/Pictures/x265enc-video-640-480-100.mkv
#也可以进一步指定输入元素的帧率
gst-launch-1.0 videotestsrc num-buffers=100 \
! 'video/x-raw, format=(string)I420, width=(int)640, height=(int)480, framerate=25/1' \
! omxh265enc ! matroskamux ! filesink location=/home/nvidia/Pictures/x265enc-video-640-480-25-100.mkv
上一节我们说到omxh265enc 的时候提过格式转换,我们使用了videoconvert,这个其实也是一个CPU占用比较高的转换,Jetson TX1 也提供了硬件转换加速。
先举个小例子
gst-launch-1.0 videotestsrc num-buffers=500 \
! 'video/x-raw, format=(string)UYVY, width=(int)1280, height=(int)720' \
! nvvidconv \
! 'video/x-raw(memory:NVMM), format=(string)I420' \
! omxh264enc ! 'video/x-h264,stream-format=(string)byte-stream' \
! h264parse ! qtmux ! filesink location=/home/nvidia/Pictures/test-nvvidconv.mp4 -e
使用videotestsrc 生成UYVY 1280X720 尺寸的测试视频
使用nvvidconv 转换程格式video/x-rawI420
使用 omxh264enc 编码并保存到MP4文件中。
# omxh264enc 压缩,保存mp4文件
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=200 \
! 'video/x-raw,format=YUY2,width=640, height=480, framerate=25/1' \
! nvvidconv \
! 'video/x-raw(memory:NVMM), format=(string)I420, width=640, height=480, framerate=25/1' \
! omxh264enc ! h264parse \
! mp4mux ! filesink location=/home/nvidia/Pictures/omxh264enc-video-640-480-25-1000.mp4 -e
# omxh265enc 压缩,保存mkv文件
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=200 \
! 'video/x-raw,format=YUY2,width=640, height=480, framerate=25/1' \
! nvvidconv \
! 'video/x-raw(memory:NVMM), format=(string)I420, width=640, height=480, framerate=25/1' \
! omxh265enc ! matroskamux ! filesink location=/home/nvidia/Pictures/omxh265enc-video-640-480-25-200.mkv
# omxh265enc 压缩,保存MP4文件
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=300 \
! 'video/x-raw,format=YUY2,width=640, height=480, framerate=25/1' \
! nvvidconv \
! 'video/x-raw(memory:NVMM), format=(string)I420, width=640, height=480, framerate=25/1' \
! omxh265enc \
! qtmux ! filesink location=/home/nvidia/Pictures/omxh265enc-video-640-480-25-nvvidconv.mp4 -e
整体测试一遍后,其实发现确实硬件加速要快很多,而且CPU的负载要小很多,觉得后面有必整个都整理一下,没有必要纠结还有USB相机的源。
觉得以上有点用处,点个赞呗,谢谢。