当前位置: 首页 > news >正文

ffmpeg 时间相关--时间基,timebase,pts,dts,duration

在编码时 video 的情况如下:

1. 在 yuv 数据 阶段,和时间相关参数如下:

yuv数据我们在设置的时候要 设置参数,其中和时间相关的是 yuvfps 和 timebase,yuvfps一般是每秒25帧,yuvfps=25;timebase 一般设置为 1000,000 这样 我们就能计算出来再yuv数据阶段一张图片花费时间为:  1/25 * 1000000 = 40,000 

整理:也就是说:我们在yuv阶段,yuv的timebase 是1000000,yuv的pts 的计算是每次读取一张图片,就给pts+= 1.0 / yuvfps * videotimebase

这两个值都是开发者设定的。

2. 当yuv数据在变成AVFrame时的过程中,时间相关

在从yuv 变成 avframe的过程中,一定要弄一个AVCodecContext,这时候要设置AVCodecContext 的相关参数,除了video的三要素外,还需要设置 AVCodecContext.timebase 为 1000000。

在将yuv数据变成AVFrame的代码中,我们需要重新计算并设置 AVFrame的pts。如何设置呢?

yuv的pts * yuv的timebase = 这张图片显示的时间 = avframe阶段的 pts  * avframe阶段的 timebase

avframe阶段的 pts = yuv的pts * yuv的timebase/avframe阶段的 timebase

整理:

avframe阶段的 timebase就是avcodeContext 中的timebase,对于video 来说:avcodeContext 中的timebase也是开发者手动设自动的。

在计算出来avframe的pts 后,记得设置avframe的pts的值。

3.当从avframe变成avpacket的过程中。时间相关

在前面,我们计算了avframe的pts,并设置了avframe的pts,也知道avframe的timebase 就是avcodecContext的timebase。

那么avpacket 的pts 也要重新计算。

AVFrame pts * avFrame timebase = 这张图片的显示时间 = avpacket pts * avpacket timebase

也就是:

avpacket pts = AVFrame pts * avFrame timebase / avpacket timebase

AVFrame pts 和 avFrame timebase 的值我们在前面已经知道了,

关键问题是 avpacket timebase 是怎么来的呢?

实际上是,avpacket timebase 使用的是 AVStream中的timebase,那么AVStream 的timebase又是怎么来的呢?当我们使用 

avformat_write_header(this->_avformatContext,nullptr);

发送头部的后,AVStream的timebase就有值了,不同的格式,AVStream的timebase不同,对于video来说,很多都是1,90000.

值的注意的是,我们在将avframe变成avpacket的时候,这时候还没有调用 avformat_write_header这个方法,因此这时候avpacket 中的pts,dts ,duration是和avframe的pts,dts,duration一样的值。

4. 最终将avpacket 变成 MP4或者flv,时间相关

上述第三步,更加准确的说:在avframe 变成 avpacket后,avpacket的pts和 avframe的pts 是一样的。

一般情况下,我们在调用了 是当 调用了 avformat_write_header 方法后,才会将 avpacket->pts重新计算,使用的 avpacket的pts会是 avstream中的pts

而且在这个时候 会将 avpacket 的dts,duration,pts都计算完成。

    dst_timebase = this->_video_avstream->time_base;avpacket->pts = av_rescale_q(avpacket->pts, src_timebase,dst_timebase);avpacket->dts = av_rescale_q(avpacket->dts, src_timebase,dst_timebase);avpacket->duration = av_rescale_q(avpacket->duration, src_timebase,dst_timebase);

在编码时 audio 的情况如下:

1. 在 pcm 数据 阶段,和时间相关参数如下:

我们以 44100 的pcm 转换成 aac 的例子说明:

我们在还是pcm数据的时候,会计算出来1024个样本帧的花费的时间,具体的计算公式为 1024/44100 * 1000,000。这里1000000 是转化为微秒的时间基。

2  avframe阶段的计算,和时间相关参数如下:


/// 当我们将读取的数据要存储到avframe中的时候,就需要重新计算avframe的pts,使用avframe对应的时间基
/// 首先要明确的是的 对于avframe 对应的时间基用的是avcodec中的timebase,那么avcodec中的timebase是怎么知道的呢?观察源码会发现,音频编码器上下文的timebase 是在 avcodec_open2方法中 设置的,且设置的值的为 avcodecContext中的 sample_rate 的倒数,也就是1/44100
/// 注意,avcodecContext中的 sample_rate实际上是需要user 手动的设定的,因此你就明白了为什么在 编码的时候一定要设置 编码器上下文的 sample_rate了
/// 那么现在我们有了三个值了,一个是 pcm的pts,一个是pcm的时间基,一个是avframe的时间基,求avframe的pts?
///  pcm的pts * pcm 的时间基 = avframe 的pts * avframe的时间基(也就是avcodecContext的timebase)
/// 结论为 :avframe 的pts  = pcm的pts * pcm 的时间基 / avframe的时间基(avcodecContext的timebase)
/// 为了防止内存溢出等问题,使用ffmpeg给我们提供的方法 :av_rescale_q(pts, AVRational{1, (int)time_base}, this->_avcodecContext->time_base)
/// 可以观察 :av_rescale_q方法的本质,就是第一个参数乘以第二个参数,最后除以第三个参数

3 avpacket阶段的计算


/// 到这里,我们最终生成的avpacket的 pts,dts,duration的值又是多少呢?
/// 实际上,在我们这个阶段,avpacket的 pts,dts,duration的值会直接 copy avframe中的pts,dts,duration(都是通过avcodec_receive_packet(this->_avcodecContext, avpacket) 方法传递的)
/// 这明显是不合理的。我们可以回顾一下 avframe 和avpacket 的本质,avframe装的是未压缩的pcm数据,avpacket装的是压缩过的pcm数据(也就是类似aac这样的数据)
/// 那么依然存在着  avframe的pts(当前已经存储在avpacket的pts) 转化成 真正的avpacket的pts的问题,那么avframe的时间基我们是知道的--是avcodec中的timebase,那么 这个真正的avpacket的时间基是什么呢?是avstream中的timebase
/// 那么avstream中的timebase怎么知道呢?实际上不同的编码器,它的avstream中的timebase是不同的,ffmpeg在你调用 avformat_write_header(fmt_ctx_, NULL);函数的时候就确定了您的timebase 是多少了,这也很容易想到,对于不同的编码器,它的头部信息一定就含有了 timebase这样重要的信息
/// avframe 的pts(当前旧的avpacket的pts) * avframe的时间基(avcodec的时间基) = 真正的avpacket的pts * 真正的avpacket的时间基(也就是avstream的时间基)
/// 结论为 :真正的avpacket的pts  = avframe 的pts(当前旧的avpacket的pts) * avframe的时间基(avcodec的时间基) / 真正的avpacket的时间基(也就是avstream的时间基)
/// 对应代码在 muxer.cpp的sendPacket中。

在解码时 video 的情况如下:

在解码时 audio 的情况如下:






 

/// 关于时间问题,看了网上的资料,大致结论如下,

/// 不同结构体的 time_base
///1、AVStream的time_base的单位是秒。每种格式的time_base的值不一样,根据采样来计算,比如mpeg的pts、dts都是以90kHz来采样的,所以采样间隔就是1/900000秒。
///2、AVCodecContext的time_base单位同样为秒,不过精度没有AVStream->time_base高,大小为1/framerate。
///3、AVPacket下的pts和dts以AVStream->time_base为单位(数值比较大),时间间隔就是AVStream->time_base。
///4、AVFrame里面的pkt_pts和pkt_dts是拷贝自AVPacket,同样以AVStream->time_base为单位;而pts是为输出(显示)准备的,以AVCodecContex->time_base为单位。
///5、输入流InputStream下的pts和dts以AV_TIME_BASE为单位(微秒),至于为什么要转化为微秒,可能是为了避免使用浮点数。
///6、输出流OutputStream涉及音视频同步,结构和InputStream不同,暂时只作记录,不分析

相关文章:

  • 充气膜游泳馆安全吗—轻空间
  • Log4j的原理及应用详解(四)
  • 基于单片机的智能医疗监护系统设计
  • EasyAnimate-v3版本支持I2V及超长视频生成
  • Netty一文搞懂——核心原理篇<随手笔记>
  • flink 配置表
  • buuctf-web
  • 一图了解网络通信原理
  • 在linux中查找 / 目录下的以.jar结尾的文件(find / -name *.jar)
  • qt 创建一个左侧边线拖拽的矩形
  • 主机安全-开源HIDS字节跳动Elkeid安装使用
  • pgsql(guass)可获取到对应的表名称、字段名称、注释、字段类型
  • OrangePi AIpro 浅上手
  • MATLAB实现一个车辆悬架PID模拟系统
  • Django相关的基本操作
  • 《Java编程思想》读书笔记-对象导论
  • Android Volley源码解析
  • Angular4 模板式表单用法以及验证
  • canvas 五子棋游戏
  • create-react-app项目添加less配置
  • go语言学习初探(一)
  • JavaScript函数式编程(一)
  • JS专题之继承
  • Linux快速复制或删除大量小文件
  • Netty 4.1 源代码学习:线程模型
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Shadow DOM 内部构造及如何构建独立组件
  • Vultr 教程目录
  • 笨办法学C 练习34:动态数组
  • 彻底搞懂浏览器Event-loop
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 对象引论
  • 服务器从安装到部署全过程(二)
  • 基于web的全景—— Pannellum小试
  • 在electron中实现跨域请求,无需更改服务器端设置
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • puppet连载22:define用法
  • zabbix3.2监控linux磁盘IO
  • 扩展资源服务器解决oauth2 性能瓶颈
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • #pragam once 和 #ifndef 预编译头
  • #我与Java虚拟机的故事#连载19:等我技术变强了,我会去看你的 ​
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (6) 深入探索Python-Pandas库的核心数据结构:DataFrame全面解析
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (Java)【深基9.例1】选举学生会
  • (java)关于Thread的挂起和恢复
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (三)docker:Dockerfile构建容器运行jar包
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .JPG图片,各种压缩率下的文件尺寸