音视频播放器—快进快退及逐帧播放
------------------------------------全系列文章目錄------------------------------------
快進快退
大致流程
獲取跳轉的文件位置
-
通過捕獲SDL_KEYDOWN按鍵按下事件,并通過標志位判斷當前的鍵位SDL_Event::SDL_KeyboardEvent::SDL_Keysym::SDL_Keycode為SDLK_LEFT或SDLK_RIGHT,以此來確定是向前跳轉還是向后跳轉。
switch (_event.type) {case SDL_KEYDOWN:switch (_event.key.keysym.sym) {case SDLK_LEFT:avc->set_seek_pos(-SEEK_POS_CHANGE);break;case SDLK_RIGHT:avc->set_seek_pos(SEEK_POS_CHANGE);break;default:break;} } -
使用一個標志位seek_pos來表示跳轉到文件中的位置;每次發生跳轉時,先更新當前文件位置,將seek_pos加上上次跳轉時時間和當前時間的時間差作為最新的seek_pos;然后加上當前的跳轉變化量,作為跳轉到文件中的位置。
void AVCtrl::set_seek_pos(int64_t _pos) {int64_t _pos_time = av_gettime() / MICROSECOND_TO_SECOND; seek_flag = 1;//加上 距離上次跳轉到現在的時間差 作為最新的seek_pos, 并加上當前的變化量seek_pos += (_pos + _pos_time - pos_time);seek_pos = seek_pos < 0 ? 0 : seek_pos;seek_pos = seek_pos > file_duration ? file_duration : seek_pos;pos_time = _pos_time; //更新發生跳轉時的時間 }
重定向文件
-
重定向文件使用av_seek_frame函數來實現,其函數定義如下:
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);-
s:多媒體文件的句柄,即打開文件時所使用的AVFormatContext結構體;
-
stream_index:選擇跳轉后選取的數據流,如果為 -1,則選擇默認流,并且時間戳會自動從 AV_TIME_BASE 單位轉換為特定于流的 time_base;
-
timestamp:以 AVStream.time_base 為單位的時間戳,如果未指定流,則以 AV_TIME_BASE 為單位。
-
flags:用于選擇方向和搜索模式的標志位(主要是對關鍵幀的選取),可選標志如下
/*跳轉到非關鍵幀時, 往回找到關鍵幀, 作為跳轉點*/ #define AVSEEK_FLAG_BACKWARD 1 ///< seek backward #define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes /*可以跳轉到任何幀*/ #define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes /*跳轉到非關鍵幀時, 往后找到關鍵幀, 作為跳轉點*/ #define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number -
返回≥0表示成功
-
-
因此在線程中檢測重定事件是否發生,若發生了,則通過av_seek_frame函數進行文件重定向處理
if (avc->get_seek_flag()) {avc->set_seek_flag(0);av_seek_frame(avc->pFormatCtx, -1, avc->get_seek_pos() * AV_TIME_BASE, AVSEEK_FLAG_BACKWARD); //重定位文件, 定位至關鍵幀........ } -
當發生文件跳轉時,原本demux時存取在隊列中的數據包,以及解碼后的數據包都不能使用,因此要進行清空隊列操作。
逐幀播放
事件捕獲
- 通過捕獲SDL_KEYDOWN按鍵按下事件,并通過標志位判斷當前的鍵位SDL_Event::SDL_KeyboardEvent::SDL_Keysym::SDL_Keycode是否為一特定按鍵如SDLK_p來啟動逐幀播放操作。需要注意的是SDLK_p按鍵應該在暫停時才會觸發,并且需要保證播放完一幀后才會繼續觸發。
大致流程如下
- 當播放暫停時,若按下SDLK_p鍵,標記該事件,同時暫停接收SDLK_p按鍵事件;
- 視頻線程解碼一幀,并將其顯示出來;并判斷當前視頻幀pts是否大于音頻幀pts,若大于則解鎖音頻播放標志;最后取消SDLK_p按鍵事件,并解鎖再次接收SDLK_p按鍵事件;
- 音頻線程若檢測到可以播放,則解碼音頻幀并播放,直到音頻幀pts大于等于視頻幀pts,則取消音頻播放事件;
總結
以上是生活随笔為你收集整理的音视频播放器—快进快退及逐帧播放的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Open Sans字体
- 下一篇: 现代字体栈