ZLMedia中RTCP协议的处理简要分析(4)--source description)
![](https://img2022.cnblogs.com/blog/2525040/202207/2525040-20220727171353120-2061171173.png)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class RtcpHeader { public: #if __BYTE_ORDER == __BIG_ENDIAN //版本号,固定为2 uint32_t version: 2; //padding,固定为0 uint32_t padding: 1; //reception report count uint32_t report_count: 5; #else //reception report count uint32_t report_count: 5; //padding,末尾是否有追加填充 uint32_t padding: 1; //版本号,固定为2 uint32_t version: 2; #endif //rtcp类型,RtcpType uint32_t pt: 8; private: //长度 uint32_t length: 16; public: /** * 解析rtcp并转换网络字节序为主机字节序,返回RtcpHeader派生类列表 * @param data 数据指针 * @param size 数据总长度 * @return rtcp对象列表,无需free */ static std::vector<RtcpHeader *> loadFromBytes(char *data, size_t size); /** * rtcp包转Buffer对象 * @param rtcp rtcp包对象智能指针 * @return Buffer对象 */ static toolkit::Buffer::Ptr toBuffer(std::shared_ptr<RtcpHeader> rtcp); /** * 打印rtcp相关字段详情(调用派生类的dumpString函数) * 内部会判断是什么类型的派生类 * 使用net2Host转换成主机字节序后才可使用此函数 */ std::string dumpString() const; /** * 根据length字段获取rtcp总长度 */ size_t getSize() const; /** * 后面追加padding数据长度 */ size_t getPaddingSize() const; /** * 设置rtcp length字段 * @param size rtcp总长度,单位字节 */ void setSize(size_t size); protected: /** * 打印字段详情 * 使用net2Host转换成主机字节序后才可使用此函数 */ std::string dumpHeader() const; private: /** * 调用派生类的net2Host函数 * @param size rtcp字符长度 */ void net2Host(size_t size); } PACKED;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class SdesChunk { public: friend class RtcpSdes; uint32_t ssrc; //SdesType uint8_t type; //text长度股,可以为0 uint8_t txt_len; //不定长 char text[1]; //最后以RTCP_SDES_END结尾 //只字段为占位字段,不代表真实位置 uint8_t end; public: /** * 返回改对象字节长度 */ size_t totalBytes() const; /** * 本对象最少长度 */ static size_t minSize(); private: /** * 打印字段详情 * 使用net2Host转换成主机字节序后才可使用此函数 */ std::string dumpString() const; /** * 网络字节序转换为主机字节序 */ void net2Host(); } PACKED;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class RtcpSdes : public RtcpHeader { public: friend class RtcpHeader; //可能有很多个 SdesChunk chunks; public: /** * 创建SDES包,只赋值了RtcpHeader以及SdesChunk对象的length和text部分 * @param item_text SdesChunk列表,只赋值length和text部分 * @return SDES包 */ static std::shared_ptr<RtcpSdes> create(const std::vector<std::string> &item_text); /** * 获取SdesChunk对象指针列表 * 使用net2Host转换成主机字节序后才可使用此函数 */ std::vector<SdesChunk*> getChunkList(); private: /** * 打印字段详情 * 使用net2Host转换成主机字节序后才可使用此函数 */ std::string dumpString() const; /** * 网络字节序转换为主机字节序 * @param size 字节长度,防止内存越界 */ void net2Host(size_t size); } PACKED;
通过结构图,我们可以看到Source Description分组,也可以叫做SDES的组织结构是按照KLV的格式组织的,key表示具体的类型,length为长度,value为具体的值, key占用1个字节, length占用1个字节!RTCP中可选的KEY如结构图中所列,有如下几种:
CNAME(值为1)
规范终端标识,像SSRC标识,CNAME标识在RTP连接的所有参加者中应是唯一的;
NAME(值为2)
用户名称,用于描述源的用户名;
E-mail(值为3)
电子邮件地址,用于描述源的邮件地址,格式如 John.Deo@megacorp.com;
PHONE(值为4)
用于描述源的电话号码;
LOC(值为5)
用于描述源的地理位置;
TOOL(值为6)
用于描述应用或工具的名称,表示产生流的应用的名称与版本,如"videotool 1.2";
NOTE(值为7)
用于描述源当前状态的过渡信息;
PRIV(值为8)
用于描述针对源的扩展项;