介紹
在本系列,我打算花大篇幅講解我的 gitee 項目音視頻播放器,在這個項目,您可以學到音視頻解封裝,解碼,SDL渲染相關的知識。您對源代碼感興趣的話,請查看基于FFmpeg和SDL的音視頻播放器
如果您不理解本文,可參考我的前一篇文章音視頻項目—基于FFmpeg和SDL的音視頻播放器解析(十九)
解析
接著上文,我們繼續解析 videooutput 的函數。
videoRefresh
void VideoOutput::videoRefresh(double* remaining_time){AVFrame* frame = nullptr;frame = frame_queue->Front();if(frame){double pts = frame->pts * av_q2d(time_base);double diff = pts - avsync->GetClock();if(diff > 0){*remaining_time = FFMIN(*remaining_time, diff);return;}rect.x = 0;rect.y = 0;rect.w = video_width;rect.h = video_height;SDL_UpdateTexture(texture, &rect, frame->data[0], frame->linesize[0],frame->data[1], frame->linesize[1],frame->data[2], frame->linesize[2]);SDL_RenderClear(renderer);SDL_RenderCopy(renderer, texture, NULL, &rect);SDL_RenderPresent(renderer);frame = frame_queue->Pop(1);av_frame_free(&frame);}
}
這個函數負責渲染幀。
首先,frame = frame_queue->Front();取出視頻幀隊列的頭部數據。
然后,double pts = frame->pts * av_q2d(time_base); 計算出這一幀在時間的顯示位置
diff 是該幀顯示時間與當前時間的差值
當 diff 大于 0 時,說明當前幀比較快,要等一會播放。FFMIN 是取最小值的宏定義
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
remaining_time 就是取兩者的最小值。然后返回,等待。
rect.x = 0;窗口的左上角的橫向偏移值為 0?
rect.y = 0;窗口的左上角的縱向偏移值為 0?
rect.w = video_width;設置窗口的寬度
rect.h = video_height;設置窗口的高度
SDL_UpdateTexture 更新紋理
SDL_RenderClear 清除屏幕上的舊內容,為繪制新的幀做準備
SDL_RenderCopy?用于將一個表面(surface)復制到當前的渲染目標(destination)。這通常用于在屏幕上顯示圖像或紋理。
SDL_RenderPresent?該函數將渲染器上下文中的內容顯示到屏幕上,通常在渲染循環的末尾調用以完成繪制并顯示結果。
最后,彈出幀隊列數據,并釋放數據。
好了,先講到這里。
欲知后事如何,請聽下回分解。