USB_Config_Vendor/CC_SDK/Include/Module/Comm/CCSDP.h

269 lines
11 KiB
C
Raw Normal View History

2026-02-03 14:36:30 +08:00
#ifndef CC_SDP_BUILDER_H
#define CC_SDP_BUILDER_H
#include <string>
#include <vector>
#include <map>
#include <sstream>
namespace CTL {
class SDPBuilder {
std::string session_id;
std::string session_version;
std::string session_name;
std::string origin_username;
std::string origin_session_id;
std::string origin_nettype;
std::string origin_addrtype;
std::string origin_address;
std::string connection_nettype;
std::string connection_addrtype;
std::string connection_address;
std::string timing_start;
std::string timing_stop;
struct MediaDescription {
std::string media_type; // video, audio, etc.
int port; // transport port
std::string protocol; // RTP/AVP, etc.
int fmt; // format identifier
std::string rtpmap; // rtpmap information
std::string fmtp; // format specific parameters
std::string control_url; // control URL
std::vector<std::string> attributes; // additional attributes
};
std::vector<MediaDescription> media_descriptions;
public:
SDPBuilder() : session_id("0"), session_version("0"), session_name("RTSP Session"),
origin_username("-"), origin_session_id("0"), origin_nettype("IN"),
origin_addrtype("IP4"), origin_address("127.0.0.1"),
connection_nettype("IN"), connection_addrtype("IP4"),
connection_address("0.0.0.0"), timing_start("0"), timing_stop("0") {}
// 设置会话ID
SDPBuilder& setSessionId(const std::string& id) {
session_id = id;
return *this;
}
// 设置会话版本
SDPBuilder& setSessionVersion(const std::string& version) {
session_version = version;
return *this;
}
// 设置会话名称
SDPBuilder& setSessionName(const std::string& name) {
session_name = name;
return *this;
}
// 设置源信息
SDPBuilder& setOriginInfo(const std::string& username, const std::string& session_id_val,
const std::string& nettype = "IN", const std::string& addrtype = "IP4",
const std::string& address = "127.0.0.1") {
origin_username = username;
origin_session_id = session_id_val;
origin_nettype = nettype;
origin_addrtype = addrtype;
origin_address = address;
return *this;
}
// 设置连接信息
SDPBuilder& setConnectionInfo(const std::string& nettype = "IN", const std::string& addrtype = "IP4",
const std::string& address = "0.0.0.0") {
connection_nettype = nettype;
connection_addrtype = addrtype;
connection_address = address;
return *this;
}
// 添加视频媒体描述
SDPBuilder& addVideoMedia(int port, const std::string& codec, int payload_type,
const std::string& clock_rate = "90000",
const std::string& fmtp_params = "") {
MediaDescription media;
media.media_type = "video";
media.port = port;
media.protocol = "RTP/AVP";
media.fmt = payload_type;
if (codec == "H264") {
media.rtpmap = std::to_string(payload_type) + " " + codec + "/" + clock_rate;
if (!fmtp_params.empty()) {
media.fmtp = "a=fmtp:" + std::to_string(payload_type) + " " + fmtp_params;
}
} else if (codec == "H265") {
media.rtpmap = std::to_string(payload_type) + " " + codec + "/" + clock_rate;
if (!fmtp_params.empty()) {
media.fmtp = "a=fmtp:" + std::to_string(payload_type) + " " + fmtp_params;
}
} else if (codec == "VP8" || codec == "VP9") {
media.rtpmap = std::to_string(payload_type) + " " + codec + "/" + clock_rate;
} else {
media.rtpmap = std::to_string(payload_type) + " " + codec + "/" + clock_rate;
}
media.control_url = "stream";
media_descriptions.push_back(media);
return *this;
}
// 添加音频媒体描述
SDPBuilder& addAudioMedia(int port, const std::string& codec, int payload_type,
const std::string& clock_rate = "8000", int channels = 1,
const std::string& fmtp_params = "") {
MediaDescription media;
media.media_type = "audio";
media.port = port;
media.protocol = "RTP/AVP";
media.fmt = payload_type;
if (channels > 1) {
media.rtpmap = std::to_string(payload_type) + " " + codec + "/" + clock_rate + "/" + std::to_string(channels);
} else {
media.rtpmap = std::to_string(payload_type) + " " + codec + "/" + clock_rate;
}
if (!fmtp_params.empty()) {
media.fmtp = "a=fmtp:" + std::to_string(payload_type) + " " + fmtp_params;
}
media.control_url = "stream";
media_descriptions.push_back(media);
return *this;
}
// 添加自定义属性
SDPBuilder& addAttribute(const std::string& attr) {
if (!media_descriptions.empty()) {
media_descriptions.back().attributes.push_back("a=" + attr);
}
return *this;
}
// 生成SDP字符串
std::string build() const {
std::ostringstream sdp;
// 版本行
sdp << "v=0\r\n";
// 源行
sdp << "o=" << origin_username << " " << origin_session_id << " " << session_version
<< " " << origin_nettype << " " << origin_addrtype << " " << origin_address << "\r\n";
// 会话名称
sdp << "s=" << session_name << "\r\n";
// 连接信息
sdp << "c=" << connection_nettype << " " << connection_addrtype << " " << connection_address << "\r\n";
// 时间信息
sdp << "t=" << timing_start << " " << timing_stop << "\r\n";
// 媒体描述
for (const auto& media : media_descriptions) {
sdp << "m=" << media.media_type << " " << media.port << " " << media.protocol << " " << media.fmt << "\r\n";
sdp << "a=rtpmap:" << media.rtpmap << "\r\n";
if (!media.fmtp.empty()) {
sdp << media.fmtp << "\r\n";
}
sdp << "a=control:" << media.control_url << "\r\n";
// 添加自定义属性
for (const auto& attr : media.attributes) {
sdp << attr << "\r\n";
}
}
return sdp.str();
}
static SDPBuilder parse(const std::string& sdp) {
SDPBuilder builder;
std::istringstream stream(sdp);
std::string line;
while (std::getline(stream, line)) {
// 移除行末的换行符和回车符
if (!line.empty() && line.back() == '\r') {
line.pop_back();
}
if (line.empty()) continue;
// 解析行类型 (字母部分)
size_t colon_pos = line.find('=');
if (colon_pos == std::string::npos) continue;
std::string type = line.substr(0, colon_pos);
std::string value = line.substr(colon_pos + 1);
if (type == "v") {
// 版本行 - 通常为 "v=0"
}
else if (type == "o") {
// 源行: o=username sessionid version nettype addrtype address
std::istringstream origin_stream(value);
std::string username, session_id, version, nettype, addrtype, address;
origin_stream >> username >> session_id >> version >> nettype >> addrtype >> address;
builder.setOriginInfo(username, session_id, nettype, addrtype, address);
}
else if (type == "s") {
// 会话名称
builder.setSessionName(value);
}
else if (type == "c") {
// 连接信息: c=nettype addrtype address
std::istringstream conn_stream(value);
std::string nettype, addrtype, address;
conn_stream >> nettype >> addrtype >> address;
builder.setConnectionInfo(nettype, addrtype, address);
}
else if (type == "t") {
// 时间信息: t=start stop
size_t space_pos = value.find(' ');
if (space_pos != std::string::npos) {
builder.timing_start = value.substr(0, space_pos);
builder.timing_stop = value.substr(space_pos + 1);
}
}
else if (type == "m") {
// 媒体行: m=media port protocol fmt
std::istringstream media_stream(value);
std::string media_type, protocol;
int port, fmt;
media_stream >> media_type >> port >> protocol >> fmt;
// 简单处理,假设是视频或音频
if (media_type == "video") {
builder.addVideoMedia(port, "H264", fmt);
} else if (media_type == "audio") {
builder.addAudioMedia(port, "PCMU", fmt);
}
}
else if (type == "a") {
// 属性行
if (value.substr(0, 7) == "rtpmap:") {
// rtpmap 属性
size_t space_pos = value.find(' ', 7);
if (space_pos != std::string::npos) {
std::string rtpmap_info = value.substr(7);
// 这里可以进一步解析rtpmap信息但需要根据当前media进行设置
}
} else if (value.substr(0, 5) == "fmtp:") {
// fmtp 属性
size_t space_pos = value.find(' ', 5);
if (space_pos != std::string::npos) {
std::string fmtp_info = value.substr(5);
// 这里可以进一步解析fmtp信息
}
} else if (value.substr(0, 8) == "control:") {
// control 属性
std::string control_url = value.substr(8);
// 需要更新当前媒体描述的control_url
}
}
}
return builder;
}
};
}
#endif