ffmpeg視頻文件PTS與時間戳,幀號的換算


 ffmpeg中的pts,dts,duration時間記錄都是基於timebase換算,很多剛接觸ffmpeg的同學都不容易搞清楚它的時間計算方法。
我們先看下ffmpeg時間是怎么算的:
一幀圖像(音頻)的時間戳(時間戳一般以第一幀為0開始,但也有很多首幀不是從0開始,這里用first_frame_pts表示)
時間戳 = pts * (AVRational.num/AVRational.den) ,這里的pts是相對pts = 絕對PTS - 首幀PTS
看下ffmpeg的說明:
“當有理數用浮點數做轉換時是有損的,ffmpeg要求高精度的計算的時間戳,所以用分數來做換算”。
我們在看下換算用到的結構體,一看到他是用分數就容易理解了
typedef struct AVRational{
int num; ///<分子
int den; ///< 分母
} AVRational;
其實當num=1,den=1000的時候pts的時間單位就相當於毫秒 1/1000秒
其實當num=1,den=1000000的時候pts的時間單位就相當於微秒 1/1000000秒
時間換算
     比如我們要通過ffmpeg實現直播推流,推流一個文件,文件中的時間基數一般是{ num=1,den=1000000} ,推流用的正常是timebase {num=1,den=1000}。那就可以做如下計算:
     推流的pts = 文件pts * 文件timebase / 推流timebase
     如果手動計算要判斷分母是否為0,不然會造成程序宕掉。當然ffmpeg內部也提供了轉換的函數
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;

下面是我根據我們業務系統定義的JSON文件,對文件內容進行了PTS到時間戳的轉換,采用JAVA實現如下:

   // metadata,視頻流信息
   int fps = video_results.getJSONObject("metadata").getIntValue("fps"); //幀率
   int time_base_num = video_results.getJSONObject("metadata").getIntValue("time_base_num"); //時間戳基數:分子
   int time_base_den = video_results.getJSONObject("metadata").getIntValue("time_base_den"); //時間戳基數:分母
   int first_frame_pts = video_results.getJSONObject("metadata").getIntValue("first_frame_pts"); //起始幀號

      //輸出pts
     int begin_pts = track_results.getJSONObject(j).getJSONArray("faces").getJSONObject(0).getIntValue("pts"); //開始PTS
     int end_pts = track_results.getJSONObject(j).getJSONArray("faces").getJSONObject(1).getIntValue("pts");     //結束PTS
     System.out.printf("track %d pts:%d,%d\n", j,begin_pts,end_pts);

      //轉換成時間戳輸出,格式:s    
     double begin_timestamp = (double)((begin_pts-first_frame_pts)*time_base_num)/(double)time_base_den;
     double end_timestamp = (double)((end_pts-first_frame_pts)*time_base_num)/(double)time_base_den; 
     System.out.printf("track %d time(sec):%f,%f\n", j,begin_timestamp,end_timestamp);
         
     //輸出格式:秒+幀
     int begin_frame = (begin_pts-first_frame_pts)*fps*time_base_num/time_base_den;
     int end_frame = (end_pts-first_frame_pts)*fps*time_base_num/time_base_den;     
     int begin_second = begin_frame/fps; //秒
     int begin_pts_t =  begin_frame -  begin_second*fps;
     int end_second = end_frame/fps; //秒
     int end_pts_t =  end_frame -  end_second*fps; 
     System.out.printf("track %d time(sec.frame):%d.%d,%d.%d\n", j,begin_second,begin_pts_t,end_second,end_pts_t);
   


免責聲明!

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



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