gortmp
gortmp copied to clipboard
defines.go文件中GetTimestamp()函数的问题
- 下面rtmp_specification_1.0.pdf文件中关于timestamp的描述。
Because timestamps are 32 bits long, they roll over every 49 days, 17 hours, 2 minutes and 47.296 seconds. Because streams are allowed to run continuously, potentially for years on end, an RTMP application SHOULD use serial number arithmetic [RFC1982] when processing timestamps, and SHOULD be capable of handling wraparound. For example, an application assumes that all adjacent timestamps are within 2^31 - 1 milliseconds of each other, so 10000 comes after 4000000000, and 3000000000 comes before 4000000000.
上面的描述说明了的timestamp是32的无符号整数所表示的毫秒,由于该值最大只能表示不到50天的时间戳,所以需要对时间戳做环绕式处理。 2. defines.go文件中GetTimestamp的实现
466 // Get timestamp
467 func GetTimestamp() uint32 {
468 //return uint32(0)
469 return uint32(time.Now().UnixNano()/int64(1000000)) % MAX_TIMESTAMP
470 }
该函数取系统当前时间(毫秒)作为时间戳,然后与 MAX_TIMESTAMP取模,这样也确实实现的环绕处理, 但是我看到MAX_TIMESTAMP的定义如下:
278 MAX_TIMESTAMP = uint32(2000000000)
正确的定义该值应该是32位无符号整数的最大值+1, 即0x100000000,defines.go文件对该值的定义的显然不对。 3. defines.go文件的第469行有一种更简单的改写方式, 如下:
469 return uint32(time.Now().UnixNano()/int64(1000000))
超过32位无符号整数的部分会被自然溢出,我们强制转换得到溢出后剩下的部分,即实现了环绕,也相当于对0x100000000做取模操作。
@programmerZhou 你的意思不取余反而是正确的?
@hy05190134 强转让其溢出即是取模。
return uint32(time.Now().UnixNano()/int64(1000000))
return uint32(time.Now().UnixNano()/int64(1000000) % 0x100000000)
上面这两行等价。
类似的写法还有
// 对一个数除2
a := x / 2
// 也可写成
a = x >> 1
上面的问题主要是MAX_TIMESTAMP定义的不对,应该是0x100000000, 时间戳是环绕的,达到最大值之后,下一个值为0,即0xffffffff的下一个值为0。
注:位运算一般效率更高。
这个需要实测,spec里面写的有些不准确,所以设置了一个最大支持的时间范围。