日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ffmpeg rtp时间戳

發布時間:2025/4/16 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ffmpeg rtp时间戳 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ffmpeg rtp時間戳

ffmpeg? c?

一、介紹

在ffmpeg中,每幀都會存在一個pts用來表示該幀圖像在視頻流中的位置。而在多路流(比如視頻、音頻)時,往往需要進行多媒體的同步,使得畫面和聲音同步,這時便需要使用兩者的pts來做同步。那么pts是如何計算得到的呢,如何使用它做同步呢?

1.1 時間基轉換

ffmpeg中時間存在一個基,可以理解成單位,比如把1s分成1000000等份,每個等份就是1us,那么1s就可以表示成1000000;而如果把1s分成90000等份,那么1s的值就是90000。

基的轉換,把a從b基轉到c基,計算公式為:,比如2s以1000000為基則是2000000,轉換成以90000為基,則有2000000 / 1000000 * 90000 = 180000。

ffmpeg中提供了兩個函數用于基的轉換,可以更好地處理溢出與round問題:

av_rescale(a, b, c): 時間基從c -- > b。b, c可以直接是數字。
av_rescale_q(a, b, c): 時間基從 b --> c。 b,c需要使用AVRaional結構。

1.2 時間戳類型

ffmpeg中常用的幾個時間戳:
rtcp_ntp_timestamp: 真實時間, 絕對時間,在網絡傳輸時的時間基(1 << 32),
rtcp_timestamp: rtcp時間,一般會有一個base, 在網絡傳輸時的時間基90000
rtp_timestamp: rtp時間,和rtcp_timestamp類似,網絡時間基90000
Avpacket->pts: 通過如上計算得到,video一般是以90000為基

1.3 pts剛開始為負值

為什么剛開始的Avpacket->pts的值是負的?
因為我們實現時,rtcp_timestamp是使用clock_gettime()獲取當前時間,而rtp_timestamp是用的h264 buffer里的時間, 所以rtp_timestamp < rtcp_timestamp, 而又是以rtcp_timestamp為基準0, 所以出現了剛開始幀的pts為負值。將rtcp_timestamp和rtp_timestamp使用相同的值,pts則從0開始。

二、Encode

在推流時,要將rtcp時間戳、rtp時間戳寫入到包中,以供客戶端解析,下面介紹如何將三個值寫入。


rtsp encode

2.1 rtcp編碼時間戳:

這里寫了兩個時間戳,這個值我們實現的時候是以clock_gettime()獲取的時間戳,在此基礎上分別計算rtcp_ntp_time和rtcp_time:

rtcp_ntp_timestamp: 以為基

rtcp_send_sr(s1, av_get_cur_time());#define NTP_TO_RTP_FORMAT(x) av_rescale((x), INT64_C(1) << 32, 1000000) val = NTP_TO_RTP_FORMAT(ntp_time); *((int *)&rtcp_header[8]) = htonl(val >> 32); *((int *)&rtcp_header[12]) = htonl(val & 0xffffffff);

last_rtcp_timestamp: 從1000000rescale到90000

我們這邊又再加上一個隨機值base_timestamp,這個base_timestamp一次連接中是不變的:

rtp_ts = av_rescale_q(ntp_time, (AVRational){1, 1000000},s1->streams[0]->time_base) + s->base_timestamp; *((int *)&rtcp_header[16]) = htonl(rtp_ts);

2.2 rtp編碼時間戳:

在我們的實現中,rtp時間戳是由輸入packet的pts計算得到,而packet.pts最開始是h264 buffer的timestamp 從1000000rescale到90000:

packet.pts = av_rescale_q(packet.pts,in->time_base,out->time_base);s->cur_timestamp = s->base_timestamp + pkt->pts;

把cur_timestamp寫入到 rtp包中:

s->timestamp = s->cur_timestamp;*((short *)&rtp_header[2]) = htons(s->seq);*((int *)&rtp_header[4]) = htonl(s->timestamp);*((int *)&rtp_header[8]) = htonl(s->ssrc);

可以看到rtcp_time和rtp_time都是以90000以基,而rtcp_ntp_time是為基,所以在使用rtcp_ntp_time時要注意基的轉換。

三、Decode

ffmpeg rtsp, rtp解碼主要流程:


rtsp decode

3.1 解析 rtp packet:

讀取的代碼在libavofrmat/rtpdec.c --> rtp_parse_packet_internal()函數中:

seq = AV_RB16(buf + 2); timestamp = AV_RB32(buf + 4); ssrc = AV_RB32(buf + 8);

讀出的timestamp會傳入到finalize_packet中計算pts,如下方式傳入:

// now perform timestamp things.... finalize_packet(s, pkt, timestamp);

當然只有rtp_time還是不夠的,還需要rtcp_time,在多個流中還需要rtcp_ntp_time做多個流之間的同步。

3.2 解析rtcp時間戳:

rtpdec.c --> rtcp_parse_packet()函數中:

s->last_rtcp_ntp_time = AV_RB64(buf + 8); s->last_rtcp_timestamp = AV_RB32(buf + 16); if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) {s->first_rtcp_ntp_time = s->last_rtcp_ntp_time;if (!s->base_timestamp)s->base_timestamp = s->last_rtcp_timestamp;s->rtcp_ts_offset = (int32_t)(s->last_rtcp_timestamp - s->base_timestamp); }

其中,last_rtcp_ntp_time是ntp時間戳,last_rtcp_timestamp是rtcp時間戳,這兩個值會在rtcp同步時進行更新。

第一次的時候,會執行s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; ,first_rtcp_ntp_time一旦會一直保持這個值不變,后面rtcp同步的時候只會修改last_rtcp_ntp_time。

另外,s->base_timestamp = s->last_rtcp_timestamp, 這個值也會一直不變,有了這兩個基準,其它的就是要和這兩個比較,最后計算出pts。

從上面的計算方式可以知道,rtcp_ts_offset為0,這個值在一個流中也不會變,不過不同流之間或許有差別。

3.3 pts計算

av_read_frame會返回一個Avpacket對象,其中的pts變量存儲了計算后的時間戳,計算方式在rtpdec.c --> finalize_packet()函數中,如下,分兩種情況:

1. 如果是多路(如同時包含video, audio)

我們知道,傳入的timestamp是rtp時間戳,需要使用ntp時間做同步:

delta_timestamp = timestamp - s->last_rtcp_timestamp; /* convert to the PTS timebase */ addend = av_rescale(s->last_rtcp_ntp_time - s->first_rtcp_ntp_time, s->st->time_base.den, (uint64_t) s->st->time_base.num << 32); pkt->pts = s->range_start_offset + s->rtcp_ts_offset + addend + delta_timestamp;

range_start_offset = 0
rtcp_ts_offset = 0
addend: 最后一次rtcp同步的ntp時間 - first_rtcp_ntp_time,相當于做了一次ntp time同步,可以清除之前的rtp計算累積的誤差
delta_timestamp: rtp時間戳 - 最后一次rtcp同步的rtcp時間


multi stream sync

測試打印:

printf("multi stream: %ld, range_start_off: %ld, rtcp_ts_offset: %ld,addend: %ld, last timestamp: %ld, timestamp: %ld, dalta: %ld, rescale: %ld\n", pkt->pts, s->range_start_offset, s->rtcp_ts_offset, addend, s->last_rtcp_timestamp, timestamp, delta_timestamp, av_rescale(pkt->pts - old_pts, 1e6, 90000));

輸出:

multi stream: 71279, range_start_off: 0, rtcp_ts_offset: 0,addend: 0, last timestamp: 3619407542, timestamp: 3619478821, dalta: 71279, rescale: 0

2. 如果是單路:

單路計算pts代碼如下,可以看到單路不需要用到rtcp_ntp_time,只需要rtcp_time, rtp_time就可以了:

/* unwrapped是rtp時間累加 */ s->unwrapped_timestamp += (int32_t)(timestamp - s->timestamp); /* unwrapped時間最后要減去rtcp_base_time */ pkt->pts = s->unwrapped_timestamp + s->range_start_offset - s->base_timestamp;

unwrapped_timestamp: 如果是第1幀,則為第1幀的rtp_time, 之后的值是當前幀與上一幀差rtp_time逐漸累加的結果,那么,實際上一般情況下unwrapped_timestamp就等于當前幀的rtp_time
range_start_offset是0,
base_timestamp是rtcp解析時最初的rtcp_timestamp


single stream

測試打印:

printf("single stream: %ld, base: %u, unwrapped: %ld, range: %ld, last timestamp:%ld, timestamp: %ld\n", pkt->pts, s->base_timestamp, s->unwrapped_timestamp, s->range_start_offset, old_timestamp, timestamp);

輸出:

single stream: 6321193, base: 3079643606, unwrapped: 3085964799, range: 0, last timestamp:3085964799, timestamp: 3085964799 single stream: 6325714, base: 3079643606, unwrapped: 3085969320, range: 0, last timestamp:3085969320, timestamp: 3085969320

四、Reference

https://www.cnblogs.com/yinxiangpei/articles/3892982.html
http://www.cppblog.com/gtwdaizi/articles/65515.html

轉載于:https://www.cnblogs.com/gr-nick/p/10993363.html

總結

以上是生活随笔為你收集整理的ffmpeg rtp时间戳的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久久久久久久久99 | 欧美黑人巨大xxx极品 | 欧美激情免费看 | 日朝毛片| 亚洲精品成人影视 | 曰批又黄又爽免费视频 | 有码视频在线观看 | 秋霞成人 | 天天干天天干天天 | 中文字幕1区2区 | 伊人久久综合视频 | 泷泽萝拉在线播放 | 深夜福利视频网站 | 老色批av | v在线 | 日本一区二区视频在线播放 | 亚洲h在线观看 | 嫩草嫩草嫩草嫩草嫩草嫩草 | 毛片在线免费 | 天天色一色 | 日韩一区二区三区免费在线观看 | 国产在线色站 | 一级片黄色片 | 国内露脸中年夫妇交换 | 色爱色| 国产成人无码精品久在线观看 | 久久人人爽人人人人片 | 91最新地址永久入口 | 色校园 | 久草视频首页 | 欧美高清精品一区二区 | 久久av一区二区三区亚洲 | 婷婷调教口舌奴ⅴk | 日韩国产精品一区二区三区 | 日韩精品视频在线观看网站 | 久久久精品中文字幕 | 国产精品免费av一区二区三区 | 色综合久久久久综合体桃花网 | 91中文字幕网 | 97超碰免费在线 | 国产情侣在线播放 | 久久人精品 | 欧美乱插| 四虎三级 | 性色在线 | 久久成人乱码欧美精品一区二区 | 波多野吉衣中文字幕 | 黄色免费av | 韩日av网站 | 婷婷色亚洲 | 男女免费网站 | 麻豆69| 国产精品无码AV无码国产 | 少妇脱了内裤让我添 | 大牛影视剧免费播放在线 | 欧美日色 | 欧美激情校园春色 | 日本激情一区二区 | 韩国成年人网站 | 成人在线激情 | 777久久 | 国产乱码一区二区 | 日本a级黄 | 一区二区三区午夜 | 秋霞成人午夜伦在线观看 | 日韩精品在线观看一区二区三区 | 国产九色视频 | 亚洲成人自拍网 | 国产人妻aⅴ色偷 | 视频在线观看一区 | 日本高清视频www夜色资源 | 亚洲日本激情 | 国产又爽又黄无码无遮挡在线观看 | 日日摸天天爽天天爽视频 | 中文字幕免费高清视频 | 一区二区三区日韩精品 | 91在线网 | 91视频第一页 | 日韩麻豆视频 | 香蕉视频在线看 | 免费午夜视频 | 精品福利影院 | 亚洲精品久久久久中文字幕二区 | 免费人成视频在线播放 | 久久国产乱子伦精品 | 九色自拍视频 | 亚洲精品综合在线观看 | 免费黄色一级 | 日本一区二区三区在线免费观看 | 亚洲永久免费av | 91av免费在线观看 | 免费黄色资源 | 伊人久久网站 | 欧美一级爱爱视频 | 又欲又污又肉又黄短文 | 国产艳情片| 亚洲av无码片一区二区三区 | 美女在线播放 | 免费观看一区二区三区毛片 |