AidStream-SDK
快速上手
C++示例代码
tip
使用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命令:
sh
需要注意的是在8550 / 6490 aibox平台执行:
#cmake ..
而在6490 QL平台则执行(这是因为6490 QL平台有不同的数据处理方式及不同的推理模型):
#cmake -DV4L2=ON ..然后执行make命令
sh
#make编译链接成功后会得到4个可执行程序: demo / qnn_rtsp / rtsp / start
设置配置文件之后,通过start可执行程序可以快速启动流(关于配置文件,请参考Reference):
sh
比如执行以下命令(1为stream id):
#start 1通过qnn_rtsp可执行程序可以快速启动自带模型推理的推拉流:
sh
与start类似启动:
#qnn_rtsp 1
模型目录:/usr/local/share/aidstream-gst/example/datas/通过rtsp可执行程序可以快速启动多线程的推拉流,当前示例设置为2个线程的推拉流,可通过修改代码实现多个线程推拉流。
sh
可直接执行:
#rtsp根据配置文件参数来选择输入输出流。关于配置文件,请参考Reference
cpp
#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;
}tips
<视频输入源> (例如rtsp://admin:aidlux123@192.168.110.234:554)
<视频输出推流> (例如rtsp://192.168.111.115:8554)读取rtsp流显示,不做任何处理,输出RTSP流到<视频输出推流>/aidstream-gst-rtsp-test
cpp
#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;
}根据参数同时开启多路流显示,不做任何处理
cpp
#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;
}模型执行异步处理,可用于模型推理时间较长的场景
tip
1. 由于该部分代码较多,下面仅贴出主函数部分,完整代码请参阅安装文件/usr/local/share/aidstream-gst/example/cxx/qnn_rtsp.cpp (对于6490 ql请参考qnn_rtsp_v4l2.cpp文件)
2. 对于追求实时性的推拉流而言,留给应用程序处理数据的时间窗口极短。比如,当帧率为25帧的时候,时间窗口仅20ms。所以异步处理属于一个折中方案。当模型推理时间太大的时候,异步处理虽能解决,但是在显示方面带来的体验感欠缺仍无法解决。总而言之,实时性与模型推理时间较长是一对不可调和的矛盾。cpp
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;
}C++ API预览
结构体(struct) | 成员变量名(public member variable) | 类型(Type) | 描述(Description) |
|---|---|---|---|
| Image | data | const char * | 指向存放数据的缓冲区的指针 |
| data_mask | const char * | 指向存放mask数据的缓冲区的指针(预留) | |
| stream_id | string | 标识stream流的唯一ID(必填,方便在多线程条件下定位) | |
| width | int | 目标图片宽度 | |
| height | int | 目标图片高度 | |
| width_padding | int | 目标图片宽度填充位(仅6490 ql使用) | |
| height_padding | int | 目标图片高度填充位(仅6490 ql使用) | |
| size | uint64_t | 图片数据所占内存长度 | |
| fps | double | 帧率 | |
| idx | uint64_t | 帧计数 | |
| frame_time | string | 帧时间戳(仅6490 ql使用) |
公共函数(public function) | 描述(Description) |
|---|---|
void clogger(const char* path_and_prefix) | 创建日志,设置文件名及路径 |
void set_log_level(GSTLogLevel log_level) | 设置日志级别 |
typedef function<int8_t( const Image & )> GetImageCB | 启流函数的入参,用于获取图片资源。此函数由使用者自定义。接口仅提供类型定义来规范回调函数的定义。 |
int start_stream(string stream_id, GetImageCB &cb) | 根据stream id 启动流(由于stream流配置繁多,建议通过配置文件的方式配置流,此接口为唯一建议使用接口) |
int start_stream_input_file(string file_path, GetImageCB cb, StreamType display_type, string target_path, int width, int height, string stream_id) | 启动文件流 |
int start_stream_input_rtsp(string rtsp_addr, GetImageCB cb, StreamType display_type, string target_path, int width, int height, string stream_id) | 启动RTSP流 |
int start_stream_input_rtmp(string rtmp_addr, GetImageCB cb, StreamType display_type, string target_path, int width, int height, string stream_id) | 启动RTMP流 |
枚举(ENUM) | 成员变量名(public member variable) | 类型(Type) | 描述(Description) |
|---|---|---|---|
| GSTLogLevel | SINFO | uint8_t | 日志级别SINFO |
| SWARNING | uint8_t | 日志级别SWARNING | |
| SERROR | uint8_t | 日志级别SERROR | |
| SDEBUG | uint8_t | 日志级别SDEBUG | |
| SOFF | uint8_t | 日志级别SOFF | |
| StreamType | EMPTY | uint8_t | 流协议类型为空 |
| WAYLANDSINK | uint8_t | 流协议类型为WayLand | |
| RTSPSINK | uint8_t | 流协议类型为RTSP | |
| RTMPSINK | uint8_t | 流协议类型为RTMP |
结构体Image
定义图片数据相关信息,包括图片配置信息及指针变量。
成员变量名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| data | const char * | 指向存放数据的缓冲区的指针 | |
| data_mask | const char * | 指向存放mask数据的缓冲区的指针(预留) | |
| stream_id | string | 标识stream流的唯一ID(必填,方便在多线程条件下定位) | |
| width | int | 图片宽度 | |
| height | int | 图片高度 | |
| width_padding | int | 目标图片宽度填充位(仅6490 ql使用) | |
| height_padding | int | 目标图片高度填充位(仅6490 ql使用) | |
| size | uint64_t | 图片数据所占内存长度 | |
| fps | double | 帧率 | |
| idx | uint64_t | 帧计数 | |
| frame_time | string | 帧时间戳(仅6490 ql使用) |
WARNING
如非特殊说明,所有的定义都属于名字空间Aidlux::AidStream。可通过以下命令在代码中引入:
using namespace Aidlux::AidStream;
根据stream id 启动流
API | int start_stream(string stream_id, GetImageCB &cb) |
|---|---|
| 描述 | 启动流。 入参为stream id。 stream id及对应配置定义在文件/usr/local/share/aidstream-gst/conf/aidstream-gst.conf中。 在此配置文件中stream id 要求唯一。 注:此接口为唯一强烈建议使用接口 |
| 参数 | stream_id:标识唯一的流配置。 cb:回调函数。关于回调函数,请参考回调函数。 关于如何设置配置文件,请参考Reference |
| 返回值 | 0:成功, -1: 失败 |
举例如下:
cpp
// 启动流,标识为stream1
int res = start_stream("stream1", my_cb);启动文件流
API | int start_stream_input_file(string file_path, GetImageCB cb, StreamType display_type, string target_path, int width, int height, string stream_id) |
|---|---|
| 描述 | 启动文件流。 不依赖配置文件,直接配置相应参数。 |
| 参数 | file_path:源MP4数据文件。 cb:回调函数。 display_type:输出流类型。 target_path:输出流目标地址。 注:width和height已无效 |
| 返回值 | 0:成功, -1:失败 |
举例如下:
cpp
// 启动文件流
int res = start_stream_input_file("./test.mp4", my_cb, StreamType::WAYLANDSINK, "<视频输出推流>/aidstream-gst-test-6");启动 RTSP 流
API | int start_stream_input_rtsp(string rtsp_addr, GetImageCB cb, StreamType display_type, string target_path, int width, int height, string stream_id) |
|---|---|
| 描述 | 启动rtsp流。 不依赖配置文件,直接配置相应参数。 |
| 参数 | rtsp_addr:源rtsp地址。 cb:回调函数。 display_type:输出流类型。 target_path:输出流目标地址。 注:width和height已无效 |
| 返回值 | 0:成功, -1: 失败 |
举例如下:
cpp
// 启动rtsp流
int res = start_stream_input_rtsp("<视频输入源>/h264/ch1/main/av_stream", my_cb, StreamType::RTSPSINK, "<视频输出推流>/aidstream-gst-test-3");启动 RTMP 流
API | int start_stream_input_rtmp(string rtmp_addr, GetImageCB cb, StreamType display_type, string target_path, int width, int height, string stream_id) |
|---|---|
| 描述 | 启动rtmp流。 不依赖配置文件,直接配置相应参数。 |
| 参数 | rtmp_addr:源rtmp地址。 cb:回调函数。 display_type:输出流类型。 target_path:输出流目标地址。 注:width和height已无效 |
| 返回值 | 0:成功, -1: 失败 |
举例如下:
cpp
// 启动rtmp流
int res = start_stream_input_rtmp("<视频输入源>/h264/ch1/main/av_stream", my_cb, StreamType::EMPTY, "<视频输出推流>/aidstream-gst-test-2");创建日志,设置文件名及路径(函数clogger)
API | void clogger(const char* path_and_prefix) |
|---|---|
| 描述 | 创建日志,设置文件名及路径 |
| 参数 | path_and_prefix:带路径的日志文件名。 例如: "./aidclog_aidstream_"。 |
| 返回值 | 无 |
举例如下:
cpp
// 创建日志,设置文件名及路径
const char* log_path = "./aidclog_aidstream_";
Aidlux::AidStream::clogger(log_path);设置日志级别(函数set_log_level)
API | void set_log_level(GSTLogLevel log_level) |
|---|---|
| 描述 | 设置日志级别。 |
| 参数 | log_level为GSTLogLevel类型的枚举。 关于GSTLogLevel请参考枚举GSTLogLevel |
| 返回值 | 无 |
举例如下:
cpp
//设置日志级别
Aidlux::AidStream::set_log_level(GSTLogLevel::SINFO);日志级别(枚举GSTLogLevel)
成员变量名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| SINFO | uint8_t | 0 | 日志级别SINFO |
| SWARNING | uint8_t | 日志级别SWARNING | |
| SERROR | uint8_t | 日志级别SERROR | |
| SDEBUG | uint8_t | 日志级别SDEBUG | |
| SOFF | uint8_t | 日志级别SOFF |
流类型(枚举StreamType流协议类型)
成员变量名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| EMPTY | uint8_t | 0 | 流协议类型为空 |
| WAYLANDSINK | uint8_t | 流协议类型为Wayland | |
| RTSPSINK | uint8_t | 流协议类型为rtsp | |
| RTMPSINK | uint8_t | 流协议类型为rtmp |
回调函数GetImageCB
API | typedef std::function<int8_t(const Image & )> GetImageCB |
|---|---|
| 描述 | 启流函数的入参,用于获取图片资源。此函数由使用者自定义。接口仅提供类型定义来规范回调函数的定义。 |
| 参数 | 参数一是结构体Image 的实例化对象,数据由此传入。 Image对象包括的参数有指向数据缓冲区的指针、数据宽高、帧率等。 具体请参考Image |
| 返回值 | 自定义 |
举例如下:
cpp
//回调函数定义
int8_t my_get_img_cb(const Image & img)
{
printf("width: %d, height: %d, fps: %f\n", img.width, img.height, img.fps);
......
return 0;
}