請接上一個簡書內(nèi)容觀看,會對上一章的代碼進(jìn)行改進(jìn)和修改~~~
ffmpeg播放器4-音視頻同步
1.ffmpeg 音視頻同步的開發(fā)
AudioChannel中:getPcm()方法中 獲取到音頻播放的相對時間
//獲得 frame 的一個相對播放時間 (相對開始播放的時間)
// 獲取相對播放這一段數(shù)據(jù)的秒數(shù)
clock = frame->pts * av_q2d(time_base);
VideoChannel.cpp中 play()中 callback之前 獲取當(dāng)前畫面的播放時間宿接,并與音頻中的播放時間進(jìn)行對比:
// 獲得 當(dāng)前這一個畫面 播放的相對時間
double clock = frame->best_effort_timestamp * av_q2d(time_base);
// 計算額外的延遲時間
double extra_delay = frame->repeat_pict / (2*fps);
// 真實需要的間隔時間
frame_delays += extra_delay;
if (!audioChannel || clock == 0) {
// 休眠 微秒 -> #include <libavutil/time.h> 防止卡頓
av_usleep(frame_delays * 1000 * 1000);
} else {
// 用來比較音視頻
double audioClock = audioChannel->clock;
// 音視頻相差的間隔
double diff = clock - audioClock;
if (diff > 0) {
// 視頻比較快 讓視頻休眠時間長一些
av_usleep((frame_delays + diff) * 1000 * 1000);
} else if (diff < 0) {
// 音頻比較快
if(fabs(diff) >= 0.05){
// 丟包 packet
// packets.sync();
// 丟包 frame
frames.sync();
continue;
}else{
// 不睡眠 趕上音頻播放進(jìn)度
}
} else {
av_usleep(frame_delays * 1000 * 1000);
}
}
2.相關(guān)知識整理
簡書鏈接:
音視頻同步方式:
1赘淮、將視頻根據(jù)音頻同步(以音頻為主)
2、以視頻為主
3睦霎、以一個外部時間進(jìn)度為主
幀率:單位時間內(nèi) 需要顯示多少個圖像 25fp:1s內(nèi)顯示25個圖像
//音頻
//獲得 frame 的一個相對播放時間 (相對開始播放的時間)
// 獲取相對播放這一段數(shù)據(jù)的秒數(shù)
clock = frame->pts * av_q2d(time_base);
//視頻
// 獲得 當(dāng)前這一個畫面 播放的相對時間
double clock = frame->best_effort_timestamp * av_q2d(time_base);
I frame :幀內(nèi)編碼幀 梢卸,I 幀通常是每個 GOP(MPEG 所使用的一種視頻壓縮技術(shù))的第一個幀,經(jīng)過適度地壓縮副女,做為隨機(jī)訪問的參考點蛤高,可以當(dāng)成圖象。I幀可以看成是一個圖像經(jīng)過壓縮后的產(chǎn)物碑幅。
P frame: 前向預(yù)測編碼幀戴陡,通過充分將低于圖像序列中前面已編碼幀的時間冗余信息來壓縮傳輸數(shù)據(jù)量的編碼圖像,也叫預(yù)測幀沟涨;
B frame: 雙向預(yù)測內(nèi)插編碼幀 猜欺,既考慮與源圖像序列前面已編碼幀,也顧及源圖像序列后面已編碼幀之間的時間冗余信息來壓縮傳輸數(shù)據(jù)量的編碼圖像拷窜,也叫雙向預(yù)測幀;
I frame:自身可以通過視頻解壓算法解壓成一張單獨的完整的圖片。
P frame:需要參考其前面的一個I frame 或者B frame來生成一張完整的圖片篮昧。
B frame:則要參考其前一個I或者P幀及其后面的一個P幀來生成一張完整的圖片赋荆。
PTS:Presentation Time Stamp。PTS主要用于度量解碼后的音視頻幀什么時候被顯示出來
DTS:Decode Time Stamp懊昨。DTS主要是標(biāo)識讀入內(nèi)存中的幀數(shù)據(jù)在什么時候開始送入解碼器中進(jìn)行解碼窄潭。
在沒有B幀存在的情況下DTS的順序和PTS的順序應(yīng)該是一樣的。
DTS主要用于視頻的解碼,在解碼階段使用酵颁。PTS主要用于視頻的同步和輸出.在顯示的時候使用嫉你。
如上圖:I frame 的解碼不依賴于任何的其它的幀.而p frame的解碼則依賴于其前面的I frame或者P frame.B frame的解碼則依賴于其前的最近的一個I frame或者P frame 及其后的最近的一個P frame.