AidStream 开发者文档
简介
AidStream 是用来构建流媒体应用的视频框架,其目标是要简化视频+AI应用程序的开发中需要插入算法的程序构建。 AidStream 基于pipeline的概念,aidstream中的pipeline元素也非常简单,只分为输入端和输出端,使用函数调用即可,且在pipeline开始后时,sdk可以在输入端和输出端之间通过回调函数获取RGB数据,在回调函数中可以将此RGB数据经算法处理后再返回给pipeline,经处理后的RGB数据会继续pipeline的后续输出过程。 V3版本是对之前AidStream初始版本的一次重大升级。
AidStream通用流程如下图所示:

通用示例参考
**💡💡注意💡💡**
<自定义输入地址:视频源地址>:摄像头IP地址
例如 "rtsp://admin:aidlux123@192.168.111.236:554/h264/ch1/main/av_stream"
<自定义输出地址:流媒体服务器地址>:可以将视频流推入的地址
例如 "rtsp://admin:aidlux123@192.168.111.115:8554/test-111"系统版本ubuntu2204-硬件型号8550
<示例:基于 Aidlite 工具链的使用示例>
gst-launch-1.0 -e rtspsrc location=<自定义输入地址:视频源地址> latency=200 protocols=tcp \
! rtph264depay ! h264parse config-interval=-1 ! qtic2vdec ! qtivtransform engine=2 \
! video/x-raw\(memory:GBM\),format=NV12,width=3840,height=2160,framerate=25/1 ! tee name=t \
t. ! queue ! qtimetamux name=mux \
t. ! queue max-size-buffers=4 max-size-bytes=0 max-size-time=0 \
! qtivtransform engine=2 ! video/x-raw\(memory:GBM\),format=BGR,width=640,height=640 \
! videorate ! video/x-raw\(memory:GBM\),format=BGR,width=640,height=640,framerate=25/1 \
! ast-aidlite model=./cutoff_yolov5s_sigmoid_qcs8550_w8a8.qnn236.ctx.bin roi-width=3840 roi-height=2160 ! text/x-raw,format=utf8 ! mux. \
mux.src ! qtioverlay ! qtic2venc ! h264parse ! rtspclientsink protocols=tcp location=<自定义输出地址:流媒体服务器地址>编码插件:qtic2venc 解码插件:qtic2vdec
系统版本ubuntu2204-硬件型号6490-932
gst-launch-1.0 rtspsrc location=<自定义输入地址:视频源地址> \
! rtph264depay \
! h264parse \
! v4l2h264dec capture-io-mode=5 output-io-mode=2 \
! qtivtransform \
! video/x-raw,format=RGB \
! qtivtransform \
! video/x-raw\(memory:GBM\),format=NV12,colorimetry=bt601 \
! v4l2h264enc capture-io-mode=2 output-io-mode=5 \
! h264parse \
! rtspclientsink location=<自定义输出地址:流媒体服务器地址>该实例中用到了如下插件:
系统版本ubuntu2404-硬件型号6490-932
gst-launch-1.0 rtspsrc location=<自定义输入地址:视频源地址> latency=200 protocols=tcp \
! rtph264depay \
! h264parse \
! v4l2h264dec capture-io-mode=4 output-io-mode=4 \
! video/x-raw,format=NV12,colorimetry=bt709 \
! qtivtransform engine=3 \
! video/x-raw,format=RGB,colorimetry=bt709 \
! qtivtransform engine=3 \
! video/x-raw,format=NV12,colorimetry=bt709 \
! v4l2h264enc capture-io-mode=4 output-io-mode=4 \
! h264parse \
! rtspclientsink location=<自定义输出地址:流媒体服务器地址>该实例中用到了如下插件:
**💡💡6490 aidlux2204融合系统 执行时请设置以下环境变量💡💡**
export GST_PLUGIN_PATH=/opt/ubun20/usr/lib/aarch64-linux-gnu/gstreamer-1.0/ && export
LD_LIBRARY_PATH=/opt/ubun20/usr/lib/aarch64-linux-gnu/:/opt/ubun20/usr/lib:/usr/local/lib/aidlux_opencv/lib/:$LD_LIBRARY_PATH系统版本aidlux2204融合系统-硬件型号6490-932
gst-launch-1.0 rtspsrc location=<自定义输入地址:视频源地址> \
! rtph264depay \
! h264parse \
! qtivdec \
! qtivtransform \
! video/x-raw,format=RGB \
! qtivtransform \
! qtic2venc \
! video/x-h264,profile=baseline \
! h264parse \
! rtspclientsink location=<自定义输出地址:流媒体服务器地址>该实例中用到了如下插件:
编码插件:qtic2venc 解码插件:qtivdec
系统版本aidlux2404融合系统-硬件型号6490-932
gst-launch-1.0 rtspsrc location=<自定义输入地址:视频源地址> \
! rtph264depay \
! h264parse \
! qtivdec \
! qtivtransform \
! video/x-raw,format=RGB \
! qtivtransform \
! qtic2venc \
! video/x-h264,profile=baseline \
! h264parse \
! rtspclientsink location=<自定义输出地址:流媒体服务器地址>编码插件:qtic2venc 解码插件:qtivdec
该实例中用到了如下插件:
系统版本ubuntu2404-硬件型号8550-972
H.264
gst-launch-1.0 rtspsrc location=<自定义输入地址:视频源地址> \
! rtph264depay \
! h264parse \
! qtic2vdec \
! qtivtransform engine=2 \
! video/x-raw,format=RGB \
! qtivtransform engine=2 \
! qtic2venc \
! queue \
! h264parse \
! rtspclientsink protocols=tcp location=<自定义输出地址:流媒体服务器地址>该实例中用到了如下插件:
编码插件:qtic2venc 解码插件:qtic2vdec
纯四合一
<1920,1080> 可替换为其他可用分辨率如<3840,2160>export WAYLAND_DISPLAY=wayland-1 && export XDG_RUNTIME_DIR=/run/user/root && gst-launch-1.0 -e qtivcomposer name=mixer \
sink_0::position="<0, 0>" sink_0::dimensions="<1920, 1080>" \
sink_1::position="<1920, 0>" sink_1::dimensions="<1920, 1080>" \
sink_2::position="<0, 1080>" sink_2::dimensions="<1920, 1080>" \
sink_3::position="<1920, 1080>" sink_3::dimensions="<1920, 1080>" \
! video/x-raw\(memory:GBM\),format=NV12,width=3840,height=2160 ! qtic2venc ! h264parse config-interval=1 ! rtspclientsink protocols=tcp location=<自定义输出地址:流媒体服务器地址> \
rtspsrc location=<自定义输入地址:视频源地址> latency=100 ! rtph264depay ! h264parse config-interval=-1 ! qtic2vdec ! qtivtransform engine=2 ! mixer. \
rtspsrc location=<自定义输入地址:视频源地址> latency=100 ! rtph264depay ! h264parse config-interval=-1 ! qtic2vdec ! qtivtransform engine=2 ! mixer. \
rtspsrc location=<自定义输入地址:视频源地址> latency=100 ! rtph264depay ! h264parse config-interval=-1 ! qtic2vdec ! qtivtransform engine=2 ! mixer. \
rtspsrc location=<自定义输入地址:视频源地址> latency=100 ! rtph264depay ! h264parse config-interval=-1 ! qtic2vdec ! qtivtransform engine=2 ! mixer.该实例中用到了如下插件:
编码插件:qtic2venc 解码插件:qtic2vdec
H.265
gst-launch-1.0 rtspsrc location=<自定义输入地址:视频源地址> \
! rtph265depay \
! h265parse \
! qtic2vdec \
! qtivtransform engine=2 \
! video/x-raw,format=RGB \
! qtivtransform engine=2 \
! qtic2venc \
! queue \
! h265parse \该实例中用到了如下插件:
编码插件:qtic2venc 解码插件:qtic2vdec
C++示例代码
使用AidStream SDK C++ API编译,需要引入AidStream SDK 头文件:
#include "aidstream.h"
链接时需要指定AidStream SDK so库,例如:
g++ example.cpp -o demo -L/usr/local/lib/ -laidstream-gst -lopencv_core -I/usr/local/include/aidlux/aidstream-gst/ -I/usr/local/lib/aidlux_opencv/include/opencv4/
AidStream SDK 头文件地址: /usr/local/include/aidlux/aidstream-gst/aidstream.h
AidStream SDK 库文件地址: /usr/local/lib/libaidstream-gst.so
在应用程序中,唯一建议使用的接口函数为:
int start_stream(string stream_id, GetImageCB &cb)
该函数配合配置文件/usr/local/share/aidstream-gst/conf/aidstream-gst.conf使用。(由于stream流配置繁多,强烈建议通过配置文件的方式起流)
安装程序自带example示例及相应的CMakeLists.txt,可到安装目录/usr/local/share/aidstream-gst/example/cxx/下查看。具体操作请参考以下介绍。根据样例程序来实现推拉流(提前配置好公共配置文件)。关于配置文件,请参考Reference
配置文件为默认公共配置文件aidstream-gst.conf,位于目录:/usr/local/share/aidstream-gst/conf/下。
具体编译执行操作方法如下:
进入/usr/local/share/aidstream-gst/example/cxx/目录,创建build目录,然后进入build目录。
在build目录里执行cmake命令:
需要注意的是在8550 / 6490 aibox平台执行:
#cmake ..
而在6490 QL平台则执行(这是因为6490 QL平台有不同的数据处理方式及不同的推理模型):
#cmake -DV4L2=ON ..然后执行make命令
#make编译链接成功后会得到4个可执行程序: demo / qnn_rtsp / rtsp / start
设置配置文件之后,通过start可执行程序可以快速启动流(关于配置文件,请参考Reference):
比如执行以下命令(1为stream id):
#start 1通过qnn_rtsp可执行程序可以快速启动自带模型推理的推拉流:
与start类似启动:
#qnn_rtsp 1
模型目录:/usr/local/share/aidstream-gst/example/datas/通过rtsp可执行程序可以快速启动多线程的推拉流,当前示例设置为2个线程的推拉流,可通过修改代码实现多个线程推拉流。
可直接执行:
#rtsp根据配置文件参数来选择输入输出流。关于配置文件,请参考Reference
#include <cstdlib>
#include <string>
#include <iostream>
#include "aidstream.h"
using namespace std;
using namespace Aidlux::AidStream;
int8_t my_img_cb(const Image &img)
{
printf("width: %d, height: %d, fps: %f, id:%s \n", img.width, img.height, img.fps, img.stream_id.c_str());
return 0;
}
int main(int argc, char* argv[])
{
string _idx;
if (argc > 1)
{
_idx = argv[1];
}
else
{
_idx = "1";
}
Aidlux::AidStream::GetImageCB callback = my_img_cb;
start_stream(_idx, callback);
return 0;
}<视频输入源> (例如rtsp://admin:aidlux123@192.168.110.234:554)
<视频输出推流> (例如rtsp://192.168.111.115:8554)读取rtsp流显示,不做任何处理,输出RTSP流到<视频输出推流>/aidstream-gst-rtsp-test
#include <cstdlib>
#include <string>
#include <iostream>
#include "aidstream.h"
using namespace std;
using namespace Aidlux::AidStream;
int8_t my_img_cb(const Image &img)
{
printf("width: %d, height: %d, fps: %f\n", img.width, img.height, img.fps);
return 0;
}
int main()
{
string rtsp_path = "<视频输入源>/h264/ch1/main/av_stream";
int res = start_stream_input_rtsp(rtsp_path, my_img_cb, StreamType::RTSPSINK, "<视频输出推流>/aidstream-gst-rtsp-test");
if(res != 0)
{
return -1;
}
return 0;
}<根据参数同时开启多路流显示,不做任何处理>
#include <cstdlib>
#include <thread>
#include <string>
#include <iostream>
#include "aidstream.h"
using namespace std;
using namespace Aidlux::AidStream;
int8_t my_img_cb(const Image &img)
{
printf("width: %d, height: %d, fps: %f\n", img.width, img.height, img.fps);
return 0;
}
int main(int argc, char* argv[])
{
clogger("./aidclog_aidstream_c");
set_log_level(GSTLogLevel::SINFO);
Aidlux::AidStream::GetImageCB callback = my_img_cb;
std::thread t1(start_stream, "1", ref(callback));
std::thread t2(start_stream, "7", ref(callback));
t1.join();
t2.join();
return 0;
}模型执行异步处理,可用于模型推理时间较长的场景
1. 由于该部分代码较多,下面仅贴出主函数部分,完整代码请参阅安装文件/usr/local/share/aidstream-gst/example/cxx/qnn_rtsp.cpp (对于6490 ql请参考qnn_rtsp_v4l2.cpp文件)
2. 对于追求实时性的推拉流而言,留给应用程序处理数据的时间窗口极短。比如,当帧率为25帧的时候,时间窗口仅20ms。所以异步处理属于一个折中方案。当模型推理时间太大的时候,异步处理虽能解决,但是在显示方面带来的体验感欠缺仍无法解决。总而言之,实时性与模型推理时间较长是一对不可调和的矛盾。int main(int argc, char *argv[]) {
// 日志开关, 一般情况可不设置
// Aidlux::AidClog::clog_log_to_file("./snpe2_yolov5_multi_");
// Aidlux::AidClog::clog_set_log_level(Aidlux::AidClog::LogLevel::INFO);
init_share_mem_vec();
if (argc < 1) {
std::cerr << "Parameter missing, param1: streamId[reference /usr/local/share/aidstream-gst/conf/aidstream-gst.conf file]. eg: ./example 7" << std::endl;
return -1;
}
int r = model_init();
if (r != 0)
{
std::cerr << "model init failed" << std::endl;
exit(1);
}
Aidlux::AidStream::GetImageCB callback = myCallback;
std::set<std::string> validIDs = loadValidIDs();
std::vector<std::thread> threads;
bool allIDsFound = true;
std::string arg = argv[1];
// 配置文件有id才启线程
if (validIDs.find(arg) == validIDs.end())
{
allIDsFound = false;
}
if (!allIDsFound)
{
std::cerr << "Parameter has an id that is not included in the configuration file, please check" << std::endl;
return -1;
}
else
{
// gstreamer取数据主线程
threads.emplace_back(start_stream, arg, ref(callback));
// 启动三个模型推理处理线程
// 具体启动多少个线程需要依据模型推理时间长短,模型推理时间越长需要启动的线程数越多。比如推理时间在50 ~ 60ms,则启动3个线程已能应对。
// 如果模型不支持并发,则只需要配置一个推理线程
threads.emplace_back(update_data, 1);
threads.emplace_back(update_data, 2);
threads.emplace_back(update_data, 3);
}
for (auto &t : threads)
{
if (t.joinable())
{
t.join();
}
}
return 0;
}