首页 > 其他分享 >JRTPLIB详解

JRTPLIB详解

时间:2023-10-08 16:00:44浏览次数:26  
标签:JRTPLIB INCLUDE set 详解 JTHREAD include DIR

简介

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

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

CMake介绍

CMake是一个工程文件生成工具。用户可以使用预定义好的CMake脚本,根据自己配置选择开发环境(像是Visual Studio, Code::Blocks, Eclipse)生成不同IDE的工程文件。
Cmake下载地址:https://cmake.org/download/
解压后直接运行cmake-gui.exe。
image

JThread编译

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

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();

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)进行链接,不再赘述。

标签:JRTPLIB,INCLUDE,set,详解,JTHREAD,include,DIR
From: https://www.cnblogs.com/xianfengzhike/p/17749414.html

相关文章

  • MYSQL中 find_in_set() 函数用法详解(匹配部门id或父id为100的数据)
    https://blog.csdn.net/carefree31441/article/details/119563685   ......
  • odoo14 生成PDF报表详解
    1.新建report目录-新建报表xml文件material_storage_pdf.xml2. 定义xml文件报表参数参数ir.actions.report报表属性name:打印动作按钮下的报表名字model:你的报表相关的模型,也就是说是你下载pdf中,pdf中数据的来源report_type:PDF报表的qweb-pdf或HTML的qweb-html,就是下载的报......
  • JS 全屏和退出全屏--requestFullScreen详解及兼容代码
    浏览器全屏实现方式1.利用h5的 requestFullScreen2.摁F11实现全屏效果requestFullscreen全屏具体实现1.进入全屏   functionfull(ele){ if(ele.requestFullscreen){ ele.requestFullscreen(); }elseif(ele.mozRequestFullScr......
  • redis服务配置文件详解
    bind0.0.0.0#监听地址,可以用空格隔开后多个监听IPprotected-modeyes#redis3.2之后加入的新特性,在没有设置bindIP和密码的时候,redis只允许访问127.0.0.1:6379,可以远程连接,但当访问将提示警告信息并拒绝远程访问port6379#监听端口,默认6379/tcptcp-backlog511#三次......
  • RDB、AOF详解及优缺点总结
    1.RDB模式优缺点1.1.RDB模式优点1.1.1.RDB快照保存了某个时间点的数据,可以通过脚本执行redis指令bgsave(非阻塞,后台执行)或者save(会阻塞写操作,不推荐)命令自定义时间点备份,可以保留多个备份,当出现问题可以恢复到不同时间点的版本,很适合备份,并且此文件格式也支持有不少第三......
  • 详解PHP反射API
    反射API的部分类使用反射API这些类,可以获得在运行时访问对象、函数和脚本中的扩展的信息。通过这些信息可以用来分析类或者构建框架。类描    述Reflection为类的摘要信息提供静态函数export()ReflectionClass类信息和工具ReflectionMethod类方法信......
  • 若依系统将Mybatis升级为Mybatis-Plus详解
    1.找到ruoyi-framework/...../config/MybatisConfig,将其sqlSessionFactory(DataSourcedataSource)注释2.找到整个项目的pom文件,添加Mybatis-plus版本号3.找到ruoyi-common的pom文件,添加依赖4.找到ruoyi-admin/../resources/application.yml文件,添加plus的配置文件简简单......
  • c#组合模式详解
    基础介绍:  组合模式用于表示部分-整体的层次结构。适用于希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象的情况。  顾名思义,什么叫部分-整体,比如常见的前端UI,一个DIV标签中可以存在多个A标签、P标签、DIV标签等等。  相较于DIV这个容器整体......
  • vue3中defineComponent 的作用详解
    转自:https://www.jb51.net/article/263096.htm 这篇文章主要介绍了vue3中defineComponent 的作用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 vue3中,新增了defineComponent,它并没有实现任何的逻辑,只是把接收的......
  • sqlServer安装步骤详解
    1、sqlserver下载步骤sqlserver下载地址——https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads下载下面的免费的developer即可;然后直接选择B就可以啦:选择中文简体,并接受:选择安装路径:等待安装完成:安装的确实有点子慢的;安装完成!然后选择安装SSMS;自......