視頻、音頻打時間戳的方法

http://blog.csdn.net/wfqxx/article/details/5497138

一 固定幀率

1. 視頻時間戳

     pts = inc++ *(1000/fps);  其中inc是一個靜態的,初始值爲0,每次打完時間戳inc加1.

    在ffmpeg,中的代碼爲

    pkt.pts= m_nVideoTimeStamp++ * (m_VCtx->time_base.num * 1000 / m_VCtx->time_base.den);

 

2. 音頻時間戳

    pts = inc++ * (frame_size * 1000 / sample_rate)

   在ffmpeg中的代碼爲

   pkt.pts= m_nAudioTimeStamp++ * (m_ACtx->frame_size * 1000 / m_ACtx->sample_rate);

採樣頻率是指將模擬聲音波形進行數字化時,每秒鐘抽取聲波幅度樣本的次數。

。正常人聽覺的頻率範圍大約在20Hz~20kHz之間,根據奈奎斯特採樣理論,爲了保證聲音不失真,採樣頻率應該在40kHz左右。常用的音頻採樣頻率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,如果採用更高的採樣頻率,還可以達到DVD的音質

對採樣率爲44.1kHz的AAC音頻進行解碼時,一幀的解碼時間須控制在23.22毫秒內。

背景知識:

(一個AAC原始幀包含一段時間內1024個採樣及相關數據)

分析:

1 AAC

音頻幀的播放時間=一個AAC幀對應的採樣樣本的個數/採樣頻率(單位爲s)

一幀 1024個 sample。採樣率 Samplerate 44100KHz,每秒44100個sample, 所以 根據公式   音頻幀的播放時間=一個AAC幀對應的採樣樣本的個數/採樣頻率

當前AAC一幀的播放時間是= 1024*1000000/44100= 22.32ms(單位爲ms)

2 MP3

 

mp3 每幀均爲1152個字節, 則:

frame_duration = 1152 * 1000000 / sample_rate

例如:sample_rate = 44100HZ時, 計算出的時長爲26.122ms,這就是經常聽到的mp3每幀播放時間固定爲26ms的由來。



二 可變幀率


有很多的採集卡,攝像頭,在做採集的時候,明明設置的25FPS,但實際採集數據回調過來,發現並不是40毫秒的間隔,而是50,60,甚至100不等的時間間隔。

這就給編碼後打時間戳帶來很大的困難。


在libav裏,我們的默認編碼參數都是:

ptAvEncoder->ptAvStreamVideo->codec->time_base.den = s32Fps;

ptAvEncoder->ptAvStreamVideo->codec->time_base.num = 1;

這樣在編碼後的時間戳以1遞增,只適合於固定幀率。


我們來改一下:

ptAvEncoder->ptAvStreamVideo->codec->time_base.den = s32Fps * 1000;

ptAvEncoder->ptAvStreamVideo->codec->time_base.num = 1* 1000;

這樣就把時間戳的scale變成了毫秒,就可以以毫秒爲單位進行計算了,如下:

tAvPacket.pts = ((s64)u32TimeStamp * (s64)s32Fps);

u32TimeStamp是從開始記錄的時間差值,以毫秒爲單位;s32Fps是幀率。


對於音頻,mp4文件默認是採樣率爲tick的,時間戳計算爲:

tAvPacket.pts = (AvEncoderAudioInSizeGet(hHandle) * ( (s64)(u32TimeStamp)) / (AvEncoderAudioInSizeGet(hHandle) * 1000 / ptAvEncoder->ptAvStreamAudio->codec->sample_rate);

AvEncoderAudioInSizeGet(hHandle) 每次編碼器需要的PCM數據長度。

u32TimeStamp是從開始記錄的時間差值,以毫秒爲單位。

 ptAvEncoder->ptAvStreamAudio->codec->sample_rate PCM採樣率,代表一秒的數據量。

因爲乘以了1000,所以也化成了毫秒單位。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章