本來是想寫一篇time_base的詳細文章,後來發現很多大神寫過,那這裏我就總結一下各種time_base,方便大家理解。
一、time_base
AVStream
的time_base
的單位是秒。每種格式的time_base
的值不一樣,根據採樣來計算,比如mpeg
的pts
、dts
都是以90kHz
來採樣的,所以採樣間隔就是1/900000
秒。
AVCodecContext
的time_base
單位同樣爲秒,不過精度沒有AVStream->time_base
高,大小爲1/framerate
。
AVPacket
下的pts
和dts
以AVStream->time_base
爲單位(數值比較大),時間間隔就是AVStream->time_base
。
AVFrame
裏面的pkt_pts
和pkt_dts
是拷貝自AVPacket
,同樣以AVStream->time_base
爲單位;而pts
是爲輸出(顯示)準備的,以AVCodecContex->time_base
爲單位。
輸入流InputStream
下的pts
和dts
以AV_TIME_BASE
爲單位(微秒),至於爲什麼要轉化爲微秒,可能是爲了避免使用浮點數。
輸出流OutputStream
涉及音視頻同步,結構和InputStream
不同,暫時只作記錄,不分析。
二、各個time_base
之前的轉換
ffmpeg提供av_rescale_q
函數用於time_base
之間轉換,av_rescale_q(a,b,c)
作用相當於執行a*b/c
,通過設置b,c
的值,可以很方便的實現time_base
之間轉換。
例如
InputStream(AV_TIME_BASE)到AVPacket(AVStream->time_base)
static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
{
pkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base);
}
AVPacket(AVStream->time_base)到InputStream(AV_TIME_BASE)
static int process_input_packet(InputStream *ist, const AVPacket *pkt)
{
if (pkt->dts != AV_NOPTS_VALUE)
{
ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
}
}
三、其他
AVFrame->pts
和AVPacket->pts
、AVPacket->dts
的值,在解碼/編碼後,會經歷短暫的time_base
不匹配的情況:
解碼後,decoded_frame->pts
的值使用AVStream->time_base
爲單位,後在AVFilter
裏面轉換成以AVCodecContext->time_base
爲單位。
編碼後,pkt.pts
、pkt.dts
使用AVCodecContext->time_base
爲單位,後通過調用"av_packet_rescale_ts"
轉換爲AVStream->time_base
爲單位。
四、結束
這其實就是篇筆記,在前人的基礎上對time_base的進行了大概總結, 以後會繼續更新。
作者:耕地
鏈接:https://www.jianshu.com/p/bf323cee3b8e
來源:簡書