IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> QT使用RTP实现高清实时视频聊天,RTP协议封装库jrtplib的使用 -> 正文阅读

[网络协议]QT使用RTP实现高清实时视频聊天,RTP协议封装库jrtplib的使用

说在前面

RTP,实时传输协议(Real-time Transport Protocol或简写RTP)是一个网络传输协议,基于UDP;
jrtplib,基于C++、面向对象的RTP封装库;
jthread,是一个基础库,jrtplib依赖于该库;
jrtplib是对RTP协议的封装库,QT调用jrtplib库使用RTP协议;
Qt根据编译器类型(msvc、mingw)不同,需要使用不同方式编译的jrtplib库和jthread库;

jrtplib库和jthread库的编译参见另一篇博文:
https://blog.csdn.net/weixin_40355471/article/details/119574994

视频聊天说明

一般视频聊天需要识别摄像头、图像采集、图像转换为内存二进制数据并发送,对端需要接收二进制数据转换为图片并显示到界面;
当图片大于MTU(最大传输单元)时,一次数据包无法正常发送,需要做分包处理,接收端再进行组包,建议单个包大小1000字节;
使用RTP协议的优势:之前使用udp发送数据,当图片较大时丢包丢帧严重,无法进行高清视频聊天,RTP则能实现稳定的数据收发;
本博文只介绍RTP数据收发。

动态库引用

jrtplib库和jthread库编译完成后,把包含头文件的文件夹jrtplib3\和jthread\拷贝到工程pro文件同级目录的include文件夹,把编译好的库拷贝的构建目录(exe可执行文件所在文件夹),在pro文件添加:

LIBS += -lWs2_32
INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD/include

LIBS +=-LD:\HSCompany\Qtcode\VideoCallHljVTM\source\build-VideoCallHljVTM_kf-Desktop_Qt_5_12_2_MinGW_64_bit-Release\bin -ljthread
LIBS +=-LD:\HSCompany\Qtcode\VideoCallHljVTM\source\build-VideoCallHljVTM_kf-Desktop_Qt_5_12_2_MinGW_64_bit-Release\bin -ljrtp

调用代码

首先初始化,设置参数,创建RTPSession会话,发送数据给对方,需要添加目标RtpAddDestination(QString ip, int port),可以添加多个目标,也可以删除目标,接收数据是通过while循环轮询方式。

初始化RTPSession会话

#include <WinSock2.h>
#include <jrtplib3/rtpconfig.h>
#include <jrtplib3/rtpsession.h>
#include <jrtplib3/rtpudpv4transmitter.h>
#include <jrtplib3/rtpipv4address.h>
#include <jrtplib3/rtpsessionparams.h>
#include <jrtplib3/rtperrors.h>
#include <jrtplib3/rtplibraryversion.h>
using namespace jrtplib;
using namespace std;

RTPSession sess;
sess.SetDefaultPayloadType(96);//设置传输类型
sess.SetDefaultMark(true);      //设置位
sess.SetTimestampUnit(1.0/9000.0); //设置采样间隔
sess.SetDefaultTimestampIncrement(10);//设置时间戳增加间隔

#ifdef RTP_SOCKETTYPE_WINSOCK
    WSADATA dat;
    WSAStartup(MAKEWORD(2,2),&dat);
#endif // RTP_SOCKETTYPE_WINSOCK

    uint16_t portbase = GlobalVar_VC::g_Video_SendLocal_Port.toInt();//设置端口号为0,则自动选择一个端口号
    int status;

    RTPSessionParams sessparams;
    sessparams.SetOwnTimestampUnit(1.0/10.0); //时间戳单位
    sessparams.SetAcceptOwnPackets(true);   //接收自己发送的数据包
    sessparams.SetUsePredefinedSSRC(true);  //设置使用预先定义的SSRC
    sessparams.SetPredefinedSSRC(1);     //定义SSRC

    RTPUDPv4TransmissionParams transparams;
    transparams.SetPortbase(portbase);
    status = sess.Create(sessparams,&transparams);//创建RTP会话
    qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<RTPGetErrorString(status).c_str();//打印错误信息

发送数据,添加RTP目标端,删除RTP目标端

/**
 * @brief RTP发送数据
 * @param data 数据
 * @param len 数据长度
 * @return 返回状态码,0正常
 */
int ImageCaptureThre::sendDataRTP(char *data, int len)
{
	//图片数据分包处理后,单个数据包调用这个接口发送
    int status = sess.SendPacket((void *)data,len,0,false,10);
    return status;
}

/**
 * @brief 添加RTP目标
 * @param ip
 * @param port
 */
void ImageCaptureThre::RtpAddDestination(QString ip, int port)
{
    int status;

    std::string ipstr;
    ipstr = ip.toStdString();
    uint16_t destport;
    uint32_t destip;
    destip = inet_addr(ipstr.c_str());
    if (destip == INADDR_NONE)
    {
        qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<"Bad IP address specified ";
        return;
    }

    destip = ntohl(destip);
    destport = port;
    RTPIPv4Address addr(destip,destport);

    status = sess.AddDestination(addr);
    qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<RTPGetErrorString(status).c_str();
}

/**
 * @brief 删除RTP目标
 * @param ip
 * @param port
 */
void ImageCaptureThre::RtpDelDestination(QString ip, int port)
{
    int status;

    std::string ipstr;
    ipstr = ip.toStdString();
    uint16_t destport;
    uint32_t destip;
    destip = inet_addr(ipstr.c_str());
    if (destip == INADDR_NONE)
    {
        qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<"Bad IP address specified ";
        return;
    }

    destip = ntohl(destip);
    destport = port;
    RTPIPv4Address addr(destip,destport);

    status = sess.DeleteDestination(addr);
    qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<RTPGetErrorString(status).c_str();
}

接收数据


/**
 * @brief RTP接收数据
 */
void RcvImageUdp::revData()
{
    while(isRevImage == true)
    {
        QThread::msleep(10);
        sess.BeginDataAccess();
        if (sess.GotoFirstSourceWithData())
        {
            do
            {
                RTPPacket *pack;//要包含头文件rtppacket.h,否则报类型不完整错误
                while ((pack = sess.GetNextPacket()) != NULL)
                {
                    int recvSize = pack->GetPacketLength();//接收数据长度
                    uint8_t * recvData=pack->GetPacketData();//接收到的数据
                    //在这里对接收的数据进行处理,组包
                    sess.DeletePacket(pack);
                }
            } while (sess.GotoNextSourceWithData());
        }
        sess.EndDataAccess();
    }
}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 12:24:57  更:2021-08-19 12:26:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:55:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码