場景
騰訊視頻云直播答題NTP時間同步方案是在推流 URL 之后添加 &txAddTimestamp=2 參數(shù)(之前的txAddTimestamp=1會在小程序上遭遇播放黑屏問題)部脚,由服務器在視頻流每一幀打入一個帶有國際標準時間(誤差在 100ms 以內)的 SEI 時間戳。通過TXLiteAVSDK的 PLAY_EVT_GET_MESSAGE 消息事件獲取的是一個8字節(jié)的64位時間戳。以下介紹了如何把這個8字節(jié)的64位時間戳轉換成Unix時間戳沾谜。
原理圖
iOS轉換Unix時間戳
-(void) onPlayEvent:(int)EvtID withParam:(NSDictionary*)param
{
NSDictionary* dict = param;
dispatch_async(dispatch_get_main_queue(), ^{
//消息事件
if (EvtID == PLAY_EVT_GET_MESSAGE) {
//事件戳轉換
long tv = [self byteArrayToInt:param[@"EVT_GET_MSG"]];;
long sv = tv / 1000; // 服務器返回的是毫秒Unix timestamp沃呢,這里轉換成秒
NSLog(@"time %ld", sv);
}
});
}
-(long)byteArrayToInt:(NSData *)data {
Byte *byteArray = (Byte *)data.bytes;
int a_len = 8;
Byte *a = (Byte *)malloc(a_len);
int i = a_len - 1;
int j = (int)data.length - 1;
for (; i >= 0; i--, j--) {// 從b的尾部(即int值的低位)開始copy數(shù)據(jù)
if (j >= 0)
a[i] = byteArray[j];
else
a[i] = 0;// 如果b.length不足4,則將高位補0
}
// 注意此處和byte數(shù)組轉換成int的區(qū)別在于擦耀,下面的轉換中要將先將數(shù)組中的元素轉換成long型再做移位操作霸奕,
// 若直接做位移操作將得不到正確結果轴咱,因為Java默認操作數(shù)字時铭乾,若不加聲明會將數(shù)字作為int型來對待剪廉,此處必須注意。
long v0 = (long) (a[0] & 0xff) << 56;// &0xff將byte值無差異轉成int,避免Java自動類型提升后,會保留高位的符號位
long v1 = (long) (a[1] & 0xff) << 48;
long v2 = (long) (a[2] & 0xff) << 40;
long v3 = (long) (a[3] & 0xff) << 32;
long v4 = (long) (a[4] & 0xff) << 24;
long v5 = (long) (a[5] & 0xff) << 16;
long v6 = (long) (a[6] & 0xff) << 8;
long v7 = (long) (a[7] & 0xff);
free(a);
return v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7;
}
Android轉換Unix時間戳
long timeStamp = byteArrayToInt(param.getByteArray(TXLiveConstants.EVT_GET_MSG));
/**
* 將8字節(jié)的byte數(shù)組轉成一個long值
*/
public static long byteArrayToInt(byte[] byteArray) {
byte[] a = new byte[8];
int i = a.length - 1, j = byteArray.length - 1;
for (; i >= 0; i--, j--) {// 從b的尾部(即int值的低位)開始copy數(shù)據(jù)
if (j >= 0)
a[i] = byteArray[j];
else
a[i] = 0;// 如果b.length不足4,則將高位補0
}
// 注意此處和byte數(shù)組轉換成int的區(qū)別在于炕檩,下面的轉換中要將先將數(shù)組中的元素轉換成long型再做移位操作斗蒋,
// 若直接做位移操作將得不到正確結果,因為Java默認操作數(shù)字時捧书,若不加聲明會將數(shù)字作為int型來對待吹泡,此處必須注意。
long v0 = (long) (a[0] & 0xff) << 56;// &0xff將byte值無差異轉成int,避免Java自動類型提升后,會保留高位的符號位
long v1 = (long) (a[1] & 0xff) << 48;
long v2 = (long) (a[2] & 0xff) << 40;
long v3 = (long) (a[3] & 0xff) << 32;
long v4 = (long) (a[4] & 0xff) << 24;
long v5 = (long) (a[5] & 0xff) << 16;
long v6 = (long) (a[6] & 0xff) << 8;
long v7 = (long) (a[7] & 0xff);
return v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7;
}
示例
運行示例圖
轉換示例圖