摄像头流媒体和多媒体
0. 引言
该项目通过各种接口和协议支持流式视频源和图像,包括:
- MIPI CSI摄像机
- V4L2摄像机
- RTP/RTSP协议
- 视频和图像
- 图像序列
- OpenGL窗口
1. 流媒体的 URI 标识
流通过资源URI标识,并通过videoSource和videoOutput api访问。下表显示了每种类型的流所支持的输入/输出协议和示例URI:
1.1 输入流
| . | Protocol Resource | URI | Notes |
|---|---|---|---|
| MIPI CSI 摄像头 | csi:// | csi://0 | CSI camera 0 (substitute other camera numbers for 0) |
| V4L2 摄像头 | v4l2:// | v4l2:///dev/video0 | V4L2 device 0 (substitute other camera numbers for 0) |
| RTP 流 | rtp:// | rtp://@:1234 localhost, port | 1234 (requires additional configuration) |
| RTSP 流 | rtsp:// | rtsp://<remote-ip>:1234 | Replace with remote host’s IP or hostname |
| 视频文件 | file:// | file://my_video.mp4 | Supports loading MP4, MKV, AVI, FLV (see codecs below) |
| 图像文件 | file:// | file://my_image.jpg | Supports loading JPG, PNG, TGA, BMP, GIF, ect. |
| 图像序列 | file:// | file://my_directory/ | Searches for images in alphanumeric order |
- 支持的解码器编解码器:H.264, H.265, VP8, VP9, MPEG-2, MPEG-4, MJPEG
file://,v4l2://, andcsi://协议前缀可以作为缩写从 URI 的地址中省略。
1.2 输出流
| . | Protocol | Resource URI | Notes |
|---|---|---|---|
| RTP 流 | rtp:// | rtp://:1234 | Replace with remote host’s IP or hostname |
| 视频文件 | file:// | file://my_video.mp4 | Supports saving MP4, MKV, AVI, FLV (see codecs below) |
| 图像文件 | file:// | file://my_image.jpg | Supports saving JPG, PNG, TGA, BMP |
| 图像序列 | file:// | file://image_%i.jpg | %i is replaced by the image number in the sequence |
| OpenGL 窗口 | display:// | display://0 | Creates GUI window on screen 0 |
- 支持的编码器: H.264, H.265, VP8, VP9, MJPEG
- file:// 协议前缀可以从URI中省略
- 默认情况下,除非指定–headless,否则将创建OpenGL显示窗口
2. 命令行参数
JETSON推理中的每个示例C++和Python程序都接受相同的命令行参数集,用于指定流URI和附加选项。因此,这些选项可以用于任何示例(例如 imagenet/imagenet.py, detectnet/detectnet.py, segnet/segnet.py, video-viewer/video-viewer.py 等)。这些命令行参数通常采用以下形式:
$ imagenet [options] input_URI [output_URI] # output URI is optional
其中输入和输出 URI 由两个位置参数指定。例如:
$ imagenet input.jpg output.jpg # classify input.jpg, save as output.jpg
如上所述,这里可以替换来自jetson推断的任何示例,因为它们使用相同的命令行解析。以下是运行每个程序时可以指定的其他流选项:
2.1 Input Options
input_URI resource URI of the input stream (see table above)
--input-width=WIDTH explicitly request a resolution of the input stream
--input-height=HEIGHT (resolution is optional, except required for RTP)
--input-codec=CODEC RTP requires the codec to be set, one of these:
* h264, h265
* vp8, vp9
* mpeg2, mpeg4
* mjpeg
--input-flip=FLIP flip method to apply to input (excludes V4L2):
* none (default)
* counterclockwise
* rotate-180
* clockwise
* horizontal
* vertical
* upper-right-diagonal
* upper-left-diagonal
--input-loop=LOOP for file-based inputs, the number of loops to run:
* -1 = loop forever
* 0 = don't loop (default)
* >0 = set number of loops
2.2 输出选项
output_URI resource URI of the output stream (see table above)
--output-codec=CODEC desired codec for compressed output streams:
* h264 (default), h265
* vp8, vp9
* mpeg2, mpeg4
* mjpeg
--bitrate=BITRATE desired target VBR bitrate for compressed streams,
in bits per second. The default is 4000000 (4 Mbps)
--headless don't create a default OpenGL GUI window
下面是在各种类型的流上启动视频查看器工具的命令示例。在这些命令中,您可以用其他程序代替video viewer,因为它们解析相同的参数。在本页的源代码部分,您可以浏览视频查看器源代码的内容,以显示如何在自己的应用程序中使用videoSource和videoOutput API。
3. MIPI CSI摄像头
MIPI CSI摄像头是由Jetson的硬件CSI/ISP接口直接获取的紧凑型传感器。支持的CSI摄像机包括:
- 用于Jetson Nano和Jetson Xavier NX的Raspberry Pi摄像头模块v2(IMX219)
- 来自Jetson TX1/TX2 devkits的OV5693摄像头模块。
- 有关生态系统支持的更多传感器,请参阅Jetson Partner Supported Cameras页面。
下面是一些使用MIPI CSI相机启动的示例。如果您连接了多个CSI摄像头,请将摄像头编号替换为0:
$ video-viewer csi://0 # MIPI CSI camera 0 (substitue other camera numbers)
$ video-viewer csi://0 output.mp4 # save output stream to MP4 file (H.264 by default)
$ video-viewer csi://0 rtp://<remote-ip>:1234 # broadcast output stream over RTP to <remote-ip>
默认情况下,将创建分辨率为1280x720的CSI相机。要指定不同的分辨率,请使用–input-width 和 input-height 选项。请注意,指定的分辨率必须与相机支持的格式之一匹配。
$ video-viewer --input-width=1920 --input-height=1080 csi://0
4. V4L2摄像机
USB网络摄像头通常作为V4L2设备支持,例如Logitech C270或C920。
$ video-viewer v4l2:///dev/video0 # /dev/video0 can be replaced with /dev/video1, ect.
$ video-viewer /dev/video0 # dropping the v4l2:// protocol prefix is fine
$ video-viewer /dev/video0 output.mp4 # save output stream to MP4 file (H.264 by default)
$ video-viewer /dev/video0 rtp://<remote-ip>:1234 # broadcast output stream over RTP to <remote-ip>
注意:如果您插入了MIPI CSI摄像机,它也会显示为/dev/video0。然后,如果您插入一个USB网络摄像头,它将显示为/dev/video1,因此您需要在上面的命令中替换/dev/video1。在这个项目中不支持通过V4L2使用CSI摄像机,因为通过V4L2他们使用的是没有ISP的原始Bayer(相反,使用如上所示的CSI摄像机)。
4.1 V4L2格式
默认情况下,V4L2相机将使用与所需分辨率最接近的最高帧速率的相机格式创建(默认情况下,该分辨率为1280x720)。具有最高帧速率的格式可以被编码(例如用H.264或MJPEG),因为USB相机通常以较低的帧速率传输未压缩的YUV/RGB。在这种情况下,将检测到该编解码器,并且将使用Jetson的硬件解码器自动解码相机流以获得最高帧速率。
如果您显式地想要选择V4L2相机使用的格式,那么可以使用–input width、–input height和–input codec选项进行选择。可能的解码器编解码器选项有–input codec=h264、h265、vp8、vp9、mpeg2、mpeg4、mjpeg。
$ video-viewer --input-width=1920 --input-height=1080 --input-codec=h264 /dev/video0
在V4L2源上运行jetson推断程序之一时,V4L2摄像头支持的不同格式将记录到终端。但是,您也可以使用v4l2-ctl命令列出这些受支持的格式:
$ sudo apt-get install v4l-utils
$ v4l2-ctl --device=/dev/video0 --list-formats-ext
5. RTP
RTP网络流通过UDP/IP广播到特定主机或多播组。接收RTP流时,必须指定编解码器(–input codec),因为RTP无法动态查询此编解码器。这将使用RTP作为另一个设备的输入:
$ video-viewer --input-codec=h264 rtp://@:1234 # recieve on localhost port 1234
$ video-viewer --input-codec=h264 rtp://224.0.0.0:1234 # subscribe to multicast group
上面的命令指定RTP作为输入源,其中网络上的另一个远程主机正在流式传输到Jetson。但是,您也可以从Jetson输出RTP流,并将其传输到网络上的另一个远程主机。
5.1 传输RTP
要传输RTP输出流,请将目标IP/端口指定为输出URI。如果需要,可以指定比特率(默认为–bitrate=4000000或4Mbps)和/或输出编解码器(默认为–output codec=h264),可以是h264、h265、vp8、vp9、mjpeg。
$ video-viewer --bitrate=1000000 csi://0 rtp://<remote-ip>:1234 # transmit camera over RTP, encoded as H.264 @ 1Mbps
$ video-viewer --output-codec=h265 my_video.mp4 rtp://<remote-ip>:1234 # transmit a video file over RTP, encoded as H.265
在输出RTP时,需要显式设置流发送到的远程主机(或多播组)的IP地址或主机名(如上所示为)。有关从PC查看RTP流的一些指针,请参见下文。
5.2 远程查看RTP
如果您的Jetson正在将RTP传输到另一个远程主机(如PC),下面是一些用于查看流的示例命令:
- 使用GStreamer:
安装GStreamer并运行此管道(用您正在使用的端口替换port=1234)
$ gst-launch-1.0 -v udpsrc port=1234 \
caps = "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96" ! \
rtph264depay ! decodebin ! videoconvert ! autovideosink
- 使用VLC播放器:
创建一个包含以下内容的SDP文件(.SDP)(用您正在使用的端口替换1234)
通过双击SDP文件在VLC中打开流
您可能希望减少VLC中的文件缓存和网络缓存设置,如下所示
c=IN IP4 127.0.0.1
m=video 1234 RTP/AVP 96
a=rtpmap:96 H264/90000
- 如果您的远程主机是另一个Jetson:
使用与上述相同的视频查看器命令(将1234替换为您正在使用的端口)
$ video-viewer --input-codec=h264 rtp://@:1234
6. RTSP
RTSP网络流通过UDP/IP从远程主机订阅。与RTP不同,RTSP可以动态查询流属性(如分辨率和编解码器),因此不需要显式提供这些选项。
$ video-viewer rtsp://<remote-ip>:1234 my_video.mp4 # subscribe to RTSP feed from <remote-ip>, port 1234 (and save it to file)
$ video-viewer rtsp://username:password@<remote-ip>:1234 # with authentication (replace username/password with credentials)
注意:RTSP仅支持作为输入。输出RTSP需要GStreamer对RTSP服务器的额外支持。
7. 视频文件
您可以播放和录制MP4、MKV、AVI和FLV格式的视频文件。
# playback
$ video-viewer my_video.mp4 # display the video file
$ video-viewer my_video.mp4 rtp://<remote-ip>:1234 # transmit the video over RTP
# recording
$ video-viewer csi://0 my_video.mp4 # record CSI camera to video file
$ video-viewer /dev/video0 my_video.mp4 # record V4L2 camera to video file
7.1 编解码器
加载视频文件时,会自动检测编解码器和分辨率,因此不需要设置这些。保存视频文件时,默认的编解码器是H.264,但可以使用--output-codec选项进行设置。
$ video-viewer --output-codec=h265 input.mp4 output.mp4 # transcode video to H.265
支持以下编解码器:
- Decode - H.264, H.265, VP8, VP9, MPEG-2, MPEG-4, MJPEG
- Encode - H.264, H.265, VP8, VP9, MJPEG
7.2 调整输入大小
加载视频文件时,会自动检测分辨率。但是,如果希望将输入视频重新缩放为其他分辨率,可以指定–input-width和–input-height选项:
$ video-viewer --input-width=640 --input-height=480 my_video.mp4 # resize video to 640x480
7.3 循环输入
默认情况下,一旦到达流结束(EOS),视频将终止。但是,通过指定–loop选项,可以设置希望视频运行的循环数。–loop的可能选项有:
- 1 = loop forever
- 0 = don’t loop (default)
- > 0 = set number of loops
$ video-viewer --loop=10 my_video.mp4 # loop the video 10 times
$ video-viewer --loop=-1 my_video.mp4 # loop the video forever (until user quits)
8. 图像文件
可以按以下格式加载/保存图像文件:
- 读取: JPG, PNG, TGA, BMP, GIF, PSD, HDR, PIC, and PNM (PPM/PGM binary)
- 保存: JPG, PNG, TGA, BMP
$ video-viewer input.jpg output.jpg # load/save an image
您还可以循环图像和图像序列-请参阅上面的循环输入部分。
8.1 序列
如果路径是目录或包含通配符,则所有图像都将按顺序加载/保存(按字母数字顺序)。
$ video-viewer input_dir/ output_dir/ # load all images from input_dir and save them to output_dir
$ video-viewer "*.jpg" output_%i.jpg # load all jpg images and save them to output_0.jpg, output_1.jpg, ect
注意:使用通配符时,请始终将其括在引号(“*.jpg”)中。否则,操作系统将自动扩展序列并修改命令行上参数的顺序,这可能会导致其中一个输入图像被输出覆盖。
保存一系列图像时,如果路径仅指向一个目录(output_dir),则图像将自动保存为JPG,格式为output_dir/%i.jpg,使用图像编号作为文件名(output_dir/0.jpg、output_dir/1.jpg 等)。
如果要指定文件名格式,请在路径(output_dir/image_%i.png)中使用printf样式 %i。可以应用其他printf修饰符(如%04i)来创建文件名,如output_dir/image_0001.jpg。
9. 源代码
使用videoSource和videoOutput对象访问流。它们能够通过一组统一的api来处理上述每种类型的流。可以以下列数据格式捕获和输出图像:
| Format string | imageFormat enum | Data Type | Bit Depth |
|---|---|---|---|
| rgb8 | IMAGE_RGB8 | uchar3 | 24 |
| rgba8 | IMAGE_RGBA8 | uchar4 | 32 |
| rgb32f | IMAGE_RGB32F | float3 | 96 |
| rgba32f | IMAGE_RGBA32F | float4 | 128 |
- 数据类型和 imageFormat 是C++类型
- 在Python中,格式字符串可以传递给视频源。捕获()请求特定格式(默认为 rgb8)
- 在C++中,videoSource::Capture() 模板将从输出指针的数据类型推断格式。
要将图像转换为/从不同格式转换,请参阅“使用CUDA进行图像处理”页面以获取更多信息。
下面是video-viewer.py和video-viewer.cpp,略略缩略,以提高可读性:
9.1 Python 源代码
import jetson.utils
import argparse
import sys
# parse command line
parser = argparse.ArgumentParser()
parser.add_argument("input_URI", type=str, help="URI of the input stream")
parser.add_argument("output_URI", type=str, default="", nargs='?', help="URI of the output stream")
opt = parser.parse_known_args()[0]
# create video sources & outputs
input = jetson.utils.videoSource(opt.input_URI, argv=sys.argv)
output = jetson.utils.videoOutput(opt.output_URI, argv=sys.argv)
# capture frames until user exits
while output.IsStreaming():
image = input.Capture(format='rgb8') // can also be format='rgba8', 'rgb32f', 'rgba32f'
output.Render(image)
output.SetStatus("Video Viewer | {:d}x{:d} | {:.1f} FPS".format(image.width, image.height, output.GetFrameRate()))
9.2 C++ 源代码
#include "videoSource.h"
#include "videoOutput.h"
int main( int argc, char** argv )
{
// create input/output streams
videoSource* inputStream = videoSource::Create(argc, argv, ARG_POSITION(0));
videoOutput* outputStream = videoOutput::Create(argc, argv, ARG_POSITION(1));
if( !inputStream )
return 0;
// capture/display loop
while( true )
{
uchar3* nextFrame = NULL; // can be uchar3, uchar4, float3, float4
if( !inputStream->Capture(&nextFrame, 1000) )
continue;
if( outputStream != NULL )
{
outputStream->Render(nextFrame, inputStream->GetWidth(), inputStream->GetHeight());
// update status bar
char str[256];
sprintf(str, "Video Viewer (%ux%u) | %.1f FPS", inputStream->GetWidth(), inputStream->GetHeight(), outputStream->GetFrameRate());
outputStream->SetStatus(str);
// check if the user quit
if( !outputStream->IsStreaming() )
break;
}
if( !inputStream->IsStreaming() )
break;
}
// destroy resources
SAFE_DELETE(inputStream);
SAFE_DELETE(outputStream);
}
注意,C++ 代码编译时,需要自己编写 CMakeLists.txt 文件。该文件编写模板,参见:

本文档详细介绍了在英伟达Jetson平台上处理摄像头流媒体和多媒体的程序设计,涵盖MIPI CSI摄像头、V4L2摄像机、RTP/RTSP协议、视频文件和图像文件等,提供了多种接口和协议的支持,并给出了相应的命令行参数和源代码示例。
1万+

被折叠的 条评论
为什么被折叠?



