SDK 简介
简介
AidStream 是用来构建流媒体应用的视频框架,其目标是要简化视频+AI应用程序的开发中需要插入算法的程序构建。 AidStream 基于pipeline的概念,aidstream中的pipeline元素也非常简单,只分为输入端和输出端,使用函数调用即可,且在pipeline开始后时,sdk可以在输入端和输出端之间通过回调函数获取RGB数据,在回调函数中可以将此RGB数据经算法处理后再返回给pipeline,经处理后的RGB数据会继续pipeline的后续输出过程。 V3版本是对之前AidStream初始版本的一次重大升级。
处理流程:
快速上手
C++示例代码
使用AidStream SDK V3 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流显示,不做任何处理,输出RTSP流到rtsp://192.168.111.115:8554/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 = "rtsp://admin:aidlux123@192.168.110.234:554/h264/ch1/main/av_stream";
int res = start_stream_input_rtsp(rtsp_path, my_img_cb, StreamType::RTSPSINK, "rtsp://192.168.111.115:8554/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;
}
模型执行异步处理,可用于模型推理时间较长的场景
-
由于该部分代码较多,下面仅贴出主函数部分,完整代码请参阅安装文件/usr/local/share/aidstream-gst/example/cxx/qnn_rtsp.cpp (对于6490 ql请参考qnn_rtsp_v4l2.cpp文件)
-
对于追求实时性的推拉流而言,留给应用程序处理数据的时间窗口极短。比如,当帧率为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;
}