zoukankan      html  css  js  c++  java
  • 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 ", 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 ", 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 ", j,begin_second,begin_pts_t,end_second,end_pts_t);
       
  • 相关阅读:
    就现在的几种代码管理库的比较
    就书籍“构造之法”的问题
    软件工程之中期学习总结
    软件项目管理之理解
    软件代码规范之理解
    介绍几个常用的代码管理工具
    关于构建之法的问题
    研究生竞赛系统需求规格说明书
    各种GIT代码托管工具比较
    第一个作业
  • 原文地址:https://www.cnblogs.com/yangxiayi1987/p/13223063.html
Copyright © 2011-2022 走看看