從零開始學習音視訊程式設計技術(八)FFMPEG Qt視訊播放器之音視訊同步
前面分別講解了:
現在我們就將視訊和音訊合併,並讓聲音和畫面同步。
加入音訊的部分就不做講解了,這裡主要講下聲音和視訊同步的步驟。
首先剛開始播放的時候通過av_gettime()獲取系統主時鐘,記錄下來。
以後便不斷呼叫av_gettime()獲取系統時鐘 減去之前記錄下的差值,便得到了一個視訊播放了多久的實際時間。
對於視訊的同步我們這樣做:
從視訊讀取出的資料中包含一個pts的資訊(每一幀影象都會帶有pts的資訊,pts就是播放視訊的時候此影象應該顯示的時間)。 這樣只需要使用pts和前面獲取的時間進行對比,pts比實際時間大,就呼叫sleep函式等一等,否則就直接播放出來。這樣就達到了某種意義上的同步了。
而對於音訊:
從前面使用SDL的例子,其實就能夠發現一個現象:我們讀取音訊的執行緒差不多就是瞬間讀完放入佇列的,但是音訊播放速度卻是正常的,並不是一下子播放完畢。因此可以看出,在音訊播放上,SDL已經幫我們做了處理了,只需要將資料直接交給SDL就行了。
視訊部分同步程式碼大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
int64_t start_time = av_gettime();
int64_t pts = 0; //當前視訊的pts
while (1)
{
if (av_read_frame(pFormatCtx, packet) < 0)
{
break ; //這裡認為視訊讀取完了
}
int64_t realTime = av_gettime() - start_time; //主時鐘時間
while (pts > realTime)
{
SDL_Delay(10);
realTime = av_gettime() - start_time; //主時鐘時間
}
if (packet->stream_index == videoStream)
{
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,packet);
if (packet->dts == AV_NOPTS_VALUE && pFrame->opaque&& *(uint64_t*) pFrame->opaque != AV_NOPTS_VALUE)
{
pts = *(uint64_t *) pFrame->opaque;
}
else if (packet->dts != AV_NOPTS_VALUE)
{
pts = packet->dts;
}
|