Skip to content

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)
Imagedataconst char *指向存放数据的缓冲区的指针
data_maskconst char *指向存放mask数据的缓冲区的指针(预留)
stream_idstring标识stream流的唯一ID(必填,方便在多线程条件下定位)
widthint目标图片宽度
heightint目标图片高度
width_paddingint目标图片宽度填充位(仅6490 ql使用)
height_paddingint目标图片高度填充位(仅6490 ql使用)
sizeuint64_t图片数据所占内存长度
fpsdouble帧率
idxuint64_t帧计数
frame_timestring帧时间戳(仅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)
GSTLogLevelSINFOuint8_t日志级别SINFO
SWARNINGuint8_t日志级别SWARNING
SERRORuint8_t日志级别SERROR
SDEBUGuint8_t日志级别SDEBUG
SOFFuint8_t日志级别SOFF
StreamTypeEMPTYuint8_t流协议类型为空
WAYLANDSINKuint8_t流协议类型为WayLand
RTSPSINKuint8_t流协议类型为RTSP
RTMPSINKuint8_t流协议类型为RTMP

结构体Image

定义图片数据相关信息,包括图片配置信息及指针变量。

成员变量名类型默认值描述
dataconst char *指向存放数据的缓冲区的指针
data_maskconst char *指向存放mask数据的缓冲区的指针(预留)
stream_idstring标识stream流的唯一ID(必填,方便在多线程条件下定位)
widthint图片宽度
heightint图片高度
width_paddingint目标图片宽度填充位(仅6490 ql使用)
height_paddingint目标图片高度填充位(仅6490 ql使用)
sizeuint64_t图片数据所占内存长度
fpsdouble帧率
idxuint64_t帧计数
frame_timestring帧时间戳(仅6490 ql使用)

WARNING

如非特殊说明,所有的定义都属于名字空间Aidlux::AidStream。可通过以下命令在代码中引入:

using namespace Aidlux::AidStream;

根据stream id 启动流

APIint 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);

启动文件流

APIint 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 流

APIint 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 流

APIint 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)

APIvoid 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)

APIvoid set_log_level(GSTLogLevel log_level)
描述设置日志级别。
参数log_level为GSTLogLevel类型的枚举。
关于GSTLogLevel请参考枚举GSTLogLevel
返回值

举例如下:

cpp
//设置日志级别
Aidlux::AidStream::set_log_level(GSTLogLevel::SINFO);

日志级别(枚举GSTLogLevel)

成员变量名类型默认值描述
SINFOuint8_t0日志级别SINFO
SWARNINGuint8_t日志级别SWARNING
SERRORuint8_t日志级别SERROR
SDEBUGuint8_t日志级别SDEBUG
SOFFuint8_t日志级别SOFF

流类型(枚举StreamType流协议类型)

成员变量名类型默认值描述
EMPTYuint8_t0流协议类型为空
WAYLANDSINKuint8_t流协议类型为Wayland
RTSPSINKuint8_t流协议类型为rtsp
RTMPSINKuint8_t流协议类型为rtmp

回调函数GetImageCB

APItypedef 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;
}