zoukankan      html  css  js  c++  java
  • 简单RTP发送类c++实现

    我之前编译了jrtplib 3.9.1,并且在项目中使用,结果发现在用这个库时,程序体积有增加了300多K,感觉实在是有点笨重,我无法就是用来发送rtp包而已。想想还是自己重新实现一个简单的类用用拉倒了,所以有了下面的代码。

    头文件:

    [cpp] view plaincopy
     
    1. /*! 
    2. @brief 简单rtp库 
    3. @file easy_rtp.h 
    4. */  
    5. #ifndef _EASY_RTP_H  
    6. #define _EASY_RTP_H  
    7.   
    8. #include <string>  
    9.   
    10. #include <stdint.h>  
    11.   
    12. #ifdef _WIN32  
    13. #include <winsock2.h>  
    14. #else  
    15. #include <netinet/in.h>  
    16. #include <sys/types.h>  
    17. #include <sys/socket.h>  
    18. #include <arpa/inet.h>  
    19. #include <errno.h>  
    20. #ifndef INVALID_SOCKET  
    21. #define INVALID_SOCKET  (SOCKET)(~0)  
    22. #endif  
    23. #ifndef SOCKET_ERROR  
    24. #define SOCKET_ERROR    (-1)  
    25. #endif  
    26. #ifndef closesocket  
    27. #define closesocket(x)  close(x)  
    28. #endif  
    29. typedef int SOCKET;  
    30. #endif  
    31.   
    32. // 默认最大包大小(MTU 1500 - IP头 20 - UDP头 8)  
    33. #define DEFAULT_MAX_PACKET_SIZE 1472  
    34.   
    35. /*! 
    36. @brief 简单rtp数据包装发送库 
    37. */  
    38. class EasyRtp  
    39. {  
    40. public:  
    41.     /*! 
    42.     @brief 构造 
    43.     @param destIp 目标ip地址 
    44.     @param port 目标端口 
    45.     @param localport 本地帮定端口,默认端口采用随机值 
    46.     */  
    47.     EasyRtp(const std::string& destIp, uint16_t port, uint16_t localPort = 0, int16_t maxpacketsize = DEFAULT_MAX_PACKET_SIZE);  
    48.     /*! 
    49.     @brief 构造 
    50.     @param destIp 目标ip地址 
    51.     @param port 目标端口 
    52.     @param localport 本地帮定端口,默认端口采用随机值 
    53.     */  
    54.     EasyRtp(uint32_t destIp, uint16_t port, uint16_t localPort = 0, int16_t maxpacketsize = DEFAULT_MAX_PACKET_SIZE);  
    55.     ~EasyRtp();  
    56. public:  
    57.     /*! 
    58.     @brief 发送rtp包给目标 
    59.     @param buf 发送的缓冲 
    60.     @param len 发送的缓冲大小 
    61.     @param pt 负载类型 
    62.     @param mark 标记位 
    63.     @param timestampInc 时间戳增量 
    64.     @param 错误为-1 
    65.     */  
    66.     int32_t sendPacket(const char* buf, int32_t len, int8_t pt, bool mark, int32_t timestampInc);  
    67. private:  
    68.     /// 简单rtp头12字节,不含扩展头,csrc列表等信息  
    69.     typedef struct  
    70.     {  
    71.         uint8_t ver;                /// 版本号(2bit)  
    72.         bool p;                     /// 填充位,一直置0(1bit)  
    73.         bool x;                     /// 扩充头位,一直置0(1bit)  
    74.         uint8_t cc;                 /// csrc列表数量,一直置0(4bit)  
    75.         bool mark;                  /// 标记位(1bit)  
    76.         int8_t pt;                  /// 负载类型(7bit)  
    77.         uint16_t sn;                /// 序列号(16bit)  
    78.         uint32_t ts;                /// 时间戳(32bit)  
    79.         uint32_t ssrc;              /// 来源标示(32bit)  
    80.     }RtpHeader;  
    81.   
    82.     // 最大包大小  
    83.     int16_t _maxPacketSize;  
    84.     // 发送的缓冲  
    85.     char* _sbuf;  
    86.     // 序列号  
    87.     uint16_t _sn;  
    88.     // 时间戳  
    89.     uint32_t _ts;  
    90.     // 源标示  
    91.     uint32_t _ssrc;  
    92.     // 句柄  
    93.     SOCKET _socket;  
    94.     // 目标地址  
    95.     struct sockaddr_in _destTo;  
    96. };  
    97.   
    98. #endif  // _EASY_RTP_H  


    cpp源码:

    [cpp] view plaincopy
     
    1. #include <stdio.h>  
    2. #include <string.h>  
    3.   
    4. #include <stdexcept>  
    5.   
    6. #include "easy_rtp.h"  
    7. #include "byte_write.h"  
    8. #include "utils.h"  
    9.   
    10. // 默认的rtp版本  
    11. #define RTP_VERSION         2  
    12. // rtp头大小  
    13. #define RTP_HEADER_SIZE     12  
    14.   
    15. EasyRtp::EasyRtp( const std::string& destIp, uint16_t port, uint16_t localPort /*= 0*/, int16_t maxpacketsize /*= 1500*/ )  
    16.     :_maxPacketSize(maxpacketsize),  
    17.     _sbuf(NULL),  
    18.     _sn(Utils::createRandam32()),  
    19.     _ts(Utils::createRandam32()),  
    20.     _ssrc(Utils::createRandam32())  
    21. {  
    22.     if (maxpacketsize >= RTP_HEADER_SIZE)  
    23.         _sbuf = new char[maxpacketsize];  
    24.     else  
    25.         throw std::runtime_error("[EasyRtp] too small packet size, must more than 12 Byte");  
    26.   
    27.     _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);  
    28.     if (_socket == INVALID_SOCKET)  
    29.         throw std::runtime_error("[EasyRtp] invalid socket");  
    30.   
    31.     _destTo.sin_family = AF_INET;  
    32.     _destTo.sin_port = htons(port);  
    33.     _destTo.sin_addr.s_addr = inet_addr(destIp.c_str());  
    34.   
    35.     if (localPort != 0)  
    36.     {  
    37.         struct sockaddr_in sockAddr;  
    38.         sockAddr.sin_family = AF_INET;  
    39.         sockAddr.sin_port = htons(localPort);  
    40.         sockAddr.sin_addr.s_addr = INADDR_ANY;  
    41.   
    42.         if (bind(_socket, (const sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR)  
    43.         {  
    44. #ifndef NPRINT  
    45. #ifdef _WIN32  
    46.             printf("[EasyRtp] bind error: %d ", WSAGetLastError());  
    47. #else  
    48.             printf("[EasyRtp] bind error: %d ", errno);  
    49. #endif  
    50. #endif  
    51.             closesocket(_socket);  
    52.             throw std::runtime_error("[EasyRtp] bind error");  
    53.         }  
    54.     }  
    55. }  
    56.   
    57. EasyRtp::EasyRtp( uint32_t destIp, uint16_t port, uint16_t localPort /*= 0*/, int16_t maxpacketsize /*= DEFAULT_MAX_PACKET_SIZE*/ )  
    58.     :_maxPacketSize(maxpacketsize),  
    59.     _sbuf(NULL),  
    60.     _sn(Utils::createRandam32()),  
    61.     _ts(Utils::createRandam32()),  
    62.     _ssrc(Utils::createRandam32())  
    63. {  
    64.     if (maxpacketsize >= RTP_HEADER_SIZE)  
    65.         _sbuf = new char[maxpacketsize];  
    66.     else  
    67.         throw std::runtime_error("[EasyRtp] too small packet size, must more than 12 Byte");  
    68.   
    69.     _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);  
    70.     if (_socket == INVALID_SOCKET)  
    71.         throw std::runtime_error("[EasyRtp] invalid socket");  
    72.   
    73.     _destTo.sin_family = AF_INET;  
    74.     _destTo.sin_port = htons(port);  
    75.     _destTo.sin_addr.s_addr = htonl(destIp);  
    76.   
    77.     if (localPort != 0)  
    78.     {  
    79.         struct sockaddr_in sockAddr;  
    80.         sockAddr.sin_family = AF_INET;  
    81.         sockAddr.sin_port = htons(localPort);  
    82.         sockAddr.sin_addr.s_addr = INADDR_ANY;  
    83.   
    84.         if (bind(_socket, (const sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR)  
    85.         {  
    86. #ifndef NPRINT  
    87. #ifdef _WIN32  
    88.             printf("[EasyRtp] bind error: %d ", WSAGetLastError());  
    89. #else  
    90.             printf("[EasyRtp] bind error: %d ", errno);  
    91. #endif  
    92. #endif  
    93.             closesocket(_socket);  
    94.             throw std::runtime_error("[EasyRtp] bind error");  
    95.         }  
    96.     }  
    97. }  
    98.   
    99. EasyRtp::~EasyRtp()  
    100. {  
    101.     if (_socket != INVALID_SOCKET)  
    102.         closesocket(_socket);  
    103.     if (_sbuf != NULL)  
    104.         delete [] _sbuf;  
    105. }  
    106.   
    107. int32_t EasyRtp::sendPacket( const char* buf, int32_t len, int8_t pt, bool mark, int32_t timestampInc )  
    108. {  
    109.     if ((len + RTP_HEADER_SIZE) > _maxPacketSize)  
    110.         return -1;  
    111.   
    112.     ++_sn;  
    113.     _ts += timestampInc;  
    114.   
    115.     // 只设置版本号,其它的全是默认0  
    116.     _sbuf[0] = 0;  
    117.     _sbuf[0] |= RTP_VERSION << 6;  
    118.     _sbuf[1] = 0;  
    119.     _sbuf[1] |= mark << 7;  
    120.     _sbuf[1] |= pt;  
    121.     write_be_w(_sbuf + 2, _sn);  
    122.     write_be_dw(_sbuf + 4, _ts);  
    123.     write_be_dw(_sbuf + 8, _ssrc);  
    124.     // 保存数据  
    125.     memcpy(_sbuf + RTP_HEADER_SIZE, buf, len);  
    126.     int32_t ret = sendto(_socket, (const char*)_sbuf, len + RTP_HEADER_SIZE, 0, (const sockaddr*)&_destTo, sizeof(_destTo));  
    127. #ifndef NPRINT  
    128.     if (ret < 0)  
    129.     {  
    130. #ifdef _WIN32  
    131.         printf("[EasyRtp] sendto error: %d ", WSAGetLastError());  
    132. #else  
    133.         printf("[EasyRtp] sendto error: %d ", errno);  
    134. #endif  
    135.     }  
    136. #endif  
    137.     return ret;  
    138. }  


    注:

    stdint.h是新c++标准中的头文件,定义了int32_t int8_t等typedef 类型。

  • 相关阅读:
    Cg:访问OpenGL的状态
    C++ Exception Handling
    C语言的调用规约(Calling Convension)之参数传递和返回值
    Why is FBX readonly in animation editor when imported?
    如何在Visual Studio中编译wxWidgets
    ICU字符集编码转换一例
    VisTools
    关于数值分析和LCP问题的一些开源项目
    C++: The Case Against Global Variables
    老男孩筷子兄弟
  • 原文地址:https://www.cnblogs.com/lidabo/p/4245447.html
Copyright © 2011-2022 走看看