NTP和RTP时间戳
来源:互联网 发布:电子商城源码 编辑:程序博客网 时间:2024/05/16 23:49
时间戳
关于时间戳的解释来自wiki:时间戳(英语:Timestamp)是指字符串或编码信息用于辨识记录下来的时间日期
。
它并没有规定时间戳的单位,所以我们在讨论时间戳的时候要记得把单位加上,要不别人并不知道你说什么。在音视频领域常用的时间戳单位有毫秒(Milliseconds)/微秒(Microseconds)/纳秒(Nanoseconds)。
- 时间单位之间的关系
static const int64_t kNumMillisecsPerSec = INT64_C(1000);static const int64_t kNumMicrosecsPerSec = INT64_C(1000000);static const int64_t kNumNanosecsPerSec = INT64_C(1000000000);
- 获取时间的函数
几个函数的区别在于获取时间的精度不同
- clock id
clock_gettime
可以指定获取的时间类型(id),gettimeofday
获取的是墙上时间(CLOCK_REALTIME)。
RTP时间戳
所谓的RTP时间戳就是RTP包头中存放的那个时间戳,单位是毫秒。RTP时间戳必须是一个单调递增的时间戳,因为它用于表示数据的采集时间,所以不能受系统时间的影响。在WebRTC中采集和编码使用的时间戳单位都是毫秒,并且只取低32位。
- WebRTC中RTP时间戳的获取
主要提供了TimeInMilliseconds
和TimeInMicroseconds
两个函数获取毫秒和微妙时间戳,通过代码可以知道它是获取当前一个单调递增的时间。
int64_t TimeInMilliseconds() const override { return rtc::TimeMillis();}int64_t TimeInMicroseconds() const override { return rtc::TimeMicros();}int64_t TimeMillis() { return TimeNanos() / kNumNanosecsPerMillisec;}int64_t TimeMicros() { return TimeNanos() / kNumNanosecsPerMicrosec;}int64_t TimeNanos() { if (g_clock) { return g_clock->TimeNanos(); } return SystemTimeNanos();}int64_t SystemTimeNanos() { int64_t ticks; struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); ticks = kNumNanosecsPerSec * static_cast<int64_t>(ts.tv_sec) + static_cast<int64_t>(ts.tv_nsec); return ticks;}
NTP时间戳
NTP是Network Time Protocol的简称,在rfc3550#section-4中有详细的解释。它用于表示从格林时间(UTC)1900年1月1日以来的秒数。通常它用一个uint64_t表示(SR包中的SenderInfo部分的NTP时间戳就是用64位表示),分为整数部分(前32位表示妙)和小数部分(后32位表示1/0x100000000秒{=(0x1 << 32)=(2^32)})。在一些更紧凑的领域(SR和RR中的ReportBlobck中的LSR和DLSR就是使用32位表示)使用32位表示NTP时间戳,前16位表示整数部分,后16位表示小数部分。WebRTC中RTT的计算方式就是用当前接收时刻的NTP时间戳 - 上一次发送的NTP时间戳 - 处理时间戳,这部分可以看HandleReportBlock函数。
- NtpTime
NtpTime是WebRTC中一个用来表示NTP时间戳的类,从构造函数可以知道NTP时间戳的组成和上面的说法是吻合的。ToMs
是一个NTP时间戳转换为普通时间戳(单位是毫秒)的方式。
static constexpr uint64_t kFractionsPerSecond = 0x100000000;NtpTime(uint32_t seconds, uint32_t fractions) : value_(seconds * kFractionsPerSecond + fractions) {}int64_t ToMs() const { static constexpr double kNtpFracPerMs = 4.294967296E6; // 2^32 / 1000. const double frac_ms = static_cast<double>(fractions()) / kNtpFracPerMs; return 1000 * static_cast<int64_t>(seconds()) + static_cast<int64_t>(frac_ms + 0.5);}
- WebRTC中NTP时间戳的获取
- 获取当前时间戳,这个是系统相关的,posix的通过
gettimeofday
获取 - 把获取后的时间戳加上1970到1900之间间隔的时间(kNtpJan1970),再转换为NTP的格式(前32位表示秒,后32位表示1/2^32秒);kNtpJan1970的值等于(1900到1970经过的秒数);kMagicNtpFractionalUnit等于2^32
- 获取当前时间戳,这个是系统相关的,posix的通过
// January 1970, in NTP seconds.const uint32_t kNtpJan1970 = 2208988800UL;// Magic NTP fractional unit.const double kMagicNtpFractionalUnit = 4.294967296E+9;NtpTime CurrentNtpTime() const override { timeval tv = CurrentTimeVal(); double microseconds_in_seconds; uint32_t seconds; Adjust(tv, &seconds, µseconds_in_seconds); uint32_t fractions = static_cast<uint32_t>( microseconds_in_seconds * kMagicNtpFractionalUnit + 0.5); return NtpTime(seconds, fractions);}timeval CurrentTimeVal() const override { struct timeval tv; struct timezone tz; tz.tz_minuteswest = 0; tz.tz_dsttime = 0; gettimeofday(&tv, &tz); return tv;}static void Adjust(const timeval& tv, uint32_t* adjusted_s, double* adjusted_us_in_s) { *adjusted_s = tv.tv_sec + kNtpJan1970; *adjusted_us_in_s = tv.tv_usec / 1e6; if (*adjusted_us_in_s >= 1) { *adjusted_us_in_s -= 1; ++*adjusted_s; } else if (*adjusted_us_in_s < -1) { *adjusted_us_in_s += 1; --*adjusted_s; }}
- NTP转RTP
以下是WebRTC中NTP时间戳转RTP时间戳的函数,函数很容易看懂,但是我并没有找到转换的依据(算法的依据)。传入的参数有ntp和freq,其中ntp在前面有介绍,freq的值是根据编码类型而定的,一般来说视频都是90kHz,详情可以看RTP Payload Format media types
// Converts NTP timestamp to RTP timestamp.inline uint32_t NtpToRtp(NtpTime ntp, uint32_t freq) { uint32_t tmp = (static_cast<uint64_t>(ntp.fractions()) * freq) >> 32; return ntp.seconds() * freq + tmp;}
- RTP扩展中的绝对发送时间(abs-send-time)
WebRTC官网有介绍abs-send-time,它的计算方式是abs_send_time_24 = (ntp_timestamp_64 » 14) & 0x00ffffff
,关于它的格式如下:
// 0 1 2 3// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+// | ID | len=2 | absolute send time |// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- NTP和RTP时间戳
- RTP类型和时间戳
- NTP和互联网时间同步
- NTP服务和时间同步
- 时间服务器ntp和chrony
- NTP of rtp
- RTP时间戳
- RTP时间戳
- RTP时间戳
- RTP时间戳相关
- RTP时间戳
- RTP 时间戳
- RTP时间戳相关
- RTP时间戳
- RTP时间戳总结
- RTP时间戳
- RTP 时间戳
- RTP 的时间戳
- Kolakoski(思维+找规律)
- [RK3288][Android6.0] 调试笔记 --- 读取cmd_type失败
- vue-resource全攻略
- javaday15-IO(整理和训练)
- HDU2053 Switch Game
- NTP和RTP时间戳
- 为什么还是说信息没填写完整呢
- 汉诺塔问题
- Proc
- java数据结构与算法-线性探测哈希表
- Android SmsManager 短信群发
- Java构造方法的作用
- 实现热部署时记得设置eclipse开发工具
- [hihocoder1324]希尔伯特曲线