AidStream SDK for C++
简介
AidStream 是用来构建流媒体应用的视频框架,其目标是要简化视频+AI应用程序的开发中需要插入算法的程序构建。 AidStream 以 pipeline 为基础,开发者需要为每条 pipeline 配置 输入流 与 输出流 信息。 在一条完整的 pipeline 中,数据从 输入流 流出,开发者可以通过 AidStream 的 api 获取对应的 RGB 数据,并在处理后输入到 输出流 中。
功能说明
现有的pipeline有
0.拉流->显示(用于测试网路流)
1.获取RTSP流->解码->处理->显示
2.获取RTSP流->解码->处理->编码->推送RTSP流
3.获取RTSP流->解码->处理->编码->推送RTSP流&&保存MPEG-4
4.原生相机->处理->显示
5.原生相机->处理->推送RTSP流
6.UVC相机->处理->显示
7.MPEG-4->处理->推送RTSP流&&保存MPEG-4
8.仅解码
9.仅编码->推送RTSP流&&保存MPEG-4
备注: 原生相机、UVC相机只支持1路1920*1080,文件路径只能只能配置一路,且是sdcard路径。
上述pipeline中的处理环节需要自己去实现,即获取到解码转后后rgb数据后经过处理后送回到pipeline的编码入口。
现有的pipeline实现原理上基于不同的输入流和输出流的组合,如下方表格所示:
输入 \ 输出 | null | rtsp | file | screan | rtsp & file |
---|---|---|---|---|---|
null | ❌ | ✔️ | ❌ | ❌ | ❌ |
rtsp | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
file | ❌ | ❌ | ❌ | ❌ | ✔️ |
mipi_camera | ❌ | ✔️ | ❌ | ✔️ | ❌ |
usb_camera | ❌ | ❌ | ❌ | ✔️ | ❌ |
快速上手
使用 Aidlite-SDK C++ 开发需要了解如下事项:
- 编译时需要包含头文件,存放路径 /usr/local/include/aidlux/aidstream/aidstream.h
- 链接时需要指定库文件,存放路径 /usr/local/lib/libaidstream.so
拉流加显示
访问远端RTSP链接,获取h265/h264的数据,通过解码和颜色空间转换后,获取rgb数据,处理后再发送到显示端。
#include "aidstream.h"
std::string config = "[{\"inputUrl\": \"rtsp://192.168.110.38:8554/a\"},{\"inputUrl\": \"rtsp://192.168.110.38:8554/b\"},{ \"inputUrl\": \"rtsp://192.168.110.38:8554/c\"},{\"inputUrl\": \"rtsp://192.168.110.38:8554/d\"}]";
// 此处使用的 inputUrl 仅供参考,请使用你的 rtsp 视频流地址替换它们
//创建Android对象
Android android;
void start(int index)
{
while (true)
{
char *buffer;
// 获取解码后的rgb数据,index对应配置文件中的顺序
int64_t size = android.getRGB(&buffer, index);
std::cout<<"size:"<<size<<std::endl;
//这里可以作rgb处理
// 塞入到显示的buffer中
int8_t result1 = android.pushBufferForDisplay(buffer, index);
}
}
int main()
{
//传入配置文件和pipeline的类型
nlohmann::json result = android.start(config, 1);
for (size_t i = 0; i < 4; i++)
{
std::thread worker(start, i); // 创建一个线程,运行start·函数
worker.detach();
}
std::cout << "Press ENTER to stop the program..." << std::endl;
std::cin.get(); // 等待开发者按下回车
// 可以在这里进行必要的资源清理和状态检查
std::cout << "Main thread stopping." << std::endl;
return 0;
}
示例详解
首先引入必要的头文件
#include "aidstream.h"
参数是配置和类型,不同的类型对应不同配置文件
nlohmann::json result = android.start(config, 1);
针对配置中的每一路获取相应的RGB buffer的指针,并返回size
char *buffer;
int64_t size = android.getRGB(&buffer, index);
将更改后的buffer、经算法后的buffer或者原buffer输入到显示buffer中
int8_t result1 = android.pushBufferForDisplay(buffer, index);
拉流加推流
访问远端RTSP链接,获取h265/h264的数据,通过解码和颜色空间转换后,获取rgb数据,处理后再发送到编码端,最后根据配置好的远端地址推送。
#include "aidstream.h"
std::string config ;
Android android;
void start(int index)
{
while (true)
{
char *buffer;
int64_t size = android.getRGB(&buffer, index);
std::cout<<"size:"<<size<<std::endl;
int8_t result = android.pushBuffer(buffer, index);
}
}
int main()
{
std::ifstream file("encode_config.json");
if (!file.is_open()) {
std::cerr << "Failed to open file\n";
return 1;
}
std::stringstream buffer;
buffer << file.rdbuf(); // 读取文件到字符串流中
config= buffer.str(); // 将字符串流转换为std::string
std::cout<<"config:"<<config<<std::endl;
nlohmann::json result = android.start(config, 2);
std::cout << result.dump(4) << std::endl;
// android.run();
for (size_t i = 0; i < 4; i++)
{
std::thread worker(start, i); // 创建一个线程,运行keep函数
worker.detach();
}
std::cout << "Press ENTER to stop the program..." << std::endl;
std::cin.get(); // 等待开发者按下回车
// 可以在这里进行必要的资源清理和状态检查
std::cout << "Main thread stopping." << std::endl;
return 0;
}
配置文件:encode_config.json:
// 此处使用的 inputUrl,outUrl 仅供参考,请使用你的 rtsp 视频流地址 和 流媒体服务器地址 替换它们
[
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.234:554/h264/ch1/main/av_stream",
"inputFormat": "video/avc",
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.38:8554/stream1",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.234:554/h264/ch1/main/av_stream",
"inputFormat": "video/avc",
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.38:8554/stream2",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.234:554/h264/ch1/main/av_stream",
"inputFormat": "video/avc",
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.38:8554/stream3",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.234:554/h264/ch1/main/av_stream",
"inputFormat": "video/avc",
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.38:8554/stream4",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
}
]
示例详解
首先引入必要的头文件
#include "aidstream.h"
参数是配置和类型,不同的类型对应不同配置文件
//读取json文件
std::ifstream file("encode_config.json");
if (!file.is_open()) {
std::cerr << "Failed to open file\n";
return 1;
}
std::stringstream buffer;
buffer << file.rdbuf();
config= buffer.str();
//启动type为2的流水线,即 拉流->解码->算法->编码->推流
nlohmann::json result = android.start(config, 2);
针对配置中的每一路获取相应的RGB buffer的指针,并返回size
char *buffer;
int64_t size = android.getRGB(&buffer, index);
将更改后的buffer、经算法后的buffer或者原buffer输入到推流buffer中
int8_t result = android.pushBuffer(buffer, index);
API详细说明
启动函数
nlohmann::json Android::start(std::string config, int type)
成员变量名 | 类型 | 描述 |
---|---|---|
config | std::string | 配置 |
type | std::string | pipeline类型 |
获取解码后的RGB数据
int8_t getRGB(char **buffer, int index);
成员变量名 | 类型 | 描述 |
---|---|---|
buffer | char* | 获取最新解码的RGB数据 |
index | int | 标记(和config数据对应) |
传入RGB数据接口--显示
int8_t pushBufferForDisplay(char *buffer, int index);
成员变量名 | 类型 | 描述 |
---|---|---|
buffer | char* | 需要存储或者推流中此帧的指针 |
index | int | 标记(和config数据对应) |
传入RGB数据接口--推流\存储
int8_t pushBuffer(char *buffer, int index);
成员变量名 | 类型 | 描述 |
---|---|---|
buffer | char* | 需要存储或者推流中此帧的指针 |
index | int | 标记(和config数据对应) |
pipeline详解及配置JSON样例
获取RTSP流->解码->处理->显示
从远端RTSP流获取h264/h265码流,解码且转RGB,RGB经开发者处理后放回pipeline,最后pipeline将回传的RGB显示到surface上。
// 此处使用的 inputUrl 仅供参考,请使用你的 rtsp 视频流地址替换它们
[
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.186:554/h264/ch1/main/av_stream"
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.186:554/h264/ch1/main/av_stream"
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.186:554/h264/ch1/main/av_stream"
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.186:554/h264/ch1/main/av_stream"
}
]
获取RTSP流->解码->处理->编码->推送RTSP流
从远端RTSP流获取h264/h265码流,解码且转RGB,RGB经开发者处理后放回pipeline,最后pipeline将回传的RGB推送到RTSP地址上。
// 此处使用的 inputUrl,outUrl 仅供参考,请使用你的 rtsp 视频流地址和 流媒体服务器地址 替换它们
[
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.234:554/h264/ch1/main/av_stream",
"inputFormat": "video/avc",
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.62:8554/stream-a",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.234:554/h264/ch1/main/av_stream",
"inputFormat": "video/avc",
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.62:8554/stream-b",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.234:554/h264/ch1/main/av_stream",
"inputFormat": "video/avc",
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.62:8554/stream-c",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.234:554/h264/ch1/main/av_stream",
"inputFormat": "video/avc",
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.62:8554/stream-d",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
}
]
获取RTSP流->解码->处理->编码->推送RTSP流&&保存MPEG-4
从远端RTSP流获取h264/h265码流,解码且转RGB,RGB经开发者处理后放回pipeline,最后pipeline将回传的RGB推送到RTSP地址且存到本地上,是否推送或保存根据字段outUrl和outPath是否存在确定。
备注: outPath只支持sdcard目录
// 此处使用的 inputUrl,outUrl 仅供参考,请使用你的 rtsp 视频流地址和 流媒体服务器地址 替换它们
[
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.199:554/h265/ch1/main/av_stream",
"inputFormat": "video/hevc",
"outPath":"/sdcard/Download/rtsp-h265-a.mp4",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.199:554/h265/ch1/main/av_stream",
"inputFormat": "video/hevc",
"outFormat":"video/hevc",
"outPath":"/sdcard/Download/rtsp-h265-b.mp4",
"outUrl": "rtsp://127.0.0.1:8554/rtsp-h265-b",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.199:554/h265/ch1/main/av_stream",
"inputFormat": "video/hevc",
"outPath":"/sdcard/Download/rtsp-h264-c.mp4",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.199:554/h265/ch1/main/av_stream",
"inputFormat": "video/hevc",
"outPath":"/sdcard/Download/rtmp-d.mp4",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
}
]
原生相机->处理->显示
获取前置或后置摄像头的图像,解码且转RGB,RGB经开发者处理后放回pipeline,最后pipeline将回传的RGB显示到surface上。
[
{
"camera_id": 0
}
]
原生相机->处理->推送RTSP流
获取前置或后置摄像头的图像,解码且转RGB,RGB经开发者处理后放回pipeline,最后pipeline将回传的RGB推送到RTSP地址上。
// 此处使用的 outUrl 仅供参考,请使用你的 流媒体服务器地址 替换它们
[
{
"camera_id":0,
"outUrl": "rtsp://127.0.0.1:8554/a",
"outFrameRate": 25,
"inputResizeWidth": 1920,
"inputResizeHeight": 1080,
"outWidth": 1920,
"outHeight": 1080
}
]
UVC相机->处理->显示
获取UVC相机图像,转化为RGB,RGB经开发者处理后放回pipeline,最后pipeline将回传的RGB显示到surface上。
备注: usbDeviceId需要python3脚本查询,见附录;仅支持单路。
[
{
"usbDeviceId":3004
}
]
MPEG-4->处理->推送RTSP流&&保存MPEG-4
获取MPEG-4文件,解码且转RGB,RGB经开发者处理后放回pipeline,最后pipeline将回传的RGB显示到surface上。
备注: file_path只支持sdcard目录,仅支持单路。
// 此处使用的 outUrl 仅供参考,请使用你的 流媒体服务器地址 替换它们
[{
"file_path"="/sdcard/test_kobe.mp4",
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.38:8554/stream2",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
}]
仅解码
从远端RTSP流获取h264/h265码流,解码且转RGB,不放回pipeline,
// 此处使用的 inputUrl 仅供参考,请使用你的 rtsp 视频流地址 替换它们
[
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.186:554/h264/ch1/main/av_stream"
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.186:554/h264/ch1/main/av_stream"
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.186:554/h264/ch1/main/av_stream"
},
{
"inputUrl": "rtsp://admin:aidlux123@192.168.110.186:554/h264/ch1/main/av_stream"
}
]
仅编码->推送RTSP流&&保存MPEG-4
传入RGB图像,将回传的RGB推送到RTSP地址且存到本地上,是否推送或保存根据字段outUrl和outPath是否存在确定。
// 此处使用的 outUrl 仅供参考,请使用你的 流媒体服务器地址 替换它们
[
{
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.62:8554/stream-a",
"outPath":"/sdcard/Download/rtsp-d.mp4",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.62:8554/stream-b",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.62:8554/stream-c",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
},
{
"outFormat":"video/hevc",
"outUrl": "rtsp://192.168.110.62:8554/stream-d",
"outFrameRate": 25,
"inputResizeWidth": 960,
"inputResizeHeight": 540,
"outWidth": 960,
"outHeight": 540
}
]
附录
配置文件字段详解
字段名 | 描述 | 取值 |
---|---|---|
inputUrl | RTSP源 | RTSP有效地址 |
inputFormat | RTSP源格式 | 1.video/avc:格式h264 2.video/hevc:格式h265 |
inputResizeWidth | 缩放源数据的图像的宽度,不输入就不缩放 | 不大于源数据图像的宽 |
inputResizeHeight | 是否缩放源数据的图像大小,不输入就不缩放 | 不大于源数据图像的高 |
outUrl | RTSP推送地址 | RTSP有效地址 |
outFormat | RTSP推送格式 | 1.video/avc:格式h264 2.video/hevc:格式h265 |
outWidth | 输出RGB宽度 | 与放回RGB宽度相同 |
outHeight | 输出RGB高度 | 与放回RGB宽度相同 |
camera_id | 前后置摄像头 | 0:前置 1:后置 |
usbDeviceId | usb摄像头id | |
file_path | 文件地址 | 仅sdcard |
outPath | 输出文件地址 | 仅sdcard |
查询usb相机信息
import android
droid = android.Android()
usb=droid.searchUSB()
print(usb)
请求usb相机权限
import android
droid = android.Android()
hasPermission=droid.requestPermission(id)//id由查询usb相机信息中可得
print(hasPermission)
查询usb相机权限
import android
droid = android.Android()
hasPermission=droid.hasPermission(id)//id由查询usb相机信息中可得
print(hasPermission)