音視頻技術應用(18)- 控制播放進度——av_seek_frame()


一. 概述

用於將視頻移動到指定的關鍵幀位置。

二. 函數說明

/**
 * 移動視頻到指定的關鍵幀位置
 *
 * @param s 輸入媒體的上下文
 * @param stream_index seek的流索引。就是seek時究竟是以音頻流索引還是以視頻流索引為基准進行seek
 * @param timestamp 起始位置的時間戳,單位是AVStream.time_base
 * @param flags seek的具體策略
 * @return >= 0 on success
 */
int av_seek_frame(AVFromatContext *s, int stream_index, int64_t timestmap, int flags);

第二個參數timestamp的詳細說明:

這里的timestamp代表的是想要移動到的起始位置的時間戳,注意這里是起始位置的時間戳,不是起始位置的秒數! 通俗地講,它就是起始位置的pts,因此一個10s的視頻,你想移動到5s的位置,直接傳5是不對的。在 FFmpeg 中,時間戳(timestamp)的單位是時間基數(time_base)時間戳值乘以時間基,可以得到實際的時刻值(以秒等為單位)。例如,如果一個視頻幀的 dts 是 40,pts 是 160,其 time_base1/1000 秒,那么可以計算出此視頻幀的解碼時刻是 40 毫秒(40/1000),顯示時刻是 160 毫秒(160/1000)。FFmpeg 中時間戳(pts/dts)的類型是 int64_t 類型,如果把一個 time_base 看作一個時鍾脈沖,那么 dts/pts 則可以看作是時鍾脈沖的計數。

第四個參數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

下面分別對其進行詳細說明:

一. AVSEEK_FLAG_BACKWARD

實際業務中有這樣一個場景:用戶經常會通過拖動視頻底部進度條的方式來跳轉到某一幀的位置,那這個時候如何確定當前幀的具體位置呢?有一種辦法就是計算當前拖動位置的百分比,然后根據當前視頻的總時長,乘以該百分比,得到當前跳轉位置的時間,然后根據該時間進行seek操作。

比方說總時長是1000ms, 那如果用戶拖動到中間的位置,那就應該seek到500ms的位置,這個時候把500ms傳入到上面的函數中進行seek就可以了。可這樣有一個問題,你把500ms傳入到上面的視頻幀當中,是否真的有pts為500ms的視頻幀呢?很難,有可能根本就沒有pts為500ms的視頻幀,這個時候可能有498,也有可能有501的,那到底是取498的呢?還是取501的呢?這個時候就要有一套策略,AVSEEK_FLAG_BACKWARD 這個FLAG就相當於標識往后走,也就是找pts為501的視頻幀。

二. AVSEEK_FLAG_BYTE

這種對應的另外一種場景:假設我想移動視頻到中間的位置,但是當前視頻文件卻沒有索引, 不過我卻知道這個視頻文件的大小(1M), 那這個時候要移動視頻到中間位置的話,其實就是應該對應在500KB左右的位置,AVSEEK_FLAG_BYTE這個FLAG就相當於是根據字節數來移動它的位置。

三. AVSEEK_FLAG_ANY

移動視頻到任意幀的位置。也就是說,seek到的位置可能是關鍵幀,也可能是非關鍵幀,注意:如果移動到的是非關鍵幀,這個時候解碼可能會失敗(因為少了前面的關鍵幀做參考),出現的后果是可能會造成花屏。

四. AVSEEK_FLAG_FRAME

移動視頻到關鍵幀位置。與上面的FLAG不同,這種情況下會強制移動到關鍵幀位置,比如你要移動的位置是500ms, 但是在500ms沒有關鍵幀,但是在前面400ms的位置有關鍵幀,它就會移到400ms的位置,這樣的話畫面就能夠正常顯示。

注意這種策略也有一定的問題,假設當前視頻的GOP是100幀,這100幀的時長是4s, 那這樣的話拖動到這4s的任意位置,畫面可能都不會改變(由於設置了移動到關鍵幀,而一個GOP中只有第一幀才是關鍵幀),這樣會給人一個錯覺——移動失敗了,這點需要注意。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM