关于RTP时间戳以及播放器对时间戳的处理

2024-04-19 15:08
文章标签 rtp 处理 时间 播放器

本文主要是介绍关于RTP时间戳以及播放器对时间戳的处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    首先,了解时间戳几个基本概念:

    时间戳单位:时间戳计算的单位不是秒之类的单位,而是由采样频率所代替的单位,这样做的目的就是为了是时间戳单位更为精准。比如说一个音频的采样频率为8000Hz,那么我们可以把时间戳单位设为1 / 8000。
    时间戳增量:相邻两帧之间的时间差(以时间戳单位为基准)。
    采样频率: 有些地方也叫时钟频率,即 每秒钟抽取样本的次数,例如音频的采样率一般为8000Hz
    帧率:      每秒传输或者显示帧数,例如25f/s
    
    再看看RTP时间戳课本中的定义:

    RTP包头的第2个32Bit即为RTP包的时间戳,Time Stamp ,占32位。
    时间戳反映了RTP分组中的数据的第一个字节的采样时刻。在一次会话开始时的时间戳初值也是随机选择的。即使是没有信号发送时,时间戳的数值也要随时间不断的增加。接收端使用时间戳可准确知道应当在什么时间还原哪一个数据块,从而消除传输中的抖动。时间戳还可用来使视频应用中声音和图像同步。
    在RTP协议中并没有规定时间戳的粒度,这取决于有效载荷的类型。因此RTP的时间戳又称为媒体时间戳,以强调这种时间戳的粒度取决于信号的类型。例如,对于8kHz采样的话音信号,若每隔20ms构成一个数据块,则一个数据块中包含有160个样本(0.02×8000=160)。因此每发送一个RTP分组,其时间戳的值就增加160。

   关于时间戳,归纳为以下几个重要的点:

    首先,时间戳就是一个值,用来反映某个数据块的产生(采集)时间点的,后采集的数据块的时间戳一般大于先采集的数据块的。为什么说一般呢?因为时间戳是一个32位无符号整型,如果一直递增到了一定时间数值就会回滚,所以时间戳只是对数据块先后顺序的一个参考。
    第二,在实时流传输中,数据采集后立刻传递到RTP模块进行发送,那么,其实,数据块的采集时间戳就直接作为RTP包的时间戳(要转换为某个时钟频率)。
    第三,如果用RTP来传输固定的文件,则这个时间戳就是视频文件中每一帧携带的时间戳,但是也需要转换为对应RTP通道的时钟频率。
    第四,时间戳的单位采用的是采样频率的倒数,例如采样频率为8000Hz时,时间戳的单位为1 / 8000 ,在Jrtplib库中,有设置时间戳单位的函数接口,而ORTP库中根据负载类型直接给定了时间戳的单位(音频负载1/8000,视频负载1/90000)
    第五,时间戳增量是指相邻两帧(不一定是相邻两个RTP包)之间的时间间隔。

    如果采样频率为90000Hz,则由上面讨论可知,时间戳单位为1/90000,我们就假设1s钟被划分了90000个时间块,那么,如果每秒发送25帧,那么,每一个帧的发送占多少个时间块呢?当然是 90000/25 = 3600。因此,我们根据定义“时间戳增量是发送第二个RTP包相距发送第一个RTP包时的时间间隔”,故时间戳增量应该为3600。

    下面说一下播放器如何对编码器发送的RTP包的时间戳做处理。这里的编码器是指发送RTP包的服务器,一般是指网络摄像机或RTSP服务器。

    播放器本地建立了一个系统时钟,这个时钟一般根据系统的CPU时间来计算出来,当播放开始,时钟的时间为0。时间戳有分绝对时间和相对时间,收到的RTP包的时间戳为绝对时间,播放器需要把这个RTP时间戳转为播放器本地的相对时间戳,相对时间戳以0为开始,时间戳决定了一帧播放或渲染的时刻。当播放开始时,时钟开始运行,时间戳一直增加,播放器会用系统时钟的时间跟视频帧的时间戳(相对时间戳)进行对比,根据它们的大小关系决定是否马上渲染这帧还是要等待。但是,编码器发过来的时间戳只是一个参考值,有可能是不准的,为什么呢?编码器打时间戳基于的时钟跟播放器的本地时钟是可能不一样的,不同的编码器有不同的打时间戳算法,我只说一下常见的做法,一般地,编码器打时间戳是基于一个简单的规则:每发一个视频帧,PTS就递增一个固定的时间增量。根据TS流和Rtp协议的规定,视频的时钟频率是90000,也就是时间单位是1/90000秒。如果帧率是25帧,则相邻两帧的PTS增量就是3600,也就是每发一个帧,时间戳就增加3600,但是实际上两帧的时间增量应该根据它们实际经过的时间,而不是一个固定的值。实际上,编码器每秒采集图像的帧率并不是绝对固定的(取决于物理时钟的精度以及CPU处理的速度),有一定误差,平均采集帧率是25,但可能编码器某1秒采集了25帧,某一秒采集了24帧,假如都是按固定增量的方式递增时间戳,过一段时间后,编码器的时间戳跟播放器的时钟的时间就有很大差异,可能导致播放不流畅,或者缓冲了很多帧延时加大了。
   所以,解码器不能盲目相信编码器的时间戳,发现时间戳跟本地的时间差异太远需要尽快调整,应该实现一个动态适应的机制:当发现接收缓冲区里的帧数比较多时,要加快渲染速度;当缓冲区的帧数在一个比较低的水平(1-4),则稳定渲染速度。

 

这篇关于关于RTP时间戳以及播放器对时间戳的处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/917886

相关文章

如何利用Java获取当天的开始和结束时间

《如何利用Java获取当天的开始和结束时间》:本文主要介绍如何使用Java8的LocalDate和LocalDateTime类获取指定日期的开始和结束时间,展示了如何通过这些类进行日期和时间的处... 目录前言1. Java日期时间API概述2. 获取当天的开始和结束时间代码解析运行结果3. 总结前言在J

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

Go Mongox轻松实现MongoDB的时间字段自动填充

《GoMongox轻松实现MongoDB的时间字段自动填充》这篇文章主要为大家详细介绍了Go语言如何使用mongox库,在插入和更新数据时自动填充时间字段,从而提升开发效率并减少重复代码,需要的可以... 目录前言时间字段填充规则Mongox 的安装使用 Mongox 进行插入操作使用 Mongox 进行更

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

Spring Boot 整合 ShedLock 处理定时任务重复执行的问题小结

《SpringBoot整合ShedLock处理定时任务重复执行的问题小结》ShedLock是解决分布式系统中定时任务重复执行问题的Java库,通过在数据库中加锁,确保只有一个节点在指定时间执行... 目录前言什么是 ShedLock?ShedLock 的工作原理:定时任务重复执行China编程的问题使用 Shed

Redis如何使用zset处理排行榜和计数问题

《Redis如何使用zset处理排行榜和计数问题》Redis的ZSET数据结构非常适合处理排行榜和计数问题,它可以在高并发的点赞业务中高效地管理点赞的排名,并且由于ZSET的排序特性,可以轻松实现根据... 目录Redis使用zset处理排行榜和计数业务逻辑ZSET 数据结构优化高并发的点赞操作ZSET 结

微服务架构之使用RabbitMQ进行异步处理方式

《微服务架构之使用RabbitMQ进行异步处理方式》本文介绍了RabbitMQ的基本概念、异步调用处理逻辑、RabbitMQ的基本使用方法以及在SpringBoot项目中使用RabbitMQ解决高并发... 目录一.什么是RabbitMQ?二.异步调用处理逻辑:三.RabbitMQ的基本使用1.安装2.架构

对postgresql日期和时间的比较

《对postgresql日期和时间的比较》文章介绍了在数据库中处理日期和时间类型时的一些注意事项,包括如何将字符串转换为日期或时间类型,以及在比较时自动转换的情况,作者建议在使用数据库时,根据具体情况... 目录PostgreSQL日期和时间比较DB里保存到时分秒,需要和年月日比较db里存储date或者ti

一文详解Python中数据清洗与处理的常用方法

《一文详解Python中数据清洗与处理的常用方法》在数据处理与分析过程中,缺失值、重复值、异常值等问题是常见的挑战,本文总结了多种数据清洗与处理方法,文中的示例代码简洁易懂,有需要的小伙伴可以参考下... 目录缺失值处理重复值处理异常值处理数据类型转换文本清洗数据分组统计数据分箱数据标准化在数据处理与分析过