从零开始精通RTSP之深入理解RTP协议

概述

        RTP,即实时传输协议,英文全称为Real-Time Transport Protocol,是一种用于在互联网上传输视频、音频等实时数据的网络协议。RTP本身不提供任何服务质量保证,而是依赖于底层传输协议(比如:UDP)来进行数据传输。RTP的主要功能是为实时数据提供时间戳和序列号,以便接收端能够按照正确的顺序和时间重建数据流。

RTP与RTSP的关系

        RTP专为在IP网络上传输实时音视频等连续媒体数据而设计,承担着数据封装、传输与同步的任务。相较于负责会话控制和媒体描述的RTSP,RTP更侧重于实时数据的实际传输过程。

        RTSP与RTP形成互补关系:RTSP用于建立、控制和终结媒体会话,定义媒体类型、传输参数等;RTP则依据RTSP设定的参数,实际传输封装好的媒体数据。二者通过交互消息,比如:RTSP的SETUP、PLAY命令与RTP数据流,实现无缝对接。

        总的来说,RTP与RTSP之间的关系是相辅相成的。RTP提供了实时数据传输的基础,而RTSP则在此基础上实现了对媒体流的控制和管理。两者共同协作,使得实时流媒体的传输和控制变得更加高效和可靠。

RTP数据包

        RTP数据包由RTP头部(RTP Header)和RTP负载(RTP Payload)两部分组成。RTP头部包含了关于数据包的重要信息,比如:版本号、负载类型、序列号、时间戳等。RTP负载包含实际的媒体数据,其格式和内容取决于载荷类型(PT)字段所指示的编码或格式。比如:如果载荷类型是H.264视频,那么RTP负载将包含H.264编码的视频帧。

        关于RTP数据包,这里不再深入,我们会在后续的专栏文章中专门进行介绍。

基于UDP的传输特性

        RTP使用UDP来进行实时音视频等流媒体数据的传输,故其具有UDP的一些传输特性。

        1、无连接性:RTP利用UDP的无连接特性,无需预先建立连接即可发送数据。这简化了会话建立过程,降低了延迟,尤其适用于实时媒体流,其中快速启动传输至关重要。

        2、多播支持:由于UDP支持多播,RTP可以通过单一数据发送操作到达多个接收者,这对于大规模直播场景非常有利,减少了服务器负载和网络带宽消耗。

        3、低延迟:UDP避免了TCP的握手、确认、重传等机制,使得RTP数据包几乎可以立即发送,从而保持较低的端到端延迟,符合实时流对时延敏感的要求。

        虽然UDP不提供可靠传输,但RTP通过以下机制增强了传输的可靠性。

        1、校验和:RTP头部包含一个校验和字段,用于检测数据包在传输过程中是否发生错误。接收端计算收到数据包的校验和,并与包内校验和比较,若不一致则丢弃该包。

        2、前向纠错(FEC):通过RTP扩展,可以添加前向纠错码,发送冗余数据。这允许接收端在一定比例丢包的情况下恢复原始数据,提高传输的稳健性。

        3、RTCP反馈与控制:与RTP配套的RTCP协议定期发送控制报文(比如:Sender Report、Receiver Report),提供丢包率、抖动、延迟等统计信息,用于监测会话质量并触发相应的补偿措施(比如:重新发送请求、码率调整等)。

重组数据包

        重组数据包是指客户端接收一系列RTP数据包后,根据它们的序列号、时间戳等信息,将这些包按照发送时的原始顺序重新组织起来的过程。重组数据包的目的是:确保解码器能够按照正确的顺序处理这些数据,从而正确解码并输出音视频流。在重组过程中,客户端需要处理丢包、乱序到达的包以及可能存在的分包数据。

        重组数据包的过程主要涉及以下5个步骤。

        1、接收与存储RTP数据包

        客户端通过UDP接收来自服务器的RTP数据包。每当接收到一个RTP包时,客户端首先检查其头部中的序列号字段。这个序列号是递增的16位整数,每发送一个新的RTP数据包,发送端就会将其增加1。客户端需要将接收到的RTP包及其序列号存储在一个适当的结构(比如:队列、环形缓冲区等)中,以便后续处理。

        2、检测与处理丢包

        根据RTP数据包的序列号,客户端可以检测是否存在丢包。如果连续接收的两个RTP包之间的序列号差值大于1,则表明在这两个包之间存在一个或多个丢包。客户端可以根据需要通过RTCP的Receiver Report报文向服务器报告丢包情况,或者使用其他应用层重传机制(比如:RTCP的NACK请求)请求丢失的数据包。

        3、基于序列号排序

        存储在客户端内部结构中的RTP包需要按照其序列号进行排序,以恢复原始的发送顺序。排序算法可以是简单的插入排序、快速排序、堆排序等,也可以是针对RTP包特性优化的排序方法。排序的目标是确保RTP包按照其在发送端生成的顺序排列,以便后续解码器正确处理。

        比如:对于一个简单的环形缓冲区,可以设置一个指向当前已排序部分最后一个包的指针。每当接收到一个新包时,将其与指针处的包进行序列号比较。如果新包的序列号大于指针处包的序列号且小于下一个预期包的序列号(当前已排序部分最大序列号+1),则将新包插入到适当位置。如果新包的序列号小于等于指针处包的序列号,说明收到了旧包或重复包,可以直接丢弃。如果新包的序列号大于下一个预期包的序列号,说明存在未接收到的中间包,此时可以暂时将新包存放在待排序区域,等待缺失的包到达后再进行插入排序。

        4、处理乱序包

        在实际网络环境中,RTP包可能会因为网络延迟不均等原因出现乱序到达的情况,客户端在排序过程中应能妥善处理乱序包。当发现新包的序列号大于下一个预期包的序列号时,说明该包是乱序到达的。此时,客户端不应立即插入该包,而应将其暂存于乱序包队列,等待所有位于其前序的中间包到达后再插入到正确位置。乱序包队列应有限定的容量,防止内存过度消耗。超出容量的乱序包可以选择丢弃,或者根据具体应用需求采取其他处理策略。

        5、数据包交付给解码器

        当RTP包按照序列号正确排序后,客户端可以将连续的一段无丢包、无乱序的RTP包提交给解码器进行解码。解码器按照包的顺序进行解码处理,生成可供播放的音视频数据。

        通过上述步骤,客户端能够基于RTP包的序列号有效地重组数据包,确保音视频流的正确解码和播放。在整个过程中,客户端需要实时监测网络状况,根据丢包率、延迟、抖动等指标调整接收策略,比如:调整缓冲区大小、请求重传、切换码率等,以优化用户体验。同时,与服务器之间的RTCP通信也是必不可少的,用于交换会话控制信息、反馈接收质量以及请求丢包恢复等。

分包与组包

        分包是指将一个较大的编码单元(比如:H.264/AVC、H.265/HEVC的NAL单元)分割成多个较小的数据块(分包),以便通过RTP协议进行传输。分包通常发生在编码器端,当原始编码单元过大,不适合单个RTP包承载时,会选择将其拆分成多个RTP包发送。每个分包都有相应的标识信息(比如:分包索引、分包类型等),以便接收端识别并正确重组。

        可能很多初学者会有疑问:为什么需要分包呢?主要有以下两点原因。

        1、MTU限制

        网络传输中存在最大传输单元MTU(Maximum Transmission Unit)的限制,比如:以太网的MTU通常是1500个字节。考虑到IP头部、UDP头部和RTP头部的开销,实际留给RTP有效载荷的空间更小,通常约1400字节。如果一个编码单元超过了这个有效载荷限制,就需要进行分包。

        2、带宽管理

        分包有助于更有效地利用带宽,尤其是在网络条件不稳定或带宽有限的情况下,通过将大编码单元拆分为较小的部分,可以更灵活地调整传输速率,降低丢包风险。

        常见的分包方法有如下两种,下面分别进行介绍。

        单个NAL单元打包:对于大小适中的NAL单元,可以直接将其放入一个RTP包中,去除NAL单元起始码(Start Code),将剩余数据作为RTP的有效载荷。

        FU-A分片:当NAL单元过大时,可以采用Fragmentation Unit (FU)分片机制(比如:H.264/AVC中定义的FU-A模式)。这种机制将一个大的NAL单元切割成若干个较小的片段,每个片段称为一个FU。每个FU封装在一个单独的RTP包内,且包含分片相关的标识信息。更详细的信息,我们会在后续的专栏文章中进行介绍。

        组包则是指在接收端或客户端,将属于同一原始编码单元的所有分包重新组合成完整编码单元的过程。组包是重组数据包过程中的一个子步骤,专门针对那些经过分包处理的RTP数据。客户端需要根据分包标识信息,将属于同一编码单元的分包收集在一起,并按照正确的顺序拼接起来,最终还原成完整的编码单元,供解码器进行解码。

        组包主要包含如下的4个步骤。

        1、接收端(客户端或解码器)接收到包含分片数据的RTP包后,依据RTP包头的序列号、时间戳以及FU Header中的分片信息进行重组。

        2、根据RTP包的序列号,确保分片按照发送顺序进行重组。如果有乱序或丢包情况,可能需要通过重传请求或前向纠错等机制进行恢复。

        3、对于FU-A分片,依据FU Header中的分片索引和结束标志,将属于同一NAL单元的所有片段按照正确的顺序拼接起来,恢复成完整的NAL单元。拼接时需要去除FU Header,还原NAL单元起始码。

        4、组包过程中,接收端可能需要缓存未完成重组的分片数据,直到收到所有分片或达到重组超时。同时,还需要考虑时间戳信息,确保解码时的同步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/1522.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ACE框架学习2

目录 ACE Service Configurator框架 ACE_Server_Object类 ACE_Server_Repository类 ACE_Server_Config类 ACE Task框架 ACE_Message_Queue类 ACE_TASK类 在开始之前&#xff0c;首先介绍一下模板类的实例化和使用。给出以下代码 //ACCEPTOR代表模板的方法 template <…

VSCode插件开发学习

一、环境准备 0、参考文档&#xff1a;VS Code插件创作中文开发文档 1、大于18版本的nodejs 2、安装Yeoman和VS Code Extension Generator&#xff1a; npm install -g yo generator-code 3、生成脚手架 yo code 选择内容&#xff1a; ? What type of extension do yo…

DASCTF X GFCTF 2024|四月开启第一局

前言 题目都比较简单&#xff0c;&#xff0c;&#xff0c;没啥好说的&#xff0c;很久没做题了&#xff0c;简单记录一下 dynamic_but_static 仅仅开了 NX 保护栈溢出 先泄漏 libc 地址&#xff0c;然后栈溢出打 ret2libc&#xff0c;开了沙箱得 orw from pwn import * c…

Vue3+TS版本Uniapp:项目前置操作

作者&#xff1a;前端小王hs 阿里云社区博客专家/清华大学出版社签约作者✍/CSDN百万访问博主/B站千粉前端up主 环境&#xff1a;使用vscode进行开发 如果一开始是使用的HbuilderX&#xff0c;请看hbuilderX创建的uniapp项目转移到vscode 为什么选择vscode&#xff1f;有更好…

Docker容器的原理及应用详解(三)

本系列文章简介&#xff1a; Docker是一种开源的容器化技术&#xff0c;它将应用程序及其依赖项打包为一个容器&#xff0c;以便在任何环境下运行。与传统的虚拟机相比&#xff0c;Docker容器更加轻量级且快速&#xff0c;可以在几秒钟内启动和停止。Docker的原理和应用非常广泛…

Windows进入黑屏,操作CMD提示命令提示符已被系统管理员停用

背景 由于安装或者卸载某些服务导致主机无法正常显示桌面&#xff0c;从控制台进入打开操作执行命令提示禁用。 操作步骤 注意务必做好快照备份后再操作。 打开注册表中将其重新启用&#xff1a; 依次打开“运行”命令&#xff0c;然后在打开的“运行”对话框中输入 “regedit…

一个简单的记工tkinter窗口

代码分享: 导入datetime模块&#xff0c;用于获取当前日期 import datetime as da 导入csv模块&#xff0c;用于读写csv文件 import csv 导入tkinter模块&#xff0c;用于创建窗口和按钮 from tkinter import * 创建主窗口 appTk() 设置窗口大小为1048x2048&#xff0…

华为海思校园招聘-芯片-数字 IC 方向 题目分享——第六套

华为海思校园招聘-芯片-数字 IC 方向 题目分享——第六套 (共9套&#xff0c;有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09; 部分题目分享&#xff0c;完整版获取&#xff08;WX:didadidadidida313&#xff0c;加我备注&#x…

【OpenHarmony-NDK技术】简单将cJson移植到OpenHarmony中,并在c层修改参数值再返回json

1、cJson的简单介绍 cJson - github网址 概述 一般使用cJson是&#xff0c;需要将json文本转化为json对象–编码&#xff0c;将json对象转化为json文本–解析。 git clone https://github.com/DaveGamble/cJSON.git 后留意cJSON.h和cJSON.h两个文件。 1、cJson的介绍 cJso…

【Kafka】KafkaTopic命令

【Kafka】KafkaTopic命令 1. topic命令 1. topic命令 查看集群中所有的topic [roothcss-ecs-2ff4 kafka]# kafka-topics.sh --bootstrap-server 101.42.49.137:9092,139.9.133.30:9092,114.116.254.124:9092 --list# 创建一个topic 一个节点创建其他节点也有 [rootVM-8-7-cen…

Golang那些违背直觉的编程陷阱

目录 知识点1&#xff1a;切片拷贝之后都是同一个元素 知识点2&#xff1a;方法集合决定接口实现&#xff0c;类型方法集合是接口方法集合的超集则认定为实现接口&#xff0c;否则未实现接口 切片拷贝之后都是同一个元素 package mainimport ("encoding/json"&quo…

深入解读:BIO、NIO与IO多路复用——理解现代网络编程基石

在现代软件开发中&#xff0c;高效的数据交换是构建高性能网络应用的核心要素。深入理解输入输出&#xff08;Input/Output,简称IO&#xff09;模型的底层原理与工作机制&#xff0c;对于设计和实现高并发、低延迟的网络服务至关重要。本文将深度剖析阻塞式I/O&#xff08;BIO&…

k8s和docker的一些学习(一)

https://www.cnblogs.com/dazhoushuoceshi/p/7066041.html //dockerfile总结&#xff08;TO READ&#xff09; 不太懂的就是VOLUME的概念&#xff08;数据卷&#xff09;&#xff0c;问了一下GPT Q:docker的VOLUME是什么作用&#xff1f;详细解答一下 A:在 Docker 中&#x…

Redis 如何实现分布式锁

课程地址 单机 Redis naive 版 加锁&#xff1a; SETNX ${lockName} ${value} # set if not exist如果不存在则插入成功&#xff0c;返回 1&#xff0c;加锁成功&#xff1b;否则返回 0&#xff0c;加锁失败 解锁&#xff1a; DEL ${lockName}问题1 2 个线程 A、B&#…

前后端交互概念

前后端交互概念 1前后端分离开发概念2搭建后端环境2.1配置文件commomcommon-utilservice-utilmodelservice gitee使用 1前后端分离开发概念 前段&#xff1a;运用html、css、js和现成库&#xff0c;对数据作展示。 后端&#xff1a;运用Java和Java框架&#xff0c;提供数据或操…

立创·实战派ESP32-C3开发板 with lv_micropython

一、lv_micropython对驱动芯片的支持 ESP32-C3开发板的Display drivers:ST7789&#xff0c;Input drivers:FT6336&#xff0c;从LVGL的官方文档了解到lv_micropython包含了这两颗IC的驱动。 参考文档&#xff1a; lv_micropython already contains these drivers: 链接:Micro…

智慧化转型赋能园区创新:科技创新引领产业智慧化,打造高效发展新格局

在全球化和信息化浪潮的推动下&#xff0c;园区作为区域经济发展的重要引擎&#xff0c;正面临着前所未有的机遇与挑战。为应对这些挑战并把握机遇&#xff0c;园区需积极拥抱智慧化转型&#xff0c;通过科技创新引领产业智慧化&#xff0c;打造高效发展的新格局。本文将深入探…

贝叶斯分类 python

贝叶斯分类 python 贝叶斯分类器是一种基于贝叶斯定理的分类方法&#xff0c;常用于文本分类、垃圾邮件过滤等领域。 在Python中&#xff0c;我们可以使用scikit-learn库来实现贝叶斯分类器。 下面是一个使用Gaussian Naive Bayes(高斯朴素贝叶斯)分类器的简单示例&#xff1…

go | defer、panic、recover

刷一道题&#xff0c; 将当函数触发panic 之后&#xff0c;函数是怎么执行的 然后我去找相关博客&#xff0c;发现这篇讲的蛮好的 接下来我直接上demo &#xff0c;然后通过demo 来逐个分析 package mainimport ("fmt" )func f() {defer func() {if r : recover();…

毕业设计——基于ESP32的智能家居系统(语音识别、APP控制)

ESP32嵌入式单片机实战项目 一、功能演示二、项目介绍1、功能演示2、外设介绍 三、资料获取 一、功能演示 多种控制方式 ① 语音控制 ②APP控制 ③本地按键控制 ESP32嵌入式单片机实战项目演示 二、项目介绍 1、功能演示 这一个基于esp32c3的智能家居控制系统&#xff0c;能实…