jrtplib的使用

簡介

jrtplib是用C++開發的rtp/rtcp庫,非常方便嵌入到C++工程中,可用於rtsp server或rtsp client的開發之中,或者其他以rtp/rtcp格式的推流與收流。

初始化

示例代碼:

RTPSession rtp_session;
unsigned short rtp_port = 6666;
unsigned int payload_type = 96; //以H264爲例
const std::string dst_ip = "224.124.1.101";
unsigned short dst_port = 8856;
int status = 0;

RTPUDPv4TransmissionParams transparams;  
RTPSessionParams sessparams; 
sessparams.SetOwnTimestampUnit(1.0/25.0);//必須設置  
transparams.SetPortbase(rtp_port);//rtp_port必須是偶數  
base_type::SetDefaultPayloadType(payload_type); 
// 創建,成功返回0
status = rtp_session.Create(sessparams, &transparams);

// 添加目標地址與端口,成功返回0
status = rtp_session.AddDestination( RTPIPv4Address(ntohl(inet_addr(dst_ip.c_str()),dst_port) );

發送

示例代碼:

unsigned char* packetData;
unsigned int packetDataSize;
unsigned int payload_type = 96; //以H264爲例
unsigned int timestamp; //時間戳
bool end_mark = true; //結束標誌,當分片發送時,最後一篇true,其他的false,當單發送nal時爲true
int status = 0;
status = rtp_session.SendPacket(PacketData,packetDataSize,payload_type,end_mark,timestamp);

接收

示例代碼:

//num循環的次數
for (i = 1 ; i <= num ; i++)
{
    rtp_session.BeginDataAccess();
    if (rtp_session.GotoFirstSourceWithData())
    {
        do
        {
            RTPPacket *pack;
            while ((pack = rtp_session.GetNextPacket()) != NULL)
            {
                /* 收到的數據在pack中 */


                //釋放pack
                rtp_session.DeletePacket(pack);
            }
        } while (rtp_session.GotoNextSourceWithData());
    }
    rtp_session.EndDataAccess();
    //等待
    RTPTime::Wait(RTPTime(1,0));
}

移除目標地址和端口

示例代碼:

status = rtp_session.DeleteDestination( RTPIPv4Address(ntohl(inet_addr(dst_ip.c_str()),dst_port) );

釋放

示例代碼:

//void BYEDestroy(const RTPTime &maxwaittime,const void *reason,size_t reasonlength);
rtp_session.BYEDestroy(RTPTime(10,0),0,0);

爲更方便的使用,新建了RTPSessionUtils.cpp和RTPSessionUtils.h,把jrtp接口再封裝一遍。

RTPSessionUtils.h

#include "rtpsession.h"  
#include "rtppacket.h"  
#include "rtpudpv4transmitter.h"  
#include "rtpipv4address.h"  
#include "rtpsessionparams.h"  
#include "rtperrors.h"  
#ifndef WIN32  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#else  
#include <winsock2.h>  
#endif // WIN32  
#include "rtpsourcedata.h"  
#include <stdlib.h>  
#include <stdio.h>  
#include <iostream>  
#include <string>  

//jrtplib應用需鏈接的lib  
#pragma comment(lib,"ws2_32.lib")  
#pragma comment(lib, "jrtplib_d.lib")  
#pragma comment(lib,"jthread_d.lib")  

namespace jrtplib  
{  
    class RTPSessionUtils : public RTPSession  
    {  
        typedef RTPSession base_type;  
    public:  
        RTPSessionUtils();  
        ~RTPSessionUtils();  

        int AddDestination(const std::string& ip, uint16_t port);  
        int DeleteDestination(const std::string& ip, uint16_t port);  
        int CreateDefault(uint16_t port);  
    protected:  
        void OnNewSource(RTPSourceData *dat);  
        void OnBYEPacket(RTPSourceData *dat);  
        void OnRemoveSource(RTPSourceData *dat);  
        void OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime,  
            const RTPAddress *senderaddress);  
        void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,  
            const RTPAddress *senderaddress);  
        void OnPollThreadStep();  
    private:  
        int GetAddrFromSource(RTPSourceData *dat, uint32_t& ip, uint16_t& port);  
    };  
}  

//整形的ip轉成字符串ip  
static std::string IPToString(const unsigned int iIP)  
{  
    struct in_addr inaddr;  
    inaddr.s_addr = htonl(iIP);  
    return std::string(inet_ntoa(inaddr));  
}  

//字符串ip轉成整形ip  
static unsigned int IPToInt(const std::string& sIP)  
{  
    return inet_addr(sIP.c_str());  
}  

RTPSessionUtils.cpp

#include "RTPSessionUtils.h"  

namespace jrtplib{  
    RTPSessionUtils::RTPSessionUtils()  
    {  
#ifdef WIN32  
        WSADATA dat;  
        WSAStartup(MAKEWORD(2,2),&dat);  
#endif // WIN32  
    }  

    RTPSessionUtils::~RTPSessionUtils()  
    {  
#ifdef WIN32  
        WSACleanup();  
#endif // WIN32  
    }  

    int RTPSessionUtils::CreateDefault(uint16_t port)  
    {  
        RTPUDPv4TransmissionParams transparams;  
        RTPSessionParams sessparams; 
    //sessparams.SetAcceptOwnPackets(true);
        sessparams.SetOwnTimestampUnit(1.0/25.0);//必須設置  
        transparams.SetPortbase(port);//port必須是偶數  
        base_type::SetDefaultPayloadType(96); 
        return base_type::Create(sessparams, &transparams);  

        base_type::SetDefaultPayloadType(96);  
        base_type::SetDefaultTimestampIncrement(0);  
        base_type::SetDefaultMark(false);  
    }  

    int RTPSessionUtils::AddDestination(const std::string& ip, uint16_t port)  
    {  
        return base_type::AddDestination(RTPIPv4Address(ntohl(inet_addr(ip.c_str())), port));  
    }  

    int RTPSessionUtils::DeleteDestination(const std::string& ip, uint16_t port)  
    {  
        return base_type::DeleteDestination(RTPIPv4Address(ntohl(inet_addr(ip.c_str())), port));  
    }  

    int RTPSessionUtils::GetAddrFromSource(RTPSourceData *dat, uint32_t& ip, uint16_t& port)  
    {  
        if (dat->IsOwnSSRC())  
            return -1;  

        if (dat->GetRTPDataAddress() != 0)  
        {  
            const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTPDataAddress());  
            ip = addr->GetIP();  
            port = addr->GetPort();  
        }  
        else if (dat->GetRTCPDataAddress() != 0)  
        {  
            const RTPIPv4Address *addr = (const RTPIPv4Address *)(dat->GetRTCPDataAddress());  
            ip = addr->GetIP();  
            port = addr->GetPort()-1;  
        }  

        return 0;  
    }  

    void RTPSessionUtils::OnNewSource(RTPSourceData *dat)  
    {  
        uint32_t ip;  
        uint16_t port;  

        if (GetAddrFromSource(dat, ip, port))  
            return;  


        RTPIPv4Address dest(ip,port);  
        base_type::AddDestination(dest);  

        std::cout << "OnNewSource Adding destination " << IPToString(ip) << ":" << port << std::endl;  
    }  

    void RTPSessionUtils::OnRemoveSource(RTPSourceData *dat)  
    {  
        if (dat->ReceivedBYE())  
            return;  

        uint32_t ip;  
        uint16_t port;  

        if (GetAddrFromSource(dat, ip, port))  
            return;  

        RTPIPv4Address dest(ip,port);  
        base_type::DeleteDestination(dest);  

        std::cout << "OnRemoveSource Deleting destination " << IPToString(ip) << ":" << port << std::endl;  
    }  

    void RTPSessionUtils::OnBYEPacket(RTPSourceData *dat)  
    {  
        uint32_t ip;  
        uint16_t port;  

        if (GetAddrFromSource(dat, ip, port))  
            return;  

        RTPIPv4Address dest(ip,port);  
        base_type::DeleteDestination(dest);  

        std::cout << "OnBYEPacket Deleting destination " << IPToString(ip) << ":" << port << std::endl;  
    }  

    //只要有rtp包就會觸發  
    void RTPSessionUtils::OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime,  
        const RTPAddress *senderaddress)  
    {  
        std::cout << "OnRTPPacket: data:" << pack->GetPayloadData() << std::endl;  
    }  

    //收到rtcp包觸發  
    void RTPSessionUtils::OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,  
        const RTPAddress *senderaddress)  
    {  
        std::cout << "OnRTCPCompoundPacket: data:" << pack->GetCompoundPacketData() << std::endl;  
    }  

    //隔段時間就會觸發,也可以用於收包回調函數  
    //void RTPSessionUtils::OnPollThreadStep()  
    //{  
    //  BeginDataAccess();  

    //  // check incoming packets  
    //  if (GotoFirstSourceWithData())  
    //  {  
    //      do  
    //      {  
    //          RTPPacket *pack;  
    //          RTPSourceData *srcdat;  

    //          srcdat = GetCurrentSourceInfo();  

    //          while ((pack = GetNextPacket()) != NULL)  
    //          {  
    //              std::cout << "Got packet " << pack->GetExtendedSequenceNumber() << " from SSRC " << srcdat->GetSSRC() << std::endl;  
    //              DeletePacket(pack);  
    //          }  
    //      } while (GotoNextSourceWithData());  
    //  }  

    //  EndDataAccess();  
    //}  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章