我之前编译了jrtplib 3.9.1,并且在项目中使用,结果发现在用这个库时,程序体积有增加了300多K,感觉实在是有点笨重,我无法就是用来发送rtp包而已。想想还是自己重新实现一个简单的类用用拉倒了,所以有了下面的代码。
头文件:
- #ifndef _EASY_RTP_H
- #define _EASY_RTP_H
-
- #include <string>
-
- #include <stdint.h>
-
- #ifdef _WIN32
- #include <winsock2.h>
- #else
- #include <netinet/in.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <errno.h>
- #ifndef INVALID_SOCKET
- #define INVALID_SOCKET (SOCKET)(~0)
- #endif
- #ifndef SOCKET_ERROR
- #define SOCKET_ERROR (-1)
- #endif
- #ifndef closesocket
- #define closesocket(x) close(x)
- #endif
- typedef int SOCKET;
- #endif
-
- #define DEFAULT_MAX_PACKET_SIZE 1472
-
- class EasyRtp
- {
- public:
-
- EasyRtp(const std::string& destIp, uint16_t port, uint16_t localPort = 0, int16_t maxpacketsize = DEFAULT_MAX_PACKET_SIZE);
-
- EasyRtp(uint32_t destIp, uint16_t port, uint16_t localPort = 0, int16_t maxpacketsize = DEFAULT_MAX_PACKET_SIZE);
- ~EasyRtp();
- public:
-
- int32_t sendPacket(const char* buf, int32_t len, int8_t pt, bool mark, int32_t timestampInc);
- private:
-
- typedef struct
- {
- uint8_t ver;
- bool p;
- bool x;
- uint8_t cc;
- bool mark;
- int8_t pt;
- uint16_t sn;
- uint32_t ts;
- uint32_t ssrc;
- }RtpHeader;
-
-
- int16_t _maxPacketSize;
-
- char* _sbuf;
-
- uint16_t _sn;
-
- uint32_t _ts;
-
- uint32_t _ssrc;
-
- SOCKET _socket;
-
- struct sockaddr_in _destTo;
- };
-
- #endif // _EASY_RTP_H
cpp源码:
- #include <stdio.h>
- #include <string.h>
-
- #include <stdexcept>
-
- #include "easy_rtp.h"
- #include "byte_write.h"
- #include "utils.h"
-
- #define RTP_VERSION 2
- #define RTP_HEADER_SIZE 12
-
- EasyRtp::EasyRtp( const std::string& destIp, uint16_t port, uint16_t localPort
- :_maxPacketSize(maxpacketsize),
- _sbuf(NULL),
- _sn(Utils::createRandam32()),
- _ts(Utils::createRandam32()),
- _ssrc(Utils::createRandam32())
- {
- if (maxpacketsize >= RTP_HEADER_SIZE)
- _sbuf = new char[maxpacketsize];
- else
- throw std::runtime_error("[EasyRtp] too small packet size, must more than 12 Byte");
-
- _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (_socket == INVALID_SOCKET)
- throw std::runtime_error("[EasyRtp] invalid socket");
-
- _destTo.sin_family = AF_INET;
- _destTo.sin_port = htons(port);
- _destTo.sin_addr.s_addr = inet_addr(destIp.c_str());
-
- if (localPort != 0)
- {
- struct sockaddr_in sockAddr;
- sockAddr.sin_family = AF_INET;
- sockAddr.sin_port = htons(localPort);
- sockAddr.sin_addr.s_addr = INADDR_ANY;
-
- if (bind(_socket, (const sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR)
- {
- #ifndef NPRINT
- #ifdef _WIN32
- printf("[EasyRtp] bind error: %d\n", WSAGetLastError());
- #else
- printf("[EasyRtp] bind error: %d\n", errno);
- #endif
- #endif
- closesocket(_socket);
- throw std::runtime_error("[EasyRtp] bind error");
- }
- }
- }
-
- EasyRtp::EasyRtp( uint32_t destIp, uint16_t port, uint16_t localPort
- :_maxPacketSize(maxpacketsize),
- _sbuf(NULL),
- _sn(Utils::createRandam32()),
- _ts(Utils::createRandam32()),
- _ssrc(Utils::createRandam32())
- {
- if (maxpacketsize >= RTP_HEADER_SIZE)
- _sbuf = new char[maxpacketsize];
- else
- throw std::runtime_error("[EasyRtp] too small packet size, must more than 12 Byte");
-
- _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (_socket == INVALID_SOCKET)
- throw std::runtime_error("[EasyRtp] invalid socket");
-
- _destTo.sin_family = AF_INET;
- _destTo.sin_port = htons(port);
- _destTo.sin_addr.s_addr = htonl(destIp);
-
- if (localPort != 0)
- {
- struct sockaddr_in sockAddr;
- sockAddr.sin_family = AF_INET;
- sockAddr.sin_port = htons(localPort);
- sockAddr.sin_addr.s_addr = INADDR_ANY;
-
- if (bind(_socket, (const sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR)
- {
- #ifndef NPRINT
- #ifdef _WIN32
- printf("[EasyRtp] bind error: %d\n", WSAGetLastError());
- #else
- printf("[EasyRtp] bind error: %d\n", errno);
- #endif
- #endif
- closesocket(_socket);
- throw std::runtime_error("[EasyRtp] bind error");
- }
- }
- }
-
- EasyRtp::~EasyRtp()
- {
- if (_socket != INVALID_SOCKET)
- closesocket(_socket);
- if (_sbuf != NULL)
- delete [] _sbuf;
- }
-
- int32_t EasyRtp::sendPacket( const char* buf, int32_t len, int8_t pt, bool mark, int32_t timestampInc )
- {
- if ((len + RTP_HEADER_SIZE) > _maxPacketSize)
- return -1;
-
- ++_sn;
- _ts += timestampInc;
-
-
- _sbuf[0] = 0;
- _sbuf[0] |= RTP_VERSION << 6;
- _sbuf[1] = 0;
- _sbuf[1] |= mark << 7;
- _sbuf[1] |= pt;
- write_be_w(_sbuf + 2, _sn);
- write_be_dw(_sbuf + 4, _ts);
- write_be_dw(_sbuf + 8, _ssrc);
-
- memcpy(_sbuf + RTP_HEADER_SIZE, buf, len);
- int32_t ret = sendto(_socket, (const char*)_sbuf, len + RTP_HEADER_SIZE, 0, (const sockaddr*)&_destTo, sizeof(_destTo));
- #ifndef NPRINT
- if (ret < 0)
- {
- #ifdef _WIN32
- printf("[EasyRtp] sendto error: %d\n", WSAGetLastError());
- #else
- printf("[EasyRtp] sendto error: %d\n", errno);
- #endif
- }
- #endif
- return ret;
- }
注:
stdint.h是新c++标准中的头文件,定义了int32_t int8_t等typedef 类型。
简单RTP发送类c++实现
原文:http://www.cnblogs.com/lidabo/p/4245447.html