解決ffmpeg中的時間戳同步問題


PTS/DTS(時間戳)

要想解決時間同步問題就必須要了解ffmpeg中的PTS和DTS到底是什么

  • PTS:

    PTS(Presentation TimeStamp)是渲染用的時間戳,播放器會根據這個時間戳進行渲染播放

  • DTS:

    DTS(Decoding TimeStamp)解碼時間戳,在視頻packet進行解碼成frame的時候會使用到

  • 有了PTS為什么還需要DTS

    就拿編碼H264來說,H264編碼分為I幀,B幀,P幀,I幀是關鍵幀,也就是一個GOP的最開始幀,B幀是前后參考幀,它屬於幀間壓縮技術,B幀會通過記錄前后兩幀進行壓縮,P幀是向前參考幀,比B幀的壓縮率要低

    因為B幀要參考前后幀,那么在編碼之后的幀的時間順序就會發生變化,所以在沒有B幀的時候PTS和DTS應該是一樣的,有了B幀之后PTS和DTS也就會發生變化

時間基

有了時間戳之后,還需要將PTS的時間戳轉成以秒為單位的時間。這里就需要用到ffmpeg的時間基來進行計算了

先了解一下tbr,tbn,tbc

  • tbr: 是通常說的幀率
  • tbn: 視頻流的時間基
  • tbc: 時間解碼的時間基

在ffmpeg中,不同的時間戳對應不同的時間基。一般在視頻進行渲染的時候渲染的時候用到的就是視頻流的時間基tbn,視頻流的時間基和幀率有關,每秒30幀,代表一幀需要1/30秒

  • ffmpeg內部有自己的時間基,分別定義了

      // ffmpeg中內部的時間基
      #define		AV_TIME_BASE   1000000
    
      // ffmpeg中分數所表示法
      #define 	AV_TIME_BASE_Q (AVRatonal){1, AV_TIME_BASE}
    
  • av_q2d,計算真實秒數

    // ffmpeg 中進行轉換,將時間轉成秒,av_q2d可以將時間基轉換成double類型小數
    typedef struct AVRational{
    int num; //numerator
    int den; //denominator
    } AVRational;
    static inline double av_q2d(AVRational a){
    /**
    * Convert rational to double.
    * @param a rational to convert
    **/
        return a.num / (double) a.den;
    }
    // 通過pts*時間基的小數可以算出當前的流的秒數
    AVRational time_base = {1, 30};
    double time_sec = pts * av_q2d(time_base)
    
    
  • av_rescale_q(),不同的時間基直接的轉換

    /**
     * Rescale a 64-bit integer by 2 rational numbers.
     *
     * The operation is mathematically equivalent to `a * bq / cq`.
     *
     * This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF.
     *
     * @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd()
     */
    int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;
    
    /*
    @param a : 需要進行轉換的時間戳
    @bq	: 對應轉換的時間戳的原來的時間基
    @cq	: 轉換之后的時間基
    
    */
    

總結

通過ffmpeg的時間戳和時間基的使用,可以有效的解決音視頻的同步的問題


免責聲明!

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



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