• 解决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的时间戳和时间基的使用,可以有效的解决音视频的同步的问题

  • 相关阅读:
    编程语言 编译型语言与解释型语言及汇编语言
    Alpha冲刺2
    事后诸葛亮
    Alpha阶段项目复审
    PostgreSQL的表膨胀与Vacuum和Vacuum Full
    PostgreSQL查看表膨胀(对所有表进行膨胀率排序)
    python中from __future__ import division/print_function的用法
    【IT企业笔试集】2013年阿里巴巴实习生招聘笔试题目及解答
    【WPF编程】一个未完成的12306本地客户端的源代码
    【深入理解计算机系统第二版】3.55习题
  • 原文地址:https://www.cnblogs.com/fandx/p/12199472.html
Copyright © 2020-2023  润新知