RTP实时音视频数据传输,发送端和接收端

来源:岁月联盟 编辑:exp 时间:2012-11-03

1.项目前期工作(配置好环境)
2.发送端文件编写(见下面的send.cpp)
3.接收端文件编写(见下面的receive.cpp)
4.编译文件
(1)发送端
                      g++ -o send send.cpp -I /usr/local/include/jrtplib3/ -ljrtp
(2)接收端
                      g++ -o receive  receive.cpp -I /usr/local/include/jrtplib3/ -ljrtp
附录:
(1)send.cpp
[cpp]
#include "rtpsession.h" 
#include "rtppacket.h" 
#include "rtpudpv4transmitter.h" 
#include "rtpipv4address.h" 
#include "rtpsessionparams.h" 
#include "rtperrors.h" 
#include "rtpmemorymanager.h" 
#ifndef WIN32 
    #include <netinet/in.h> 
    #include <arpa/inet.h> 
#else 
    #include <winsock2.h> 
#endif // WIN32 
#include <stdlib.h> 
#include <stdio.h> 
#include <iostream> 
#include <string> 
 
// 
// This function checks if there was a RTP error. If so, it displays an error 
// message and exists. 
// 
 
void checkerror(int rtperr) 

    if (rtperr < 0) 
    { 
        std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl; 
        exit(-1); 
    } 

 
// 
// The main routine 
// 
 
#ifdef RTP_SUPPORT_THREAD 
 
class MyMemoryManager : public RTPMemoryManager 

public: 
    MyMemoryManager()  
    {  
        mutex.Init(); 
        alloccount = 0;  
        freecount = 0;  
    } 
    ~MyMemoryManager()  
    {  
        std::cout << "alloc: " << alloccount << " free: " << freecount << std::endl;  
    } 
    void *AllocateBuffer(size_t numbytes, int memtype) 
    { 
        mutex.Lock(); 
        void *buf = malloc(numbytes); 
        std::cout << "Allocated " << numbytes << " bytes at location " << buf << " (memtype = " << memtype << ")" << std::endl; 
        alloccount++; 
        mutex.Unlock(); 
        return buf; 
    } 
 
    void FreeBuffer(void *p) 
    { 
        mutex.Lock(); 
        std::cout << "Freeing block " << p << std::endl; 
        freecount++; 
        free(p); 
        mutex.Unlock(); 
    } 
private: 
    int alloccount,freecount; 
    JMutex mutex; 
}; 
 
#else 
 
class MyMemoryManager : public RTPMemoryManager 

public: 
    MyMemoryManager()  
    {  
        alloccount = 0;  
        freecount = 0;  
    } 
    ~MyMemoryManager()  
    {  
        std::cout << "alloc: " << alloccount << " free: " << freecount << std::endl;  
    } 
    void *AllocateBuffer(size_t numbytes, int memtype) 
    { 
        void *buf = malloc(numbytes); 
        std::cout << "Allocated " << numbytes << " bytes at location " << buf << " (memtype = " << memtype << ")" << std::endl; 
        alloccount++; 
        return buf; 
    } 
 
    void FreeBuffer(void *p) 
    { 
        std::cout << "Freeing block " << p << std::endl; 
        freecount++; 
        free(p); 
    } 
private: 
    int alloccount,freecount; 
}; 
 
#endif // RTP_SUPPORT_THREAD 
 
int main(void) 

#ifdef WIN32 
    WSADATA dat; 
    WSAStartup(MAKEWORD(2,2),&dat); 
#endif // WIN32 
     
    MyMemoryManager mgr; 
    RTPSession sess(&mgr); 
    uint16_t portbase,destport; 
    uint32_t destip; 
    std::string ipstr; 
    int status,i,num; 
 
        // First, we'll ask for the necessary information 
         
    std::cout << "Enter local portbase:" << std::endl; 
    std::cin >> portbase; 
    std::cout << std::endl; 
     
    std::cout << "Enter the destination IP address" << std::endl; 
    std::cin >> ipstr; 
    destip = inet_addr(ipstr.c_str()); 
    if (destip == INADDR_NONE) 
    { 
        std::cerr << "Bad IP address specified" << std::endl; 
        return -1; 
    } 
     
    // The inet_addr function returns a value in network byte order, but 
    // we need the IP address in host byte order, so we use a call to 
    // ntohl 
    destip = ntohl(destip); 
     
    std::cout << "Enter the destination port" << std::endl; 
    std::cin >> destport; 
     
    std::cout << std::endl; 
    std::cout << "Number of packets you wish to be sent:" << std::endl; 
    std::cin >> num; 
     
    // Now, we'll create a RTP session, set the destination, send some 
    // packets and poll for incoming data. 
     
    RTPUDPv4TransmissionParams transparams; 
    RTPSessionParams sessparams; 
     
    // IMPORTANT: The local timestamp unit MUST be set, otherwise 
    //            RTCP Sender Report info will be calculated wrong 
    // In this case, we'll be sending 10 samples each second, so we'll 
    // put the timestamp unit to (1.0/10.0) 
    sessparams.SetOwnTimestampUnit(1.0/10.0);        
     
    sessparams.SetAcceptOwnPackets(true); 
    transparams.SetPortbase(portbase); 
    status = sess.Create(sessparams,&transparams);   
    checkerror(status); 
     
    RTPIPv4Address addr(destip,destport); 
     
    status = sess.AddDestination(addr); 
    checkerror(status); 
     
    for (i = 1 ; i <= num ; i++) 
    { 
        printf("/nSending packet %d/%d/n",i,num); 
         
        // send the packet 
        status = sess.SendPacket((void *)"1234567890",10,0,false,10); 
        checkerror(status); 
         
        sess.BeginDataAccess(); 
         
        // check incoming packets 
        if (sess.GotoFirstSourceWithData()) 
        { 
            do 
            { 
                RTPPacket *pack; 
                 
                while ((pack = sess.GetNextPacket()) != NULL) 
                { 
                    // You can examine the data here 
                    printf("Got packet !/n"); 
                     
                    // we don't longer need the packet, so 
                    // we'll delete it 
                    sess.DeletePacket(pack); 
                } 
            } while (sess.GotoNextSourceWithData()); 
        } 
         
        sess.EndDataAccess(); 
 
#ifndef RTP_SUPPORT_THREAD 
        status = sess.Poll(); 
        checkerror(status); 
#endif // RTP_SUPPORT_THREAD 
         
        RTPTime::Wait(RTPTime(1,0)); 
    } 
     
    sess.BYEDestroy(RTPTime(10,0),0,0); 
 
#ifdef WIN32 
    WSACleanup(); 
#endif // WIN32 
    return 0; 

(2) receive.cpp
[cpp] view plaincopy
#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> 
 
// 
// This function checks if there was a RTP error. If so, it displays an error 
// message and exists. 
// 
 
void checkerror(int rtperr) 

    if (rtperr < 0) 
    { 
        std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl; 
        exit(-1); 
    } 

 
// 
// The new class routine 
// 
 
class MyRTPSession : public RTPSession 

protected: 
    void OnNewSource(RTPSourceData *dat) 
    { 
        if (dat->IsOwnSSRC()) 
            return; 
 
        uint32_t ip; 
        uint16_t port; 
         
        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; 
        } 
        else 
            return; 
         
        RTPIPv4Address dest(ip,port); 
        AddDestination(dest); 
 
        struct in_addr inaddr; 
        inaddr.s_addr = htonl(ip); 
        std::cout << "Adding destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl; 
    } 
 
    void OnBYEPacket(RTPSourceData *dat) 
    { 
        if (dat->IsOwnSSRC()) 
            return; 
         
        uint32_t ip; 
        uint16_t port; 
         
        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; 
        } 
        else 
            return; 
         
        RTPIPv4Address dest(ip,port); 
        DeleteDestination(dest); 
         
        struct in_addr inaddr; 
        inaddr.s_addr = htonl(ip); 
        std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl; 
    } 
 
    void OnRemoveSource(RTPSourceData *dat) 
    { 
        if (dat->IsOwnSSRC()) 
            return; 
        if (dat->ReceivedBYE()) 
            return; 
         
        uint32_t ip; 
        uint16_t port; 
         
        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; 
        } 
        else 
            return; 
         
        RTPIPv4Address dest(ip,port); 
        DeleteDestination(dest); 
         
        struct in_addr inaddr; 
        inaddr.s_addr = htonl(ip); 
        std::cout << "Deleting destination " << std::string(inet_ntoa(inaddr)) << ":" << port << std::endl; 
    } 
}; 
 
// 
// The main routine 
//  
 
int main(void) 

#ifdef WIN32 
    WSADATA dat; 
    WSAStartup(MAKEWORD(2,2),&dat); 
#endif // WIN32 
     
    MyRTPSession sess; 
    uint16_t portbase; 
    std::string ipstr; 
    int status,i,num; 
 
        // First, we'll ask for the necessary information 
         
    std::cout << "Enter local portbase:" << std::endl; 
    std::cin >> portbase; 
    std::cout << std::endl; 
     
    std::cout << std::endl; 
    std::cout << "Number of seconds you wish to wait:" << std::endl; 
    std::cin >> num; 
     
    // Now, we'll create a RTP session, set the destination 
    // and poll for incoming data. 
     
    RTPUDPv4TransmissionParams transparams; 
    RTPSessionParams sessparams; 
     
    // IMPORTANT: The local timestamp unit MUST be set, otherwise 
    //            RTCP Sender Report info will be calculated wrong 
    // In this case, we'll be just use 8000 samples per second. 
    sessparams.SetOwnTimestampUnit(1.0/8000.0);      
     
    sessparams.SetAcceptOwnPackets(true); 
    transparams.SetPortbase(portbase); 
    status = sess.Create(sessparams,&transparams);   
    checkerror(status); 
     
    for (i = 1 ; i <= num ; i++) 
    { 
        sess.BeginDataAccess(); 
         
        // check incoming packets 
        if (sess.GotoFirstSourceWithData()) 
        { 
            do 
            { 
                RTPPacket *pack; 
                 
                while ((pack = sess.GetNextPacket()) != NULL) 
                { 
                    // You can examine the data here 
                    printf("Got packet !/n"); 
                     
                    // we don't longer need the packet, so 
                    // we'll delete it 
                    sess.DeletePacket(pack); 
                } 
            } while (sess.GotoNextSourceWithData()); 
        } 
         
        sess.EndDataAccess(); 
 
#ifndef RTP_SUPPORT_THREAD 
        status = sess.Poll(); 
        checkerror(status); 
#endif // RTP_SUPPORT_THREAD 
         
        RTPTime::Wait(RTPTime(1,0)); 
    } 
     
    sess.BYEDestroy(RTPTime(10,0),0,0); 
 
#ifdef WIN32 
    WSACleanup(); 
#endif // WIN32 
    return 0;