【ffmpeg】时间基与时间戳

FFmpeg 中的时间基与时间戳

时间基与时间戳的概念

在 FFmpeg 中,时间基(time_base)是时间戳(timestamp)的基本单位。时间戳值乘以时间基,可以得到实际的时刻值(以秒等为单位)。

例如,如果一个视频帧的 pts=5760, time_base=1/16000 ,那么可以计算出此视频帧的 显示时刻
= p t s ∗ t i m e _ b a s e = 5760 ∗ 1 / 16000 = 0.36 s \begin{aligned} & = pts*time\_base\\ & = 5760 * 1 / 16000\\ & = 0.36 s \end{aligned} =ptstime_base=57601/16000=0.36s

三种时间基 tbr、tbn 和 tbc

不同的封装格式具有不同的时间基。在 FFmpeg 处理音视频过程中的不同阶段,也会采用不同的时间基。
FFmepg 中有三种时间基,命令行中 tbr、tbn 和 tbc 的打印值就是这三种时间基的倒数:
tbn:对应容器中的时间基。值是 AVStream.time_base 的倒数
tbc:对应编解码器中的时间基。值是 AVCodecContext.time_base 的倒数
tbr:从视频流中猜算得到,可能是帧率或场率(帧率的 2 倍)

FFmpeg时间戳详解

相关函数

在ffmpeg中可以使用av_rescale_q函数将pts转换到指定时间基下

int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;
  • 第一个参数:原pts
  • 第二个参数:原time_base
  • 第三个参数:新time_base
  • 返回值:新pts

在ffmpeg中可以使用av_q2d函数将pts转化为以ms为单位的时间

double pts = frame->pts * av_q2d(tb);

例子

下面代码中每取出一个解码帧就打印其pts转换前后的信息

int ret = avcodec_receive_frame(video_dec_ctx, frame);
if(ret >= 0)
{
    AVRational tb = video_dec_ctx->pkt_timebase;
    double pts = av_rescale_q(frame->pts, video_dec_ctx->pkt_timebase, tb);
    pts = pts * av_q2d(tb);
    spdlog::get("file_logger")->info("Video: pts = {}, pkt_timebase = {}/{}, tb = {}/{}, new_pts {}", 
    frame->pts, video_dec_ctx->pkt_timebase.num, video_dec_ctx->pkt_timebase.den, tb.num, tb.den, pts);
    frame->pts = frame->best_effort_timestamp;
}

log日志如下

[2024-07-04 17:20:43.492] [file_logger] [info] Video: pts = 1280, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.08
[2024-07-04 17:20:43.499] [file_logger] [info] Video: pts = 1920, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.12
[2024-07-04 17:20:43.505] [file_logger] [info] Video: pts = 2560, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.16
[2024-07-04 17:20:43.512] [file_logger] [info] Video: pts = 3200, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.2
[2024-07-04 17:20:43.520] [file_logger] [info] Video: pts = 3840, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.24
[2024-07-04 17:20:43.526] [file_logger] [info] Video: pts = 4480, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.28
[2024-07-04 17:20:43.533] [file_logger] [info] Video: pts = 5120, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.32
[2024-07-04 17:20:43.545] [file_logger] [info] Video: pts = 5760, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.36
[2024-07-04 17:20:43.547] [file_logger] [info] Video: pts = 6400, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.4
[2024-07-04 17:20:43.561] [file_logger] [info] Video: pts = 7040, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.44
[2024-07-04 17:20:43.612] [file_logger] [info] Video: pts = 7680, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.48
[2024-07-04 17:20:43.657] [file_logger] [info] Video: pts = 8320, pkt_timebase = 1/16000, tb = 1/16000, new_pts 0.52

值得一提的是video_dec_ctx->pkt_timebase一般为0,通常需要我们手动赋值。我们可以在创建解码器时从stream中获取该值

dec_ctx->pkt_timebase = videoStream->time_base;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值