美文网首页
9.JRTPLIB使用

9.JRTPLIB使用

作者: Pokerpoke | 来源:发表于2017-11-28 23:05 被阅读0次

    JRTPLIB使用

    1.RTP简介

    实时传输协议(Real-time Transport Protocol或简写RTP)是一个网络传输协议,它是由IETF的多媒体传输工作小组1996年在RFC 1889中公布的。

    国际电信联盟ITU-T也发布了自己的RTP文档,作为H.225.0,但是后来当IETF发布了关于它的稳定的标准RFC后就被取消了。它作为因特网标准在RFC 3550(该文档的旧版本是RFC 1889)有详细说明。RFC 3551(STD 65,旧版本是RFC 1890)详细描述了使用最小控制的音频和视频会议。

    RTP协议详细说明了在互联网上传递音频和视频的标准数据包格式。它一开始被设计为一个多播协议,但后来被用在很多单播应用中。RTP协议常用于流媒体系统(配合RTSP协议),视频会议和一键通(Push to Talk)系统(配合H.323或SIP),使它成为IP电话产业的技术基础。RTP协议和RTP控制协议RTCP一起使用,而且它是建立在UDP协议上的。实时传输协议------wiki

    2.JRTPLIB

    RTP 是目前解决流媒体实时传输问题的最好办法,如果需要在Linux平台上进行实时流媒体编程,可以考虑使用一些开放源代码的RTP库,如LIBRTP、 JRTPLIB等。 JRTPLIB是一个面向对象的RTP库,它完全遵循RFC 1889设计,在很多场合下是一个非常不错的选择,下面就以JRTPLIB为例,讲述如何在Linux平台上运用RTP协议进行实时流媒体编程。

    JRTPLIB 是一个用C++语言实现的RTP库,目前已经可以运行在Windows、Linux、FreeBSD、Solaris、Unix和 VxWorks等多种操作系统上。------jrtp详细介绍

    3.JRTPLIB编译

    git clone https://github.com/j0r1/JRTPLIB.git
    cd JRTPLIB
    mkdir build
    cd build
    cmake .. && make && sudo make install
    

    如果需要启用JThread支持,需要在编译JRTPLIB之前编译JThread

    git clone https://github.com/j0r1/JThread.git
    cd JRTPLIB
    mkdir build
    cd build
    cmake .. && make && sudo make install
    

    4.JRTPLIB例程

    官方历程参见https://github.com/j0r1/JRTPLIB/tree/master/examples,以下是example1.cpp,添加了一些中文注释

    #include "rtpsession.h"
    #include "rtpudpv4transmitter.h"
    #include "rtpipv4address.h"
    #include "rtpsessionparams.h"
    #include "rtperrors.h"
    #include "rtplibraryversion.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <iostream>
    #include <string>
    
    using namespace jrtplib;
    
    // 打印错误信息
    void checkerror(int rtperr)
    {
        if (rtperr < 0)
        {
            std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
            exit(-1);
        }
    }
    
    // 主循环
    
    int main(void)
    {
    
    // windows相关,不需要可以删了
    #ifdef RTP_SOCKETTYPE_WINSOCK
        WSADATA dat;
        WSAStartup(MAKEWORD(2,2),&dat);
    #endif // RTP_SOCKETTYPE_WINSOCK
    
        RTPSession sess;
        uint16_t portbase,destport;
        uint32_t destip;
        std::string ipstr;
        int status,i,num;
    
        // 打印JRTPLIB版本
        std::cout << "Using version " << RTPLibraryVersion::GetVersion().GetVersionString() << std::endl;
    
        // 获取本地端口,用以接收
        std::cout << "Enter local portbase:" << std::endl;
        std::cin >> portbase;
        std::cout << std::endl;
    
        // 目标地址,本机使用127.0.0.1
        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;
        }
    
        // inet_addr函数返回的是网络字节序,需要将网络字节序转化为主机字节序
        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;
    
        // 创建传输参数和会话参数
        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);
    
        // 写入IPv4地址和端口
        RTPIPv4Address addr(destip,destport);
    
        // 添加目标地址
        status = sess.AddDestination(addr);
        checkerror(status);
    
        for (i = 1 ; i <= num ; i++)
        {
            printf("\nSending packet %d/%d\n",i,num);
    
            // 发包
            status = sess.SendPacket((void *)"1234567890",10,0,false,10);
            checkerror(status);
    
            sess.BeginDataAccess();
    
            // 检查收包
            if (sess.GotoFirstSourceWithData())
            {
                do
                {
                    RTPPacket *pack;
    
                    while ((pack = sess.GetNextPacket()) != NULL)
                    {
                        // 在这里进行数据处理
                        printf("Got packet !\n");
    
                        // 不再需要这个包了,删除之
                        sess.DeletePacket(pack);
                    }
                } while (sess.GotoNextSourceWithData());
            }
    
            sess.EndDataAccess();
    
    // 这部分与JThread库相关
    #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);
    
    // Windows相关
    #ifdef RTP_SOCKETTYPE_WINSOCK
        WSACleanup();
    #endif // RTP_SOCKETTYPE_WINSOCK
        return 0;
    }
    

    这里会有问题,怎么读取收到的packet中的data,需要先包含头文件

    #include "rtppacket.h"
    

    在进行数据处理的地方使用以下函数获取负载数据,和负载长度

    pack->GetPayloadData();
    pack->GetPayloadLength();
    

    5.CMake配置

    在使用CMake进行编译的时候可能会出现找不到库的情况,需要手写FindJRTPLIB.cmake

    # - Find JRTPLIB library
    # Once done this will define
    # JRTPLIB_FOUND - system has JRTPLIB
    # JRTPLIB_INCLUDE_DIR - JRTPLIB include directories
    # JRTPLIB_LIBRARY - where to find the JRTPLIB library
    
    if(JRTPLIB_INCLUDE_DIR)
        # Already in cache, be silent
        set(JRTPLIB_FIND_QUIETLY TRUE)
    endif()
    
    find_path(JRTPLIB_INCLUDE_DIR
        NAMES rtpsession.h
        PATH_SUFFIXES jrtplib jrtplib3
        DOC "JRTPLIB include directories"
        )
    
    find_library(JRTPLIB_LIBRARY
        NAMES jrtp
        DOC "JRTPLIB library"
        )
    
    # handle the QUIETLY and REQUIRED arguments and set JRTPLIB_FOUND to TRUE if all listed variables are TRUE
    include(FindPackageHandleStandardArgs)
    find_package_handle_standard_args(JRTPLIB
                                      REQUIRED_VARS JRTPLIB_LIBRARY JRTPLIB_INCLUDE_DIR
                                      VERSION_VAR JRTPLIB_VERSION_STRING)
    
    if(JRTPLIB_INCLUDE_DIR AND JRTPLIB_LIBRARY)
        set(JRTPLIB_FOUND TRUE)
        set(JRTPLIB_LIBRARIES ${JRTPLIB_LIBRARY})
        set(JRTPLIB_INCLUDE_DIRS ${JRTPLIB_INCLUDE_DIR})
    else()
        set (JRTPLIB_FOUND FALSE)
        message(FATAL_ERROR "JRTPLIB not found")
    endif()
    
    mark_as_advanced(
        JRTPLIB_INCLUDE_DIR
        JRTPLIB_LIBRARY)
    

    如果前面编译了JThread库,或者在编译的时候提示

    This function is not available when using the RTP Poll thread feature.
    

    则还需要将JThread库进行链接,FindJTHREAD.cmake如下

    # - Find JTHREAD library
    # Once done this will define
    # JTHREAD_FOUND - system has JTHREAD
    # JTHREAD_INCLUDE_DIR - JTHREAD include directories
    # JTHREAD_LIBRARY - where to find the JTHREAD library
    
    if(JTHREAD_INCLUDE_DIR)
        # Already in cache, be silent
        set(JTHREAD_FIND_QUIETLY TRUE)
    endif()
    
    find_path(JTHREAD_INCLUDE_DIR
        NAMES jthread.h
        PATH_SUFFIXES jthread jthread3
        DOC "JTHREAD include directories"
        )
    
    find_library(JTHREAD_LIBRARY
        NAMES jthread
        DOC "JTHREAD library"
        )
    
    # handle the QUIETLY and REQUIRED arguments and set JTHREAD_FOUND to TRUE if all listed variables are TRUE
    include(FindPackageHandleStandardArgs)
    find_package_handle_standard_args(JTHREAD
                                      REQUIRED_VARS JTHREAD_LIBRARY JTHREAD_INCLUDE_DIR
                                      VERSION_VAR JTHREAD_VERSION_STRING)
    
    if(JTHREAD_INCLUDE_DIR AND JTHREAD_LIBRARY)
        set(JTHREAD_FOUND TRUE)
        set(JTHREAD_LIBRARIES ${JTHREAD_LIBRARY})
        set(JTHREAD_INCLUDE_DIRS ${JTHREAD_INCLUDE_DIR})
    else()
        set (JTHREAD_FOUND FALSE)
        message(FATAL_ERROR "JTHREAD not found")
    endif()
    
    mark_as_advanced(
        JTHREAD_INCLUDE_DIR
        JTHREAD_LIBRARY)
    

    之后在顶层的CMakeLists.txt中使用find_package(JRTPLIB)进行链接,不再赘述。

    相关文章

      网友评论

          本文标题:9.JRTPLIB使用

          本文链接:https://www.haomeiwen.com/subject/hleybxtx.html